Loading libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java +10 −3 Original line number Diff line number Diff line Loading @@ -215,7 +215,7 @@ class AppPair implements ShellTaskOrganizer.TaskListener, SplitLayout.SplitLayou if (mSplitLayout != null) { if (mSplitLayout.updateConfiguration(mRootTaskInfo.configuration)) { onBoundsChanged(mSplitLayout); onLayoutChanged(mSplitLayout); } // updateConfiguration re-inits the dividerbar, so show it now mSyncQueue.runInSync(t -> t.show(mSplitLayout.getDividerLeash())); Loading Loading @@ -299,17 +299,24 @@ class AppPair implements ShellTaskOrganizer.TaskListener, SplitLayout.SplitLayou } @Override public void onBoundsChanging(SplitLayout layout) { public void onLayoutChanging(SplitLayout layout) { mSyncQueue.runInSync(t -> layout.applySurfaceChanges(t, mTaskLeash1, mTaskLeash2, mDimLayer1, mDimLayer2)); } @Override public void onBoundsChanged(SplitLayout layout) { public void onLayoutChanged(SplitLayout layout) { final WindowContainerTransaction wct = new WindowContainerTransaction(); layout.applyTaskChanges(wct, mTaskInfo1, mTaskInfo2); mSyncQueue.queue(wct); mSyncQueue.runInSync(t -> layout.applySurfaceChanges(t, mTaskLeash1, mTaskLeash2, mDimLayer1, mDimLayer2)); } @Override public void onLayoutShifted(int offsetX, int offsetY, SplitLayout layout) { final WindowContainerTransaction wct = new WindowContainerTransaction(); layout.applyLayoutShifted(wct, offsetX, offsetY, mTaskInfo1, mTaskInfo2); mController.getTaskOrganizer().applyTransaction(wct); } } libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java +69 −7 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.wm.shell.common.split; import static android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED; import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED; import static android.view.WindowManager.DOCKED_LEFT; import static android.view.WindowManager.DOCKED_TOP; Loading Loading @@ -224,13 +226,13 @@ public final class SplitLayout { void updateDivideBounds(int position) { updateBounds(position); mSplitWindowManager.setResizingSplits(true); mSplitLayoutHandler.onBoundsChanging(this); mSplitLayoutHandler.onLayoutChanging(this); } void setDividePosition(int position) { mDividePosition = position; updateBounds(mDividePosition); mSplitLayoutHandler.onBoundsChanged(this); mSplitLayoutHandler.onLayoutChanged(this); mSplitWindowManager.setResizingSplits(false); } Loading Loading @@ -352,6 +354,46 @@ public final class SplitLayout { .setBounds(task2.token, mImePositionProcessor.adjustForIme(mBounds2)); } /** * Shift configuration bounds to prevent client apps get configuration changed or relaunch. And * restore shifted configuration bounds if it's no longer shifted. */ public void applyLayoutShifted(WindowContainerTransaction wct, int offsetX, int offsetY, ActivityManager.RunningTaskInfo taskInfo1, ActivityManager.RunningTaskInfo taskInfo2) { if (offsetX == 0 && offsetY == 0) { wct.setBounds(taskInfo1.token, mBounds1); wct.setAppBounds(taskInfo1.token, null); wct.setScreenSizeDp(taskInfo1.token, SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED); wct.setBounds(taskInfo2.token, mBounds2); wct.setAppBounds(taskInfo2.token, null); wct.setScreenSizeDp(taskInfo2.token, SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED); } else { final Rect bounds = new Rect(); bounds.set(taskInfo1.configuration.windowConfiguration.getBounds()); bounds.offset(offsetX, offsetY); wct.setBounds(taskInfo1.token, bounds); bounds.set(taskInfo1.configuration.windowConfiguration.getAppBounds()); bounds.offset(offsetX, offsetY); wct.setAppBounds(taskInfo1.token, bounds); wct.setScreenSizeDp(taskInfo1.token, taskInfo1.configuration.screenWidthDp, taskInfo1.configuration.screenHeightDp); bounds.set(taskInfo2.configuration.windowConfiguration.getBounds()); bounds.offset(offsetX, offsetY); wct.setBounds(taskInfo2.token, bounds); bounds.set(taskInfo2.configuration.windowConfiguration.getAppBounds()); bounds.offset(offsetX, offsetY); wct.setAppBounds(taskInfo2.token, bounds); wct.setScreenSizeDp(taskInfo2.token, taskInfo2.configuration.screenWidthDp, taskInfo2.configuration.screenHeightDp); } } /** Handles layout change event. */ public interface SplitLayoutHandler { Loading @@ -359,10 +401,18 @@ public final class SplitLayout { void onSnappedToDismiss(boolean snappedToEnd); /** Calls when the bounds is changing due to animation or dragging divider bar. */ void onBoundsChanging(SplitLayout layout); void onLayoutChanging(SplitLayout layout); /** Calls when the target bounds changed. */ void onBoundsChanged(SplitLayout layout); void onLayoutChanged(SplitLayout layout); /** * Notifies when the layout shifted. So the layout handler can shift configuration * bounds correspondingly to make sure client apps won't get configuration changed or * relaunch. If the layout is no longer shifted, layout handler should restore shifted * configuration bounds. */ void onLayoutShifted(int offsetX, int offsetY, SplitLayout layout); /** Calls when user double tapped on the divider bar. */ default void onDoubleTappedDivider() { Loading Loading @@ -427,6 +477,18 @@ public final class SplitLayout { && !isFloating && !isLandscape(mRootBounds) && showing; mTargetYOffset = needOffset ? getTargetYOffset() : 0; if (mTargetYOffset != mLastYOffset) { // Freeze the configuration size with offset to prevent app get a configuration // changed or relaunch. This is required to make sure client apps will calculate // insets properly after layout shifted. if (mTargetYOffset == 0) { mSplitLayoutHandler.onLayoutShifted(0, 0, SplitLayout.this); } else { mSplitLayoutHandler.onLayoutShifted(0, mTargetYOffset - mLastYOffset, SplitLayout.this); } } // Make {@link DividerView} non-interactive while IME showing in split mode. Listen to // ImePositionProcessor#onImeVisibilityChanged directly in DividerView is not enough // because DividerView won't receive onImeVisibilityChanged callback after it being Loading @@ -441,7 +503,7 @@ public final class SplitLayout { public void onImePositionChanged(int displayId, int imeTop, SurfaceControl.Transaction t) { if (displayId != mDisplayId) return; onProgress(getProgress(imeTop)); mSplitLayoutHandler.onBoundsChanging(SplitLayout.this); mSplitLayoutHandler.onLayoutChanging(SplitLayout.this); } @Override Loading @@ -449,7 +511,7 @@ public final class SplitLayout { SurfaceControl.Transaction t) { if (displayId != mDisplayId || cancel) return; onProgress(1.0f); mSplitLayoutHandler.onBoundsChanging(SplitLayout.this); mSplitLayoutHandler.onLayoutChanging(SplitLayout.this); } @Override Loading @@ -459,7 +521,7 @@ public final class SplitLayout { if (!controlling && mImeShown) { reset(); mSplitWindowManager.setInteractive(true); mSplitLayoutHandler.onBoundsChanging(SplitLayout.this); mSplitLayoutHandler.onLayoutChanging(SplitLayout.this); } } Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +16 −4 Original line number Diff line number Diff line Loading @@ -425,7 +425,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, if (mSideStageListener.mVisible && updateBounds) { if (wct == null) { // onBoundsChanged builds/applies a wct with the contents of updateWindowBounds. onBoundsChanged(mSplitLayout); onLayoutChanged(mSplitLayout); } else { updateWindowBounds(mSplitLayout, wct); } Loading Loading @@ -743,12 +743,12 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, } @Override public void onBoundsChanging(SplitLayout layout) { public void onLayoutChanging(SplitLayout layout) { mSyncQueue.runInSync(t -> updateSurfaceBounds(layout, t)); } @Override public void onBoundsChanged(SplitLayout layout) { public void onLayoutChanged(SplitLayout layout) { final WindowContainerTransaction wct = new WindowContainerTransaction(); updateWindowBounds(layout, wct); mSyncQueue.queue(wct); Loading Loading @@ -791,6 +791,18 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, return SPLIT_POSITION_UNDEFINED; } @Override public void onLayoutShifted(int offsetX, int offsetY, SplitLayout layout) { final StageTaskListener topLeftStage = mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mSideStage : mMainStage; final StageTaskListener bottomRightStage = mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mMainStage : mSideStage; final WindowContainerTransaction wct = new WindowContainerTransaction(); layout.applyLayoutShifted(wct, offsetX, offsetY, topLeftStage.mRootTaskInfo, bottomRightStage.mRootTaskInfo); mTaskOrganizer.applyTransaction(wct); } @Override public void onDisplayAreaAppeared(DisplayAreaInfo displayAreaInfo) { mDisplayAreaInfo = displayAreaInfo; Loading @@ -813,7 +825,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, if (mSplitLayout != null && mSplitLayout.updateConfiguration(mDisplayAreaInfo.configuration) && mMainStage.isActive()) { onBoundsChanged(mSplitLayout); onLayoutChanged(mSplitLayout); mSyncQueue.runInSync(t -> applyDividerVisibility(t)); } } Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java +2 −2 Original line number Diff line number Diff line Loading @@ -92,13 +92,13 @@ public class SplitLayoutTests extends ShellTestCase { @Test public void testUpdateDivideBounds() { mSplitLayout.updateDivideBounds(anyInt()); verify(mSplitLayoutHandler).onBoundsChanging(any(SplitLayout.class)); verify(mSplitLayoutHandler).onLayoutChanging(any(SplitLayout.class)); } @Test public void testSetDividePosition() { mSplitLayout.setDividePosition(anyInt()); verify(mSplitLayoutHandler).onBoundsChanged(any(SplitLayout.class)); verify(mSplitLayoutHandler).onLayoutChanged(any(SplitLayout.class)); } @Test Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java +10 −3 Original line number Diff line number Diff line Loading @@ -215,7 +215,7 @@ class AppPair implements ShellTaskOrganizer.TaskListener, SplitLayout.SplitLayou if (mSplitLayout != null) { if (mSplitLayout.updateConfiguration(mRootTaskInfo.configuration)) { onBoundsChanged(mSplitLayout); onLayoutChanged(mSplitLayout); } // updateConfiguration re-inits the dividerbar, so show it now mSyncQueue.runInSync(t -> t.show(mSplitLayout.getDividerLeash())); Loading Loading @@ -299,17 +299,24 @@ class AppPair implements ShellTaskOrganizer.TaskListener, SplitLayout.SplitLayou } @Override public void onBoundsChanging(SplitLayout layout) { public void onLayoutChanging(SplitLayout layout) { mSyncQueue.runInSync(t -> layout.applySurfaceChanges(t, mTaskLeash1, mTaskLeash2, mDimLayer1, mDimLayer2)); } @Override public void onBoundsChanged(SplitLayout layout) { public void onLayoutChanged(SplitLayout layout) { final WindowContainerTransaction wct = new WindowContainerTransaction(); layout.applyTaskChanges(wct, mTaskInfo1, mTaskInfo2); mSyncQueue.queue(wct); mSyncQueue.runInSync(t -> layout.applySurfaceChanges(t, mTaskLeash1, mTaskLeash2, mDimLayer1, mDimLayer2)); } @Override public void onLayoutShifted(int offsetX, int offsetY, SplitLayout layout) { final WindowContainerTransaction wct = new WindowContainerTransaction(); layout.applyLayoutShifted(wct, offsetX, offsetY, mTaskInfo1, mTaskInfo2); mController.getTaskOrganizer().applyTransaction(wct); } }
libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java +69 −7 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.wm.shell.common.split; import static android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED; import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED; import static android.view.WindowManager.DOCKED_LEFT; import static android.view.WindowManager.DOCKED_TOP; Loading Loading @@ -224,13 +226,13 @@ public final class SplitLayout { void updateDivideBounds(int position) { updateBounds(position); mSplitWindowManager.setResizingSplits(true); mSplitLayoutHandler.onBoundsChanging(this); mSplitLayoutHandler.onLayoutChanging(this); } void setDividePosition(int position) { mDividePosition = position; updateBounds(mDividePosition); mSplitLayoutHandler.onBoundsChanged(this); mSplitLayoutHandler.onLayoutChanged(this); mSplitWindowManager.setResizingSplits(false); } Loading Loading @@ -352,6 +354,46 @@ public final class SplitLayout { .setBounds(task2.token, mImePositionProcessor.adjustForIme(mBounds2)); } /** * Shift configuration bounds to prevent client apps get configuration changed or relaunch. And * restore shifted configuration bounds if it's no longer shifted. */ public void applyLayoutShifted(WindowContainerTransaction wct, int offsetX, int offsetY, ActivityManager.RunningTaskInfo taskInfo1, ActivityManager.RunningTaskInfo taskInfo2) { if (offsetX == 0 && offsetY == 0) { wct.setBounds(taskInfo1.token, mBounds1); wct.setAppBounds(taskInfo1.token, null); wct.setScreenSizeDp(taskInfo1.token, SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED); wct.setBounds(taskInfo2.token, mBounds2); wct.setAppBounds(taskInfo2.token, null); wct.setScreenSizeDp(taskInfo2.token, SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED); } else { final Rect bounds = new Rect(); bounds.set(taskInfo1.configuration.windowConfiguration.getBounds()); bounds.offset(offsetX, offsetY); wct.setBounds(taskInfo1.token, bounds); bounds.set(taskInfo1.configuration.windowConfiguration.getAppBounds()); bounds.offset(offsetX, offsetY); wct.setAppBounds(taskInfo1.token, bounds); wct.setScreenSizeDp(taskInfo1.token, taskInfo1.configuration.screenWidthDp, taskInfo1.configuration.screenHeightDp); bounds.set(taskInfo2.configuration.windowConfiguration.getBounds()); bounds.offset(offsetX, offsetY); wct.setBounds(taskInfo2.token, bounds); bounds.set(taskInfo2.configuration.windowConfiguration.getAppBounds()); bounds.offset(offsetX, offsetY); wct.setAppBounds(taskInfo2.token, bounds); wct.setScreenSizeDp(taskInfo2.token, taskInfo2.configuration.screenWidthDp, taskInfo2.configuration.screenHeightDp); } } /** Handles layout change event. */ public interface SplitLayoutHandler { Loading @@ -359,10 +401,18 @@ public final class SplitLayout { void onSnappedToDismiss(boolean snappedToEnd); /** Calls when the bounds is changing due to animation or dragging divider bar. */ void onBoundsChanging(SplitLayout layout); void onLayoutChanging(SplitLayout layout); /** Calls when the target bounds changed. */ void onBoundsChanged(SplitLayout layout); void onLayoutChanged(SplitLayout layout); /** * Notifies when the layout shifted. So the layout handler can shift configuration * bounds correspondingly to make sure client apps won't get configuration changed or * relaunch. If the layout is no longer shifted, layout handler should restore shifted * configuration bounds. */ void onLayoutShifted(int offsetX, int offsetY, SplitLayout layout); /** Calls when user double tapped on the divider bar. */ default void onDoubleTappedDivider() { Loading Loading @@ -427,6 +477,18 @@ public final class SplitLayout { && !isFloating && !isLandscape(mRootBounds) && showing; mTargetYOffset = needOffset ? getTargetYOffset() : 0; if (mTargetYOffset != mLastYOffset) { // Freeze the configuration size with offset to prevent app get a configuration // changed or relaunch. This is required to make sure client apps will calculate // insets properly after layout shifted. if (mTargetYOffset == 0) { mSplitLayoutHandler.onLayoutShifted(0, 0, SplitLayout.this); } else { mSplitLayoutHandler.onLayoutShifted(0, mTargetYOffset - mLastYOffset, SplitLayout.this); } } // Make {@link DividerView} non-interactive while IME showing in split mode. Listen to // ImePositionProcessor#onImeVisibilityChanged directly in DividerView is not enough // because DividerView won't receive onImeVisibilityChanged callback after it being Loading @@ -441,7 +503,7 @@ public final class SplitLayout { public void onImePositionChanged(int displayId, int imeTop, SurfaceControl.Transaction t) { if (displayId != mDisplayId) return; onProgress(getProgress(imeTop)); mSplitLayoutHandler.onBoundsChanging(SplitLayout.this); mSplitLayoutHandler.onLayoutChanging(SplitLayout.this); } @Override Loading @@ -449,7 +511,7 @@ public final class SplitLayout { SurfaceControl.Transaction t) { if (displayId != mDisplayId || cancel) return; onProgress(1.0f); mSplitLayoutHandler.onBoundsChanging(SplitLayout.this); mSplitLayoutHandler.onLayoutChanging(SplitLayout.this); } @Override Loading @@ -459,7 +521,7 @@ public final class SplitLayout { if (!controlling && mImeShown) { reset(); mSplitWindowManager.setInteractive(true); mSplitLayoutHandler.onBoundsChanging(SplitLayout.this); mSplitLayoutHandler.onLayoutChanging(SplitLayout.this); } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +16 −4 Original line number Diff line number Diff line Loading @@ -425,7 +425,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, if (mSideStageListener.mVisible && updateBounds) { if (wct == null) { // onBoundsChanged builds/applies a wct with the contents of updateWindowBounds. onBoundsChanged(mSplitLayout); onLayoutChanged(mSplitLayout); } else { updateWindowBounds(mSplitLayout, wct); } Loading Loading @@ -743,12 +743,12 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, } @Override public void onBoundsChanging(SplitLayout layout) { public void onLayoutChanging(SplitLayout layout) { mSyncQueue.runInSync(t -> updateSurfaceBounds(layout, t)); } @Override public void onBoundsChanged(SplitLayout layout) { public void onLayoutChanged(SplitLayout layout) { final WindowContainerTransaction wct = new WindowContainerTransaction(); updateWindowBounds(layout, wct); mSyncQueue.queue(wct); Loading Loading @@ -791,6 +791,18 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, return SPLIT_POSITION_UNDEFINED; } @Override public void onLayoutShifted(int offsetX, int offsetY, SplitLayout layout) { final StageTaskListener topLeftStage = mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mSideStage : mMainStage; final StageTaskListener bottomRightStage = mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mMainStage : mSideStage; final WindowContainerTransaction wct = new WindowContainerTransaction(); layout.applyLayoutShifted(wct, offsetX, offsetY, topLeftStage.mRootTaskInfo, bottomRightStage.mRootTaskInfo); mTaskOrganizer.applyTransaction(wct); } @Override public void onDisplayAreaAppeared(DisplayAreaInfo displayAreaInfo) { mDisplayAreaInfo = displayAreaInfo; Loading @@ -813,7 +825,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, if (mSplitLayout != null && mSplitLayout.updateConfiguration(mDisplayAreaInfo.configuration) && mMainStage.isActive()) { onBoundsChanged(mSplitLayout); onLayoutChanged(mSplitLayout); mSyncQueue.runInSync(t -> applyDividerVisibility(t)); } } Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java +2 −2 Original line number Diff line number Diff line Loading @@ -92,13 +92,13 @@ public class SplitLayoutTests extends ShellTestCase { @Test public void testUpdateDivideBounds() { mSplitLayout.updateDivideBounds(anyInt()); verify(mSplitLayoutHandler).onBoundsChanging(any(SplitLayout.class)); verify(mSplitLayoutHandler).onLayoutChanging(any(SplitLayout.class)); } @Test public void testSetDividePosition() { mSplitLayout.setDividePosition(anyInt()); verify(mSplitLayoutHandler).onBoundsChanged(any(SplitLayout.class)); verify(mSplitLayoutHandler).onLayoutChanged(any(SplitLayout.class)); } @Test Loading