From 76522e99389975177affdcb5bf83694556f04d43 Mon Sep 17 00:00:00 2001 From: Tony Huang Date: Tue, 14 Sep 2021 17:23:07 +0800 Subject: [PATCH] Fix divider display issue onDisplayAreaInfoChanged might callback many times in one action such like fold to unfold, it might cause some issues because we don't use lastet config resources to set SplitLayout. Another bug is we cannot get divider leash immediately after we init it because leash is built after attachToParentSurface. Fix both bug by always do whole SplitLayout setting if any cared configs changed. And add a callback after divider leash build, show the leash on this callback to ensure we got null leash. Fix: 198581512 Fix: 197296095 Test: manual Test: pass existing tests Change-Id: I06a4093927d6469a85b2104b36c16d6e16519a51 --- .../android/wm/shell/apppairs/AppPair.java | 19 +++++++++++---- .../wm/shell/common/split/SplitLayout.java | 23 ++++++++----------- .../common/split/SplitWindowManager.java | 2 ++ .../shell/splitscreen/StageCoordinator.java | 19 +++++++++++---- .../shell/common/split/SplitLayoutTests.java | 5 ++-- .../common/split/SplitWindowManagerTests.java | 5 ++-- 6 files changed, 46 insertions(+), 27 deletions(-) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java index 3800b8d234f3f..c2cb72a530a39 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java @@ -43,6 +43,7 @@ import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.SurfaceUtils; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.split.SplitLayout; +import com.android.wm.shell.common.split.SplitWindowManager; import java.io.PrintWriter; @@ -70,6 +71,19 @@ class AppPair implements ShellTaskOrganizer.TaskListener, SplitLayout.SplitLayou private final DisplayImeController mDisplayImeController; private SplitLayout mSplitLayout; + private final SplitWindowManager.ParentContainerCallbacks mParentContainerCallbacks = + new SplitWindowManager.ParentContainerCallbacks() { + @Override + public void attachToParentSurface(SurfaceControl.Builder b) { + b.setParent(mRootTaskLeash); + } + + @Override + public void onLeashReady(SurfaceControl leash) { + mSyncQueue.runInSync(t -> t.show(leash)); + } + }; + AppPair(AppPairsController controller) { mController = controller; mSyncQueue = controller.getSyncTransactionQueue(); @@ -110,8 +124,7 @@ class AppPair implements ShellTaskOrganizer.TaskListener, SplitLayout.SplitLayou mSplitLayout = new SplitLayout(TAG + "SplitDivider", mDisplayController.getDisplayContext(mRootTaskInfo.displayId), mRootTaskInfo.configuration, this /* layoutChangeListener */, - b -> b.setParent(mRootTaskLeash), mDisplayImeController, - mController.getTaskOrganizer()); + mParentContainerCallbacks, mDisplayImeController, mController.getTaskOrganizer()); final WindowContainerToken token1 = task1.token; final WindowContainerToken token2 = task2.token; @@ -218,8 +231,6 @@ class AppPair implements ShellTaskOrganizer.TaskListener, SplitLayout.SplitLayou if (mSplitLayout.updateConfiguration(mRootTaskInfo.configuration)) { onLayoutChanged(mSplitLayout); } - // updateConfiguration re-inits the dividerbar, so show it now - mSyncQueue.runInSync(t -> t.show(mSplitLayout.getDividerLeash())); } } else if (taskInfo.taskId == getTaskId1()) { mTaskInfo1 = taskInfo; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java index 754b8dadbfad9..27c8d7ac00325 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java @@ -125,8 +125,8 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange mRotation = configuration.windowConfiguration.getRotation(); mSplitLayoutHandler = splitLayoutHandler; mDisplayImeController = displayImeController; - mSplitWindowManager = new SplitWindowManager( - windowName, mContext, configuration, parentContainerCallbacks); + mSplitWindowManager = new SplitWindowManager(windowName, mContext, configuration, + parentContainerCallbacks); mTaskOrganizer = taskOrganizer; mImePositionProcessor = new ImePositionProcessor(mContext.getDisplayId()); mDismissingParallaxPolicy = new DismissingParallaxPolicy(); @@ -181,22 +181,19 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange public boolean updateConfiguration(Configuration configuration) { boolean affectsLayout = false; - // Make sure to render the divider bar with proper resources that matching the screen - // orientation. - final int orientation = configuration.orientation; - if (orientation != mOrientation) { - mOrientation = orientation; - mContext = mContext.createConfigurationContext(configuration); - mSplitWindowManager.setConfiguration(configuration); - affectsLayout = true; - } - // Update the split bounds when necessary. Besides root bounds changed, split bounds need to // be updated when the rotation changed to cover the case that users rotated the screen 180 // degrees. + // Make sure to render the divider bar with proper resources that matching the screen + // orientation. final int rotation = configuration.windowConfiguration.getRotation(); final Rect rootBounds = configuration.windowConfiguration.getBounds(); - if (rotation != mRotation || !mRootBounds.equals(rootBounds)) { + final int orientation = configuration.orientation; + if (rotation != mRotation || !mRootBounds.equals(rootBounds) + || orientation != mOrientation) { + mContext = mContext.createConfigurationContext(configuration); + mSplitWindowManager.setConfiguration(configuration); + mOrientation = orientation; mTempRect.set(mRootBounds); mRootBounds.set(rootBounds); mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java index fc7edfc4bcebf..47dceb3921839 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java @@ -64,6 +64,7 @@ public final class SplitWindowManager extends WindowlessWindowManager { public interface ParentContainerCallbacks { void attachToParentSurface(SurfaceControl.Builder b); + void onLeashReady(SurfaceControl leash); } public SplitWindowManager(String windowName, Context context, Configuration config, @@ -100,6 +101,7 @@ public final class SplitWindowManager extends WindowlessWindowManager { .setCallsite("SplitWindowManager#attachToParentSurface"); mParentContainerCallbacks.attachToParentSurface(builder); mLeash = builder.build(); + mParentContainerCallbacks.onLeashReady(mLeash); b.setParent(mLeash); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index d9708f05e7dd6..bf2f930644ea4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -90,6 +90,7 @@ import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.common.split.SplitLayout; import com.android.wm.shell.common.split.SplitLayout.SplitPosition; +import com.android.wm.shell.common.split.SplitWindowManager; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.transition.Transitions; @@ -163,6 +164,19 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, mDismissTop = NO_DISMISS; }; + private final SplitWindowManager.ParentContainerCallbacks mParentContainerCallbacks = + new SplitWindowManager.ParentContainerCallbacks() { + @Override + public void attachToParentSurface(SurfaceControl.Builder b) { + mRootTDAOrganizer.attachToDisplayArea(mDisplayId, b); + } + + @Override + public void onLeashReady(SurfaceControl leash) { + mSyncQueue.runInSync(t -> applyDividerVisibility(t)); + } + }; + StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue, RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellTaskOrganizer taskOrganizer, DisplayImeController displayImeController, @@ -726,7 +740,6 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, } else { t.hide(dividerLeash); } - } private void onStageHasChildrenChanged(StageListenerImpl stageListener) { @@ -852,8 +865,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, mDisplayAreaInfo = displayAreaInfo; if (mSplitLayout == null) { mSplitLayout = new SplitLayout(TAG + "SplitDivider", mContext, - mDisplayAreaInfo.configuration, this, - b -> mRootTDAOrganizer.attachToDisplayArea(mDisplayId, b), + mDisplayAreaInfo.configuration, this, mParentContainerCallbacks, mDisplayImeController, mTaskOrganizer); mDisplayInsetsController.addInsetsChangedListener(mDisplayId, mSplitLayout); } @@ -871,7 +883,6 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, && mSplitLayout.updateConfiguration(mDisplayAreaInfo.configuration) && mMainStage.isActive()) { onLayoutChanged(mSplitLayout); - mSyncQueue.runInSync(t -> applyDividerVisibility(t)); } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java index 3557906531b2f..defa58d7fe935 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java @@ -29,7 +29,6 @@ import static org.mockito.Mockito.verify; import android.content.res.Configuration; import android.graphics.Rect; -import android.view.SurfaceControl; import androidx.test.annotation.UiThreadTest; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -53,7 +52,7 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) public class SplitLayoutTests extends ShellTestCase { @Mock SplitLayout.SplitLayoutHandler mSplitLayoutHandler; - @Mock SurfaceControl mRootLeash; + @Mock SplitWindowManager.ParentContainerCallbacks mCallbacks; @Mock DisplayImeController mDisplayImeController; @Mock ShellTaskOrganizer mTaskOrganizer; @Captor ArgumentCaptor mRunnableCaptor; @@ -67,7 +66,7 @@ public class SplitLayoutTests extends ShellTestCase { mContext, getConfiguration(), mSplitLayoutHandler, - b -> b.setParent(mRootLeash), + mCallbacks, mDisplayImeController, mTaskOrganizer)); } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java index c456c7de8821c..9bb54a18063f6 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java @@ -23,7 +23,6 @@ import static org.mockito.Mockito.when; import android.content.res.Configuration; import android.graphics.Rect; import android.view.InsetsState; -import android.view.SurfaceControl; import androidx.test.annotation.UiThreadTest; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -41,8 +40,8 @@ import org.mockito.MockitoAnnotations; @SmallTest @RunWith(AndroidJUnit4.class) public class SplitWindowManagerTests extends ShellTestCase { - @Mock SurfaceControl mSurfaceControl; @Mock SplitLayout mSplitLayout; + @Mock SplitWindowManager.ParentContainerCallbacks mCallbacks; private SplitWindowManager mSplitWindowManager; @Before @@ -51,7 +50,7 @@ public class SplitWindowManagerTests extends ShellTestCase { final Configuration configuration = new Configuration(); configuration.setToDefaults(); mSplitWindowManager = new SplitWindowManager("TestSplitDivider", mContext, configuration, - b -> b.setParent(mSurfaceControl)); + mCallbacks); when(mSplitLayout.getDividerBounds()).thenReturn( new Rect(0, 0, configuration.windowConfiguration.getBounds().width(), configuration.windowConfiguration.getBounds().height()));