diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java
index 616e56288392e..3def945dd03c5 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java
@@ -28,7 +28,6 @@ import com.android.systemui.car.window.SystemUIOverlayWindowManager;
import com.android.systemui.globalactions.GlobalActionsComponent;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.dagger.KeyguardModule;
-import com.android.systemui.onehanded.OneHandedUI;
import com.android.systemui.power.PowerUI;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsModule;
@@ -94,12 +93,6 @@ public abstract class CarSystemUIBinder {
@ClassKey(LatencyTester.class)
public abstract SystemUI bindLatencyTester(LatencyTester sysui);
- /** Inject into OneHandedUI. */
- @Binds
- @IntoMap
- @ClassKey(OneHandedUI.class)
- public abstract SystemUI bindOneHandedUI(OneHandedUI sysui);
-
/** Inject into PowerUI. */
@Binds
@IntoMap
diff --git a/packages/SystemUI/README.md b/packages/SystemUI/README.md
index bd93c396aa163..ee8d02301d5d3 100644
--- a/packages/SystemUI/README.md
+++ b/packages/SystemUI/README.md
@@ -111,10 +111,6 @@ Plays ringtones.
Shows UI for keyboard shortcuts (triggered by keyboard shortcut).
-### [com.android.systemui.onehanded.OneHandedUI](/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedUI.java)
-
-Shows the overlay controls when One handed is triggered.
-
### [com.android.systemui.shortcut.ShortcutKeyDispatcher](/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java)
Dispatches shortcut to System UI components.
diff --git a/packages/SystemUI/res/values-television/config.xml b/packages/SystemUI/res/values-television/config.xml
index 4a94038f4533a..66304013da460 100644
--- a/packages/SystemUI/res/values-television/config.xml
+++ b/packages/SystemUI/res/values-television/config.xml
@@ -39,7 +39,6 @@
- com.android.systemui.SizeCompatModeActivityController
- com.android.systemui.statusbar.notification.InstantAppNotifier
- com.android.systemui.toast.ToastUI
- - com.android.systemui.onehanded.OneHandedUI
- com.android.systemui.wmshell.WMShell
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 7faa2a44bb6cc..0cc0dfd19fdfe 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -320,7 +320,6 @@
- com.android.systemui.accessibility.WindowMagnification
- com.android.systemui.accessibility.SystemActions
- com.android.systemui.toast.ToastUI
- - com.android.systemui.onehanded.OneHandedUI
- com.android.systemui.wmshell.WMShell
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
index c331bd377eecc..3a5ce4d82540e 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
@@ -28,7 +28,6 @@ import com.android.systemui.bubbles.dagger.BubbleModule;
import com.android.systemui.globalactions.GlobalActionsComponent;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.dagger.KeyguardModule;
-import com.android.systemui.onehanded.OneHandedUI;
import com.android.systemui.power.PowerUI;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsModule;
@@ -90,12 +89,6 @@ public abstract class SystemUIBinder {
@ClassKey(LatencyTester.class)
public abstract SystemUI bindLatencyTester(LatencyTester sysui);
- /** Inject into OneHandedUI. */
- @Binds
- @IntoMap
- @ClassKey(OneHandedUI.class)
- public abstract SystemUI bindOneHandedUI(OneHandedUI sysui);
-
/** Inject into PowerUI. */
@Binds
@IntoMap
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHanded.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHanded.java
new file mode 100644
index 0000000000000..b7c6262b07e0b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHanded.java
@@ -0,0 +1,80 @@
+/*
+ * 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.systemui.onehanded;
+
+import androidx.annotation.NonNull;
+
+import com.android.systemui.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback;
+
+import java.io.PrintWriter;
+
+/**
+ * Interface to engage one handed feature.
+ */
+public interface OneHanded {
+ /**
+ * Return whether the device has one handed feature or not.
+ */
+ boolean hasOneHandedFeature();
+
+ /**
+ * Return one handed settings enabled or not.
+ */
+ boolean isOneHandedEnabled();
+
+ /**
+ * Return swipe to notification settings enabled or not.
+ */
+ boolean isSwipeToNotificationEnabled();
+
+ /**
+ * Enters one handed mode.
+ */
+ void startOneHanded();
+
+ /**
+ * Exits one handed mode.
+ */
+ void stopOneHanded();
+
+ /**
+ * Exits one handed mode with {@link OneHandedEvents}.
+ */
+ void stopOneHanded(int event);
+
+ /**
+ * Set navigation 3 button mode enabled or disabled by users.
+ */
+ void setThreeButtonModeEnabled(boolean enabled);
+
+ /**
+ * Register callback to be notified after {@link OneHandedDisplayAreaOrganizer}
+ * transition start or finish
+ */
+ void registerTransitionCallback(OneHandedTransitionCallback callback);
+
+ /**
+ * Register callback for one handed gesture, this gesture callbcak will be activated on
+ * 3 button navigation mode only
+ */
+ void registerGestureCallback(OneHandedGestureEventCallback callback);
+
+ /**
+ * Dump one handed status.
+ */
+ void dump(@NonNull PrintWriter pw);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedController.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedController.java
index bb59449d114da..90adf838440c9 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedController.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedController.java
@@ -16,82 +16,61 @@
package com.android.systemui.onehanded;
+import static android.os.UserHandle.USER_CURRENT;
import static android.view.Display.DEFAULT_DISPLAY;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ONE_HANDED_ACTIVE;
-
-import android.content.ComponentName;
import android.content.Context;
+import android.content.om.IOverlayManager;
+import android.content.om.OverlayInfo;
+import android.database.ContentObserver;
import android.graphics.Point;
-import android.graphics.Rect;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.SystemProperties;
-import android.view.KeyEvent;
+import android.provider.Settings;
+import android.util.Log;
import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Dumpable;
-import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.model.SysUiState;
-import com.android.systemui.navigationbar.NavigationModeController;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.TaskStackChangeListener;
-import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback;
import com.android.wm.shell.common.DisplayChangeController;
import com.android.wm.shell.common.DisplayController;
-import java.io.FileDescriptor;
import java.io.PrintWriter;
-import javax.inject.Inject;
-
/**
* Manages and manipulates the one handed states, transitions, and gesture for phones.
*/
-@SysUISingleton
-public class OneHandedController implements Dumpable {
- private static final String TAG = "OneHandedManager";
+public class OneHandedController implements OneHanded {
+ private static final String TAG = "OneHandedController";
+
private static final String ONE_HANDED_MODE_OFFSET_PERCENTAGE =
"persist.debug.one_handed_offset_percentage";
+ private static final String ONE_HANDED_MODE_GESTURAL_OVERLAY =
+ "com.android.internal.systemui.onehanded.gestural";
+ static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode";
+
+ private final boolean mHasOneHandedFeature;
private boolean mIsOneHandedEnabled;
private boolean mIsSwipeToNotificationEnabled;
private boolean mTaskChangeToExit;
private float mOffSetFraction;
- private final CommandQueue mCommandQueue;
+ private final Context mContext;
private final DisplayController mDisplayController;
private final OneHandedGestureHandler mGestureHandler;
private final OneHandedTimeoutHandler mTimeoutHandler;
private final OneHandedTouchHandler mTouchHandler;
private final OneHandedTutorialHandler mTutorialHandler;
- private final SysUiState mSysUiFlagContainer;
+ private final IOverlayManager mOverlayManager;
+ private final Handler mMainHandler = new Handler(Looper.getMainLooper());
private OneHandedDisplayAreaOrganizer mDisplayAreaOrganizer;
- /**
- * Handler for system task stack changes, exit when user lunch new task or bring task to front
- */
- private final TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
- @Override
- public void onTaskCreated(int taskId, ComponentName componentName) {
- if (!mIsOneHandedEnabled || !mDisplayAreaOrganizer.isInOneHanded()) {
- return;
- }
- OneHandedEvents.writeEvent(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_APP_TAPS_OUT);
- stopOneHanded();
- }
-
- @Override
- public void onTaskMovedToFront(int taskId) {
- if (!mIsOneHandedEnabled || !mDisplayAreaOrganizer.isInOneHanded()) {
- return;
- }
- OneHandedEvents.writeEvent(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_APP_TAPS_OUT);
- stopOneHanded();
- }
- };
-
/**
* Handle rotation based on OnDisplayChangingListener callback
*/
@@ -102,109 +81,197 @@ public class OneHandedController implements Dumpable {
}
};
- /**
- * Constructor of OneHandedManager
- */
- @Inject
- public OneHandedController(Context context,
- CommandQueue commandQueue,
- DisplayController displayController,
- NavigationModeController navigationModeController,
- SysUiState sysUiState) {
- mCommandQueue = commandQueue;
- mDisplayController = displayController;
- mDisplayController.addDisplayChangingController(mRotationController);
- mSysUiFlagContainer = sysUiState;
- mOffSetFraction = SystemProperties.getInt(ONE_HANDED_MODE_OFFSET_PERCENTAGE, 50) / 100.0f;
+ private final ContentObserver mEnabledObserver = new ContentObserver(mMainHandler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ final boolean enabled = OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
+ mContext.getContentResolver());
+ OneHandedEvents.writeEvent(enabled
+ ? OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_ENABLED_ON
+ : OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_ENABLED_OFF);
- mIsOneHandedEnabled = OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
- context.getContentResolver());
- mIsSwipeToNotificationEnabled = OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
- context.getContentResolver());
- mTimeoutHandler = OneHandedTimeoutHandler.get();
- mTouchHandler = new OneHandedTouchHandler();
- mTutorialHandler = new OneHandedTutorialHandler(context);
- mDisplayAreaOrganizer = new OneHandedDisplayAreaOrganizer(context, displayController,
- new OneHandedAnimationController(context), mTutorialHandler);
- mGestureHandler = new OneHandedGestureHandler(
- context, displayController, navigationModeController);
- updateOneHandedEnabled();
- setupGestures();
+ setOneHandedEnabled(enabled);
+
+ // Also checks swipe to notification settings since they all need gesture overlay.
+ setEnabledGesturalOverlay(
+ enabled || OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
+ mContext.getContentResolver()));
+ }
+ };
+
+ private final ContentObserver mTimeoutObserver = new ContentObserver(mMainHandler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ final int newTimeout = OneHandedSettingsUtil.getSettingsOneHandedModeTimeout(
+ mContext.getContentResolver());
+ int metricsId = OneHandedEvents.OneHandedSettingsTogglesEvent.INVALID.getId();
+ switch (newTimeout) {
+ case OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_NEVER:
+ metricsId = OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_TIMEOUT_SECONDS_NEVER;
+ break;
+ case OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_SHORT_IN_SECONDS:
+ metricsId = OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_TIMEOUT_SECONDS_4;
+ break;
+ case OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS:
+ metricsId = OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_TIMEOUT_SECONDS_8;
+ break;
+ case OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_LONG_IN_SECONDS:
+ metricsId = OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_TIMEOUT_SECONDS_12;
+ break;
+ default:
+ // do nothing
+ break;
+ }
+ OneHandedEvents.writeEvent(metricsId);
+
+ if (mTimeoutHandler != null) {
+ mTimeoutHandler.setTimeout(newTimeout);
+ }
+ }
+ };
+
+ private final ContentObserver mTaskChangeExitObserver = new ContentObserver(mMainHandler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ final boolean enabled = OneHandedSettingsUtil.getSettingsTapsAppToExit(
+ mContext.getContentResolver());
+ OneHandedEvents.writeEvent(enabled
+ ? OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_APP_TAPS_EXIT_ON
+ : OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_APP_TAPS_EXIT_OFF);
+
+ setTaskChangeToExit(enabled);
+ }
+ };
+
+ private final ContentObserver mSwipeToNotificationEnabledObserver =
+ new ContentObserver(mMainHandler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ final boolean enabled =
+ OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
+ mContext.getContentResolver());
+ setSwipeToNotificationEnabled(enabled);
+
+ // Also checks one handed mode settings since they all need gesture overlay.
+ setEnabledGesturalOverlay(
+ enabled || OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
+ mContext.getContentResolver()));
+ }
+ };
+
+ /**
+ * The static constructor method to create OneHnadedController.
+ */
+ public static OneHandedController create(
+ Context context, DisplayController displayController) {
+ OneHandedTutorialHandler tutorialHandler = new OneHandedTutorialHandler(context);
+ OneHandedAnimationController animationController =
+ new OneHandedAnimationController(context);
+ OneHandedTouchHandler touchHandler = new OneHandedTouchHandler();
+ OneHandedGestureHandler gestureHandler = new OneHandedGestureHandler(
+ context, displayController);
+ OneHandedDisplayAreaOrganizer organizer = new OneHandedDisplayAreaOrganizer(
+ context, displayController, animationController, tutorialHandler);
+ return new OneHandedController(context, displayController, organizer, touchHandler,
+ tutorialHandler, gestureHandler);
}
- /**
- * Constructor of OneHandedManager for testing
- */
- // TODO(b/161980408): Should remove extra constructor.
@VisibleForTesting
OneHandedController(Context context,
- CommandQueue commandQueue,
DisplayController displayController,
OneHandedDisplayAreaOrganizer displayAreaOrganizer,
OneHandedTouchHandler touchHandler,
OneHandedTutorialHandler tutorialHandler,
- OneHandedGestureHandler gestureHandler,
- SysUiState sysUiState) {
- mCommandQueue = commandQueue;
+ OneHandedGestureHandler gestureHandler) {
+ mHasOneHandedFeature = SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false);
+ if (!mHasOneHandedFeature) {
+ Log.i(TAG, "Device config SUPPORT_ONE_HANDED_MODE off");
+ mContext = null;
+ mDisplayAreaOrganizer = null;
+ mDisplayController = null;
+ mTouchHandler = null;
+ mTutorialHandler = null;
+ mGestureHandler = null;
+ mTimeoutHandler = null;
+ mOverlayManager = null;
+ return;
+ }
+
+ mContext = context;
mDisplayAreaOrganizer = displayAreaOrganizer;
mDisplayController = displayController;
- mDisplayController.addDisplayChangingController(mRotationController);
- mSysUiFlagContainer = sysUiState;
- mOffSetFraction = SystemProperties.getInt(ONE_HANDED_MODE_OFFSET_PERCENTAGE, 50) / 100.0f;
+ mTouchHandler = touchHandler;
+ mTutorialHandler = tutorialHandler;
+ mGestureHandler = gestureHandler;
+ mOverlayManager = IOverlayManager.Stub.asInterface(
+ ServiceManager.getService(Context.OVERLAY_SERVICE));
+ mOffSetFraction = SystemProperties.getInt(ONE_HANDED_MODE_OFFSET_PERCENTAGE, 50) / 100.0f;
mIsOneHandedEnabled = OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
context.getContentResolver());
mIsSwipeToNotificationEnabled = OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
context.getContentResolver());
mTimeoutHandler = OneHandedTimeoutHandler.get();
- mTouchHandler = touchHandler;
- mTutorialHandler = tutorialHandler;
- mGestureHandler = gestureHandler;
- updateOneHandedEnabled();
- setupGestures();
+
+ mDisplayController.addDisplayChangingController(mRotationController);
+
+ setupCallback();
+ setupSettingObservers();
+ setupTimeoutListener();
+ setupGesturalOverlay();
+ updateSettings();
}
/**
- * Set one handed enabled or disabled by OneHanded UI when user update settings
+ * Set one handed enabled or disabled when user update settings
*/
- public void setOneHandedEnabled(boolean enabled) {
+ void setOneHandedEnabled(boolean enabled) {
mIsOneHandedEnabled = enabled;
updateOneHandedEnabled();
}
/**
- * Set one handed enabled or disabled by OneHanded UI when user update settings
+ * Set one handed enabled or disabled by when user update settings
*/
- public void setTaskChangeToExit(boolean enabled) {
- if (mTaskChangeToExit == enabled) {
- return;
- }
+ void setTaskChangeToExit(boolean enabled) {
mTaskChangeToExit = enabled;
- updateOneHandedEnabled();
}
/**
* Sets whether to enable swipe bottom to notification gesture when user update settings.
*/
- public void setSwipeToNotificationEnabled(boolean enabled) {
+ void setSwipeToNotificationEnabled(boolean enabled) {
mIsSwipeToNotificationEnabled = enabled;
updateOneHandedEnabled();
}
- /**
- * Enters one handed mode.
- */
+ @Override
+ public boolean hasOneHandedFeature() {
+ return mHasOneHandedFeature;
+ }
+
+ @Override
+ public boolean isOneHandedEnabled() {
+ return mIsOneHandedEnabled;
+ }
+
+ @Override
+ public boolean isSwipeToNotificationEnabled() {
+ return mIsSwipeToNotificationEnabled;
+ }
+
+ @Override
public void startOneHanded() {
if (!mDisplayAreaOrganizer.isInOneHanded()) {
final int yOffSet = Math.round(getDisplaySize().y * mOffSetFraction);
mDisplayAreaOrganizer.scheduleOffset(0, yOffSet);
mTimeoutHandler.resetTimer();
+
+ OneHandedEvents.writeEvent(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_GESTURE_IN);
}
}
- /**
- * Exits one handed mode.
- */
+ @Override
public void stopOneHanded() {
if (mDisplayAreaOrganizer.isInOneHanded()) {
mDisplayAreaOrganizer.scheduleOffset(0, 0);
@@ -212,64 +279,72 @@ public class OneHandedController implements Dumpable {
}
}
- private void setupGestures() {
- mTouchHandler.registerTouchEventListener(
- new OneHandedTouchHandler.OneHandedTouchEventCallback() {
- @Override
- public void onStart() {
- if (mIsOneHandedEnabled) {
- startOneHanded();
- }
- }
+ @Override
+ public void stopOneHanded(int event) {
+ if (!mTaskChangeToExit && event == OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_APP_TAPS_OUT) {
+ //Task change exit not enable, do nothing and return here.
+ return;
+ }
- @Override
- public void onStop() {
- if (mIsOneHandedEnabled) {
- stopOneHanded();
- }
- }
- });
+ if (mDisplayAreaOrganizer.isInOneHanded()) {
+ OneHandedEvents.writeEvent(event);
+ }
- mGestureHandler.setGestureEventListener(
- new OneHandedGestureHandler.OneHandedGestureEventCallback() {
- @Override
- public void onStart() {
- if (mIsOneHandedEnabled) {
- startOneHanded();
- } else if (mIsSwipeToNotificationEnabled) {
- mCommandQueue.handleSystemKey(KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN);
- }
- }
+ stopOneHanded();
+ }
- @Override
- public void onStop() {
- if (mIsOneHandedEnabled) {
- stopOneHanded();
- } else if (mIsSwipeToNotificationEnabled) {
- mCommandQueue.handleSystemKey(KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP);
- }
- }
- });
+ @Override
+ public void setThreeButtonModeEnabled(boolean enabled) {
+ mGestureHandler.onThreeButtonModeEnabled(enabled);
+ }
- mDisplayAreaOrganizer.registerTransitionCallback(new OneHandedTransitionCallback() {
- @Override
- public void onStartFinished(Rect bounds) {
- mSysUiFlagContainer.setFlag(SYSUI_STATE_ONE_HANDED_ACTIVE,
- true).commitUpdate(DEFAULT_DISPLAY);
- }
+ @Override
+ public void registerTransitionCallback(OneHandedTransitionCallback callback) {
+ mDisplayAreaOrganizer.registerTransitionCallback(callback);
+ }
- @Override
- public void onStopFinished(Rect bounds) {
- mSysUiFlagContainer.setFlag(SYSUI_STATE_ONE_HANDED_ACTIVE,
- false).commitUpdate(DEFAULT_DISPLAY);
- }
- });
+ @Override
+ public void registerGestureCallback(OneHandedGestureEventCallback callback) {
+ mGestureHandler.setGestureEventListener(callback);
+ }
+ private void setupCallback() {
+ mTouchHandler.registerTouchEventListener(() ->
+ stopOneHanded(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_OVERSPACE_OUT));
mDisplayAreaOrganizer.registerTransitionCallback(mTouchHandler);
mDisplayAreaOrganizer.registerTransitionCallback(mGestureHandler);
mDisplayAreaOrganizer.registerTransitionCallback(mTutorialHandler);
}
+ private void setupSettingObservers() {
+ OneHandedSettingsUtil.registerSettingsKeyObserver(Settings.Secure.ONE_HANDED_MODE_ENABLED,
+ mContext.getContentResolver(), mEnabledObserver);
+ OneHandedSettingsUtil.registerSettingsKeyObserver(Settings.Secure.ONE_HANDED_MODE_TIMEOUT,
+ mContext.getContentResolver(), mTimeoutObserver);
+ OneHandedSettingsUtil.registerSettingsKeyObserver(Settings.Secure.TAPS_APP_TO_EXIT,
+ mContext.getContentResolver(), mTaskChangeExitObserver);
+ OneHandedSettingsUtil.registerSettingsKeyObserver(
+ Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED,
+ mContext.getContentResolver(), mSwipeToNotificationEnabledObserver);
+ }
+
+ private void updateSettings() {
+ setOneHandedEnabled(OneHandedSettingsUtil
+ .getSettingsOneHandedModeEnabled(mContext.getContentResolver()));
+ mTimeoutHandler.setTimeout(OneHandedSettingsUtil
+ .getSettingsOneHandedModeTimeout(mContext.getContentResolver()));
+ setTaskChangeToExit(OneHandedSettingsUtil
+ .getSettingsTapsAppToExit(mContext.getContentResolver()));
+ setSwipeToNotificationEnabled(OneHandedSettingsUtil
+ .getSettingsSwipeToNotificationEnabled(mContext.getContentResolver()));
+ }
+
+ private void setupTimeoutListener() {
+ mTimeoutHandler.registerTimeoutListener(timeoutTime -> {
+ stopOneHanded(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_TIMEOUT_OUT);
+ });
+ }
+
/**
* Query the current display real size from {@link DisplayController}
*
@@ -293,25 +368,73 @@ public class OneHandedController implements Dumpable {
mDisplayAreaOrganizer.registerOrganizer(
OneHandedDisplayAreaOrganizer.FEATURE_ONE_HANDED);
}
- ActivityManagerWrapper.getInstance().unregisterTaskStackListener(mTaskStackListener);
- if (mTaskChangeToExit) {
- ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
- }
mTouchHandler.onOneHandedEnabled(mIsOneHandedEnabled);
mGestureHandler.onOneHandedEnabled(mIsOneHandedEnabled || mIsSwipeToNotificationEnabled);
}
+ private void setupGesturalOverlay() {
+ if (!OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(mContext.getContentResolver())) {
+ return;
+ }
+
+ OverlayInfo info = null;
+ try {
+ // TODO(b/157958539) migrate new RRO config file after S+
+ mOverlayManager.setHighestPriority(ONE_HANDED_MODE_GESTURAL_OVERLAY, USER_CURRENT);
+ info = mOverlayManager.getOverlayInfo(ONE_HANDED_MODE_GESTURAL_OVERLAY, USER_CURRENT);
+ } catch (RemoteException e) { /* Do nothing */ }
+
+ if (info != null && !info.isEnabled()) {
+ // Enable the default gestural one handed overlay.
+ setEnabledGesturalOverlay(true);
+ }
+ }
+
+ @androidx.annotation.VisibleForTesting
+ private void setEnabledGesturalOverlay(boolean enabled) {
+ try {
+ mOverlayManager.setEnabled(ONE_HANDED_MODE_GESTURAL_OVERLAY, enabled, USER_CURRENT);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
@Override
- public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
+ public void dump(@NonNull PrintWriter pw) {
final String innerPrefix = " ";
pw.println(TAG + "states: ");
- pw.print(innerPrefix + "mSysUiFlagContainer=");
- pw.println(mSysUiFlagContainer.getFlags());
pw.print(innerPrefix + "mOffSetFraction=");
pw.println(mOffSetFraction);
if (mDisplayAreaOrganizer != null) {
- mDisplayAreaOrganizer.dump(fd, pw, args);
+ mDisplayAreaOrganizer.dump(pw);
+ }
+
+ if (mTouchHandler != null) {
+ mTouchHandler.dump(pw);
+ }
+
+ if (mTimeoutHandler != null) {
+ mTimeoutHandler.dump(pw);
+ }
+
+ if (mTutorialHandler != null) {
+ mTutorialHandler.dump(pw);
+ }
+
+ OneHandedSettingsUtil.dump(pw, innerPrefix, mContext.getContentResolver());
+
+ if (mOverlayManager != null) {
+ OverlayInfo info = null;
+ try {
+ info = mOverlayManager.getOverlayInfo(ONE_HANDED_MODE_GESTURAL_OVERLAY,
+ USER_CURRENT);
+ } catch (RemoteException e) { /* Do nothing */ }
+
+ if (info != null && !info.isEnabled()) {
+ pw.print(innerPrefix + "OverlayInfo=");
+ pw.println(info);
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java
index ad9f7ea4e9458..ec40bad06b717 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java
@@ -38,10 +38,8 @@ import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.android.internal.os.SomeArgs;
-import com.android.systemui.Dumpable;
import com.android.wm.shell.common.DisplayController;
-import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
@@ -58,7 +56,7 @@ import java.util.Objects;
*
* This class is also responsible for translating one handed operations within SysUI component
*/
-public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer implements Dumpable {
+public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
private static final String TAG = "OneHandedDisplayAreaOrganizer";
private static final String ONE_HANDED_MODE_TRANSLATE_ANIMATION_DURATION =
"persist.debug.one_handed_translate_animation_duration";
@@ -353,8 +351,7 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer implemen
return args;
}
- @Override
- public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
+ void dump(@NonNull PrintWriter pw) {
final String innerPrefix = " ";
pw.println(TAG + "states: ");
pw.print(innerPrefix + "mIsInOneHanded=");
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java
index f3be699ab8215..4a493ba800ba7 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java
@@ -17,7 +17,6 @@
package com.android.systemui.onehanded;
import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
import android.annotation.Nullable;
import android.content.Context;
@@ -40,7 +39,6 @@ import android.window.WindowContainerTransaction;
import androidx.annotation.VisibleForTesting;
import com.android.systemui.R;
-import com.android.systemui.navigationbar.NavigationModeController;
import com.android.wm.shell.common.DisplayChangeController;
import com.android.wm.shell.common.DisplayController;
@@ -49,7 +47,6 @@ import com.android.wm.shell.common.DisplayController;
* others(e.g, 2-button, full gesture mode) are handled by Launcher quick steps.
*/
public class OneHandedGestureHandler implements OneHandedTransitionCallback,
- NavigationModeController.ModeChangedListener,
DisplayChangeController.OnDisplayChangingListener {
private static final String TAG = "OneHandedGestureHandler";
private static final boolean DEBUG_GESTURE = false;
@@ -66,7 +63,7 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback,
private boolean mAllowGesture;
private boolean mIsEnabled;
private int mNavGestureHeight;
- private boolean mIsThreeButtonModeEnable;
+ private boolean mIsThreeButtonModeEnabled;
private int mRotation = Surface.ROTATION_0;
@VisibleForTesting
@@ -85,14 +82,10 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback,
*
* @param context {@link Context}
* @param displayController {@link DisplayController}
- * @param navigationModeController {@link NavigationModeController}
*/
- public OneHandedGestureHandler(Context context, DisplayController displayController,
- NavigationModeController navigationModeController) {
+ public OneHandedGestureHandler(Context context, DisplayController displayController) {
mDisplayController = displayController;
displayController.addDisplayChangingController(this);
- final int NavBarMode = navigationModeController.addListener(this);
- mIsThreeButtonModeEnable = (NavBarMode == NAV_BAR_MODE_3BUTTON);
mNavGestureHeight = context.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.navigation_bar_gesture_height);
mDragDistThreshold = context.getResources().getDimensionPixelSize(
@@ -115,6 +108,11 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback,
updateIsEnabled();
}
+ void onThreeButtonModeEnabled(boolean isEnabled) {
+ mIsThreeButtonModeEnabled = isEnabled;
+ updateIsEnabled();
+ }
+
/**
* Register {@link OneHandedGestureEventCallback} to receive onStart(), onStop() callback
*/
@@ -199,7 +197,7 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback,
private void updateIsEnabled() {
disposeInputChannel();
- if (mIsEnabled && mIsThreeButtonModeEnable) {
+ if (mIsEnabled && mIsThreeButtonModeEnabled) {
final Point displaySize = new Point();
if (mDisplayController != null) {
final Display display = mDisplayController.getDisplay(DEFAULT_DISPLAY);
@@ -223,15 +221,6 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback,
}
}
- @Override
- public void onNavigationModeChanged(int mode) {
- if (DEBUG_GESTURE) {
- Log.d(TAG, "onNavigationModeChanged, mode =" + mode);
- }
- mIsThreeButtonModeEnable = (mode == NAV_BAR_MODE_3BUTTON);
- updateIsEnabled();
- }
-
@Override
public void onRotateDisplay(int displayId, int fromRotation, int toRotation,
WindowContainerTransaction t) {
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTimeoutHandler.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTimeoutHandler.java
index 6bed30425c55f..21329ea1b0e62 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTimeoutHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTimeoutHandler.java
@@ -25,9 +25,6 @@ import android.os.Message;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
-import com.android.systemui.Dumpable;
-
-import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@@ -36,7 +33,7 @@ import java.util.concurrent.TimeUnit;
/**
* Timeout handler for stop one handed mode operations.
*/
-public class OneHandedTimeoutHandler implements Dumpable {
+public class OneHandedTimeoutHandler {
private static final String TAG = "OneHandedTimeoutHandler";
private static boolean sIsDragging = false;
// Default timeout is ONE_HANDED_TIMEOUT_MEDIUM
@@ -150,8 +147,7 @@ public class OneHandedTimeoutHandler implements Dumpable {
}
}
- @Override
- public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
+ void dump(@NonNull PrintWriter pw) {
final String innerPrefix = " ";
pw.println(TAG + "states: ");
pw.print(innerPrefix + "sTimeout=");
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java
index 8265da6a5f142..3d28a426f4f8e 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java
@@ -30,9 +30,6 @@ import android.view.MotionEvent;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
-import com.android.systemui.Dumpable;
-
-import java.io.FileDescriptor;
import java.io.PrintWriter;
/**
@@ -40,7 +37,7 @@ import java.io.PrintWriter;
* to exit, reset timer when user is in one-handed mode.
* Refer {@link OneHandedGestureHandler} to see start and stop one handed gesture
*/
-public class OneHandedTouchHandler implements OneHandedTransitionCallback, Dumpable {
+public class OneHandedTouchHandler implements OneHandedTransitionCallback {
private static final String TAG = "OneHandedTouchHandler";
private final Rect mLastUpdatedBounds = new Rect();
@@ -146,8 +143,7 @@ public class OneHandedTouchHandler implements OneHandedTransitionCallback, Dumpa
mIsOnStopTransitioning = false;
}
- @Override
- public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
+ void dump(@NonNull PrintWriter pw) {
final String innerPrefix = " ";
pw.println(TAG + "states: ");
pw.print(innerPrefix + "mLastUpdatedBounds=");
@@ -169,11 +165,6 @@ public class OneHandedTouchHandler implements OneHandedTransitionCallback, Dumpa
* The touch(gesture) events to notify {@link OneHandedController} start or stop one handed
*/
public interface OneHandedTouchEventCallback {
- /**
- * Handle the start event.
- */
- void onStart();
-
/**
* Handle the exit event.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java
index 8ef9b092bc009..beccf3dbc8deb 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java
@@ -33,10 +33,8 @@ import android.widget.FrameLayout;
import androidx.annotation.NonNull;
-import com.android.systemui.Dumpable;
import com.android.systemui.R;
-import java.io.FileDescriptor;
import java.io.PrintWriter;
/**
@@ -45,7 +43,7 @@ import java.io.PrintWriter;
* Refer {@link OneHandedGestureHandler} and {@link OneHandedTouchHandler} to see start and stop
* one handed gesture
*/
-public class OneHandedTutorialHandler implements OneHandedTransitionCallback, Dumpable {
+public class OneHandedTutorialHandler implements OneHandedTransitionCallback {
private static final String TAG = "OneHandedTutorialHandler";
private static final String ONE_HANDED_MODE_OFFSET_PERCENTAGE =
"persist.debug.one_handed_offset_percentage";
@@ -170,8 +168,7 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback, Du
return lp;
}
- @Override
- public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
+ void dump(@NonNull PrintWriter pw) {
final String innerPrefix = " ";
pw.println(TAG + "states: ");
pw.print(innerPrefix + "mLastUpdatedBounds=");
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedUI.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedUI.java
deleted file mode 100644
index 3348a06d5cac4..0000000000000
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedUI.java
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * 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.systemui.onehanded;
-
-import static android.os.UserHandle.USER_CURRENT;
-import static android.view.Display.DEFAULT_DISPLAY;
-
-import android.content.Context;
-import android.content.om.IOverlayManager;
-import android.content.om.OverlayInfo;
-import android.database.ContentObserver;
-import android.inputmethodservice.InputMethodService;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemProperties;
-import android.provider.Settings;
-import android.util.Log;
-
-import androidx.annotation.VisibleForTesting;
-
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.KeyguardUpdateMonitorCallback;
-import com.android.systemui.Dependency;
-import com.android.systemui.Dumpable;
-import com.android.systemui.SystemUI;
-import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.keyguard.ScreenLifecycle;
-import com.android.systemui.statusbar.CommandQueue;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
-import javax.inject.Inject;
-
-/**
- * A service that controls UI of the one handed mode function.
- */
-@SysUISingleton
-public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dumpable {
- private static final String TAG = "OneHandedUI";
- private static final String ONE_HANDED_MODE_GESTURAL_OVERLAY =
- "com.android.internal.systemui.onehanded.gestural";
- private static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode";
-
- private final OneHandedController mOneHandedController;
- private final CommandQueue mCommandQueue;
- private final Handler mMainHandler = new Handler(Looper.getMainLooper());
- private final IOverlayManager mOverlayManager;
- private final OneHandedTimeoutHandler mTimeoutHandler;
- private final ScreenLifecycle mScreenLifecycle;
-
- private final ContentObserver mEnabledObserver = new ContentObserver(mMainHandler) {
- @Override
- public void onChange(boolean selfChange) {
- final boolean enabled = OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
- mContext.getContentResolver());
- OneHandedEvents.writeEvent(enabled
- ? OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_ENABLED_ON
- : OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_ENABLED_OFF);
- if (mOneHandedController != null) {
- mOneHandedController.setOneHandedEnabled(enabled);
- }
-
- // Also checks swipe to notification settings since they all need gesture overlay.
- setEnabledGesturalOverlay(
- enabled || OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
- mContext.getContentResolver()));
- }
- };
-
- private final ContentObserver mTimeoutObserver = new ContentObserver(mMainHandler) {
- @Override
- public void onChange(boolean selfChange) {
- final int newTimeout = OneHandedSettingsUtil.getSettingsOneHandedModeTimeout(
- mContext.getContentResolver());
- int metricsId = OneHandedEvents.OneHandedSettingsTogglesEvent.INVALID.getId();
- switch (newTimeout) {
- case OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_NEVER:
- metricsId = OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_TIMEOUT_SECONDS_NEVER;
- break;
- case OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_SHORT_IN_SECONDS:
- metricsId = OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_TIMEOUT_SECONDS_4;
- break;
- case OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS:
- metricsId = OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_TIMEOUT_SECONDS_8;
- break;
- case OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_LONG_IN_SECONDS:
- metricsId = OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_TIMEOUT_SECONDS_12;
- break;
- default:
- // do nothing
- break;
- }
- OneHandedEvents.writeEvent(metricsId);
-
- if (mTimeoutHandler != null) {
- mTimeoutHandler.setTimeout(newTimeout);
- }
- }
- };
-
- private final ContentObserver mTaskChangeExitObserver = new ContentObserver(mMainHandler) {
- @Override
- public void onChange(boolean selfChange) {
- final boolean enabled = OneHandedSettingsUtil.getSettingsTapsAppToExit(
- mContext.getContentResolver());
- OneHandedEvents.writeEvent(enabled
- ? OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_APP_TAPS_EXIT_ON
- : OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_APP_TAPS_EXIT_OFF);
-
- if (mOneHandedController != null) {
- mOneHandedController.setTaskChangeToExit(enabled);
- }
- }
- };
-
- private final ContentObserver mSwipeToNotificationEnabledObserver =
- new ContentObserver(mMainHandler) {
- @Override
- public void onChange(boolean selfChange) {
- final boolean enabled =
- OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
- mContext.getContentResolver());
- if (mOneHandedController != null) {
- mOneHandedController.setSwipeToNotificationEnabled(enabled);
- }
-
- // Also checks one handed mode settings since they all need gesture overlay.
- setEnabledGesturalOverlay(
- enabled || OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
- mContext.getContentResolver()));
- }
- };
-
- @Inject
- public OneHandedUI(Context context,
- CommandQueue commandQueue,
- OneHandedController oneHandedController,
- ScreenLifecycle screenLifecycle) {
- super(context);
-
- if (!SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false)) {
- Log.i(TAG, "Device config SUPPORT_ONE_HANDED_MODE off");
- mCommandQueue = null;
- mOneHandedController = null;
- mOverlayManager = null;
- mTimeoutHandler = null;
- mScreenLifecycle = null;
- return;
- }
-
- mCommandQueue = commandQueue;
- mOneHandedController = oneHandedController;
- mTimeoutHandler = OneHandedTimeoutHandler.get();
- mScreenLifecycle = screenLifecycle;
- mOverlayManager = IOverlayManager.Stub.asInterface(
- ServiceManager.getService(Context.OVERLAY_SERVICE));
- }
-
- @Override
- public void start() {
- if (!SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false)) {
- return;
- }
- mCommandQueue.addCallback(this);
- setupKeyguardUpdateMonitor();
- setupScreenObserver();
- setupSettingObservers();
- setupTimeoutListener();
- setupGesturalOverlay();
- updateSettings();
- }
-
- private void setupGesturalOverlay() {
- if (!OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(mContext.getContentResolver())) {
- return;
- }
-
- OverlayInfo info = null;
- try {
- // TODO(b/157958539) migrate new RRO config file after S+
- mOverlayManager.setHighestPriority(ONE_HANDED_MODE_GESTURAL_OVERLAY, USER_CURRENT);
- info = mOverlayManager.getOverlayInfo(ONE_HANDED_MODE_GESTURAL_OVERLAY, USER_CURRENT);
- } catch (RemoteException e) { /* Do nothing */ }
-
- if (info != null && !info.isEnabled()) {
- // Enable the default gestural one handed overlay.
- setEnabledGesturalOverlay(true);
- }
- }
-
- private void setupTimeoutListener() {
- mTimeoutHandler.registerTimeoutListener(timeoutTime -> {
- OneHandedEvents.writeEvent(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_TIMEOUT_OUT);
- stopOneHanded();
- });
- }
-
- private void setupKeyguardUpdateMonitor() {
- final KeyguardUpdateMonitorCallback keyguardCallback =
- new KeyguardUpdateMonitorCallback() {
- @Override
- public void onKeyguardBouncerChanged(boolean bouncer) {
- if (bouncer) {
- stopOneHanded();
- }
- }
-
- @Override
- public void onKeyguardVisibilityChanged(boolean showing) {
- stopOneHanded();
- }
- };
- Dependency.get(KeyguardUpdateMonitor.class).registerCallback(keyguardCallback);
- }
-
- @Override
- public void onCameraLaunchGestureDetected(int source) {
- stopOneHanded();
- }
-
- private void setupScreenObserver() {
- final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() {
- @Override
- public void onScreenTurningOff() {
- OneHandedEvents.writeEvent(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_SCREEN_OFF_OUT);
- stopOneHanded();
- }
- };
- mScreenLifecycle.addObserver(mScreenObserver);
- }
-
- private void setupSettingObservers() {
- OneHandedSettingsUtil.registerSettingsKeyObserver(Settings.Secure.ONE_HANDED_MODE_ENABLED,
- mContext.getContentResolver(), mEnabledObserver);
- OneHandedSettingsUtil.registerSettingsKeyObserver(Settings.Secure.ONE_HANDED_MODE_TIMEOUT,
- mContext.getContentResolver(), mTimeoutObserver);
- OneHandedSettingsUtil.registerSettingsKeyObserver(Settings.Secure.TAPS_APP_TO_EXIT,
- mContext.getContentResolver(), mTaskChangeExitObserver);
- OneHandedSettingsUtil.registerSettingsKeyObserver(
- Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED,
- mContext.getContentResolver(), mSwipeToNotificationEnabledObserver);
- }
-
- private void updateSettings() {
- mOneHandedController.setOneHandedEnabled(OneHandedSettingsUtil
- .getSettingsOneHandedModeEnabled(mContext.getContentResolver()));
- mTimeoutHandler.setTimeout(OneHandedSettingsUtil
- .getSettingsOneHandedModeTimeout(mContext.getContentResolver()));
- mOneHandedController.setTaskChangeToExit(OneHandedSettingsUtil
- .getSettingsTapsAppToExit(mContext.getContentResolver()));
- mOneHandedController.setSwipeToNotificationEnabled(OneHandedSettingsUtil
- .getSettingsSwipeToNotificationEnabled(mContext.getContentResolver()));
- }
-
- @Override
- public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition,
- boolean showImeSwitcher) {
- if (displayId != DEFAULT_DISPLAY) {
- return;
- }
- if ((vis & InputMethodService.IME_VISIBLE) != 0) {
- OneHandedEvents.writeEvent(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_POP_IME_OUT);
- stopOneHanded();
- }
- }
-
- @VisibleForTesting
- private void setEnabledGesturalOverlay(boolean enabled) {
- try {
- mOverlayManager.setEnabled(ONE_HANDED_MODE_GESTURAL_OVERLAY, enabled, USER_CURRENT);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Trigger one handed more
- */
- public void startOneHanded() {
- mOneHandedController.startOneHanded();
- OneHandedEvents.writeEvent(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_GESTURE_IN);
- }
-
- /**
- * Dismiss one handed more
- */
- public void stopOneHanded() {
- mOneHandedController.stopOneHanded();
- OneHandedEvents.writeEvent(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_GESTURE_OUT);
- }
-
- /**
- * Dump all one handed data of states
- */
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- final String innerPrefix = " ";
- pw.println(TAG + "one handed states: ");
-
- if (mOneHandedController != null) {
- mOneHandedController.dump(fd, pw, args);
- }
-
- if (mTimeoutHandler != null) {
- mTimeoutHandler.dump(fd, pw, args);
- }
-
- OneHandedSettingsUtil.dump(pw, innerPrefix, mContext.getContentResolver());
-
- if (mOverlayManager != null) {
- OverlayInfo info = null;
- try {
- info = mOverlayManager.getOverlayInfo(ONE_HANDED_MODE_GESTURAL_OVERLAY,
- USER_CURRENT);
- } catch (RemoteException e) { /* Do nothing */ }
-
- if (info != null && !info.isEnabled()) {
- pw.print(innerPrefix + "OverlayInfo=");
- pw.println(info);
- }
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 56f010d7e8665..5db4e019f7f7e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -75,7 +75,8 @@ import com.android.systemui.navigationbar.NavigationBar;
import com.android.systemui.navigationbar.NavigationBarController;
import com.android.systemui.navigationbar.NavigationBarView;
import com.android.systemui.navigationbar.NavigationModeController;
-import com.android.systemui.onehanded.OneHandedUI;
+import com.android.systemui.onehanded.OneHanded;
+import com.android.systemui.onehanded.OneHandedEvents;
import com.android.systemui.pip.Pip;
import com.android.systemui.pip.PipAnimationController;
import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
@@ -135,7 +136,7 @@ public class OverviewProxyService extends CurrentUserTracker implements
private final List mConnectionCallbacks = new ArrayList<>();
private final Intent mQuickStepIntent;
private final ScreenshotHelper mScreenshotHelper;
- private final OneHandedUI mOneHandedUI;
+ private final Optional mOneHandedOptional;
private final CommandQueue mCommandQueue;
private Region mActiveNavBarRegion;
@@ -464,9 +465,7 @@ public class OverviewProxyService extends CurrentUserTracker implements
}
long token = Binder.clearCallingIdentity();
try {
- if (mOneHandedUI != null) {
- mOneHandedUI.startOneHanded();
- }
+ mOneHandedOptional.ifPresent(oneHanded -> oneHanded.startOneHanded());
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -479,9 +478,8 @@ public class OverviewProxyService extends CurrentUserTracker implements
}
long token = Binder.clearCallingIdentity();
try {
- if (mOneHandedUI != null) {
- mOneHandedUI.stopOneHanded();
- }
+ mOneHandedOptional.ifPresent(oneHanded -> oneHanded.stopOneHanded(
+ OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_GESTURE_OUT));
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -620,7 +618,8 @@ public class OverviewProxyService extends CurrentUserTracker implements
NotificationShadeWindowController statusBarWinController, SysUiState sysUiState,
Optional pipOptional,
Optional splitScreenOptional,
- Optional> statusBarOptionalLazy, OneHandedUI oneHandedUI,
+ Optional> statusBarOptionalLazy,
+ Optional oneHandedOptional,
BroadcastDispatcher broadcastDispatcher) {
super(broadcastDispatcher);
mContext = context;
@@ -640,7 +639,7 @@ public class OverviewProxyService extends CurrentUserTracker implements
.supportsRoundedCornersOnWindows(mContext.getResources());
mSysUiState = sysUiState;
mSysUiState.addCallback(this::notifySystemUiStateFlags);
- mOneHandedUI = oneHandedUI;
+ mOneHandedOptional = oneHandedOptional;
// Assumes device always starts with back button until launcher tells it that it does not
mNavBarButtonAlpha = 1.0f;
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
index 27af5f91c9e47..93b23e51656ff 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
@@ -16,16 +16,32 @@
package com.android.systemui.wmshell;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
+
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ONE_HANDED_ACTIVE;
import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import android.app.ActivityManager;
+import android.content.ComponentName;
import android.content.Context;
+import android.graphics.Rect;
+import android.inputmethodservice.InputMethodService;
+import android.os.IBinder;
+import android.view.KeyEvent;
import com.android.internal.annotations.VisibleForTesting;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.SystemUI;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.keyguard.ScreenLifecycle;
+import com.android.systemui.model.SysUiState;
+import com.android.systemui.navigationbar.NavigationModeController;
+import com.android.systemui.onehanded.OneHanded;
+import com.android.systemui.onehanded.OneHandedEvents;
+import com.android.systemui.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback;
+import com.android.systemui.onehanded.OneHandedTransitionCallback;
import com.android.systemui.pip.Pip;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
@@ -54,8 +70,12 @@ public final class WMShell extends SystemUI implements ProtoTraceable mPipOptional;
private final Optional mSplitScreenOptional;
+ private final Optional mOneHandedOptional;
private final ProtoTracer mProtoTracer;
@Inject
@@ -63,16 +83,24 @@ public final class WMShell extends SystemUI implements ProtoTraceable pipOptional,
Optional splitScreenOptional,
+ Optional oneHandedOptional,
ProtoTracer protoTracer) {
super(context);
mCommandQueue = commandQueue;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mActivityManagerWrapper = activityManagerWrapper;
mDisplayImeController = displayImeController;
+ mNavigationModeController = navigationModeController;
+ mScreenLifecycle = screenLifecycle;
+ mSysUiState = sysUiState;
mPipOptional = pipOptional;
mSplitScreenOptional = splitScreenOptional;
+ mOneHandedOptional = oneHandedOptional;
mProtoTracer = protoTracer;
mProtoTracer.add(this);
}
@@ -83,9 +111,9 @@ public final class WMShell extends SystemUI implements ProtoTraceable
+ oneHanded.setThreeButtonModeEnabled(mode == NAV_BAR_MODE_3BUTTON));
+ oneHanded.setThreeButtonModeEnabled(currentMode == NAV_BAR_MODE_3BUTTON);
+
+ oneHanded.registerTransitionCallback(new OneHandedTransitionCallback() {
+ @Override
+ public void onStartFinished(Rect bounds) {
+ mSysUiState.setFlag(SYSUI_STATE_ONE_HANDED_ACTIVE,
+ true).commitUpdate(DEFAULT_DISPLAY);
+ }
+
+ @Override
+ public void onStopFinished(Rect bounds) {
+ mSysUiState.setFlag(SYSUI_STATE_ONE_HANDED_ACTIVE,
+ false).commitUpdate(DEFAULT_DISPLAY);
+ }
+ });
+
+ oneHanded.registerGestureCallback(new OneHandedGestureEventCallback() {
+ @Override
+ public void onStart() {
+ if (oneHanded.isOneHandedEnabled()) {
+ oneHanded.startOneHanded();
+ } else if (oneHanded.isSwipeToNotificationEnabled()) {
+ mCommandQueue.handleSystemKey(KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN);
+ }
+ }
+
+ @Override
+ public void onStop() {
+ if (oneHanded.isOneHandedEnabled()) {
+ oneHanded.stopOneHanded(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_GESTURE_OUT);
+ } else if (oneHanded.isSwipeToNotificationEnabled()) {
+ mCommandQueue.handleSystemKey(KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP);
+ }
+ }
+ });
+
+ mKeyguardUpdateMonitor.registerCallback(new KeyguardUpdateMonitorCallback() {
+ @Override
+ public void onKeyguardBouncerChanged(boolean bouncer) {
+ if (bouncer) {
+ oneHanded.stopOneHanded();
+ }
+ }
+
+ @Override
+ public void onKeyguardVisibilityChanged(boolean showing) {
+ oneHanded.stopOneHanded();
+ }
+ });
+
+ mScreenLifecycle.addObserver(new ScreenLifecycle.Observer() {
+ @Override
+ public void onScreenTurningOff() {
+ oneHanded.stopOneHanded(
+ OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_SCREEN_OFF_OUT);
+ }
+ });
+
+ mCommandQueue.addCallback(new CommandQueue.Callbacks() {
+ @Override
+ public void onCameraLaunchGestureDetected(int source) {
+ oneHanded.stopOneHanded();
+ }
+
+ @Override
+ public void setImeWindowStatus(int displayId, IBinder token, int vis,
+ int backDisposition, boolean showImeSwitcher) {
+ if (displayId != DEFAULT_DISPLAY && (vis & InputMethodService.IME_VISIBLE) == 0) {
+ return;
+ }
+ oneHanded.stopOneHanded(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_POP_IME_OUT);
+ }
+ });
+
+ mActivityManagerWrapper.registerTaskStackListener(
+ new TaskStackChangeListener() {
+ @Override
+ public void onTaskCreated(int taskId, ComponentName componentName) {
+ oneHanded.stopOneHanded(
+ OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_APP_TAPS_OUT);
+ }
+
+ @Override
+ public void onTaskMovedToFront(int taskId) {
+ oneHanded.stopOneHanded(
+ OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_APP_TAPS_OUT);
+ }
+ });
+ }
+
@Override
public void writeToProto(SystemUiTraceProto proto) {
if (proto.wmShell == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
index e63c6c3173923..d3e5f22aa0424 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
@@ -24,6 +24,7 @@ import android.view.IWindowManager;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.onehanded.OneHanded;
import com.android.systemui.pip.Pip;
import com.android.systemui.pip.PipSurfaceTransactionHelper;
import com.android.systemui.pip.PipUiEventLogger;
@@ -101,16 +102,19 @@ public abstract class WMShellBaseModule {
return organizer;
}
- @BindsOptionalOf
- abstract Pip optionalPip();
-
- @BindsOptionalOf
- abstract SplitScreen optionalSplitScreen();
-
@SysUISingleton
@Provides
static FlingAnimationUtils.Builder provideFlingAnimationUtilsBuilder(
DisplayMetrics displayMetrics) {
return new FlingAnimationUtils.Builder(displayMetrics);
}
+
+ @BindsOptionalOf
+ abstract Pip optionalPip();
+
+ @BindsOptionalOf
+ abstract SplitScreen optionalSplitScreen();
+
+ @BindsOptionalOf
+ abstract OneHanded optionalOneHanded();
}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
index 1870b7605567c..3050aefb97d22 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
@@ -24,6 +24,8 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.model.SysUiState;
+import com.android.systemui.onehanded.OneHanded;
+import com.android.systemui.onehanded.OneHandedController;
import com.android.systemui.pip.Pip;
import com.android.systemui.pip.PipBoundsHandler;
import com.android.systemui.pip.PipSurfaceTransactionHelper;
@@ -109,4 +111,10 @@ public class WMShellModule {
pipUiEventLogger, shellTaskOrganizer);
}
+ @SysUISingleton
+ @Provides
+ static OneHanded provideOneHandedController(Context context,
+ DisplayController displayController) {
+ return OneHandedController.create(context, displayController);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedControllerTest.java
index 02d587d90655c..e42cf529373ec 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedControllerTest.java
@@ -22,21 +22,20 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.provider.Settings;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.Display;
import androidx.test.filters.SmallTest;
-import com.android.systemui.model.SysUiState;
-import com.android.systemui.statusbar.CommandQueue;
import com.android.wm.shell.common.DisplayController;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -51,8 +50,6 @@ public class OneHandedControllerTest extends OneHandedTestCase {
OneHandedController mOneHandedController;
OneHandedTimeoutHandler mTimeoutHandler;
- @Mock
- CommandQueue mCommandQueue;
@Mock
DisplayController mMockDisplayController;
@Mock
@@ -64,21 +61,20 @@ public class OneHandedControllerTest extends OneHandedTestCase {
@Mock
OneHandedGestureHandler mMockGestureHandler;
@Mock
- SysUiState mMockSysUiState;
+ OneHandedTimeoutHandler mMockTimeoutHandler;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mDisplay = mContext.getDisplay();
- mOneHandedController = new OneHandedController(
- getContext(),
- mCommandQueue,
+ OneHandedController oneHandedController = new OneHandedController(
+ mContext,
mMockDisplayController,
mMockDisplayAreaOrganizer,
mMockTouchHandler,
mMockTutorialHandler,
- mMockGestureHandler,
- mMockSysUiState);
+ mMockGestureHandler);
+ mOneHandedController = Mockito.spy(oneHandedController);
mTimeoutHandler = Mockito.spy(OneHandedTimeoutHandler.get());
when(mMockDisplayController.getDisplay(anyInt())).thenReturn(mDisplay);
@@ -97,7 +93,7 @@ public class OneHandedControllerTest extends OneHandedTestCase {
@Test
public void testRegisterOrganizer() {
- verify(mMockDisplayAreaOrganizer).registerOrganizer(anyInt());
+ verify(mMockDisplayAreaOrganizer, atLeastOnce()).registerOrganizer(anyInt());
}
@Test
@@ -132,7 +128,7 @@ public class OneHandedControllerTest extends OneHandedTestCase {
final boolean enabled = true;
mOneHandedController.setOneHandedEnabled(enabled);
- verify(mMockTouchHandler, times(2)).onOneHandedEnabled(enabled);
+ verify(mMockTouchHandler, atLeastOnce()).onOneHandedEnabled(enabled);
}
@Test
@@ -140,6 +136,44 @@ public class OneHandedControllerTest extends OneHandedTestCase {
final boolean enabled = true;
mOneHandedController.setSwipeToNotificationEnabled(enabled);
- verify(mMockTouchHandler, times(2)).onOneHandedEnabled(enabled);
+ verify(mMockTouchHandler, atLeastOnce()).onOneHandedEnabled(enabled);
+ }
+
+ @Ignore("b/161980408, fix it after migration finished")
+ @Test
+ public void tesSettingsObserver_updateTapAppToExit() {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.TAPS_APP_TO_EXIT, 1);
+
+ verify(mOneHandedController).setTaskChangeToExit(true);
+ }
+
+ @Ignore("b/161980408, fix it after migration finished")
+ @Test
+ public void tesSettingsObserver_updateEnabled() {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.ONE_HANDED_MODE_ENABLED, 1);
+
+ verify(mOneHandedController).setOneHandedEnabled(true);
+ }
+
+ @Ignore("b/161980408, fix it after migration finished")
+ @Test
+ public void tesSettingsObserver_updateTimeout() {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.ONE_HANDED_MODE_TIMEOUT,
+ OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS);
+
+ verify(mMockTimeoutHandler).setTimeout(
+ OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS);
+ }
+
+ @Ignore("b/161980408, fix it after migration finished")
+ @Test
+ public void tesSettingsObserver_updateSwipeToNotification() {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, 1);
+
+ verify(mOneHandedController).setSwipeToNotificationEnabled(true);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java
index 756382a6c6300..41af53b1c5226 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java
@@ -16,12 +16,10 @@
package com.android.systemui.onehanded;
-import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON;
-
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.verify;
import android.testing.AndroidTestingRunner;
@@ -29,9 +27,6 @@ import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
-import com.android.systemui.model.SysUiState;
-import com.android.systemui.navigationbar.NavigationModeController;
-import com.android.systemui.statusbar.CommandQueue;
import com.android.wm.shell.common.DisplayController;
import org.junit.Before;
@@ -50,52 +45,55 @@ public class OneHandedGestureHandlerTest extends OneHandedTestCase {
OneHandedGestureHandler mGestureHandler;
OneHandedController mOneHandedController;
@Mock
- CommandQueue mCommandQueue;
- @Mock
DisplayController mMockDisplayController;
@Mock
OneHandedDisplayAreaOrganizer mMockDisplayAreaOrganizer;
- @Mock
- SysUiState mMockSysUiState;
- @Mock
- NavigationModeController mMockNavigationModeController;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mTouchHandler = new OneHandedTouchHandler();
mTutorialHandler = new OneHandedTutorialHandler(mContext);
- mGestureHandler = Mockito.spy(new OneHandedGestureHandler(
- mContext, mMockDisplayController, mMockNavigationModeController));
+ mGestureHandler = Mockito.spy(
+ new OneHandedGestureHandler(mContext, mMockDisplayController));
mOneHandedController = new OneHandedController(
getContext(),
- mCommandQueue,
mMockDisplayController,
mMockDisplayAreaOrganizer,
mTouchHandler,
mTutorialHandler,
- mGestureHandler,
- mMockSysUiState);
+ mGestureHandler);
+ mOneHandedController.setThreeButtonModeEnabled(true);
}
@Test
public void testOneHandedManager_registerForDisplayAreaOrganizer() {
- verify(mMockDisplayAreaOrganizer).registerTransitionCallback(mGestureHandler);
+ verify(mMockDisplayAreaOrganizer, atLeastOnce())
+ .registerTransitionCallback(mGestureHandler);
}
@Test
public void testOneHandedManager_setGestureEventListener() {
- verify(mGestureHandler).setGestureEventListener(any());
+ OneHandedGestureHandler.OneHandedGestureEventCallback callback =
+ new OneHandedGestureHandler.OneHandedGestureEventCallback() {
+ @Override
+ public void onStart() {}
- assertThat(mGestureHandler.mGestureEventCallback).isNotNull();
+ @Override
+ public void onStop() {}
+ };
+ mOneHandedController.registerGestureCallback(callback);
+
+ verify(mGestureHandler).setGestureEventListener(callback);
+ assertThat(mGestureHandler.mGestureEventCallback).isEqualTo(callback);
}
@Test
public void testReceiveNewConfig_whenSetOneHandedEnabled() {
// 1st called at init
- verify(mGestureHandler).onOneHandedEnabled(true);
+ verify(mGestureHandler, atLeastOnce()).onOneHandedEnabled(true);
mOneHandedController.setOneHandedEnabled(true);
// 2nd called by setOneHandedEnabled()
- verify(mGestureHandler, times(2)).onOneHandedEnabled(true);
+ verify(mGestureHandler, atLeast(2)).onOneHandedEnabled(true);
}
@Test
@@ -108,14 +106,14 @@ public class OneHandedGestureHandlerTest extends OneHandedTestCase {
}
@Test
- public void testChangeNavBarTo2Button_shouldDisposeInputChannel() {
+ public void testChangeNavBarToNon3Button_shouldDisposeInputChannel() {
// 1st called at init
- verify(mGestureHandler).onOneHandedEnabled(true);
+ verify(mGestureHandler, atLeastOnce()).onOneHandedEnabled(true);
mOneHandedController.setOneHandedEnabled(true);
// 2nd called by setOneHandedEnabled()
- verify(mGestureHandler, times(2)).onOneHandedEnabled(true);
+ verify(mGestureHandler, atLeast(2)).onOneHandedEnabled(true);
- mGestureHandler.onNavigationModeChanged(NAV_BAR_MODE_2BUTTON);
+ mGestureHandler.onThreeButtonModeEnabled(false);
assertThat(mGestureHandler.mInputMonitor).isNull();
assertThat(mGestureHandler.mInputEventReceiver).isNull();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTestCase.java
index 04ebf25e1b490..f111c48964581 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTestCase.java
@@ -16,8 +16,12 @@
package com.android.systemui.onehanded;
+import static com.android.systemui.onehanded.OneHandedController.SUPPORT_ONE_HANDED_MODE;
import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS;
+import static org.junit.Assume.assumeTrue;
+
+import android.os.SystemProperties;
import android.provider.Settings;
import com.android.systemui.SysuiTestCase;
@@ -54,6 +58,11 @@ public abstract class OneHandedTestCase extends SysuiTestCase {
Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, 1);
}
+ @Before
+ public void assumeOneHandedModeSupported() {
+ assumeTrue(SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false));
+ }
+
@After
public void restoreSettings() {
Settings.Secure.putInt(getContext().getContentResolver(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java
index 3c3ace052e47c..1e408313a36ee 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java
@@ -19,7 +19,8 @@ package com.android.systemui.onehanded;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.verify;
import android.testing.AndroidTestingRunner;
@@ -27,9 +28,6 @@ import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
-import com.android.systemui.model.SysUiState;
-import com.android.systemui.navigationbar.NavigationModeController;
-import com.android.systemui.statusbar.CommandQueue;
import com.android.wm.shell.common.DisplayController;
import org.junit.Before;
@@ -48,31 +46,22 @@ public class OneHandedTouchHandlerTest extends OneHandedTestCase {
OneHandedGestureHandler mGestureHandler;
OneHandedController mOneHandedController;
@Mock
- CommandQueue mCommandQueue;
- @Mock
DisplayController mMockDisplayController;
@Mock
- NavigationModeController mMockNavigationModeController;
- @Mock
OneHandedDisplayAreaOrganizer mMockDisplayAreaOrganizer;
- @Mock
- SysUiState mMockSysUiState;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mTouchHandler = Mockito.spy(new OneHandedTouchHandler());
- mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController,
- mMockNavigationModeController);
+ mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController);
mOneHandedController = new OneHandedController(
getContext(),
- mCommandQueue,
mMockDisplayController,
mMockDisplayAreaOrganizer,
mTouchHandler,
mTutorialHandler,
- mGestureHandler,
- mMockSysUiState);
+ mGestureHandler);
}
@Test
@@ -102,10 +91,10 @@ public class OneHandedTouchHandlerTest extends OneHandedTestCase {
@Test
public void testReceiveNewConfig_whenSetOneHandedEnabled() {
- // 1st called at init
- verify(mTouchHandler).onOneHandedEnabled(true);
+ // Called at init
+ verify(mTouchHandler, atLeastOnce()).onOneHandedEnabled(true);
mOneHandedController.setOneHandedEnabled(true);
- // 2nd called by setOneHandedEnabled()
- verify(mTouchHandler, times(2)).onOneHandedEnabled(true);
+ // Called by setOneHandedEnabled()
+ verify(mTouchHandler, atLeast(2)).onOneHandedEnabled(true);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java
index 1bffbf7eb8dd1..8ea5524eb7e62 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java
@@ -23,9 +23,6 @@ import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
-import com.android.systemui.model.SysUiState;
-import com.android.systemui.navigationbar.NavigationModeController;
-import com.android.systemui.statusbar.CommandQueue;
import com.android.wm.shell.common.DisplayController;
import org.junit.Before;
@@ -44,32 +41,23 @@ public class OneHandedTutorialHandlerTest extends OneHandedTestCase {
OneHandedGestureHandler mGestureHandler;
OneHandedController mOneHandedController;
@Mock
- CommandQueue mCommandQueue;
- @Mock
DisplayController mMockDisplayController;
@Mock
- NavigationModeController mMockNavigationModeController;
- @Mock
OneHandedDisplayAreaOrganizer mMockDisplayAreaOrganizer;
- @Mock
- SysUiState mMockSysUiState;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mTouchHandler = new OneHandedTouchHandler();
mTutorialHandler = Mockito.spy(new OneHandedTutorialHandler(mContext));
- mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController,
- mMockNavigationModeController);
+ mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController);
mOneHandedController = new OneHandedController(
getContext(),
- mCommandQueue,
mMockDisplayController,
mMockDisplayAreaOrganizer,
mTouchHandler,
mTutorialHandler,
- mGestureHandler,
- mMockSysUiState);
+ mGestureHandler);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedUITest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedUITest.java
deleted file mode 100644
index ae3df5db30bcc..0000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedUITest.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * 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.systemui.onehanded;
-
-import static org.junit.Assume.assumeTrue;
-import static org.mockito.Mockito.verify;
-
-import android.os.SystemProperties;
-import android.provider.Settings;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.systemui.keyguard.ScreenLifecycle;
-import com.android.systemui.statusbar.CommandQueue;
-
-import org.junit.Before;
-import org.junit.Ignore;
-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 OneHandedUITest extends OneHandedTestCase {
- private static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode";
-
- CommandQueue mCommandQueue;
- KeyguardUpdateMonitor mKeyguardUpdateMonitor;
- OneHandedUI mOneHandedUI;
- ScreenLifecycle mScreenLifecycle;
- @Mock
- OneHandedController mOneHandedController;
- @Mock
- OneHandedTimeoutHandler mMockTimeoutHandler;
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- mCommandQueue = new CommandQueue(mContext);
- mScreenLifecycle = new ScreenLifecycle();
- mOneHandedUI = new OneHandedUI(mContext,
- mCommandQueue,
- mOneHandedController,
- mScreenLifecycle);
- mOneHandedUI.start();
- mKeyguardUpdateMonitor = mDependency.injectMockDependency(KeyguardUpdateMonitor.class);
- }
-
- @Before
- public void assumeOneHandedModeSupported() {
- assumeTrue(SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false));
- }
-
- @Test
- public void testStartOneHanded() {
- mOneHandedUI.startOneHanded();
-
- verify(mOneHandedController).startOneHanded();
- }
-
- @Test
- public void testStopOneHanded() {
- mOneHandedUI.stopOneHanded();
-
- verify(mOneHandedController).stopOneHanded();
- }
-
- @Test
- public void tesSettingsObserver_updateTapAppToExit() {
- Settings.Secure.putInt(mContext.getContentResolver(),
- Settings.Secure.TAPS_APP_TO_EXIT, 1);
-
- verify(mOneHandedController).setTaskChangeToExit(true);
- }
-
- @Test
- public void tesSettingsObserver_updateEnabled() {
- Settings.Secure.putInt(mContext.getContentResolver(),
- Settings.Secure.ONE_HANDED_MODE_ENABLED, 1);
-
- verify(mOneHandedController).setOneHandedEnabled(true);
- }
-
- @Test
- public void tesSettingsObserver_updateTimeout() {
- Settings.Secure.putInt(mContext.getContentResolver(),
- Settings.Secure.ONE_HANDED_MODE_TIMEOUT,
- OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS);
-
- verify(mMockTimeoutHandler).setTimeout(
- OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS);
- }
-
- @Test
- public void tesSettingsObserver_updateSwipeToNotification() {
- Settings.Secure.putInt(mContext.getContentResolver(),
- Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, 1);
-
- verify(mOneHandedController).setSwipeToNotificationEnabled(true);
- }
-
- @Ignore("Clarifying do not receive callback")
- @Test
- public void testKeyguardBouncerShowing_shouldStopOneHanded() {
- mKeyguardUpdateMonitor.sendKeyguardBouncerChanged(true);
-
- verify(mOneHandedController).stopOneHanded();
- }
-
- @Test
- public void testScreenTurningOff_shouldStopOneHanded() {
- mScreenLifecycle.dispatchScreenTurningOff();
-
- verify(mOneHandedController).stopOneHanded();
- }
-
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
index ac9346f675be7..79da45a86f351 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
@@ -18,6 +18,7 @@ package com.android.systemui.wmshell;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.test.suitebuilder.annotation.SmallTest;
@@ -26,6 +27,12 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.keyguard.ScreenLifecycle;
+import com.android.systemui.model.SysUiState;
+import com.android.systemui.navigationbar.NavigationModeController;
+import com.android.systemui.onehanded.OneHanded;
+import com.android.systemui.onehanded.OneHandedGestureHandler;
+import com.android.systemui.onehanded.OneHandedTransitionCallback;
import com.android.systemui.pip.Pip;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
@@ -51,16 +58,21 @@ public class WMShellTest extends SysuiTestCase {
@Mock KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@Mock ActivityManagerWrapper mActivityManagerWrapper;
@Mock DisplayImeController mDisplayImeController;
+ @Mock NavigationModeController mNavigationModeController;
+ @Mock ScreenLifecycle mScreenLifecycle;
+ @Mock SysUiState mSysUiState;
@Mock Pip mPip;
@Mock SplitScreen mSplitScreen;
+ @Mock OneHanded mOneHanded;
@Mock ProtoTracer mProtoTracer;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mWMShell = new WMShell(mContext, mCommandQueue, mKeyguardUpdateMonitor,
- mActivityManagerWrapper, mDisplayImeController, Optional.of(mPip),
- Optional.of(mSplitScreen), mProtoTracer);
+ mActivityManagerWrapper, mDisplayImeController, mNavigationModeController,
+ mScreenLifecycle, mSysUiState, Optional.of(mPip), Optional.of(mSplitScreen),
+ Optional.of(mOneHanded), mProtoTracer);
}
@Test
@@ -85,4 +97,22 @@ public class WMShellTest extends SysuiTestCase {
verify(mActivityManagerWrapper).registerTaskStackListener(
any(TaskStackChangeListener.class));
}
+
+ @Test
+ public void initOneHanded_registersCallbacks() {
+ when(mOneHanded.hasOneHandedFeature()).thenReturn(true);
+ mWMShell.initOneHanded(mOneHanded);
+
+ verify(mKeyguardUpdateMonitor).registerCallback(any(KeyguardUpdateMonitorCallback.class));
+ verify(mCommandQueue).addCallback(any(CommandQueue.Callbacks.class));
+ verify(mScreenLifecycle).addObserver(any(ScreenLifecycle.Observer.class));
+ verify(mNavigationModeController).addListener(
+ any(NavigationModeController.ModeChangedListener.class));
+ verify(mActivityManagerWrapper).registerTaskStackListener(
+ any(TaskStackChangeListener.class));
+
+ verify(mOneHanded).registerGestureCallback(any(
+ OneHandedGestureHandler.OneHandedGestureEventCallback.class));
+ verify(mOneHanded).registerTransitionCallback(any(OneHandedTransitionCallback.class));
+ }
}