Android車載機携帯電話システム開発 ~マルチウィンドウモードでのPIPを詳しく解説~

ビデオチュートリアルの説明:
https://www.bilibili.com/video/BV1wj411o7A9/
ここに画像の説明を挿入

1.PIPエントリ

公式の説明と注釈:
/** 親コンテナ内の他の兄弟の常に最前面 (常に表示) */
public static Final int WINDOWING_MODE_PINNED = 2;

アプリ層:

  private void enterPiPMode() {
    
    
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    
    
            if (mPictureInPictureParamsBuilder == null) {
    
    
                mPictureInPictureParamsBuilder = new PictureInPictureParams.Builder();
            }
            if (videoView != null) {
    
    
                int mVideoWith = videoView.getWidth();
                int mVideoHeight = videoView.getHeight();
                if (mVideoWith != 0 && mVideoHeight != 0) {
    
    
                    //设置param宽高比,根据宽高比例调整初始参数
                    Rational aspectRatio = new Rational(mVideoWith, mVideoHeight);
                    mPictureInPictureParamsBuilder.setAspectRatio(aspectRatio);
                }

            }
            //进入pip模式
            enterPictureInPictureMode(mPictureInPictureParamsBuilder.build());
        }
    }

システムサーバーレベルのコア:
コアメソッド moveActivityToPinnedRootTask:


void moveActivityToPinnedRootTask(@NonNull ActivityRecord r,
            @Nullable ActivityRecord launchIntoPipHostActivity, String reason) {
    
    
      //省略
            // The intermediate windowing mode to be set on the ActivityRecord later.
            // This needs to happen before the re-parenting, otherwise we will always set the
            // ActivityRecord to be fullscreen.
            final int intermediateWindowingMode = rootTask.getWindowingMode();
        //省略
            //注意ActivityRecord设置的是intermediateWindowingMode即不是pip还是fullscreen
            r.setWindowingMode(intermediateWindowingMode);
            r.mWaitForEnteringPinnedMode = true;
            //省略
            //Task被尽快设置成了WINDOWING_MODE_PINNED
            rootTask.setWindowingMode(WINDOWING_MODE_PINNED);
      //省略
      //这里会触发sendTaskAppeared
            rootTask.setDeferTaskAppear(false);

                  //省略
        } finally {
    
    
            mService.continueWindowLayout();
        }
			//进行了Task的windowmode设置后一般要触发ensureActivitiesVisible和resumeFocusedTasksTopActivities来保证系统所有Activity的显示正常
        ensureActivitiesVisible(null, 0, false /* preserveWindows */);
        resumeFocusedTasksTopActivities();

        notifyActivityPipModeChanged(r.getTask(), r);
    }

概要:
1. pip モードに入ると、システム サーバー レベルは主に、ActivityRecord のウィンドウ モードを個別にフルスクリーンに設定し、タスク 2 のウィンドウ モードを pip モードに設定する必要があります。一般に、タスクに関連する属性を変更した後、ensureActivitiesVisible およびresumeFocusedTasksTopActivities が実行されます
。システムの現在のアクティビティを正常に表示できるようにするためにトリガーされます。

2. ライフサイクルの変化

ランチャーが再開を開始します:


obtain:78, ResumeActivityItem (android.app.servertransaction)
resumeTopActivity:1434, TaskFragment (com.android.server.wm)
resumeTopActivityInnerLocked:5003, Task (com.android.server.wm)
resumeTopActivityUncheckedLocked:4938, Task (com.android.server.wm)
resumeTopActivityUncheckedLocked:4952, Task (com.android.server.wm)
resumeTopActivityUncheckedLocked:4984, Task (com.android.server.wm)
makeActiveIfNeeded:5765, ActivityRecord (com.android.server.wm)
makeVisibleIfNeeded:5697, ActivityRecord (com.android.server.wm)
setActivityVisibilityState:210, EnsureActivitiesVisibleHelper (com.android.server.wm)
process:143, EnsureActivitiesVisibleHelper (com.android.server.wm)
updateActivityVisibilities:1111, TaskFragment (com.android.server.wm)
lambda$ensureActivitiesVisible$18:4834, Task (com.android.server.wm)
accept:-1, Task$$ExternalSyntheticLambda23 (com.android.server.wm)
forAllLeafTasks:3160, Task (com.android.server.wm)
forAllLeafTasks:3148, Task (com.android.server.wm)
ensureActivitiesVisible:4833, Task (com.android.server.wm)
lambda$ensureActivitiesVisible$45:6217, DisplayContent (com.android.server.wm)
accept:-1, DisplayContent$$ExternalSyntheticLambda38 (com.android.server.wm)
forAllRootTasks:3172, Task (com.android.server.wm)
forAllRootTasks:2014, WindowContainer (com.android.server.wm)
forAllRootTasks:2014, WindowContainer (com.android.server.wm)
forAllRootTasks:2014, WindowContainer (com.android.server.wm)
forAllRootTasks:2014, WindowContainer (com.android.server.wm)
forAllRootTasks:2014, WindowContainer (com.android.server.wm)
forAllRootTasks:2014, WindowContainer (com.android.server.wm)
forAllRootTasks:2007, WindowContainer (com.android.server.wm)
ensureActivitiesVisible:6216, DisplayContent (com.android.server.wm)
ensureActivitiesVisible:1864, RootWindowContainer (com.android.server.wm)
ensureActivitiesVisible:1845, RootWindowContainer (com.android.server.wm)
setWindowingModeInSurfaceTransaction:4632, Task (com.android.server.wm)
lambda$setWindowingMode$16$com-android-server-wm-Task:4513, Task (com.android.server.wm)
run:-1, Task$$ExternalSyntheticLambda40 (com.android.server.wm)
inSurfaceTransaction:8282, WindowManagerService (com.android.server.wm)
setWindowingMode:4513, Task (com.android.server.wm)
setWindowingMode:4501, Task (com.android.server.wm)
moveActivityToPinnedRootTask:2114, RootWindowContainer (com.android.server.wm)
lambda$enterPictureInPictureMode$5$com-android-server-wm-ActivityTaskManagerService:3474, ActivityTaskManagerService (com.android.server.wm)
run:-1, ActivityTaskManagerService$$ExternalSyntheticLambda3 (com.android.server.wm)
enterPictureInPictureMode:3497, ActivityTaskManagerService (com.android.server.wm)
enterPictureInPictureMode:740, ActivityClientController (com.android.server.wm)
onTransact:878, IActivityClientController$Stub (android.app)
onTransact:124, ActivityClientController (com.android.server.wm)
execTransactInternal:1280, Binder (android.os)
execTransact:1244, Binder (android.os)

