Update state and touch region after one handed overlay changed
The matrix for overall modes x state changes:
-----------------------------------------------------
Mode | State changed | *Before|*After
-----------------------------------------------------
OneHanded | Portrait->Landscape | 80dp | 32dp
OneHanded | Landscape->Portrait | 32dp | 80dp
-----------------------------------------------------
OneHanded | Disable->Enable | 32dp | 32dp
(Landscape)| Enable->Disable | 32dp | 32dp
-----------------------------------------------------
OneHanded | Disable->Enable | 32dp | 80dp
(Portrait) | Enable->Disable | 80dp | 32dp
-----------------------------------------------------
NO_BUTTON | Portrait->Landscape | 32dp | 32dp
NO_BUTTON | Landscape->Portrait | 32dp | 32dp
2 BUTTON | Portrait->Landscape | 48dp | 48dp
2 BUTTON | Landscape->Portrait | 48dp | 48dp
3 BUTTON | Portrait->Landscape | 48dp | 48dp
3 BUTTON | Landscape->Portrait | 48dp | 48dp
-----------------------------------------------------
* dimen : navigation_bar_gesture_height
Test: adb bugrepot | grep mOneHandedModeRegion
Test: manually triger one handed
Test: atest WindowInsetsBehaviorTests
Bug: 157958539
Change-Id: I0f4b5d18053058730a06c3c216e849850c0390f4
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
index a696c21..901c981 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -58,6 +58,7 @@
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.R;
+import com.android.launcher3.ResourceUtils;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.UserEventDispatcher;
@@ -298,6 +299,7 @@
mAM = ActivityManagerWrapper.getInstance();
mDeviceState = new RecentsAnimationDeviceState(this);
mDeviceState.addNavigationModeChangedCallback(this::onNavigationModeChanged);
+ mDeviceState.addOneHandedModeChangedCallback(this::onOneHandedModeOverlayChanged);
mDeviceState.runOnUserUnlocked(this::onUserUnlocked);
ProtoTracer.INSTANCE.get(this).add(this);
@@ -338,6 +340,13 @@
resetHomeBounceSeenOnQuickstepEnabledFirstTime();
}
+ /**
+ * Called when the one handed mode overlay package changes, to recreate touch region.
+ */
+ private void onOneHandedModeOverlayChanged(int newGesturalHeight) {
+ initInputMonitor();
+ }
+
@UiThread
public void onUserUnlocked() {
mTaskAnimationManager = new TaskAnimationManager();
@@ -811,6 +820,13 @@
}
if (mOverviewComponentObserver.canHandleConfigChanges(activity.getComponentName(),
activity.getResources().getConfiguration().diff(newConfig))) {
+ // Since navBar gestural height are different between portrait and landscape,
+ // can handle orientation changes and refresh navigation gestural region through
+ // onOneHandedModeChanged()
+ int newGesturalHeight = ResourceUtils.getNavbarSize(
+ ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE,
+ getApplicationContext().getResources());
+ mDeviceState.onOneHandedModeChanged(newGesturalHeight);
return;
}
diff --git a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
index b49bc5a..5dcdd7a 100644
--- a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
+++ b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
@@ -65,6 +65,7 @@
private final RectF mAssistantRightRegion = new RectF();
private final RectF mOneHandedModeRegion = new RectF();
private int mCurrentDisplayRotation;
+ private int mNavBarGesturalHeight;
private boolean mEnableMultipleRegions;
private Resources mResources;
private OrientationRectF mLastRectTouched;
@@ -104,18 +105,33 @@
mResources = resources;
mMode = mode;
mContractInfo = contractInfo;
+ mNavBarGesturalHeight = getNavbarSize(ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE);
}
- void setNavigationMode(SysUINavigationMode.Mode newMode, DefaultDisplay.Info info) {
+ private void refreshTouchRegion(DefaultDisplay.Info info, Resources newRes) {
+ // Swipe touch regions are independent of nav mode, so we have to clear them explicitly
+ // here to avoid, for ex, a nav region for 2-button rotation 0 being used for 3-button mode
+ // It tries to cache and reuse swipe regions whenever possible based only on rotation
+ mResources = newRes;
+ mSwipeTouchRegions.clear();
+ resetSwipeRegions(info);
+ }
+
+ void setNavigationMode(SysUINavigationMode.Mode newMode, DefaultDisplay.Info info,
+ Resources newRes) {
if (mMode == newMode) {
return;
}
this.mMode = newMode;
- // Swipe touch regions are independent of nav mode, so we have to clear them explicitly
- // here to avoid, for ex, a nav region for 2-button rotation 0 being used for 3-button mode
- // It tries to cache and reuse swipe regions whenever possible based only on rotation
- mSwipeTouchRegions.clear();
- resetSwipeRegions(info);
+ refreshTouchRegion(info, newRes);
+ }
+
+ void setGesturalHeight(int newGesturalHeight, DefaultDisplay.Info info, Resources newRes) {
+ if (mNavBarGesturalHeight == newGesturalHeight) {
+ return;
+ }
+ mNavBarGesturalHeight = newGesturalHeight;
+ refreshTouchRegion(info, newRes);
}
/**
@@ -197,7 +213,7 @@
Point size = display.realSize;
int rotation = display.rotation;
- int touchHeight = getNavbarSize(ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE);
+ int touchHeight = mNavBarGesturalHeight;
OrientationRectF orientationRectF =
new OrientationRectF(0, 0, size.x, size.y, rotation);
if (mMode == SysUINavigationMode.Mode.NO_BUTTON) {
@@ -338,6 +354,7 @@
regions.append(rectF.mRotation).append(" ");
}
pw.println(regions.toString());
+ pw.println(" mNavBarGesturalHeight=" + mNavBarGesturalHeight);
pw.println(" mOneHandedModeRegion=" + mOneHandedModeRegion);
}
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 04aba22..8a1c30f 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -52,8 +52,8 @@
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
-import android.view.Surface;
import android.view.OrientationEventListener;
+import android.view.Surface;
import androidx.annotation.BinderThread;
@@ -63,6 +63,7 @@
import com.android.launcher3.util.DefaultDisplay;
import com.android.launcher3.util.SecureSettingsObserver;
import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
+import com.android.quickstep.SysUINavigationMode.OneHandedModeChangeListener;
import com.android.quickstep.util.NavBarPosition;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -81,7 +82,8 @@
*/
public class RecentsAnimationDeviceState implements
NavigationModeChangeListener,
- DefaultDisplay.DisplayInfoChangeListener {
+ DefaultDisplay.DisplayInfoChangeListener,
+ OneHandedModeChangeListener {
private final Context mContext;
private final SysUINavigationMode mSysUiNavMode;
@@ -310,6 +312,15 @@
runOnDestroy(() -> mSysUiNavMode.removeModeChangeListener(listener));
}
+ /**
+ * Adds a listener for the one handed mode change,
+ * guaranteed to be called after the device state's mode has changed.
+ */
+ public void addOneHandedModeChangedCallback(OneHandedModeChangeListener listener) {
+ listener.onOneHandedModeChanged(mSysUiNavMode.addOneHandedOverlayChangeListener(listener));
+ runOnDestroy(() -> mSysUiNavMode.removeOneHandedOverlayChangeListener(listener));
+ }
+
@Override
public void onNavigationModeChanged(SysUINavigationMode.Mode newMode) {
mDefaultDisplay.removeChangeListener(this);
@@ -324,7 +335,8 @@
mNavBarPosition = new NavBarPosition(newMode, mDefaultDisplay.getInfo());
- mOrientationTouchTransformer.setNavigationMode(newMode, mDefaultDisplay.getInfo());
+ mOrientationTouchTransformer.setNavigationMode(newMode, mDefaultDisplay.getInfo(),
+ mContext.getApplicationContext().getResources());
if (!mMode.hasGestures && newMode.hasGestures) {
setupOrientationSwipeHandler();
} else if (mMode.hasGestures && !newMode.hasGestures){
@@ -363,6 +375,12 @@
}
}
+ @Override
+ public void onOneHandedModeChanged(int newGesturalHeight) {
+ mOrientationTouchTransformer.setGesturalHeight(newGesturalHeight, mDefaultDisplay.getInfo(),
+ mContext.getApplicationContext().getResources());
+ }
+
/**
* @return the current navigation mode for the device.
*/
diff --git a/quickstep/src/com/android/quickstep/SysUINavigationMode.java b/quickstep/src/com/android/quickstep/SysUINavigationMode.java
index 05ce2a2..26c72a2 100644
--- a/quickstep/src/com/android/quickstep/SysUINavigationMode.java
+++ b/quickstep/src/com/android/quickstep/SysUINavigationMode.java
@@ -24,6 +24,7 @@
import android.content.res.Resources;
import android.util.Log;
+import com.android.launcher3.ResourceUtils;
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.MainThreadInitializedObject;
@@ -62,11 +63,20 @@
private static final String ACTION_OVERLAY_CHANGED = "android.intent.action.OVERLAY_CHANGED";
private static final String NAV_BAR_INTERACTION_MODE_RES_NAME =
"config_navBarInteractionMode";
+ private static final String NAV_BAR_INTERACTION_MODE_OVERLAY_PACKAGE_PREFIX =
+ "com.android.internal.systemui.navbar";
+ private static final String ONE_HANDED_MODE_OVERLAY_PACKAGE_PREFIX =
+ "com.android.internal.systemui.onehanded";
+ private static final int INVALID_RESOURCE_HANDLE = -1;
private final Context mContext;
private Mode mMode;
+ private int mNavBarGesturalHeight;
+
private final List<NavigationModeChangeListener> mChangeListeners = new ArrayList<>();
+ private final List<OneHandedModeChangeListener> mOneHandedOverlayChangeListeners =
+ new ArrayList<>();
public SysUINavigationMode(Context context) {
mContext = context;
@@ -77,7 +87,15 @@
public void onReceive(Context context, Intent intent) {
updateMode();
}
- }, getPackageFilter("android", ACTION_OVERLAY_CHANGED));
+ }, getPackageFilter(NAV_BAR_INTERACTION_MODE_OVERLAY_PACKAGE_PREFIX,
+ ACTION_OVERLAY_CHANGED));
+
+ mContext.registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ updateGesturalHeight();
+ }
+ }, getPackageFilter(ONE_HANDED_MODE_OVERLAY_PACKAGE_PREFIX, ACTION_OVERLAY_CHANGED));
}
/** Updates navigation mode when needed. */
@@ -89,8 +107,24 @@
}
}
+ private void updateGesturalHeight() {
+ int newGesturalHeight = getSystemIntegerRes(mContext,
+ ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE);
+
+ if (newGesturalHeight == INVALID_RESOURCE_HANDLE) {
+ return;
+ }
+
+ if (mNavBarGesturalHeight != newGesturalHeight) {
+ mNavBarGesturalHeight = newGesturalHeight;
+ dispatchOneHandedOverlayChange();
+ }
+ }
+
private void initializeMode() {
int modeInt = getSystemIntegerRes(mContext, NAV_BAR_INTERACTION_MODE_RES_NAME);
+ mNavBarGesturalHeight = getSystemIntegerRes(mContext,
+ ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE);
for(Mode m : Mode.values()) {
if (m.resValue == modeInt) {
mMode = m;
@@ -104,6 +138,12 @@
}
}
+ private void dispatchOneHandedOverlayChange() {
+ for (OneHandedModeChangeListener listener : mOneHandedOverlayChangeListeners) {
+ listener.onOneHandedModeChanged(mNavBarGesturalHeight);
+ }
+ }
+
public Mode addModeChangeListener(NavigationModeChangeListener listener) {
mChangeListeners.add(listener);
return mMode;
@@ -113,6 +153,15 @@
mChangeListeners.remove(listener);
}
+ public int addOneHandedOverlayChangeListener(OneHandedModeChangeListener listener) {
+ mOneHandedOverlayChangeListeners.add(listener);
+ return mNavBarGesturalHeight;
+ }
+
+ public void removeOneHandedOverlayChangeListener(OneHandedModeChangeListener listener) {
+ mOneHandedOverlayChangeListeners.remove(listener);
+ }
+
public Mode getMode() {
return mMode;
}
@@ -125,7 +174,7 @@
return res.getInteger(resId);
} else {
Log.e(TAG, "Failed to get system resource ID. Incompatible framework version?");
- return -1;
+ return INVALID_RESOURCE_HANDLE;
}
}
@@ -150,4 +199,9 @@
void onNavigationModeChanged(Mode newMode);
}
+
+ public interface OneHandedModeChangeListener {
+
+ void onOneHandedModeChanged(int newGesturalHeight);
+ }
}
\ No newline at end of file