diff options
author | 2021-01-11 08:44:25 +0000 | |
---|---|---|
committer | 2021-01-11 08:44:25 +0000 | |
commit | 21538ffb1082a1c236a76dbf124fbb649a39253a (patch) | |
tree | 533866aeb76b233c473ba486d45e9ac27d439d03 | |
parent | 76b6d14f2957bd007105995e836ca92ecb1d78a5 (diff) | |
parent | 7e8e7441eefcd1c9eb38d4674a591431e5b8787c (diff) |
Merge "Fix after turning the Dark theme on, users can not clearly identify the screen has entered one handed mode"
12 files changed, 400 insertions, 22 deletions
diff --git a/core/java/android/window/DisplayAreaOrganizer.java b/core/java/android/window/DisplayAreaOrganizer.java index 1254647379b5..878439906de2 100644 --- a/core/java/android/window/DisplayAreaOrganizer.java +++ b/core/java/android/window/DisplayAreaOrganizer.java @@ -92,6 +92,14 @@ public class DisplayAreaOrganizer extends WindowOrganizer { public static final int FEATURE_IME_PLACEHOLDER = FEATURE_SYSTEM_FIRST + 7; /** + * Display area for one handed background layer, which preventing when user + * turning the Dark theme on, they can not clearly identify the screen has entered + * one handed mode. + * @hide + */ + public static final int FEATURE_ONE_HANDED_BACKGROUND_PANEL = FEATURE_SYSTEM_FIRST + 8; + + /** * The last boundary of display area for system features */ public static final int FEATURE_SYSTEM_LAST = 10_000; diff --git a/libs/WindowManager/Shell/res/values/config.xml b/libs/WindowManager/Shell/res/values/config.xml index 807e5afae890..13f1fddfdfb6 100644 --- a/libs/WindowManager/Shell/res/values/config.xml +++ b/libs/WindowManager/Shell/res/values/config.xml @@ -42,4 +42,10 @@ <!-- Bounds [left top right bottom] on screen for picture-in-picture (PIP) windows, when the PIP menu is shown in center. --> <string translatable="false" name="pip_menu_bounds">"596 280 1324 690"</string> + + <!-- one handed background panel default color RGB --> + <item name="config_one_handed_background_rgb" format="float" type="dimen">0.5</item> + + <!-- one handed background panel default alpha --> + <item name="config_one_handed_background_alpha" format="float" type="dimen">0.5</item> </resources> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedAnimationController.java index 963909621a1b..146f231a8854 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedAnimationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedAnimationController.java @@ -203,7 +203,7 @@ public class OneHandedAnimationController { mSurfaceTransactionHelper = helper; } - OneHandedTransitionAnimator<T> setOneHandedAnimationCallbacks( + OneHandedTransitionAnimator<T> addOneHandedAnimationCallback( OneHandedAnimationCallback callback) { mOneHandedAnimationCallbacks.add(callback); return this; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java new file mode 100644 index 000000000000..a74f4761af0c --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.onehanded; + +import static android.view.Display.DEFAULT_DISPLAY; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.PixelFormat; +import android.graphics.Point; +import android.graphics.Rect; +import android.os.Handler; +import android.util.Log; +import android.view.SurfaceControl; +import android.view.SurfaceSession; +import android.window.DisplayAreaAppearedInfo; +import android.window.DisplayAreaInfo; +import android.window.DisplayAreaOrganizer; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; + +import com.android.internal.annotations.GuardedBy; +import com.android.wm.shell.R; +import com.android.wm.shell.common.DisplayController; + +import java.util.List; +import java.util.concurrent.Executor; + +/** + * Manages OneHanded color background layer areas. + * To avoid when turning the Dark theme on, users can not clearly identify + * the screen has entered one handed mode. + */ +public class OneHandedBackgroundPanelOrganizer extends DisplayAreaOrganizer + implements OneHandedTransitionCallback { + private static final String TAG = "OneHandedBackgroundPanelOrganizer"; + + private final Object mLock = new Object(); + private final SurfaceSession mSurfaceSession = new SurfaceSession(); + private final float[] mColor; + private final float mAlpha; + private final Rect mRect; + private final Handler mHandler; + private final Point mDisplaySize = new Point(); + private final OneHandedSurfaceTransactionHelper.SurfaceControlTransactionFactory + mSurfaceControlTransactionFactory; + + @VisibleForTesting + @GuardedBy("mLock") + boolean mIsShowing; + @Nullable + @GuardedBy("mLock") + private SurfaceControl mBackgroundSurface; + @Nullable + @GuardedBy("mLock") + private SurfaceControl mParentLeash; + + private final OneHandedAnimationCallback mOneHandedAnimationCallback = + new OneHandedAnimationCallback() { + @Override + public void onOneHandedAnimationStart( + OneHandedAnimationController.OneHandedTransitionAnimator animator) { + mHandler.post(() -> showBackgroundPanelLayer()); + } + }; + + @Override + public void onStopFinished(Rect bounds) { + mHandler.post(() -> removeBackgroundPanelLayer()); + } + + public OneHandedBackgroundPanelOrganizer(Context context, DisplayController displayController, + Executor executor) { + super(executor); + displayController.getDisplay(DEFAULT_DISPLAY).getRealSize(mDisplaySize); + final Resources res = context.getResources(); + final float defaultRGB = res.getFloat(R.dimen.config_one_handed_background_rgb); + mColor = new float[]{defaultRGB, defaultRGB, defaultRGB}; + mAlpha = res.getFloat(R.dimen.config_one_handed_background_alpha); + mRect = new Rect(0, 0, mDisplaySize.x, mDisplaySize.y); + mHandler = new Handler(); + mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new; + } + + @Override + public void onDisplayAreaAppeared(@NonNull DisplayAreaInfo displayAreaInfo, + @NonNull SurfaceControl leash) { + synchronized (mLock) { + if (mParentLeash == null) { + mParentLeash = leash; + } else { + throw new RuntimeException("There should be only one DisplayArea for " + + "the one-handed mode background panel"); + } + } + } + + OneHandedAnimationCallback getOneHandedAnimationCallback() { + return mOneHandedAnimationCallback; + } + + @Override + public List<DisplayAreaAppearedInfo> registerOrganizer(int displayAreaFeature) { + synchronized (mLock) { + final List<DisplayAreaAppearedInfo> displayAreaInfos; + displayAreaInfos = super.registerOrganizer(displayAreaFeature); + for (int i = 0; i < displayAreaInfos.size(); i++) { + final DisplayAreaAppearedInfo info = displayAreaInfos.get(i); + onDisplayAreaAppeared(info.getDisplayAreaInfo(), info.getLeash()); + } + return displayAreaInfos; + } + } + + @Override + public void unregisterOrganizer() { + synchronized (mLock) { + super.unregisterOrganizer(); + mParentLeash = null; + } + } + + @Nullable + @VisibleForTesting + SurfaceControl getBackgroundSurface() { + synchronized (mLock) { + if (mParentLeash == null) { + return null; + } + + if (mBackgroundSurface == null) { + mBackgroundSurface = new SurfaceControl.Builder(mSurfaceSession) + .setParent(mParentLeash) + .setColorLayer() + .setFormat(PixelFormat.RGBA_8888) + .setOpaque(false) + .setName("one-handed-background-panel") + .setCallsite("OneHandedBackgroundPanelOrganizer") + .build(); + } + return mBackgroundSurface; + } + } + + @VisibleForTesting + void showBackgroundPanelLayer() { + synchronized (mLock) { + if (mIsShowing) { + return; + } + + if (getBackgroundSurface() == null) { + Log.w(TAG, "mBackgroundSurface is null !"); + return; + } + + SurfaceControl.Transaction transaction = + mSurfaceControlTransactionFactory.getTransaction(); + transaction.setLayer(mBackgroundSurface, -1 /* at bottom-most layer */) + .setColor(mBackgroundSurface, mColor) + .setAlpha(mBackgroundSurface, mAlpha) + .show(mBackgroundSurface) + .apply(); + transaction.close(); + mIsShowing = true; + } + } + + @VisibleForTesting + void removeBackgroundPanelLayer() { + synchronized (mLock) { + if (mBackgroundSurface == null) { + return; + } + + SurfaceControl.Transaction transaction = + mSurfaceControlTransactionFactory.getTransaction(); + transaction.remove(mBackgroundSurface); + transaction.apply(); + transaction.close(); + mBackgroundSurface = null; + mIsShowing = false; + } + } +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java index 69d8db20d110..00605d872e39 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java @@ -77,6 +77,7 @@ public class OneHandedController implements OneHanded { private OneHandedDisplayAreaOrganizer mDisplayAreaOrganizer; private final AccessibilityManager mAccessibilityManager; + private OneHandedBackgroundPanelOrganizer mBackgroundPanelOrganizer; /** * Handle rotation based on OnDisplayChangingListener callback @@ -204,17 +205,22 @@ public class OneHandedController implements OneHanded { OneHandedTouchHandler touchHandler = new OneHandedTouchHandler(); OneHandedGestureHandler gestureHandler = new OneHandedGestureHandler( context, displayController); + OneHandedBackgroundPanelOrganizer oneHandedBackgroundPanelOrganizer = + new OneHandedBackgroundPanelOrganizer(context, displayController, executor); OneHandedDisplayAreaOrganizer organizer = new OneHandedDisplayAreaOrganizer( - context, displayController, animationController, tutorialHandler, executor); + context, displayController, animationController, tutorialHandler, executor, + oneHandedBackgroundPanelOrganizer); IOverlayManager overlayManager = IOverlayManager.Stub.asInterface( ServiceManager.getService(Context.OVERLAY_SERVICE)); - return new OneHandedController(context, displayController, organizer, touchHandler, - tutorialHandler, gestureHandler, overlayManager, taskStackListener); + return new OneHandedController(context, displayController, + oneHandedBackgroundPanelOrganizer, organizer, touchHandler, tutorialHandler, + gestureHandler, overlayManager, taskStackListener); } @VisibleForTesting OneHandedController(Context context, DisplayController displayController, + OneHandedBackgroundPanelOrganizer backgroundPanelOrganizer, OneHandedDisplayAreaOrganizer displayAreaOrganizer, OneHandedTouchHandler touchHandler, OneHandedTutorialHandler tutorialHandler, @@ -222,6 +228,7 @@ public class OneHandedController implements OneHanded { IOverlayManager overlayManager, TaskStackListenerImpl taskStackListener) { mContext = context; + mBackgroundPanelOrganizer = backgroundPanelOrganizer; mDisplayAreaOrganizer = displayAreaOrganizer; mDisplayController = displayController; mTouchHandler = touchHandler; @@ -355,6 +362,7 @@ public class OneHandedController implements OneHanded { mDisplayAreaOrganizer.registerTransitionCallback(mTouchHandler); mDisplayAreaOrganizer.registerTransitionCallback(mGestureHandler); mDisplayAreaOrganizer.registerTransitionCallback(mTutorialHandler); + mDisplayAreaOrganizer.registerTransitionCallback(mBackgroundPanelOrganizer); } private void setupSettingObservers() { @@ -405,9 +413,12 @@ public class OneHandedController implements OneHanded { } // TODO Be aware to unregisterOrganizer() after animation finished mDisplayAreaOrganizer.unregisterOrganizer(); + mBackgroundPanelOrganizer.unregisterOrganizer(); if (mIsOneHandedEnabled) { mDisplayAreaOrganizer.registerOrganizer( OneHandedDisplayAreaOrganizer.FEATURE_ONE_HANDED); + mBackgroundPanelOrganizer.registerOrganizer( + OneHandedBackgroundPanelOrganizer.FEATURE_ONE_HANDED_BACKGROUND_PANEL); } mTouchHandler.onOneHandedEnabled(mIsOneHandedEnabled); mGestureHandler.onOneHandedEnabled(mIsOneHandedEnabled || mIsSwipeToNotificationEnabled); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java index 7fb1faa60a6f..7873318fc82d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java @@ -86,6 +86,7 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer { mSurfaceControlTransactionFactory; private OneHandedTutorialHandler mTutorialHandler; private List<OneHandedTransitionCallback> mTransitionCallbacks = new ArrayList<>(); + private OneHandedBackgroundPanelOrganizer mBackgroundPanelOrganizer; @VisibleForTesting OneHandedAnimationCallback mOneHandedAnimationCallback = @@ -152,7 +153,8 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer { public OneHandedDisplayAreaOrganizer(Context context, DisplayController displayController, OneHandedAnimationController animationController, - OneHandedTutorialHandler tutorialHandler, Executor executor) { + OneHandedTutorialHandler tutorialHandler, Executor executor, + OneHandedBackgroundPanelOrganizer oneHandedBackgroundGradientOrganizer) { super(executor); mUpdateHandler = new Handler(OneHandedThread.get().getLooper(), mUpdateCallback); mAnimationController = animationController; @@ -166,6 +168,7 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer { animationDurationConfig); mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new; mTutorialHandler = tutorialHandler; + mBackgroundPanelOrganizer = oneHandedBackgroundGradientOrganizer; } @Override @@ -300,8 +303,10 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer { mAnimationController.getAnimator(leash, fromBounds, toBounds); if (animator != null) { animator.setTransitionDirection(direction) - .setOneHandedAnimationCallbacks(mOneHandedAnimationCallback) - .setOneHandedAnimationCallbacks(mTutorialHandler.getAnimationCallback()) + .addOneHandedAnimationCallback(mOneHandedAnimationCallback) + .addOneHandedAnimationCallback(mTutorialHandler.getAnimationCallback()) + .addOneHandedAnimationCallback( + mBackgroundPanelOrganizer.getOneHandedAnimationCallback()) .setDuration(durationMs) .start(); } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizerTest.java new file mode 100644 index 000000000000..e9c4af12a0d6 --- /dev/null +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizerTest.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.onehanded; + +import static android.view.Display.DEFAULT_DISPLAY; +import static android.window.DisplayAreaOrganizer.FEATURE_ONE_HANDED_BACKGROUND_PANEL; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.when; + +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; +import android.view.Display; +import android.view.SurfaceControl; +import android.window.DisplayAreaInfo; +import android.window.IWindowContainerToken; +import android.window.WindowContainerToken; + +import androidx.test.filters.SmallTest; + +import com.android.wm.shell.common.DisplayController; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper +public class OneHandedBackgroundPanelOrganizerTest extends OneHandedTestCase { + private DisplayAreaInfo mDisplayAreaInfo; + private Display mDisplay; + private OneHandedBackgroundPanelOrganizer mBackgroundPanelOrganizer; + private WindowContainerToken mToken; + private SurfaceControl mLeash; + private TestableLooper mTestableLooper; + + @Mock + IWindowContainerToken mMockRealToken; + @Mock + DisplayController mMockDisplayController; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + mTestableLooper = TestableLooper.get(this); + mToken = new WindowContainerToken(mMockRealToken); + mLeash = new SurfaceControl(); + mDisplay = mContext.getDisplay(); + when(mMockDisplayController.getDisplay(anyInt())).thenReturn(mDisplay); + mDisplayAreaInfo = new DisplayAreaInfo(mToken, DEFAULT_DISPLAY, + FEATURE_ONE_HANDED_BACKGROUND_PANEL); + + mBackgroundPanelOrganizer = new OneHandedBackgroundPanelOrganizer(mContext, + mMockDisplayController, Runnable::run); + } + + @Test + public void testOnDisplayAreaAppeared() { + mBackgroundPanelOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash); + mTestableLooper.processAllMessages(); + + assertThat(mBackgroundPanelOrganizer.getBackgroundSurface()).isNotNull(); + } + + @Test + public void testUnregisterOrganizer() { + mBackgroundPanelOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash); + mTestableLooper.processAllMessages(); + mBackgroundPanelOrganizer.unregisterOrganizer(); + + assertThat(mBackgroundPanelOrganizer.getBackgroundSurface()).isNull(); + } + + @Test + public void testShowBackgroundLayer() { + mBackgroundPanelOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash); + mBackgroundPanelOrganizer.showBackgroundPanelLayer(); + mTestableLooper.processAllMessages(); + + assertThat(mBackgroundPanelOrganizer.mIsShowing).isTrue(); + } + + @Test + public void testRemoveBackgroundLayer() { + mBackgroundPanelOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash); + mBackgroundPanelOrganizer.removeBackgroundPanelLayer(); + mTestableLooper.processAllMessages(); + + assertThat(mBackgroundPanelOrganizer.mIsShowing).isFalse(); + } +} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java index e37e1548775a..20184bfd5541 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java @@ -54,6 +54,8 @@ public class OneHandedControllerTest extends OneHandedTestCase { @Mock DisplayController mMockDisplayController; @Mock + OneHandedBackgroundPanelOrganizer mMockBackgroundOrganizer; + @Mock OneHandedDisplayAreaOrganizer mMockDisplayAreaOrganizer; @Mock OneHandedTouchHandler mMockTouchHandler; @@ -75,6 +77,7 @@ public class OneHandedControllerTest extends OneHandedTestCase { OneHandedController oneHandedController = new OneHandedController( mContext, mMockDisplayController, + mMockBackgroundOrganizer, mMockDisplayAreaOrganizer, mMockTouchHandler, mMockTutorialHandler, @@ -94,7 +97,7 @@ public class OneHandedControllerTest extends OneHandedTestCase { mContext); OneHandedDisplayAreaOrganizer displayAreaOrganizer = new OneHandedDisplayAreaOrganizer( mContext, mMockDisplayController, animationController, mMockTutorialHandler, - Runnable::run); + Runnable::run, mMockBackgroundOrganizer); assertThat(displayAreaOrganizer.isInOneHanded()).isFalse(); } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java index 5d742b3531b9..3d9fad9097f8 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java @@ -80,6 +80,8 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase { SurfaceControl mMockLeash; @Mock WindowContainerTransaction mMockWindowContainerTransaction; + @Mock + OneHandedBackgroundPanelOrganizer mMockBackgroundOrganizer; Handler mSpyUpdateHandler; Handler.Callback mUpdateCallback = (msg) -> false; @@ -103,7 +105,7 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase { mMockSurfaceTransactionHelper); when(mMockAnimator.isRunning()).thenReturn(true); when(mMockAnimator.setDuration(anyInt())).thenReturn(mFakeAnimator); - when(mMockAnimator.setOneHandedAnimationCallbacks(any())).thenReturn(mFakeAnimator); + when(mMockAnimator.addOneHandedAnimationCallback(any())).thenReturn(mFakeAnimator); when(mMockAnimator.setTransitionDirection(anyInt())).thenReturn(mFakeAnimator); when(mMockLeash.getWidth()).thenReturn(DISPLAY_WIDTH); when(mMockLeash.getHeight()).thenReturn(DISPLAY_HEIGHT); @@ -112,7 +114,7 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase { mMockDisplayController, mMockAnimationController, mTutorialHandler, - Runnable::run); + Runnable::run, mMockBackgroundOrganizer); mSpyUpdateHandler = spy(new Handler(OneHandedThread.get().getLooper(), mUpdateCallback)); mDisplayAreaOrganizer.setUpdateHandler(mSpyUpdateHandler); } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java index ba8c737924f4..b187dc981bf8 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java @@ -45,6 +45,8 @@ public class OneHandedTutorialHandlerTest extends OneHandedTestCase { @Mock DisplayController mMockDisplayController; @Mock + OneHandedBackgroundPanelOrganizer mMockBackgroundOrganizer; + @Mock OneHandedDisplayAreaOrganizer mMockDisplayAreaOrganizer; @Mock IOverlayManager mMockOverlayManager; @@ -59,6 +61,7 @@ public class OneHandedTutorialHandlerTest extends OneHandedTestCase { mOneHandedController = new OneHandedController( getContext(), mMockDisplayController, + mMockBackgroundOrganizer, mMockDisplayAreaOrganizer, mTouchHandler, mTutorialHandler, diff --git a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java index 5952164d6554..eeb7fac30944 100644 --- a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java @@ -24,11 +24,13 @@ import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; +import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER; import static android.window.DisplayAreaOrganizer.FEATURE_FULLSCREEN_MAGNIFICATION; import static android.window.DisplayAreaOrganizer.FEATURE_HIDE_DISPLAY_CUTOUT; import static android.window.DisplayAreaOrganizer.FEATURE_IME_PLACEHOLDER; import static android.window.DisplayAreaOrganizer.FEATURE_ONE_HANDED; +import static android.window.DisplayAreaOrganizer.FEATURE_ONE_HANDED_BACKGROUND_PANEL; import static android.window.DisplayAreaOrganizer.FEATURE_WINDOWED_MAGNIFICATION; import static com.android.server.wm.DisplayAreaPolicyBuilder.Feature; @@ -131,14 +133,19 @@ public abstract class DisplayAreaPolicy { .all() .except(TYPE_NAVIGATION_BAR, TYPE_NAVIGATION_BAR_PANEL, TYPE_STATUS_BAR, TYPE_NOTIFICATION_SHADE) - .build()); + .build()) + .addFeature(new Feature.Builder(wmService.mPolicy, + "OneHandedBackgroundPanel", + FEATURE_ONE_HANDED_BACKGROUND_PANEL) + .upTo(TYPE_WALLPAPER) + .build()) + .addFeature(new Feature.Builder(wmService.mPolicy, "OneHanded", + FEATURE_ONE_HANDED) + .all() + .except(TYPE_NAVIGATION_BAR, TYPE_NAVIGATION_BAR_PANEL) + .build()); } rootHierarchy - .addFeature(new Feature.Builder(wmService.mPolicy, "OneHanded", - FEATURE_ONE_HANDED) - .all() - .except(TYPE_NAVIGATION_BAR, TYPE_NAVIGATION_BAR_PANEL) - .build()) .addFeature(new Feature.Builder(wmService.mPolicy, "FullscreenMagnification", FEATURE_FULLSCREEN_MAGNIFICATION) .all() diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java index 3306e313f95e..2f4c8e256760 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java @@ -15,7 +15,6 @@ */ package com.android.server.wm; - import static android.os.Process.INVALID_UID; import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; @@ -31,6 +30,7 @@ import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER import static android.window.DisplayAreaOrganizer.FEATURE_FULLSCREEN_MAGNIFICATION; import static android.window.DisplayAreaOrganizer.FEATURE_IME_PLACEHOLDER; import static android.window.DisplayAreaOrganizer.FEATURE_ONE_HANDED; +import static android.window.DisplayAreaOrganizer.FEATURE_ONE_HANDED_BACKGROUND_PANEL; import static android.window.DisplayAreaOrganizer.FEATURE_ROOT; import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST; import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_LAST; @@ -103,6 +103,7 @@ public class DisplayAreaPolicyBuilderTest { mImeContainer = new DisplayArea.Tokens(mWms, ABOVE_TASKS, "ImeContainer"); mDisplayContent = mock(DisplayContent.class); doReturn(true).when(mDisplayContent).isTrusted(); + mDisplayContent.isDefaultDisplay = true; mDefaultTaskDisplayArea = new TaskDisplayArea(mDisplayContent, mWms, "Tasks", FEATURE_DEFAULT_TASK_CONTAINER); mTaskDisplayAreaList = new ArrayList<>(); @@ -183,13 +184,34 @@ public class DisplayAreaPolicyBuilderTest { final DisplayAreaPolicyBuilder.Result defaultPolicy = (DisplayAreaPolicyBuilder.Result) defaultProvider.instantiate(mWms, mDisplayContent, mRoot, mImeContainer); - final List<Feature> features = defaultPolicy.getFeatures(); - boolean hasOneHandedFeature = false; - for (int i = 0; i < features.size(); i++) { - hasOneHandedFeature |= features.get(i).getId() == FEATURE_ONE_HANDED; + if (mDisplayContent.isDefaultDisplay) { + final List<Feature> features = defaultPolicy.getFeatures(); + boolean hasOneHandedFeature = false; + for (Feature feature : features) { + hasOneHandedFeature |= feature.getId() == FEATURE_ONE_HANDED; + } + + assertThat(hasOneHandedFeature).isTrue(); } + } + + @Test + public void testBuilder_defaultPolicy_hasOneHandedBackgroundFeature() { + final DisplayAreaPolicy.Provider defaultProvider = DisplayAreaPolicy.Provider.fromResources( + resourcesWithProvider("")); + final DisplayAreaPolicyBuilder.Result defaultPolicy = + (DisplayAreaPolicyBuilder.Result) defaultProvider.instantiate(mWms, mDisplayContent, + mRoot, mImeContainer); + if (mDisplayContent.isDefaultDisplay) { + final List<Feature> features = defaultPolicy.getFeatures(); + boolean hasOneHandedBackgroundFeature = false; + for (Feature feature : features) { + hasOneHandedBackgroundFeature |= + feature.getId() == FEATURE_ONE_HANDED_BACKGROUND_PANEL; + } - assertThat(hasOneHandedFeature).isTrue(); + assertThat(hasOneHandedBackgroundFeature).isTrue(); + } } @Test |