pip アプリが一時停止に入る
質問 1: pip はなぜ一時停止するだけで停止しないのですか

「onPause」と入力してください

サーバー側で PauseActivityItem を構築するときに、対応するスタックを出力できます。

obtain:75, PauseActivityItem (android.app.servertransaction)
makeActiveIfNeeded:5779, ActivityRecord (com.android.server.wm)
setActivityVisibilityState:207, EnsureActivitiesVisibleHelper (com.android.server.wm)
process:143, EnsureActivitiesVisibleHelper (com.android.server.wm)
updateActivityVisibilities:1119, TaskFragment (com.android.server.wm)
lambda$ensureActivitiesVisible$18:4834, Task (com.android.server.wm)
accept:-1, Task$$ExternalSyntheticLambda23 (com.android.server.wm)
forAllLeafTasks:3160, Task (com.android.server.wm)
ensureActivitiesVisible:4833, Task (com.android.server.wm)
lambda$ensureActivitiesVisible$45:6216, DisplayContent (com.android.server.wm)
accept:-1, DisplayContent$$ExternalSyntheticLambda38 (com.android.server.wm)
forAllRootTasks:3172, Task (com.android.server.wm)
forAllRootTasks:2020, WindowContainer (com.android.server.wm)
forAllRootTasks:2020, WindowContainer (com.android.server.wm)
forAllRootTasks:2020, WindowContainer (com.android.server.wm)
forAllRootTasks:2020, WindowContainer (com.android.server.wm)
forAllRootTasks:2020, WindowContainer (com.android.server.wm)
forAllRootTasks:2020, WindowContainer (com.android.server.wm)
forAllRootTasks:2013, WindowContainer (com.android.server.wm)
ensureActivitiesVisible:6215, DisplayContent (com.android.server.wm)
ensureActivitiesVisible:1864, RootWindowContainer (com.android.server.wm)
ensureActivitiesVisible:1845, RootWindowContainer (com.android.server.wm)
setWindowingModeInSurfaceTransaction:4632, Task (com.android.server.wm)
lambda$setWindowingMode$16$com-android-server-wm-Task:4513, Task (com.android.server.wm)
run:-1, Task$$ExternalSyntheticLambda40 (com.android.server.wm)
inSurfaceTransaction:8282, WindowManagerService (com.android.server.wm)
setWindowingMode:4513, Task (com.android.server.wm)
setWindowingMode:4501, Task (com.android.server.wm)
moveActivityToPinnedRootTask:2114, RootWindowContainer (com.android.server.wm)
lambda$enterPictureInPictureMode$5$com-android-server-wm-ActivityTaskManagerService:3474, ActivityTaskManagerService (com.android.server.wm)
run:-1, ActivityTaskManagerService$$ExternalSyntheticLambda3 (com.android.server.wm)
enterPictureInPictureMode:3497, ActivityTaskManagerService (com.android.server.wm)
enterPictureInPictureMode:740, ActivityClientController (com.android.server.wm)
onTransact:878, IActivityClientController$Stub (android.app)
onTransact:124, ActivityClientController (com.android.server.wm)
execTransactInternal:1280, Binder (android.os)
execTransact:1244, Binder (android.os)

スタック内の主な判断は次のとおりです。

boolean makeActiveIfNeeded(ActivityRecord activeActivity) {
    
    
        if (shouldResumeActivity(activeActivity)) {
    
    
         //省略
        } else if (shouldPauseActivity(activeActivity)) {
    
     //核心在与这里的shouldPauseActivity为true
            setState(PAUSING, "makeActiveIfNeeded");
            try {
    
    
                mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), token,
                        PauseActivityItem.obtain(finishing, false /* userLeaving */,
                                configChangeFlags, false /* dontReport */));
            } catch (Exception e) {
    
    
                Slog.w(TAG, "Exception thrown sending pause: " + intent.getComponent(), e);
            }
        }
          @VisibleForTesting
    boolean shouldPauseActivity(ActivityRecord activeActivity) {
    
     //这里面的isFocusable是关键,即现在已经属于不可以焦点状态
        return shouldMakeActive(activeActivity) && !isFocusable() && !isState(PAUSING, PAUSED)&& (results == null);
    }
    
    @Override
    boolean isFocusable() {
    
    
        return super.isFocusable() && (canReceiveKeys() || isAlwaysFocusable());
    }
     boolean canReceiveKeys() {
    
    
        // TODO(156521483): Propagate the state down the hierarchy instead of checking the parent
        return getWindowConfiguration().canReceiveKeys()
                && (task == null || task.getWindowConfiguration().canReceiveKeys());
    }
       /**
     * Returns true if the windows associated with this window configuration can receive input keys.
     * @hide
     */
    public boolean canReceiveKeys() {
    
     //这里是WINDOWING_MODE_PINNED,所以返回false,这里就是核心关键地方导致focusable为false
        return mWindowingMode != WINDOWING_MODE_PINNED;
    }

