Loading libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java +1 −1 Original line number Diff line number Diff line Loading @@ -77,7 +77,7 @@ public class OneHandedController implements OneHanded { private final DisplayChangeController.OnDisplayChangingListener mRotationController = (display, fromRotation, toRotation, wct) -> { if (mDisplayAreaOrganizer != null) { mDisplayAreaOrganizer.onRotateDisplay(fromRotation, toRotation); mDisplayAreaOrganizer.onRotateDisplay(fromRotation, toRotation, wct); } }; Loading libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java +40 −36 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.graphics.Rect; import android.os.Handler; import android.os.Looper; import android.os.SystemProperties; import android.util.ArrayMap; import android.util.Log; import android.view.SurfaceControl; import android.window.DisplayAreaInfo; Loading @@ -42,7 +43,6 @@ import com.android.wm.shell.common.DisplayController; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Objects; Loading Loading @@ -76,7 +76,7 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer { private int mEnterExitAnimationDurationMs; @VisibleForTesting HashMap<DisplayAreaInfo, SurfaceControl> mDisplayAreaMap = new HashMap(); ArrayMap<DisplayAreaInfo, SurfaceControl> mDisplayAreaMap = new ArrayMap(); private DisplayController mDisplayController; private OneHandedAnimationController mAnimationController; private OneHandedSurfaceTransactionHelper.SurfaceControlTransactionFactory Loading Loading @@ -117,12 +117,13 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer { private Handler.Callback mUpdateCallback = (msg) -> { SomeArgs args = (SomeArgs) msg.obj; final Rect currentBounds = args.arg1 != null ? (Rect) args.arg1 : mDefaultDisplayBounds; final WindowContainerTransaction wctFromRotate = (WindowContainerTransaction) args.arg2; final int yOffset = args.argi2; final int direction = args.argi3; switch (msg.what) { case MSG_RESET_IMMEDIATE: resetWindowsOffset(); resetWindowsOffset(wctFromRotate); mDefaultDisplayBounds.set(currentBounds); mLastVisualDisplayBounds.set(currentBounds); finishOffset(0, TRANSITION_DIRECTION_EXIT); Loading Loading @@ -165,47 +166,44 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer { @NonNull SurfaceControl leash) { Objects.requireNonNull(displayAreaInfo, "displayAreaInfo must not be null"); Objects.requireNonNull(leash, "leash must not be null"); if (displayAreaInfo.featureId != FEATURE_ONE_HANDED) { Log.w(TAG, "Bypass onDisplayAreaAppeared()! displayAreaInfo=" + displayAreaInfo); return; } synchronized (this) { if (mDisplayAreaMap.get(displayAreaInfo) == null) { // mDefaultDisplayBounds may out of date after removeDisplayChangingController() mDefaultDisplayBounds.set(getDisplayBounds()); mDisplayAreaMap.put(displayAreaInfo, leash); } } } @Override public void onDisplayAreaVanished(@NonNull DisplayAreaInfo displayAreaInfo) { Objects.requireNonNull(displayAreaInfo, "Requires valid displayArea, and displayArea must not be null"); synchronized (this) { if (!mDisplayAreaMap.containsKey(displayAreaInfo)) { Log.w(TAG, "Unrecognized token: " + displayAreaInfo.token); return; } mDisplayAreaMap.remove(displayAreaInfo); } } @Override public void unregisterOrganizer() { super.unregisterOrganizer(); resetWindowsOffset(); // Ensure all cached instance are cleared after resetWindowsOffset mUpdateHandler.post(() -> { if (mDisplayAreaMap != null && !mDisplayAreaMap.isEmpty()) { mDisplayAreaMap.clear(); } }); mUpdateHandler.post(() -> resetWindowsOffset(null)); } /** * Handler for display rotation changes by below policy which * handles 90 degree display rotation changes {@link Surface.Rotation} * handles 90 degree display rotation changes {@link Surface.Rotation}. * * @param fromRotation starting rotation of the display. * @param toRotation target rotation of the display (after rotating). * @param wct A task transaction {@link WindowContainerTransaction} from * {@link DisplayChangeController} to populate. */ public void onRotateDisplay(int fromRotation, int toRotation) { public void onRotateDisplay(int fromRotation, int toRotation, WindowContainerTransaction wct) { // Stop one handed without animation and reset cropped size immediately final Rect newBounds = new Rect(mDefaultDisplayBounds); final boolean isOrientationDiff = Math.abs(fromRotation - toRotation) % 2 == 1; Loading @@ -214,6 +212,7 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer { newBounds.set(newBounds.left, newBounds.top, newBounds.bottom, newBounds.right); SomeArgs args = SomeArgs.obtain(); args.arg1 = newBounds; args.arg2 = wct; args.argi1 = 0 /* xOffset */; args.argi2 = 0 /* yOffset */; args.argi3 = TRANSITION_DIRECTION_EXIT; Loading @@ -239,18 +238,19 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer { throw new RuntimeException("Callers should call scheduleOffset() instead of this " + "directly"); } synchronized (this) { final WindowContainerTransaction wct = new WindowContainerTransaction(); mDisplayAreaMap.forEach( (key, leash) -> { animateWindows(leash, fromBounds, toBounds, direction, durationMs); animateWindows(leash, fromBounds, toBounds, direction, durationMs); wct.setBounds(key.token, toBounds); }); applyTransaction(wct); } } private void resetWindowsOffset() { mUpdateHandler.post(() -> { private void resetWindowsOffset(WindowContainerTransaction wct) { synchronized (this) { final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction(); mDisplayAreaMap.forEach( Loading @@ -262,9 +262,13 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer { } tx.setPosition(leash, 0, 0) .setWindowCrop(leash, -1/* reset */, -1/* reset */); // DisplayRotationController will applyTransaction() after finish rotating if (wct != null) { wct.setBounds(key.token, null/* reset */); } }); tx.apply(); }); } } private void animateWindows(SurfaceControl leash, Rect fromBounds, Rect toBounds, Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java +112 −61 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import android.view.SurfaceControl; import android.window.DisplayAreaInfo; import android.window.IWindowContainerToken; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; import androidx.test.filters.SmallTest; Loading @@ -49,7 +50,6 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.Spy; @SmallTest @RunWith(AndroidTestingRunner.class) Loading @@ -60,11 +60,13 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase { DisplayAreaInfo mDisplayAreaInfo; Display mDisplay; Handler mUpdateHandler; OneHandedDisplayAreaOrganizer mDisplayAreaOrganizer; OneHandedTutorialHandler mTutorialHandler; OneHandedAnimationController.OneHandedTransitionAnimator mFakeAnimator; WindowContainerToken mToken; SurfaceControl mLeash; TestableLooper mTestableLooper; @Mock IWindowContainerToken mMockRealToken; @Mock Loading @@ -77,12 +79,13 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase { DisplayController mMockDisplayController; @Mock SurfaceControl mMockLeash; @Spy Handler mUpdateHandler; @Mock WindowContainerTransaction mMockWindowContainerTransaction; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mTestableLooper = TestableLooper.get(this); mToken = new WindowContainerToken(mMockRealToken); mLeash = new SurfaceControl(); mDisplay = mContext.getDisplay(); Loading Loading @@ -110,14 +113,10 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase { mUpdateHandler = mDisplayAreaOrganizer.getUpdateHandler(); } @Test public void testGetDisplayAreaUpdateHandler_isNotNull() { assertThat(mUpdateHandler).isNotNull(); } @Test public void testOnDisplayAreaAppeared() { mDisplayAreaOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash); mTestableLooper.processAllMessages(); verify(mMockAnimationController, never()).getAnimator(any(), any(), any()); } Loading @@ -125,17 +124,10 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase { @Test public void testOnDisplayAreaVanished() { mDisplayAreaOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onDisplayAreaVanished(mDisplayAreaInfo); } @Test public void testOnDisplayAreaInfoChanged_updateDisplayAreaInfo() { final DisplayAreaInfo newDisplayAreaInfo = new DisplayAreaInfo(mToken, DEFAULT_DISPLAY, FEATURE_ONE_HANDED); mDisplayAreaOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash); mDisplayAreaOrganizer.onDisplayAreaInfoChanged(newDisplayAreaInfo); assertThat(mDisplayAreaOrganizer.mDisplayAreaMap.containsKey(mDisplayAreaInfo)).isTrue(); assertThat(mDisplayAreaOrganizer.mDisplayAreaMap).isEmpty(); } @Ignore("b/160848002") Loading @@ -143,142 +135,201 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase { public void testScheduleOffset() { final int xOffSet = 0; final int yOffSet = 100; TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash); mDisplayAreaOrganizer.scheduleOffset(xOffSet, yOffSet); mTestableLooper.processAllMessages(); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_OFFSET_ANIMATE)).isEqualTo(true); } @Ignore("b/160848002") @Test public void testRotation_portraitToLandscape() { public void testRotation_portrait_0_to_landscape_90() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 0 -> 90 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_90); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_90, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(true); } @Test public void testRotation_portrait_0_to_seascape_270() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 0 -> 270 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_270); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_270, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(true); } @Test public void testRotation_portrait_180_to_landscape_90() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 180 -> 90 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_90); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_90, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(true); } @Test public void testRotation_portrait_180_to_seascape_270() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 180 -> 270 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_270); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_270, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(true); } @Ignore("b/160848002") @Test public void testRotation_landscapeToPortrait() { public void testRotation_landscape_90_to_portrait_0() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 90 -> 0 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_0); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_0, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(true); } @Test public void testRotation_landscape_90_to_portrait_180() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 90 -> 180 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_180); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_180, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(true); } @Test public void testRotation_Seascape_270_to_portrait_0() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 270 -> 0 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_0); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_0, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(true); } @Test public void testRotation_seascape_90_to_portrait_180() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 270 -> 180 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_180); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_180, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(true); } @Ignore("b/160848002") @Test public void testRotation_portraitToPortrait() { public void testRotation_portrait_0_to_portrait_0() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 0 -> 0 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_0); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_0, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(false); } @Test public void testRotation_portrait_0_to_portrait_180() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 0 -> 180 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_180); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_180, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(false); } @Test public void testRotation_portrait_180_to_portrait_180() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 180 -> 180 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_180); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_180, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(false); } // Rotate 180 -> 180 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_0); @Test public void testRotation_portrait_180_to_portrait_0() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 180 -> 0 mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_0, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(false); } @Ignore("b/160848002") @Test public void testRotation_landscapeToLandscape() { public void testRotation_landscape_90_to_landscape_90() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 90 -> 90 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_90); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_90, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(false); } @Test public void testRotation_landscape_90_to_seascape_270() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 90 -> 270 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_270); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_270, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(false); } @Test public void testRotation_seascape_270_to_seascape_270() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 270 -> 270 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_270); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_270, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(false); } @Test public void testRotation_seascape_90_to_landscape_90() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 270 -> 90 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_90); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_90, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(false); Loading packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java +1 −1 Original line number Diff line number Diff line Loading @@ -419,8 +419,8 @@ public final class WMShell extends SystemUI if (handleLoggingCommand(args, pw)) { return; } // Dump WMShell stuff here if no commands were handled mOneHandedOptional.ifPresent(oneHanded -> oneHanded.dump(pw)); } @Override Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java +1 −1 Original line number Diff line number Diff line Loading @@ -77,7 +77,7 @@ public class OneHandedController implements OneHanded { private final DisplayChangeController.OnDisplayChangingListener mRotationController = (display, fromRotation, toRotation, wct) -> { if (mDisplayAreaOrganizer != null) { mDisplayAreaOrganizer.onRotateDisplay(fromRotation, toRotation); mDisplayAreaOrganizer.onRotateDisplay(fromRotation, toRotation, wct); } }; Loading
libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java +40 −36 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.graphics.Rect; import android.os.Handler; import android.os.Looper; import android.os.SystemProperties; import android.util.ArrayMap; import android.util.Log; import android.view.SurfaceControl; import android.window.DisplayAreaInfo; Loading @@ -42,7 +43,6 @@ import com.android.wm.shell.common.DisplayController; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Objects; Loading Loading @@ -76,7 +76,7 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer { private int mEnterExitAnimationDurationMs; @VisibleForTesting HashMap<DisplayAreaInfo, SurfaceControl> mDisplayAreaMap = new HashMap(); ArrayMap<DisplayAreaInfo, SurfaceControl> mDisplayAreaMap = new ArrayMap(); private DisplayController mDisplayController; private OneHandedAnimationController mAnimationController; private OneHandedSurfaceTransactionHelper.SurfaceControlTransactionFactory Loading Loading @@ -117,12 +117,13 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer { private Handler.Callback mUpdateCallback = (msg) -> { SomeArgs args = (SomeArgs) msg.obj; final Rect currentBounds = args.arg1 != null ? (Rect) args.arg1 : mDefaultDisplayBounds; final WindowContainerTransaction wctFromRotate = (WindowContainerTransaction) args.arg2; final int yOffset = args.argi2; final int direction = args.argi3; switch (msg.what) { case MSG_RESET_IMMEDIATE: resetWindowsOffset(); resetWindowsOffset(wctFromRotate); mDefaultDisplayBounds.set(currentBounds); mLastVisualDisplayBounds.set(currentBounds); finishOffset(0, TRANSITION_DIRECTION_EXIT); Loading Loading @@ -165,47 +166,44 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer { @NonNull SurfaceControl leash) { Objects.requireNonNull(displayAreaInfo, "displayAreaInfo must not be null"); Objects.requireNonNull(leash, "leash must not be null"); if (displayAreaInfo.featureId != FEATURE_ONE_HANDED) { Log.w(TAG, "Bypass onDisplayAreaAppeared()! displayAreaInfo=" + displayAreaInfo); return; } synchronized (this) { if (mDisplayAreaMap.get(displayAreaInfo) == null) { // mDefaultDisplayBounds may out of date after removeDisplayChangingController() mDefaultDisplayBounds.set(getDisplayBounds()); mDisplayAreaMap.put(displayAreaInfo, leash); } } } @Override public void onDisplayAreaVanished(@NonNull DisplayAreaInfo displayAreaInfo) { Objects.requireNonNull(displayAreaInfo, "Requires valid displayArea, and displayArea must not be null"); synchronized (this) { if (!mDisplayAreaMap.containsKey(displayAreaInfo)) { Log.w(TAG, "Unrecognized token: " + displayAreaInfo.token); return; } mDisplayAreaMap.remove(displayAreaInfo); } } @Override public void unregisterOrganizer() { super.unregisterOrganizer(); resetWindowsOffset(); // Ensure all cached instance are cleared after resetWindowsOffset mUpdateHandler.post(() -> { if (mDisplayAreaMap != null && !mDisplayAreaMap.isEmpty()) { mDisplayAreaMap.clear(); } }); mUpdateHandler.post(() -> resetWindowsOffset(null)); } /** * Handler for display rotation changes by below policy which * handles 90 degree display rotation changes {@link Surface.Rotation} * handles 90 degree display rotation changes {@link Surface.Rotation}. * * @param fromRotation starting rotation of the display. * @param toRotation target rotation of the display (after rotating). * @param wct A task transaction {@link WindowContainerTransaction} from * {@link DisplayChangeController} to populate. */ public void onRotateDisplay(int fromRotation, int toRotation) { public void onRotateDisplay(int fromRotation, int toRotation, WindowContainerTransaction wct) { // Stop one handed without animation and reset cropped size immediately final Rect newBounds = new Rect(mDefaultDisplayBounds); final boolean isOrientationDiff = Math.abs(fromRotation - toRotation) % 2 == 1; Loading @@ -214,6 +212,7 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer { newBounds.set(newBounds.left, newBounds.top, newBounds.bottom, newBounds.right); SomeArgs args = SomeArgs.obtain(); args.arg1 = newBounds; args.arg2 = wct; args.argi1 = 0 /* xOffset */; args.argi2 = 0 /* yOffset */; args.argi3 = TRANSITION_DIRECTION_EXIT; Loading @@ -239,18 +238,19 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer { throw new RuntimeException("Callers should call scheduleOffset() instead of this " + "directly"); } synchronized (this) { final WindowContainerTransaction wct = new WindowContainerTransaction(); mDisplayAreaMap.forEach( (key, leash) -> { animateWindows(leash, fromBounds, toBounds, direction, durationMs); animateWindows(leash, fromBounds, toBounds, direction, durationMs); wct.setBounds(key.token, toBounds); }); applyTransaction(wct); } } private void resetWindowsOffset() { mUpdateHandler.post(() -> { private void resetWindowsOffset(WindowContainerTransaction wct) { synchronized (this) { final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction(); mDisplayAreaMap.forEach( Loading @@ -262,9 +262,13 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer { } tx.setPosition(leash, 0, 0) .setWindowCrop(leash, -1/* reset */, -1/* reset */); // DisplayRotationController will applyTransaction() after finish rotating if (wct != null) { wct.setBounds(key.token, null/* reset */); } }); tx.apply(); }); } } private void animateWindows(SurfaceControl leash, Rect fromBounds, Rect toBounds, Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java +112 −61 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import android.view.SurfaceControl; import android.window.DisplayAreaInfo; import android.window.IWindowContainerToken; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; import androidx.test.filters.SmallTest; Loading @@ -49,7 +50,6 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.Spy; @SmallTest @RunWith(AndroidTestingRunner.class) Loading @@ -60,11 +60,13 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase { DisplayAreaInfo mDisplayAreaInfo; Display mDisplay; Handler mUpdateHandler; OneHandedDisplayAreaOrganizer mDisplayAreaOrganizer; OneHandedTutorialHandler mTutorialHandler; OneHandedAnimationController.OneHandedTransitionAnimator mFakeAnimator; WindowContainerToken mToken; SurfaceControl mLeash; TestableLooper mTestableLooper; @Mock IWindowContainerToken mMockRealToken; @Mock Loading @@ -77,12 +79,13 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase { DisplayController mMockDisplayController; @Mock SurfaceControl mMockLeash; @Spy Handler mUpdateHandler; @Mock WindowContainerTransaction mMockWindowContainerTransaction; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mTestableLooper = TestableLooper.get(this); mToken = new WindowContainerToken(mMockRealToken); mLeash = new SurfaceControl(); mDisplay = mContext.getDisplay(); Loading Loading @@ -110,14 +113,10 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase { mUpdateHandler = mDisplayAreaOrganizer.getUpdateHandler(); } @Test public void testGetDisplayAreaUpdateHandler_isNotNull() { assertThat(mUpdateHandler).isNotNull(); } @Test public void testOnDisplayAreaAppeared() { mDisplayAreaOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash); mTestableLooper.processAllMessages(); verify(mMockAnimationController, never()).getAnimator(any(), any(), any()); } Loading @@ -125,17 +124,10 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase { @Test public void testOnDisplayAreaVanished() { mDisplayAreaOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onDisplayAreaVanished(mDisplayAreaInfo); } @Test public void testOnDisplayAreaInfoChanged_updateDisplayAreaInfo() { final DisplayAreaInfo newDisplayAreaInfo = new DisplayAreaInfo(mToken, DEFAULT_DISPLAY, FEATURE_ONE_HANDED); mDisplayAreaOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash); mDisplayAreaOrganizer.onDisplayAreaInfoChanged(newDisplayAreaInfo); assertThat(mDisplayAreaOrganizer.mDisplayAreaMap.containsKey(mDisplayAreaInfo)).isTrue(); assertThat(mDisplayAreaOrganizer.mDisplayAreaMap).isEmpty(); } @Ignore("b/160848002") Loading @@ -143,142 +135,201 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase { public void testScheduleOffset() { final int xOffSet = 0; final int yOffSet = 100; TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash); mDisplayAreaOrganizer.scheduleOffset(xOffSet, yOffSet); mTestableLooper.processAllMessages(); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_OFFSET_ANIMATE)).isEqualTo(true); } @Ignore("b/160848002") @Test public void testRotation_portraitToLandscape() { public void testRotation_portrait_0_to_landscape_90() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 0 -> 90 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_90); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_90, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(true); } @Test public void testRotation_portrait_0_to_seascape_270() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 0 -> 270 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_270); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_270, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(true); } @Test public void testRotation_portrait_180_to_landscape_90() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 180 -> 90 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_90); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_90, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(true); } @Test public void testRotation_portrait_180_to_seascape_270() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 180 -> 270 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_270); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_270, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(true); } @Ignore("b/160848002") @Test public void testRotation_landscapeToPortrait() { public void testRotation_landscape_90_to_portrait_0() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 90 -> 0 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_0); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_0, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(true); } @Test public void testRotation_landscape_90_to_portrait_180() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 90 -> 180 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_180); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_180, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(true); } @Test public void testRotation_Seascape_270_to_portrait_0() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 270 -> 0 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_0); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_0, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(true); } @Test public void testRotation_seascape_90_to_portrait_180() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 270 -> 180 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_180); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_180, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(true); } @Ignore("b/160848002") @Test public void testRotation_portraitToPortrait() { public void testRotation_portrait_0_to_portrait_0() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 0 -> 0 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_0); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_0, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(false); } @Test public void testRotation_portrait_0_to_portrait_180() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 0 -> 180 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_180); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_180, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(false); } @Test public void testRotation_portrait_180_to_portrait_180() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 180 -> 180 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_180); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_180, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(false); } // Rotate 180 -> 180 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_0); @Test public void testRotation_portrait_180_to_portrait_0() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 180 -> 0 mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_0, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(false); } @Ignore("b/160848002") @Test public void testRotation_landscapeToLandscape() { public void testRotation_landscape_90_to_landscape_90() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 90 -> 90 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_90); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_90, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(false); } @Test public void testRotation_landscape_90_to_seascape_270() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 90 -> 270 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_270); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_270, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(false); } @Test public void testRotation_seascape_270_to_seascape_270() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 270 -> 270 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_270); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_270, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(false); } @Test public void testRotation_seascape_90_to_landscape_90() { when(mMockLeash.isValid()).thenReturn(false); // Rotate 270 -> 90 TestableLooper.get(this).processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_90); mTestableLooper.processAllMessages(); mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_90, mMockWindowContainerTransaction); assertThat(mUpdateHandler.hasMessages( OneHandedDisplayAreaOrganizer.MSG_RESET_IMMEDIATE)).isEqualTo(false); Loading
packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java +1 −1 Original line number Diff line number Diff line Loading @@ -419,8 +419,8 @@ public final class WMShell extends SystemUI if (handleLoggingCommand(args, pw)) { return; } // Dump WMShell stuff here if no commands were handled mOneHandedOptional.ifPresent(oneHanded -> oneHanded.dump(pw)); } @Override Loading