diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java index 28d70491b6eee..16e05f1e3f26a 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java +++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java @@ -22,14 +22,12 @@ import static com.android.systemui.onehanded.OneHandedAnimationController.TRANSI import static com.android.systemui.onehanded.OneHandedAnimationController.TRANSITION_DIRECTION_TRIGGER; import android.content.Context; -import android.content.res.Resources; import android.graphics.Point; import android.graphics.Rect; import android.os.Handler; import android.os.Looper; import android.util.Log; -import android.view.Display; -import android.view.DisplayInfo; +import android.view.Surface; import android.view.SurfaceControl; import android.window.DisplayAreaInfo; import android.window.DisplayAreaOrganizer; @@ -42,7 +40,6 @@ import androidx.annotation.VisibleForTesting; import com.android.internal.os.SomeArgs; import com.android.systemui.Dumpable; import com.android.systemui.wm.DisplayController; -import com.android.systemui.wm.DisplayLayout; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -83,8 +80,6 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer implemen @VisibleForTesting HashMap mDisplayAreaMap = new HashMap(); private DisplayController mDisplayController; - private DisplayLayout mDisplayLayout; - private DisplayInfo mDisplayInfo = new DisplayInfo(); private OneHandedAnimationController mAnimationController; private OneHandedSurfaceTransactionHelper.SurfaceControlTransactionFactory mSurfaceControlTransactionFactory; @@ -129,6 +124,7 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer implemen switch (msg.what) { case MSG_RESET_IMMEDIATE: resetWindowsOffset(); + mDefaultDisplayBounds.set(currentBounds); mLastVisualDisplayBounds.set(currentBounds); finishOffset(0, TRANSITION_DIRECTION_EXIT); break; @@ -157,9 +153,8 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer implemen mUpdateHandler = new Handler(OneHandedThread.get().getLooper(), mUpdateCallback); mAnimationController = animationController; mDisplayController = displayController; - mDisplayLayout = getDisplayLayout(context); - mDisplayLayout.getStableBounds(mDefaultDisplayBounds); - mLastVisualDisplayBounds.set(mDefaultDisplayBounds); + mDefaultDisplayBounds.set(getDisplayBounds()); + mLastVisualDisplayBounds.set(getDisplayBounds()); mEnterExitAnimationDurationMs = context.getResources().getInteger( com.android.systemui.R.integer.config_one_handed_translate_animation_duration); mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new; @@ -175,6 +170,8 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer implemen Log.w(TAG, "Bypass onDisplayAreaAppeared()! displayAreaInfo=" + displayAreaInfo); return; } + // mDefaultDisplayBounds may out of date after removeDisplayChangingController() + mDefaultDisplayBounds.set(getDisplayBounds()); mDisplayAreaMap.put(displayAreaInfo, leash); } @@ -193,26 +190,35 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer implemen @Override public void unregisterOrganizer() { super.unregisterOrganizer(); - if (mDisplayAreaMap != null) { - mDisplayAreaMap.clear(); - } + resetWindowsOffset(); + + // Ensure all cached instance are cleared after resetWindowsOffset + mUpdateHandler.post(() -> { + if (mDisplayAreaMap != null && !mDisplayAreaMap.isEmpty()) { + mDisplayAreaMap.clear(); + } + }); } /** - * Handler for display rotation changes. + * Handler for display rotation changes by below policy which + * handles 90 degree display rotation changes {@link Surface.Rotation} + * */ - public void onRotateDisplay(Resources res, int toRotation) { + public void onRotateDisplay(int fromRotation, int toRotation) { // Stop one handed without animation and reset cropped size immediately - final Rect newBounds = new Rect(); - mDisplayLayout.rotateTo(res, toRotation); - mDisplayLayout.getStableBounds(newBounds); + final Rect newBounds = new Rect(mDefaultDisplayBounds); + final boolean isOrientationDiff = Math.abs(fromRotation - toRotation) % 2 == 1; - SomeArgs args = SomeArgs.obtain(); - args.arg1 = newBounds; - args.argi1 = 0 /* xOffset */; - args.argi2 = 0 /* yOffset */; - args.argi3 = TRANSITION_DIRECTION_EXIT; - mUpdateHandler.sendMessage(mUpdateHandler.obtainMessage(MSG_RESET_IMMEDIATE, args)); + if (isOrientationDiff) { + newBounds.set(newBounds.left, newBounds.top, newBounds.bottom, newBounds.right); + SomeArgs args = SomeArgs.obtain(); + args.arg1 = newBounds; + args.argi1 = 0 /* xOffset */; + args.argi2 = 0 /* yOffset */; + args.argi3 = TRANSITION_DIRECTION_EXIT; + mUpdateHandler.sendMessage(mUpdateHandler.obtainMessage(MSG_RESET_IMMEDIATE, args)); + } } /** @@ -314,12 +320,12 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer implemen } @Nullable - private Point getDisplayBounds() { + private Rect getDisplayBounds() { Point realSize = new Point(0, 0); if (mDisplayController != null && mDisplayController.getDisplay(DEFAULT_DISPLAY) != null) { mDisplayController.getDisplay(DEFAULT_DISPLAY).getRealSize(realSize); } - return realSize; + return new Rect(0, 0, realSize.x, realSize.y); } @VisibleForTesting @@ -327,16 +333,6 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer implemen return mUpdateHandler; } - private DisplayLayout getDisplayLayout(Context context) { - final Display display = mDisplayController.getDisplay(DEFAULT_DISPLAY); - if (display != null) { - display.getDisplayInfo(mDisplayInfo); - } else { - Log.w(TAG, "get DEFAULT_DISPLAY return null"); - } - return new DisplayLayout(mDisplayInfo, context.getResources(), false, false); - } - /** * Register transition callback */ @@ -368,9 +364,5 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer implemen pw.println(mLastVisualDisplayBounds); pw.print(innerPrefix + "getDisplayBounds()="); pw.println(getDisplayBounds()); - if (mDisplayLayout != null) { - pw.print(innerPrefix + "mDisplayLayout(w, h)="); - pw.println(mDisplayLayout.width() + ", " + mDisplayLayout.height()); - } } } diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java index 4dacdf3158f85..586761b0fc3d8 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java @@ -95,7 +95,7 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable { private final DisplayChangeController.OnDisplayChangingListener mRotationController = (display, fromRotation, toRotation, wct) -> { if (mDisplayAreaOrganizer != null) { - mDisplayAreaOrganizer.onRotateDisplay(mContext.getResources(), toRotation); + mDisplayAreaOrganizer.onRotateDisplay(fromRotation, toRotation); } }; diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizerTest.java index 07a32a977f828..7cf351f3efdd6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizerTest.java @@ -47,8 +47,8 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import org.mockito.Spy; @SmallTest @RunWith(AndroidTestingRunner.class) @@ -59,7 +59,6 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase { DisplayAreaInfo mDisplayAreaInfo; Display mDisplay; - Handler mUpdateHandler; OneHandedDisplayAreaOrganizer mDisplayAreaOrganizer; OneHandedAnimationController.OneHandedTransitionAnimator mFakeAnimator; WindowContainerToken mToken; @@ -76,6 +75,8 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase { DisplayController mMockDisplayController; @Mock SurfaceControl mMockLeash; + @Spy + Handler mUpdateHandler; @Before public void setUp() throws Exception { @@ -103,7 +104,7 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase { mDisplayAreaOrganizer = new OneHandedDisplayAreaOrganizer(mContext, mMockDisplayController, mMockAnimationController); - mUpdateHandler = Mockito.spy(mDisplayAreaOrganizer.getUpdateHandler()); + mUpdateHandler = mDisplayAreaOrganizer.getUpdateHandler(); } @Test @@ -139,21 +140,139 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase { final int xOffSet = 0; final int yOffSet = 100; + TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash); mDisplayAreaOrganizer.scheduleOffset(xOffSet, yOffSet); assertThat(mUpdateHandler.hasMessages( - OneHandedDisplayAreaOrganizer.MSG_OFFSET_ANIMATE)).isNotNull(); + OneHandedDisplayAreaOrganizer.MSG_OFFSET_ANIMATE)).isEqualTo(true); } @Test - public void testResetImmediately() { - // To prevent mNativeObject of Surface is null in the test flow + public void testRotation_portraitToLandscape() { when(mMockLeash.isValid()).thenReturn(false); - mDisplayAreaOrganizer.onRotateDisplay(mContext.getResources(), Surface.ROTATION_90); + // Rotate 0 -> 90 + TestableLooper.get(this).processAllMessages(); + mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_90); assertThat(mUpdateHandler.hasMessages( - OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isNotNull(); + OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(true); + + // Rotate 0 -> 270 + TestableLooper.get(this).processAllMessages(); + mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_270); + + assertThat(mUpdateHandler.hasMessages( + OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(true); + + // Rotate 180 -> 90 + TestableLooper.get(this).processAllMessages(); + mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_90); + + assertThat(mUpdateHandler.hasMessages( + OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(true); + + // Rotate 180 -> 270 + TestableLooper.get(this).processAllMessages(); + mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_270); + + assertThat(mUpdateHandler.hasMessages( + OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(true); } + @Test + public void testRotation_landscapeToPortrait() { + when(mMockLeash.isValid()).thenReturn(false); + // Rotate 90 -> 0 + TestableLooper.get(this).processAllMessages(); + mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_0); + + assertThat(mUpdateHandler.hasMessages( + OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(true); + + // Rotate 90 -> 180 + TestableLooper.get(this).processAllMessages(); + mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_180); + + assertThat(mUpdateHandler.hasMessages( + OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(true); + + // Rotate 270 -> 0 + TestableLooper.get(this).processAllMessages(); + mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_0); + + assertThat(mUpdateHandler.hasMessages( + OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(true); + + // Rotate 270 -> 180 + TestableLooper.get(this).processAllMessages(); + mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_180); + + assertThat(mUpdateHandler.hasMessages( + OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(true); + } + + @Test + public void testRotation_portraitToPortrait() { + when(mMockLeash.isValid()).thenReturn(false); + // Rotate 0 -> 0 + TestableLooper.get(this).processAllMessages(); + mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_0); + + assertThat(mUpdateHandler.hasMessages( + OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(false); + + // Rotate 0 -> 180 + TestableLooper.get(this).processAllMessages(); + mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_180); + + assertThat(mUpdateHandler.hasMessages( + OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(false); + + // Rotate 180 -> 180 + TestableLooper.get(this).processAllMessages(); + mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_180); + + assertThat(mUpdateHandler.hasMessages( + OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(false); + + // Rotate 180 -> 180 + TestableLooper.get(this).processAllMessages(); + mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_0); + + assertThat(mUpdateHandler.hasMessages( + OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(false); + } + + @Test + public void testRotation_landscapeToLandscape() { + when(mMockLeash.isValid()).thenReturn(false); + // Rotate 90 -> 90 + TestableLooper.get(this).processAllMessages(); + mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_90); + + assertThat(mUpdateHandler.hasMessages( + OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(false); + + // Rotate 90 -> 270 + TestableLooper.get(this).processAllMessages(); + mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_270); + + assertThat(mUpdateHandler.hasMessages( + OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(false); + + // Rotate 270 -> 270 + TestableLooper.get(this).processAllMessages(); + mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_270); + + assertThat(mUpdateHandler.hasMessages( + OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(false); + + // Rotate 270 -> 90 + TestableLooper.get(this).processAllMessages(); + mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_90); + + assertThat(mUpdateHandler.hasMessages( + OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(false); + } }