要約され合理化されたフローチャートは次のとおりです。
ここに画像の説明を挿入

通常の状況では、アクティビティの表示状態によって、アクティビティが停止状態に入るかどうかが決まります。

つまり、アクティビティが Pasued 状態にある場合、システムが ensureActivitiesVisible 呼び出しをトリガーすると、
各タスクの対応する EnsureActivitiesVisibleHelper プロセス メソッドをトラバースします。

void process(@Nullable ActivityRecord starting, int configChanges, boolean preserveWindows,
            boolean notifyClients) {
    
    
        reset(starting, configChanges, preserveWindows, notifyClients);
       //省略
        for (int i = mTaskFragment.mChildren.size() - 1; i >= 0; --i) {
    
    
            final WindowContainer child = mTaskFragment.mChildren.get(i);
            final TaskFragment childTaskFragment = child.asTaskFragment();
               //省略
            } else if (child.asActivityRecord() != null) {
    
    
                setActivityVisibilityState(child.asActivityRecord(), starting, resumeTopActivity);
            }
        }
    }

ここで最初に行うことは、reset を呼び出すことです

void reset(ActivityRecord starting, int configChanges, boolean preserveWindows,
            boolean notifyClients) {
    
    
        mStarting = starting;
        mTop = mTaskFragment.topRunningActivity();
        // If the top activity is not fullscreen, then we need to make sure any activities under it
        // are now visible.
        mAboveTop = mTop != null;
        mContainerShouldBeVisible = mTaskFragment.shouldBeVisible(mStarting);//这里的mContainerShouldBeVisible就代表Task是否可以显示,这个地方最为关键
        mBehindFullyOccludedContainer = !mContainerShouldBeVisible;
        mConfigChanges = configChanges;
        mPreserveWindows = preserveWindows;
        mNotifyClients = notifyClients;
    }

上記の呼び出しのキーは mTaskFragment.ShouldBeVisible(mStarting) です。

  boolean shouldBeVisible(ActivityRecord starting) {
    
    
        return getVisibility(starting) != TASK_FRAGMENT_VISIBILITY_INVISIBLE;
    }

はは、getVisibility の値を再度比較するためにここを見つけました。以前にこの場所を分析したことがあります。

小さなウィンドウの pip は一時停止状態に入っていますが、表示されているものはまだ true 状態を表示できるため、
タスクが true として表示されていることを確認した後、setActivityVisibilityState メソッドを確認します。

private void setActivityVisibilityState(ActivityRecord r, ActivityRecord starting,
            final boolean resumeTopActivity) {
    
    
     //省略
     //这里的mBehindFullyOccludedContainer再前面reset已经置为了false代表没有被覆盖
        r.updateVisibilityIgnoringKeyguard(mBehindFullyOccludedContainer);
        final boolean reallyVisible = r.shouldBeVisibleUnchecked();//这里会判断是否真正显示
        if (reallyVisible) {
    
    
            //可见状态,所以这里属于可见状态,导致不会进入makeInvisible
        } else {
    
    
        		//不可见调用makeInvisible
            r.makeInvisible();
        }

       //省略
    }
   //这里的 behindOccludedContainer为false,会返回visibleIgnoringKeyguard为true
     void updateVisibilityIgnoringKeyguard(boolean behindOccludedContainer) {
    
    
        visibleIgnoringKeyguard = (!behindOccludedContainer || mLaunchTaskBehind)
                && showToCurrentUser();
    }
       boolean shouldBeVisibleUnchecked() {
    
    
        final Task rootTask = getRootTask();
        //这里visibleIgnoringKeyguard所以不会进入,故shouldBeVisibleUnchecked一般返回true,代表可以显示
        if (rootTask == null || !visibleIgnoringKeyguard) {
    
     
            return false;
        }
        if (inPinnedWindowingMode() && rootTask.isForceHidden()) {
    
    
            return false;
        }

        if (hasOverlayOverUntrustedModeEmbedded()) {
    
    
            return false;
        }
        if (mDisplayContent.isSleeping()) {
    
    
            return canTurnScreenOn();
        } else {
    
    
            return mTaskSupervisor.getKeyguardController().checkKeyguardVisibility(this);
        }
    }

ここでは、makeInvisible メソッドが呼び出されるために停止シチュエーションが実行されるという追加のポイントを示します。

