summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jason Chang <jasonsfchang@google.com> 2021-01-11 08:44:25 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2021-01-11 08:44:25 +0000
commit21538ffb1082a1c236a76dbf124fbb649a39253a (patch)
tree533866aeb76b233c473ba486d45e9ac27d439d03
parent76b6d14f2957bd007105995e836ca92ecb1d78a5 (diff)
parent7e8e7441eefcd1c9eb38d4674a591431e5b8787c (diff)
Merge "Fix after turning the Dark theme on, users can not clearly identify the screen has entered one handed mode"
-rw-r--r--core/java/android/window/DisplayAreaOrganizer.java8
-rw-r--r--libs/WindowManager/Shell/res/values/config.xml6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedAnimationController.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java201
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java17
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java11
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizerTest.java110
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java5
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java6
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java3
-rw-r--r--services/core/java/com/android/server/wm/DisplayAreaPolicy.java19
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java34
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