Android car machine mobile phone system development--Detailed explanation of PIP in multi-window mode

Video tutorial explanation:
https://www.bilibili.com/video/BV1wj411o7A9/
insert image description here

1. PIP entry

Official explanation and remarks:
/** Always on-top (always visible). of other siblings in its parent container. */
public static final int WINDOWING_MODE_PINNED = 2;

app layer:

  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());
        }
    }

System server level core:
core method 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);
    }

Summary:
1. Entering the pip mode, the system server level mainly has to set the windowmode to fullscreen for ActivityRecord separately, and set the windowmode to pip mode for Task
2. Generally, after changing the attributes related to Task, ensureActivitiesVisible and resumeFocusedTasksTopActivities will be triggered to ensure that the current activities of the system can be displayed normally.

2. Life cycle changes

Launcher enters resume:


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)

The pip app enters pause
Question 1: Why does pip only pause but not stop

Enter onPause

You can print the corresponding stack when constructing PauseActivityItem on the server side:

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)

The key judgments in the stack are as follows:

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;
    }

The summarized and streamlined flow chart is as follows:
insert image description here

Under normal circumstances, the Visible state of the Activity will determine whether it will enter Stop

That is, if the Activity is in the Pasued state, if the system triggers the ensureActivitiesVisible call,
it will traverse a corresponding EnsureActivitiesVisibleHelper process method of each Task:

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);
            }
        }
    }

The first thing here is to call 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;
    }

The key to the above call is mTaskFragment.shouldBeVisible(mStarting)

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

Haha, I found here to compare the value of getVisibility again. We have analyzed this place before.

Because the small window pip has entered the pasued state, but the visible can still display the true state
. After knowing that the task is displayed as true, then look at the setActivityVisibilityState method:

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);
        }
    }

Here is an additional point that the stop situation will be performed because the makeInvisible method is called:

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 enters the animation process part

How does pip enter the animation process

System_server triggers:

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)

The animation on the systemui side starts to construct the stack as follows:

<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)

The start bounds and end bounds of the animation are determined:
insert image description here

Question 3: What determines and triggers the size change of pip’s own app

After the animation of the systemui process ends, the corresponding setBound will be set

 2049: 05-24 00:18:00.768   747   747 I test22  : java.lang.Exception
	行 2050: 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)

Then the systemserver process will perform the corresponding setBounds

077: 05-24 00:18:00.768   568  1263 I test22  : java.lang.Exception
	行 2078: 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)

Small window app:

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's WindowMode changes

Found the following annotations in the moveActivityToPinnedRootTask method:

     // 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);

It probably means that when entering the pip animation process, it is necessary to prohibit the activity from displaying the above changes, so it must be set to the fullscreen mode, and the windowmode can only be changed after the animation is completed.

The windowmode of ActivityRecord is relatively special and divided into 2 steps:
1. When entering pip, it enters the animation process of pip, which belongs to the state of fullscreen, but the task is already pip, so the corresponding override of ActivityRecord itself is required 2. When pip enters the
animation Completed, you need to set the ActivityRecord to the corresponding windowmode as 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)

Guess you like

Origin blog.csdn.net/learnframework/article/details/130832582