void makeInvisible() {
    
    
       //省略
       try{
    
    
            final boolean deferHidingClient = canEnterPictureInPicture
                    && !isState(STARTED, STOPPING, STOPPED, PAUSED);
            setDeferHidingClient(deferHidingClient);
            setVisibility(false);

            switch (getState()) {
    
    
                case STOPPING:
                case STOPPED:
                    // Reset the flag indicating that an app can enter picture-in-picture once the
                    // activity is hidden
                    supportsEnterPipOnTaskSwitch = false;
                    break;
                case RESUMED:
                case INITIALIZING:
                case PAUSING:
                case PAUSED://已经处于PASUED状态了
                case STARTED:
                    addToStopping(true /* scheduleIdle */,
                            canEnterPictureInPicture /* idleDelayed */, "makeInvisible");//这里会加入到Stop列表
                    break;

                default:
                    break;
            }
        } catch (Exception e) {
    
    
            // Just skip on any failure; we'll make it visible when it next restarts.
            Slog.w(TAG, "Exception thrown making hidden: " + intent.getComponent(), e);
        }
    }

3. ピップがアニメーション処理部分に入る

pip はどのようにしてアニメーション プロセスに入るのか

System_server トリガー:

05-24 00:18:00.318   568  1263 I test22  : onTaskInfoChanged taskInfo = TaskInfo{
    
    userId=0 taskId=1015 displayId=0 isRunning=true baseIntent=Intent {
    
     act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.myapplication11/.MainActivity } baseActivity=ComponentInfo{
    
    com.example.myapplication11/com.example.myapplication11.MainActivity} topActivity=ComponentInfo{
    
    com.example.myapplication11/com.example.myapplication11.MainActivity} origActivity=null realActivity=ComponentInfo{
    
    com.example.myapplication11/com.example.myapplication11.MainActivity} numActivities=1 lastActiveTime=466473 supportsSplitScreenMultiWindow=true supportsMultiWindow=true resizeMode=2 isResizeable=true minWidth=-1 minHeight=-1 defaultMinSize=220 token=WCT{
    
    RemoteToken{
    
    38f3882 Task{
    
    1a959c8 #1015 type=standard A=10118:com.example.myapplication11 U=0 visible=true visibleRequested=true mode=pinned translucent=false sz=1}}} topActivityType=1 pictureInPictureParams=PictureInPictureParams( aspectRatio=72/35 expandedAspectRatio=null sourceRectHint=null hasSetActions=false hasSetCloseAction=false isAutoPipEnabled=false isSeamlessResizeEnabled=true title=null subtitle=null isLaunchIntoPip=false) shouldDockBigOverlays=false launchIntoPipHostTaskId=0 displayCutoutSafeInsets=null topActivityInfo=ActivityInfo{
    
    dbedb93 com.example.myapplication11.MainActivity} launchCookies=[android.os.BinderProxy@7dc77d0] positionInParent=Point(0, 0) parentTaskId=-1 isFocused=false isVisible=true isSleeping=false topActivityInSizeCompat=false topActivityEligibleForLetterboxEducation= false locusId=null displayAreaFeatureId=1 cameraCompatControlState=hidden}
05-24 00:18:00.318   568  1263 I test22  : java.lang.Exception
05-24 00:18:00.318   568  1263 I test22  : 	at com.android.server.wm.TaskOrganizerController$TaskOrganizerCallbacks.onTaskInfoChanged(TaskOrganizerController.java:155)
05-24 00:18:00.318   568  1263 I test22  : 	at com.android.server.wm.TaskOrganizerController.dispatchTaskInfoChanged(TaskOrganizerController.java:817)
05-24 00:18:00.318   568  1263 I test22  : 	at com.android.server.wm.TaskOrganizerController.dispatchPendingEvents(TaskOrganizerController.java:728)
05-24 00:18:00.318   568  1263 I test22  : 	at com.android.server.wm.RootWindowContainer.performSurfacePlacementNoTrace(RootWindowContainer.java:837)
05-24 00:18:00.318   568  1263 I test22  : 	at com.android.server.wm.RootWindowContainer.performSurfacePlacement(RootWindowContainer.java:784)
05-24 00:18:00.318   568  1263 I test22  : 	at com.android.server.wm.WindowSurfacePlacer.performSurfacePlacementLoop(WindowSurfacePlacer.java:177)
05-24 00:18:00.318   568  1263 I test22  : 	at com.android.server.wm.WindowSurfacePlacer.performSurfacePlacement(WindowSurfacePlacer.java:126)
05-24 00:18:00.318   568  1263 I test22  : 	at com.android.server.wm.WindowSurfacePlacer.performSurfacePlacement(WindowSurfacePlacer.java:115)
05-24 00:18:00.318   568  1263 I test22  : 	at com.android.server.wm.WindowSurfacePlacer.continueLayout(WindowSurfacePlacer.java:97)
05-24 00:18:00.318   568  1263 I test22  : 	at com.android.server.wm.ActivityTaskManagerService.continueWindowLayout(ActivityTaskManagerService.java:4388)
05-24 00:18:00.318   568  1263 I test22  : 	at com.android.server.wm.RootWindowContainer.moveActivityToPinnedRootTask(RootWindowContainer.java:2138)
05-24 00:18:00.318   568  1263 I test22  : 	at com.android.server.wm.ActivityTaskManagerService.lambda$enterPictureInPictureMode$5$com-android-server-wm-ActivityTaskManagerService(ActivityTaskManagerService.java:3474)
05-24 00:18:00.318   568  1263 I test22  : 	at com.android.server.wm.ActivityTaskManagerService$$ExternalSyntheticLambda3.run(Unknown Source:6)
05-24 00:18:00.318   568  1263 I test22  : 	at com.android.server.wm.ActivityTaskManagerService.enterPictureInPictureMode(ActivityTaskManagerService.java:3497)
05-24 00:18:00.318   568  1263 I test22  : 	at com.android.server.wm.ActivityClientController.enterPictureInPictureMode(ActivityClientController.java:740)
05-24 00:18:00.318   568  1263 I test22  : 	at android.app.IActivityClientController$Stub.onTransact(IActivityClientController.java:878)
05-24 00:18:00.318   568  1263 I test22  : 	at com.android.server.wm.ActivityClientController.onTransact(ActivityClientController.java:124)
05-24 00:18:00.318   568  1263 I test22  : 	at android.os.Binder.execTransactInternal(Binder.java:1280)
05-24 00:18:00.318   568  1263 I test22  : 	at android.os.Binder.execTransact(Binder.java:1244)

systemui 側のアニメーションは、次のようにスタックの構築を開始します。

<init>:273, PipAnimationController$PipTransitionAnimator (com.android.wm.shell.pip)
<init>:-1, PipAnimationController$PipTransitionAnimator (com.android.wm.shell.pip)
<init>:558, PipAnimationController$PipTransitionAnimator$2 (com.android.wm.shell.pip)
ofBounds:557, PipAnimationController$PipTransitionAnimator (com.android.wm.shell.pip)
getAnimator:180, PipAnimationController (com.android.wm.shell.pip)
animateResizePip:1482, PipTaskOrganizer (com.android.wm.shell.pip)
scheduleAnimateResizePip:1171, PipTaskOrganizer (com.android.wm.shell.pip)
onTaskAppeared:630, PipTaskOrganizer (com.android.wm.shell.pip)
updateTaskListenerIfNeeded:555, ShellTaskOrganizer (com.android.wm.shell)
onTaskInfoChanged:465, ShellTaskOrganizer (com.android.wm.shell)
lambda$onTaskInfoChanged$6$android-window-TaskOrganizer$1:316, TaskOrganizer$1 (android.window)
run:-1, TaskOrganizer$1$$ExternalSyntheticLambda3 (android.window)
handleCallback:942, Handler (android.os)
dispatchMessage:99, Handler (android.os)
loopOnce:201, Looper (android.os)
loop:288, Looper (android.os)
main:7897, ActivityThread (android.app)
invoke:-1, Method (java.lang.reflect)
run:548, RuntimeInit$MethodAndArgsCaller (com.android.internal.os)
main:937, ZygoteInit (com.android.internal.os)

アニメーションの開始境界と終了境界は次のように決定されます。
ここに画像の説明を挿入

質問 3: pip 自身のアプリのサイズ変更を決定し、トリガーするものは何ですか

systemui プロセスのアニメーションが終了すると、対応する setBound が設定されます

 2049: 05-24 00:18:00.768   747   747 I test22  : java.lang.Exception2050: 05-24 00:18:00.768   747   747 I test22  : 	at android.app.WindowConfiguration.setBounds(WindowConfiguration.java:293)2051: 05-24 00:18:00.768   747   747 I test22  : 	at android.window.WindowContainerTransaction.setBounds(WindowContainerTransaction.java:92)2052: 05-24 00:18:00.768   747   747 I test22  : 	at com.android.wm.shell.pip.PipTaskOrganizer.prepareFinishResizeTransaction(PipTaskOrganizer.java:1419)2053: 05-24 00:18:00.768   747   747 I test22  : 	at com.android.wm.shell.pip.PipTaskOrganizer.finishResize(PipTaskOrganizer.java:1346)2054: 05-24 00:18:00.768   747   747 I test22  : 	at com.android.wm.shell.pip.PipTaskOrganizer.-$$Nest$mfinishResize(Unknown Source:0)2055: 05-24 00:18:00.768   747   747 I test22  : 	at com.android.wm.shell.pip.PipTaskOrganizer$1.onPipAnimationEnd(PipTaskOrganizer.java:181)2056: 05-24 00:18:00.768   747   747 I test22  : 	at com.android.wm.shell.pip.PipAnimationController$PipTransitionAnimator.onAnimationEnd(PipAnimationController.java:307)2057: 05-24 00:18:00.768   747   747 I test22  : 	at android.animation.Animator$AnimatorListener.onAnimationEnd(Animator.java:600)2058: 05-24 00:18:00.768   747   747 I test22  : 	at android.animation.ValueAnimator.endAnimation(ValueAnimator.java:1333)2059: 05-24 00:18:00.768   747   747 I test22  : 	at android.animation.ValueAnimator.doAnimationFrame(ValueAnimator.java:1575)2060: 05-24 00:18:00.768   747   747 I test22  : 	at android.animation.AnimationHandler.doAnimationFrame(AnimationHandler.java:307)2061: 05-24 00:18:00.768   747   747 I test22  : 	at android.animation.AnimationHandler.-$$Nest$mdoAnimationFrame(Unknown Source:0)2062: 05-24 00:18:00.768   747   747 I test22  : 	at android.animation.AnimationHandler$1.doFrame(AnimationHandler.java:86)2063: 05-24 00:18:00.768   747   747 I test22  : 	at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1229)2064: 05-24 00:18:00.768   747   747 I test22  : 	at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1239)2065: 05-24 00:18:00.768   747   747 I test22  : 	at android.view.Choreographer.doCallbacks(Choreographer.java:899)2066: 05-24 00:18:00.768   747   747 I test22  : 	at android.view.Choreographer.doFrame(Choreographer.java:827)2067: 05-24 00:18:00.768   747   747 I test22  : 	at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1214)2068: 05-24 00:18:00.768   747   747 I test22  : 	at android.os.Handler.handleCallback(Handler.java:942)2069: 05-24 00:18:00.768   747   747 I test22  : 	at android.os.Handler.dispatchMessage(Handler.java:99)2070: 05-24 00:18:00.768   747   747 I test22  : 	at android.os.Looper.loopOnce(Looper.java:201)2071: 05-24 00:18:00.768   747   747 I test22  : 	at android.os.Looper.loop(Looper.java:288)2072: 05-24 00:18:00.768   747   747 I test22  : 	at android.app.ActivityThread.main(ActivityThread.java:7897)2073: 05-24 00:18:00.768   747   747 I test22  : 	at java.lang.reflect.Method.invoke(Native Method)2074: 05-24 00:18:00.768   747   747 I test22  : 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)2075: 05-24 00:18:00.768   747   747 I test22  : 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:937)

