Video tutorial explanation:
https://www.bilibili.com/video/BV1wj411o7A9/
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:
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:
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)