Loading libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java +2 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,8 @@ public enum ShellProtoLogGroup implements IProtoLogGroup { Consts.TAG_WM_SHELL), WM_SHELL_PICTURE_IN_PICTURE(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false, Consts.TAG_WM_SHELL), WM_SHELL_SPLIT_SCREEN(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false, Consts.TAG_WM_SHELL), TEST_GROUP(true, true, false, "WindowManagerShellProtoLogTest"); private final boolean mEnabled; Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +90 −24 Original line number Diff line number Diff line Loading @@ -54,6 +54,9 @@ import static com.android.wm.shell.transition.Transitions.TRANSIT_SPLIT_SCREEN_P import static com.android.wm.shell.transition.Transitions.isClosingType; import static com.android.wm.shell.transition.Transitions.isOpeningType; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.annotation.CallSuper; import android.annotation.NonNull; import android.annotation.Nullable; Loading @@ -68,6 +71,7 @@ import android.content.res.Configuration; import android.graphics.Rect; import android.hardware.devicestate.DeviceStateManager; import android.os.Bundle; import android.os.Debug; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; Loading Loading @@ -147,7 +151,9 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, private final int mDisplayId; private SplitLayout mSplitLayout; private ValueAnimator mDividerFadeInAnimator; private boolean mDividerVisible; private boolean mKeyguardShowing; private final SyncTransactionQueue mSyncQueue; private final ShellTaskOrganizer mTaskOrganizer; private final Context mContext; Loading Loading @@ -404,6 +410,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, mSplitLayout.init(); // Set false to avoid record new bounds with old task still on top; mShouldUpdateRecents = false; mIsDividerRemoteAnimating = true; final WindowContainerTransaction wct = new WindowContainerTransaction(); final WindowContainerTransaction evictWct = new WindowContainerTransaction(); prepareEvictChildTasks(SPLIT_POSITION_TOP_OR_LEFT, evictWct); Loading @@ -417,7 +424,6 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps, final IRemoteAnimationFinishedCallback finishedCallback) { mIsDividerRemoteAnimating = true; RemoteAnimationTarget[] augmentedNonApps = new RemoteAnimationTarget[nonApps.length + 1]; for (int i = 0; i < nonApps.length; ++i) { Loading Loading @@ -494,8 +500,10 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, } // Using legacy transitions, so we can't use blast sync since it conflicts. mTaskOrganizer.applyTransaction(wct); mSyncQueue.runInSync(t -> updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */)); mSyncQueue.runInSync(t -> { setDividerVisibility(true, t); updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */); }); } private void onRemoteAnimationFinishedOrCancelled(WindowContainerTransaction evictWct) { Loading @@ -510,10 +518,6 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, ? mSideStage : mMainStage, EXIT_REASON_UNKNOWN)); } else { mSyncQueue.queue(evictWct); mSyncQueue.runInSync(t -> { setDividerVisibility(true, t); updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */); }); } } Loading Loading @@ -623,16 +627,12 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, } void onKeyguardVisibilityChanged(boolean showing) { mKeyguardShowing = showing; if (!mMainStage.isActive()) { return; } if (ENABLE_SHELL_TRANSITIONS) { // Update divider visibility so it won't float on top of keyguard. setDividerVisibility(!showing, null /* transaction */); } if (!showing && mTopStageAfterFoldDismiss != STAGE_TYPE_UNDEFINED) { if (!mKeyguardShowing && mTopStageAfterFoldDismiss != STAGE_TYPE_UNDEFINED) { if (ENABLE_SHELL_TRANSITIONS) { final WindowContainerTransaction wct = new WindowContainerTransaction(); prepareExitSplitScreen(mTopStageAfterFoldDismiss, wct); Loading @@ -643,7 +643,10 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, mTopStageAfterFoldDismiss == STAGE_TYPE_MAIN ? mMainStage : mSideStage, EXIT_REASON_DEVICE_FOLDED); } return; } setDividerVisibility(!mKeyguardShowing, null); } void onFinishedWakingUp() { Loading Loading @@ -727,6 +730,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, setResizingSplits(false /* resizing */); t.setWindowCrop(mMainStage.mRootLeash, null) .setWindowCrop(mSideStage.mRootLeash, null); setDividerVisibility(false, t); }); // Hide divider and reset its position. Loading Loading @@ -1055,8 +1059,31 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, } private void setDividerVisibility(boolean visible, @Nullable SurfaceControl.Transaction t) { if (visible == mDividerVisible) { return; } ProtoLog.d(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "%s: Request to %s divider bar from %s.", TAG, (visible ? "show" : "hide"), Debug.getCaller()); // Defer showing divider bar after keyguard dismissed, so it won't interfere with keyguard // dismissing animation. if (visible && mKeyguardShowing) { ProtoLog.d(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "%s: Defer showing divider bar due to keyguard showing.", TAG); return; } mDividerVisible = visible; sendSplitVisibilityChanged(); if (mIsDividerRemoteAnimating) { ProtoLog.d(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "%s: Skip animating divider bar due to it's remote animating.", TAG); return; } if (t != null) { applyDividerVisibility(t); } else { Loading @@ -1066,15 +1093,56 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, private void applyDividerVisibility(SurfaceControl.Transaction t) { final SurfaceControl dividerLeash = mSplitLayout.getDividerLeash(); if (mIsDividerRemoteAnimating || dividerLeash == null) return; if (dividerLeash == null) { ProtoLog.d(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "%s: Skip animating divider bar due to divider leash not ready.", TAG); return; } if (mIsDividerRemoteAnimating) { ProtoLog.d(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "%s: Skip animating divider bar due to it's remote animating.", TAG); return; } if (mDividerFadeInAnimator != null && mDividerFadeInAnimator.isRunning()) { mDividerFadeInAnimator.cancel(); } if (mDividerVisible) { t.show(dividerLeash); t.setAlpha(dividerLeash, 1); t.setLayer(dividerLeash, Integer.MAX_VALUE); t.setPosition(dividerLeash, final SurfaceControl.Transaction transaction = mTransactionPool.acquire(); mDividerFadeInAnimator = ValueAnimator.ofFloat(0f, 1f); mDividerFadeInAnimator.addUpdateListener(animation -> { if (dividerLeash == null) { mDividerFadeInAnimator.cancel(); return; } transaction.setAlpha(dividerLeash, (float) animation.getAnimatedValue()); transaction.apply(); }); mDividerFadeInAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { if (dividerLeash == null) { mDividerFadeInAnimator.cancel(); return; } transaction.show(dividerLeash); transaction.setAlpha(dividerLeash, 0); transaction.setLayer(dividerLeash, Integer.MAX_VALUE); transaction.setPosition(dividerLeash, mSplitLayout.getRefDividerBounds().left, mSplitLayout.getRefDividerBounds().top); transaction.apply(); } @Override public void onAnimationEnd(Animator animation) { mTransactionPool.release(transaction); mDividerFadeInAnimator = null; } }); mDividerFadeInAnimator.start(); } else { t.hide(dividerLeash); } Loading @@ -1096,10 +1164,8 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, mSplitLayout.init(); prepareEnterSplitScreen(wct); mSyncQueue.queue(wct); mSyncQueue.runInSync(t -> { updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */); setDividerVisibility(true, t); }); mSyncQueue.runInSync(t -> updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */)); } if (mMainStageListener.mHasChildren && mSideStageListener.mHasChildren) { mShouldUpdateRecents = true; Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java +8 −0 Original line number Diff line number Diff line Loading @@ -139,6 +139,7 @@ public class SplitTransitionTests extends ShellTestCase { } @Test @UiThreadTest public void testLaunchToSide() { ActivityManager.RunningTaskInfo newTask = new TestRunningTaskInfoBuilder() .setParentTaskId(mSideStage.mRootTaskInfo.taskId).build(); Loading Loading @@ -173,6 +174,7 @@ public class SplitTransitionTests extends ShellTestCase { } @Test @UiThreadTest public void testLaunchPair() { TransitionInfo info = createEnterPairInfo(); Loading @@ -195,6 +197,7 @@ public class SplitTransitionTests extends ShellTestCase { } @Test @UiThreadTest public void testMonitorInSplit() { enterSplit(); Loading Loading @@ -251,6 +254,7 @@ public class SplitTransitionTests extends ShellTestCase { } @Test @UiThreadTest public void testEnterRecents() { enterSplit(); Loading Loading @@ -288,6 +292,7 @@ public class SplitTransitionTests extends ShellTestCase { } @Test @UiThreadTest public void testDismissFromBeingOccluded() { enterSplit(); Loading Loading @@ -325,6 +330,7 @@ public class SplitTransitionTests extends ShellTestCase { } @Test @UiThreadTest public void testDismissFromMultiWindowSupport() { enterSplit(); Loading @@ -346,6 +352,7 @@ public class SplitTransitionTests extends ShellTestCase { } @Test @UiThreadTest public void testDismissSnap() { enterSplit(); Loading @@ -370,6 +377,7 @@ public class SplitTransitionTests extends ShellTestCase { } @Test @UiThreadTest public void testDismissFromAppFinish() { enterSplit(); Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java +2 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,8 @@ public enum ShellProtoLogGroup implements IProtoLogGroup { Consts.TAG_WM_SHELL), WM_SHELL_PICTURE_IN_PICTURE(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false, Consts.TAG_WM_SHELL), WM_SHELL_SPLIT_SCREEN(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false, Consts.TAG_WM_SHELL), TEST_GROUP(true, true, false, "WindowManagerShellProtoLogTest"); private final boolean mEnabled; Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +90 −24 Original line number Diff line number Diff line Loading @@ -54,6 +54,9 @@ import static com.android.wm.shell.transition.Transitions.TRANSIT_SPLIT_SCREEN_P import static com.android.wm.shell.transition.Transitions.isClosingType; import static com.android.wm.shell.transition.Transitions.isOpeningType; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.annotation.CallSuper; import android.annotation.NonNull; import android.annotation.Nullable; Loading @@ -68,6 +71,7 @@ import android.content.res.Configuration; import android.graphics.Rect; import android.hardware.devicestate.DeviceStateManager; import android.os.Bundle; import android.os.Debug; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; Loading Loading @@ -147,7 +151,9 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, private final int mDisplayId; private SplitLayout mSplitLayout; private ValueAnimator mDividerFadeInAnimator; private boolean mDividerVisible; private boolean mKeyguardShowing; private final SyncTransactionQueue mSyncQueue; private final ShellTaskOrganizer mTaskOrganizer; private final Context mContext; Loading Loading @@ -404,6 +410,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, mSplitLayout.init(); // Set false to avoid record new bounds with old task still on top; mShouldUpdateRecents = false; mIsDividerRemoteAnimating = true; final WindowContainerTransaction wct = new WindowContainerTransaction(); final WindowContainerTransaction evictWct = new WindowContainerTransaction(); prepareEvictChildTasks(SPLIT_POSITION_TOP_OR_LEFT, evictWct); Loading @@ -417,7 +424,6 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps, final IRemoteAnimationFinishedCallback finishedCallback) { mIsDividerRemoteAnimating = true; RemoteAnimationTarget[] augmentedNonApps = new RemoteAnimationTarget[nonApps.length + 1]; for (int i = 0; i < nonApps.length; ++i) { Loading Loading @@ -494,8 +500,10 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, } // Using legacy transitions, so we can't use blast sync since it conflicts. mTaskOrganizer.applyTransaction(wct); mSyncQueue.runInSync(t -> updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */)); mSyncQueue.runInSync(t -> { setDividerVisibility(true, t); updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */); }); } private void onRemoteAnimationFinishedOrCancelled(WindowContainerTransaction evictWct) { Loading @@ -510,10 +518,6 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, ? mSideStage : mMainStage, EXIT_REASON_UNKNOWN)); } else { mSyncQueue.queue(evictWct); mSyncQueue.runInSync(t -> { setDividerVisibility(true, t); updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */); }); } } Loading Loading @@ -623,16 +627,12 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, } void onKeyguardVisibilityChanged(boolean showing) { mKeyguardShowing = showing; if (!mMainStage.isActive()) { return; } if (ENABLE_SHELL_TRANSITIONS) { // Update divider visibility so it won't float on top of keyguard. setDividerVisibility(!showing, null /* transaction */); } if (!showing && mTopStageAfterFoldDismiss != STAGE_TYPE_UNDEFINED) { if (!mKeyguardShowing && mTopStageAfterFoldDismiss != STAGE_TYPE_UNDEFINED) { if (ENABLE_SHELL_TRANSITIONS) { final WindowContainerTransaction wct = new WindowContainerTransaction(); prepareExitSplitScreen(mTopStageAfterFoldDismiss, wct); Loading @@ -643,7 +643,10 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, mTopStageAfterFoldDismiss == STAGE_TYPE_MAIN ? mMainStage : mSideStage, EXIT_REASON_DEVICE_FOLDED); } return; } setDividerVisibility(!mKeyguardShowing, null); } void onFinishedWakingUp() { Loading Loading @@ -727,6 +730,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, setResizingSplits(false /* resizing */); t.setWindowCrop(mMainStage.mRootLeash, null) .setWindowCrop(mSideStage.mRootLeash, null); setDividerVisibility(false, t); }); // Hide divider and reset its position. Loading Loading @@ -1055,8 +1059,31 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, } private void setDividerVisibility(boolean visible, @Nullable SurfaceControl.Transaction t) { if (visible == mDividerVisible) { return; } ProtoLog.d(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "%s: Request to %s divider bar from %s.", TAG, (visible ? "show" : "hide"), Debug.getCaller()); // Defer showing divider bar after keyguard dismissed, so it won't interfere with keyguard // dismissing animation. if (visible && mKeyguardShowing) { ProtoLog.d(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "%s: Defer showing divider bar due to keyguard showing.", TAG); return; } mDividerVisible = visible; sendSplitVisibilityChanged(); if (mIsDividerRemoteAnimating) { ProtoLog.d(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "%s: Skip animating divider bar due to it's remote animating.", TAG); return; } if (t != null) { applyDividerVisibility(t); } else { Loading @@ -1066,15 +1093,56 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, private void applyDividerVisibility(SurfaceControl.Transaction t) { final SurfaceControl dividerLeash = mSplitLayout.getDividerLeash(); if (mIsDividerRemoteAnimating || dividerLeash == null) return; if (dividerLeash == null) { ProtoLog.d(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "%s: Skip animating divider bar due to divider leash not ready.", TAG); return; } if (mIsDividerRemoteAnimating) { ProtoLog.d(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "%s: Skip animating divider bar due to it's remote animating.", TAG); return; } if (mDividerFadeInAnimator != null && mDividerFadeInAnimator.isRunning()) { mDividerFadeInAnimator.cancel(); } if (mDividerVisible) { t.show(dividerLeash); t.setAlpha(dividerLeash, 1); t.setLayer(dividerLeash, Integer.MAX_VALUE); t.setPosition(dividerLeash, final SurfaceControl.Transaction transaction = mTransactionPool.acquire(); mDividerFadeInAnimator = ValueAnimator.ofFloat(0f, 1f); mDividerFadeInAnimator.addUpdateListener(animation -> { if (dividerLeash == null) { mDividerFadeInAnimator.cancel(); return; } transaction.setAlpha(dividerLeash, (float) animation.getAnimatedValue()); transaction.apply(); }); mDividerFadeInAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { if (dividerLeash == null) { mDividerFadeInAnimator.cancel(); return; } transaction.show(dividerLeash); transaction.setAlpha(dividerLeash, 0); transaction.setLayer(dividerLeash, Integer.MAX_VALUE); transaction.setPosition(dividerLeash, mSplitLayout.getRefDividerBounds().left, mSplitLayout.getRefDividerBounds().top); transaction.apply(); } @Override public void onAnimationEnd(Animator animation) { mTransactionPool.release(transaction); mDividerFadeInAnimator = null; } }); mDividerFadeInAnimator.start(); } else { t.hide(dividerLeash); } Loading @@ -1096,10 +1164,8 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, mSplitLayout.init(); prepareEnterSplitScreen(wct); mSyncQueue.queue(wct); mSyncQueue.runInSync(t -> { updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */); setDividerVisibility(true, t); }); mSyncQueue.runInSync(t -> updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */)); } if (mMainStageListener.mHasChildren && mSideStageListener.mHasChildren) { mShouldUpdateRecents = true; Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java +8 −0 Original line number Diff line number Diff line Loading @@ -139,6 +139,7 @@ public class SplitTransitionTests extends ShellTestCase { } @Test @UiThreadTest public void testLaunchToSide() { ActivityManager.RunningTaskInfo newTask = new TestRunningTaskInfoBuilder() .setParentTaskId(mSideStage.mRootTaskInfo.taskId).build(); Loading Loading @@ -173,6 +174,7 @@ public class SplitTransitionTests extends ShellTestCase { } @Test @UiThreadTest public void testLaunchPair() { TransitionInfo info = createEnterPairInfo(); Loading @@ -195,6 +197,7 @@ public class SplitTransitionTests extends ShellTestCase { } @Test @UiThreadTest public void testMonitorInSplit() { enterSplit(); Loading Loading @@ -251,6 +254,7 @@ public class SplitTransitionTests extends ShellTestCase { } @Test @UiThreadTest public void testEnterRecents() { enterSplit(); Loading Loading @@ -288,6 +292,7 @@ public class SplitTransitionTests extends ShellTestCase { } @Test @UiThreadTest public void testDismissFromBeingOccluded() { enterSplit(); Loading Loading @@ -325,6 +330,7 @@ public class SplitTransitionTests extends ShellTestCase { } @Test @UiThreadTest public void testDismissFromMultiWindowSupport() { enterSplit(); Loading @@ -346,6 +352,7 @@ public class SplitTransitionTests extends ShellTestCase { } @Test @UiThreadTest public void testDismissSnap() { enterSplit(); Loading @@ -370,6 +377,7 @@ public class SplitTransitionTests extends ShellTestCase { } @Test @UiThreadTest public void testDismissFromAppFinish() { enterSplit(); Loading