次に、systemserver プロセスが対応する setBounds を実行します。

077: 05-24 00:18:00.768   568  1263 I test22  : java.lang.Exception2078: 05-24 00:18:00.768   568  1263 I test22  : 	at android.app.WindowConfiguration.setBounds(WindowConfiguration.java:293)2079: 05-24 00:18:00.768   568  1263 I test22  : 	at android.app.WindowConfiguration.setTo(WindowConfiguration.java:541)2080: 05-24 00:18:00.768   568  1263 I test22  : 	at android.content.res.Configuration.setTo(Configuration.java:1792)2081: 05-24 00:18:00.768   568  1263 I test22  : 	at com.android.server.wm.WindowOrganizerController.applyChanges(WindowOrganizerController.java:534)2082: 05-24 00:18:00.768   568  1263 I test22  : 	at com.android.server.wm.WindowOrganizerController.applyWindowContainerChange(WindowOrganizerController.java:1218)2083: 05-24 00:18:00.768   568  1263 I test22  : 	at com.android.server.wm.WindowOrganizerController.applyTransaction(WindowOrganizerController.java:428)2084: 05-24 00:18:00.768   568  1263 I test22  : 	at com.android.server.wm.WindowOrganizerController.applyTransaction(WindowOrganizerController.java:373)2085: 05-24 00:18:00.768   568  1263 I test22  : 	at com.android.server.wm.WindowOrganizerController.applyTransaction(WindowOrganizerController.java:179)2086: 05-24 00:18:00.768   568  1263 I test22  : 	at android.window.IWindowOrganizerController$Stub.onTransact(IWindowOrganizerController.java:204)2087: 05-24 00:18:00.768   568  1263 I test22  : 	at com.android.server.wm.WindowOrganizerController.onTransact(WindowOrganizerController.java:163)2088: 05-24 00:18:00.768   568  1263 I test22  : 	at android.os.Binder.execTransactInternal(Binder.java:1285)2089: 05-24 00:18:00.768   568  1263 I test22  : 	at android.os.Binder.execTransact(Binder.java:1244)

