视频教程讲解:
https://www.bilibili.com/video/BV1wj411o7A9/
1、PIP进入
官方解释及备注:
/** Always on-top (always visible). of other siblings in its parent container. */
public static final int WINDOWING_MODE_PINNED = 2;
app层:
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());
}
}
systemserver层面核心:
核心方法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模式进入,systemserver层面主要有对ActivityRecord单独设置windowmode为fullscreen,对Task设置windowmode为pip模式
2、一般改变了Task相关的属性后都会触发ensureActivitiesVisible和resumeFocusedTasksTopActivities保证系统当前activity可以正常排列显示
2、 生命周期变化
launcher进入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)
pip的app进入pasue
疑问1: 为啥pip只进行pause不进行stop
进入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;
}
总结精简后的流程图如下:
一般正常情况下Activity的Visible状态就会决定它是否要进入Stop
即Activity如果属于Pasued状态了系统如果触发了ensureActivitiesVisible的调用
则会遍历每一个Task的一个对应的EnsureActivitiesVisibleHelper的process方法:
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虽然进入了pasued状态,但是visible还是可以显示的true状态
知道task显示为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);
}
}
这里额外补充一点会进行stop情况是因为有调用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进入动画流程部分
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)
动画的起始bounds和结束bounds确定:
疑问3: pip自己app大小变化靠啥确定及触发的
systemui进程进行动画结束以后,会进行对应的setBound的设置
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)
然后systemserver进程会进行对应的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)
小窗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的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);
大概意思就是在进入pip动画过程种要禁止activity进行显示上面的变化,所以要设置为fullscreen的mode,等待动画完成才可以变化windowmode
ActivityRecord的windowmode相对特殊分为2个步骤:
1、进入pip时候,即进入pip的动画过程,是属于fullscreen的状态,但是task已经是pip了,所以需要ActivityRecord自己对应的override
2、当pip进入动画完成,则需要把ActivityRecord也设置成对应的windowmode为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)