小さなウィンドウのアプリ:

05-24 00:18:00.803  2031  2031 I test22  : mBounds Rect(606, 1958 - 1384, 2336) @ {
    
     mBounds=Rect(606, 1958 - 1384, 2336) mAppBounds=Rect(606, 1958 - 1384, 2336) mMaxBounds=Rect(0, 0 - 1440, 2960) mDisplayRotation=ROTATION_0 mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_0}
05-24 00:18:00.803  2031  2031 I test22  : java.lang.Exception
05-24 00:18:00.803  2031  2031 I test22  : 	at android.app.WindowConfiguration.setBounds(WindowConfiguration.java:293)
05-24 00:18:00.803  2031  2031 I test22  : 	at android.app.WindowConfiguration.setTo(WindowConfiguration.java:450)
05-24 00:18:00.803  2031  2031 I test22  : 	at android.content.res.Configuration.setTo(Configuration.java:1047)
05-24 00:18:00.803  2031  2031 I test22  : 	at android.content.res.ResourcesImpl.calcConfigChanges(ResourcesImpl.java:502)
05-24 00:18:00.803  2031  2031 I test22  : 	at android.content.res.ResourcesImpl.updateConfiguration(ResourcesImpl.java:392)
05-24 00:18:00.803  2031  2031 I test22  : 	at android.content.res.Resources.updateConfiguration(Resources.java:2142)
05-24 00:18:00.803  2031  2031 I test22  : 	at android.content.res.Resources.updateSystemConfiguration(Resources.java:2155)
05-24 00:18:00.803  2031  2031 I test22  : 	at android.app.ResourcesManager.applyConfigurationToResources(ResourcesManager.java:1362)
05-24 00:18:00.803  2031  2031 I test22  : 	at android.app.ConfigurationController.handleConfigurationChanged(ConfigurationController.java:188)
05-24 00:18:00.803  2031  2031 I test22  : 	at android.app.ConfigurationController.handleConfigurationChanged(ConfigurationController.java:134)
05-24 00:18:00.803  2031  2031 I test22  : 	at android.app.ActivityThread.handleConfigurationChanged(ActivityThread.java:5996)
05-24 00:18:00.803  2031  2031 I test22  : 	at android.app.servertransaction.ConfigurationChangeItem.execute(ConfigurationChangeItem.java:43)
05-24 00:18:00.803  2031  2031 I test22  : 	at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
05-24 00:18:00.803  2031  2031 I test22  : 	at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
05-24 00:18:00.803  2031  2031 I test22  : 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2308)
05-24 00:18:00.803  2031  2031 I test22  : 	at android.os.Handler.dispatchMessage(Handler.java:106)
05-24 00:18:00.803  2031  2031 I test22  : 	at android.os.Looper.loopOnce(Looper.java:201)
05-24 00:18:00.803  2031  2031 I test22  : 	at android.os.Looper.loop(Looper.java:288)
05-24 00:18:00.803  2031  2031 I test22  : 	at android.app.ActivityThread.main(ActivityThread.java:7897)
05-24 00:18:00.803  2031  2031 I test22  : 	at java.lang.reflect.Method.invoke(Native Method)
05-24 00:18:00.803  2031  2031 I test22  : 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
05-24 00:18:00.803  2031  2031 I test22  : 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:937)

ActivityRecord の WindowMode の変更

moveActivityToPinnedRootTask メソッドで次の注釈が見つかりました。

     // Defer the windowing mode change until after the transition to prevent the activity
            // from doing work and changing the activity visuals while animating
            // TODO(task-org): Figure-out more structured way to do this long term.
            r.setWindowingMode(intermediateWindowingMode);

おそらく、ピップアニメーションプロセスに入るときに、アクティビティが上記の変更を表示することを禁止する必要があるため、フルスクリーンモードに設定する必要があり、ウィンドウモードはアニメーションが完了した後にのみ変更できることを意味します。

ActivityRecord のウィンドウモードは比較的特殊で、次の 2 つのステップに分かれています。
1. pip を入力すると、フルスクリーンの状態に属する pip のアニメーション プロセスに入りますが、タスクはすでに pip であるため、対応する ActivityRecord 自体のオーバーライドは必須 2. pip がアニメーション Completed に入ったら
、ActivityRecord を pip として対応するウィンドウモードに設定する必要があります。


--------- beginning of main

//ActivityRecord设置成对fullscreen,这样task的虽然已经是pip了但是ActivityRecord还是pip
06-29 16:12:14.011   567   737 I lsm11   : setWindowingMode windowingMode 1 ActivityRecord{
    
    4cde5aa u0 com.example.myapplication11/.MainActivity} t92}
06-29 16:12:14.011   567   737 I lsm11   : java.lang.Exception
06-29 16:12:14.011   567   737 I lsm11   : 	at com.android.server.wm.ConfigurationContainer.setWindowingMode(ConfigurationContainer.java:459)
06-29 16:12:14.011   567   737 I lsm11   : 	at com.android.server.wm.RootWindowContainer.moveActivityToPinnedRootTask(RootWindowContainer.java:2100)
06-29 16:12:14.011   567   737 I lsm11   : 	at com.android.server.wm.ActivityTaskManagerService.lambda$enterPictureInPictureMode$5$com-android-server-wm-ActivityTaskManagerService(ActivityTaskManagerService.java:3474)
06-29 16:12:14.011   567   737 I lsm11   : 	at com.android.server.wm.ActivityTaskManagerService$$ExternalSyntheticLambda3.run(Unknown Source:6)
06-29 16:12:14.011   567   737 I lsm11   : 	at com.android.server.wm.ActivityTaskManagerService.enterPictureInPictureMode(ActivityTaskManagerService.java:3497)
06-29 16:12:14.011   567   737 I lsm11   : 	at com.android.server.wm.ActivityClientController.enterPictureInPictureMode(ActivityClientController.java:740)
06-29 16:12:14.011   567   737 I lsm11   : 	at android.app.IActivityClientController$Stub.onTransact(IActivityClientController.java:878)
06-29 16:12:14.011   567   737 I lsm11   : 	at com.android.server.wm.ActivityClientController.onTransact(ActivityClientController.java:124)
06-29 16:12:14.011   567   737 I lsm11   : 	at android.os.Binder.execTransactInternal(Binder.java:1280)
06-29 16:12:14.011   567   737 I lsm11   : 	at android.os.Binder.execTransact(Binder.java:1244)


//ActivityRecord设置成对undefined,这样就可以直接继承task的pip了


//systemui端
06-29 17:52:59.173   749   749 I lsm11   : java.lang.Exception
06-29 17:52:59.173   749   749 I lsm11   : 	at android.window.WindowContainerTransaction.setActivityWindowingMode(WindowContainerTransaction.java:206)
06-29 17:52:59.173   749   749 I lsm11   : 	at com.android.wm.shell.pip.PipTaskOrganizer.prepareFinishResizeTransaction(PipTaskOrganizer.java:1407)
06-29 17:52:59.173   749   749 I lsm11   : 	at com.android.wm.shell.pip.PipTaskOrganizer.finishResize(PipTaskOrganizer.java:1346)
06-29 17:52:59.173   749   749 I lsm11   : 	at com.android.wm.shell.pip.PipTaskOrganizer.-$$Nest$mfinishResize(Unknown Source:0)
06-29 17:52:59.173   749   749 I lsm11   : 	at com.android.wm.shell.pip.PipTaskOrganizer$1.onPipAnimationEnd(PipTaskOrganizer.java:181)
06-29 17:52:59.173   749   749 I lsm11   : 	at com.android.wm.shell.pip.PipAnimationController$PipTransitionAnimator.onAnimationEnd(PipAnimationController.java:307)
06-29 17:52:59.173   749   749 I lsm11   : 	at android.animation.Animator$AnimatorListener.onAnimationEnd(Animator.java:600)
06-29 17:52:59.173   749   749 I lsm11   : 	at android.animation.ValueAnimator.endAnimation(ValueAnimator.java:1333)
06-29 17:52:59.173   749   749 I lsm11   : 	at android.animation.ValueAnimator.doAnimationFrame(ValueAnimator.java:1575)
06-29 17:52:59.173   749   749 I lsm11   : 	at android.animation.AnimationHandler.doAnimationFrame(AnimationHandler.java:307)
06-29 17:52:59.173   749   749 I lsm11   : 	at android.animation.AnimationHandler.-$$Nest$mdoAnimationFrame(Unknown Source:0)
06-29 17:52:59.173   749   749 I lsm11   : 	at android.animation.AnimationHandler$1.doFrame(AnimationHandler.java:86)
06-29 17:52:59.173   749   749 I lsm11   : 	at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1229)
06-29 17:52:59.173   749   749 I lsm11   : 	at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1239)
06-29 17:52:59.173   749   749 I lsm11   : 	at android.view.Choreographer.doCallbacks(Choreographer.java:899)
06-29 17:52:59.173   749   749 I lsm11   : 	at android.view.Choreographer.doFrame(Choreographer.java:827)
06-29 17:52:59.173   749   749 I lsm11   : 	at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1214)
06-29 17:52:59.173   749   749 I lsm11   : 	at android.os.Handler.handleCallback(Handler.java:942)
06-29 17:52:59.173   749   749 I lsm11   : 	at android.os.Handler.dispatchMessage(Handler.java:99)
06-29 17:52:59.173   749   749 I lsm11   : 	at android.os.Looper.loopOnce(Looper.java:201)
06-29 17:52:59.173   749   749 I lsm11   : 	at android.os.Looper.loop(Looper.java:288)
06-29 17:52:59.173   749   749 I lsm11   : 	at android.app.ActivityThread.main(ActivityThread.java:7898)
06-29 17:52:59.173   749   749 I lsm11   : 	at java.lang.reflect.Method.invoke(Native Method)
06-29 17:52:59.173   749   749 I lsm11   : 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
06-29 17:52:59.173   749   749 I lsm11   : 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)

//system_server端

06-29 16:12:14.636   567  1451 I lsm11   : setWindowingMode windowingMode 0 ActivityRecord{
    
    4cde5aa u0 com.example.myapplication11/.MainActivity} t92}
06-29 16:12:14.636   567  1451 I lsm11   : java.lang.Exception
06-29 16:12:14.636   567  1451 I lsm11   : 	at com.android.server.wm.ConfigurationContainer.setWindowingMode(ConfigurationContainer.java:459)
06-29 16:12:14.636   567  1451 I lsm11   : 	at com.android.server.wm.Task$$ExternalSyntheticLambda30.accept(Unknown Source:8)
06-29 16:12:14.636   567  1451 I lsm11   : 	at com.android.internal.util.function.pooled.PooledLambdaImpl.doInvoke(PooledLambdaImpl.java:281)
06-29 16:12:14.636   567  1451 I lsm11   : 	at com.android.internal.util.function.pooled.PooledLambdaImpl.invoke(PooledLambdaImpl.java:204)
06-29 16:12:14.636   567  1451 I lsm11   : 	at com.android.internal.util.function.pooled.OmniFunction.accept(OmniFunction.java:92)
06-29 16:12:14.636   567  1451 I lsm11   : 	at com.android.server.wm.ActivityRecord.forAllActivities(ActivityRecord.java:4515)
06-29 16:12:14.636   567  1451 I lsm11   : 	at com.android.server.wm.WindowContainer.forAllActivities(WindowContainer.java:1657)
06-29 16:12:14.636   567  1451 I lsm11   : 	at com.android.server.wm.WindowContainer.forAllActivities(WindowContainer.java:1651)
06-29 16:12:14.636   567  1451 I lsm11   : 	at com.android.server.wm.Task.setActivityWindowingMode(Task.java:4434)
06-29 16:12:14.636   567  1451 I lsm11   : 	at com.android.server.wm.WindowOrganizerController.applyTaskChanges(WindowOrganizerController.java:599)
06-29 16:12:14.636   567  1451 I lsm11   : 	at com.android.server.wm.WindowOrganizerController.applyWindowContainerChange(WindowOrganizerController.java:1222)
06-29 16:12:14.636   567  1451 I lsm11   : 	at com.android.server.wm.WindowOrganizerController.applyTransaction(WindowOrganizerController.java:427)
06-29 16:12:14.636   567  1451 I lsm11   : 	at com.android.server.wm.WindowOrganizerController.applyTransaction(WindowOrganizerController.java:372)
06-29 16:12:14.636   567  1451 I lsm11   : 	at com.android.server.wm.WindowOrganizerController.applyTransaction(WindowOrganizerController.java:179)
06-29 16:12:14.636   567  1451 I lsm11   : 	at android.window.IWindowOrganizerController$Stub.onTransact(IWindowOrganizerController.java:204)
06-29 16:12:14.636   567  1451 I lsm11   : 	at com.android.server.wm.WindowOrganizerController.onTransact(WindowOrganizerController.java:163)
06-29 16:12:14.636   567  1451 I lsm11   : 	at android.os.Binder.execTransactInternal(Binder.java:1285)
06-29 16:12:14.636   567  1451 I lsm11   : 	at android.os.Binder.execTransact(Binder.java:1244)

Supongo que te gusta

Origin blog.csdn.net/learnframework/article/details/130832582
Recomendado
Clasificación