Merge "Notify SysUi on device rotation for back gesture" into ub-launcher3-rvc-dev
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 07aed52..79b38f2 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -16,6 +16,7 @@
package com.android.quickstep;
import static android.content.Intent.ACTION_USER_UNLOCKED;
+import static android.view.Surface.ROTATION_0;
import static com.android.launcher3.util.DefaultDisplay.CHANGE_ALL;
import static com.android.launcher3.util.DefaultDisplay.CHANGE_FRAME_DELAY;
@@ -48,15 +49,18 @@
import android.provider.Settings;
import android.text.TextUtils;
import android.view.MotionEvent;
+import android.view.OrientationEventListener;
import androidx.annotation.BinderThread;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.DefaultDisplay;
import com.android.launcher3.util.SecureSettingsObserver;
import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
import com.android.quickstep.util.NavBarPosition;
+import com.android.quickstep.util.RecentsOrientedState;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
@@ -112,9 +116,53 @@
}
enableMultipleRegions(false);
}
+
+ @Override
+ public void onActivityRotation(int displayId) {
+ super.onActivityRotation(displayId);
+ // This always gets called before onDisplayInfoChanged() so we know how to process
+ // the rotation in that method. This is done to avoid having a race condition between
+ // the sensor readings and onDisplayInfoChanged() call
+ if (displayId != mDisplayId) {
+ return;
+ }
+
+ mPrioritizeDeviceRotation = true;
+ if (mInOverview) {
+ // reset, launcher must be rotating
+ mExitOverviewRunnable.run();
+ }
+ }
+ };
+
+ private Runnable mExitOverviewRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mInOverview = false;
+ enableMultipleRegions(false);
+ }
};
private OrientationTouchTransformer mOrientationTouchTransformer;
+ /**
+ * Used to listen for when the device rotates into the orientation of the current
+ * foreground app. For example, if a user quickswitches from a portrait to a fixed landscape
+ * app and then rotates rotates the device to match that orientation, this triggers calls to
+ * sysui to adjust the navbar.
+ */
+ private OrientationEventListener mOrientationListener;
+ private int mPreviousRotation = ROTATION_0;
+ /**
+ * This is the configuration of the foreground app or the app that will be in the foreground
+ * once a quickstep gesture finishes.
+ */
+ private int mCurrentAppRotation = -1;
+ /**
+ * This flag is set to true when the device physically changes orientations. When true,
+ * we will always report the current rotation of the foreground app whenever the display
+ * changes, as it would indicate the user's intention to rotate the foreground app.
+ */
+ private boolean mPrioritizeDeviceRotation = false;
private Region mExclusionRegion;
private SystemGestureExclusionListenerCompat mExclusionListener;
@@ -193,6 +241,26 @@
userSetupObserver.register();
runOnDestroy(userSetupObserver::unregister);
}
+
+ mOrientationListener = new OrientationEventListener(context) {
+ @Override
+ public void onOrientationChanged(int degrees) {
+ int newRotation = RecentsOrientedState.getRotationForUserDegreesRotated(degrees,
+ mPreviousRotation);
+ if (newRotation == mPreviousRotation) {
+ return;
+ }
+
+ mPreviousRotation = newRotation;
+ mPrioritizeDeviceRotation = true;
+
+ if (newRotation == mCurrentAppRotation) {
+ // When user rotates device to the orientation of the foreground app after
+ // quickstepping
+ toggleSecondaryNavBarsForRotation(false);
+ }
+ }
+ };
}
private void setupOrientationSwipeHandler() {
@@ -268,6 +336,18 @@
mNavBarPosition = new NavBarPosition(mMode, info);
updateGestureTouchRegions();
mOrientationTouchTransformer.createOrAddTouchRegion(info);
+ mCurrentAppRotation = mDisplayRotation;
+
+ /* Update nav bars on the following:
+ * a) if we're not expecting quickswitch, this is coming from an activity rotation
+ * b) we launch an app in the orientation that user is already in
+ * c) We're not in overview, since overview will always be portrait (w/o home rotation)
+ */
+ if ((mPrioritizeDeviceRotation
+ || mCurrentAppRotation == mPreviousRotation) // switch to an app of orientation user is in
+ && !mInOverview) {
+ toggleSecondaryNavBarsForRotation(false);
+ }
}
/**
@@ -553,9 +633,13 @@
mOrientationTouchTransformer.transform(event);
}
- void enableMultipleRegions(boolean enable) {
- mOrientationTouchTransformer.enableMultipleRegions(enable, mDefaultDisplay.getInfo());
- notifySysuiForRotation(mOrientationTouchTransformer.getQuickStepStartingRotation());
+ private void enableMultipleRegions(boolean enable) {
+ toggleSecondaryNavBarsForRotation(enable);
+ if (enable && !TestProtocol.sDisableSensorRotation) {
+ mOrientationListener.enable();
+ } else {
+ mOrientationListener.disable();
+ }
}
private void notifySysuiForRotation(int rotation) {
@@ -581,10 +665,7 @@
// If we're in landscape w/o ever quickswitching, show the navbar in landscape
enableMultipleRegions(true);
}
- activityInterface.onExitOverview(this, () -> {
- mInOverview = false;
- enableMultipleRegions(false);
- });
+ activityInterface.onExitOverview(this, mExitOverviewRunnable);
} else if (endTarget == GestureState.GestureEndTarget.HOME) {
enableMultipleRegions(false);
} else if (endTarget == GestureState.GestureEndTarget.NEW_TASK) {
@@ -594,6 +675,11 @@
} else {
notifySysuiForRotation(mOrientationTouchTransformer.getCurrentActiveRotation());
}
+
+ // A new gesture is starting, reset the current device rotation
+ // This is done under the assumption that the user won't rotate the phone and then
+ // quickswitch in the old orientation.
+ mPrioritizeDeviceRotation = false;
} else if (endTarget == GestureState.GestureEndTarget.LAST_TASK) {
if (!mTaskListFrozen) {
// touched nav bar but didn't go anywhere and not quickswitching, do nothing
@@ -603,7 +689,24 @@
}
}
- int getCurrentActiveRotation() {
+ private void notifySysuiOfCurrentRotation(int rotation) {
+ UI_HELPER_EXECUTOR.execute(() -> SystemUiProxy.INSTANCE.get(mContext)
+ .onQuickSwitchToNewTask(rotation));
+ }
+
+ /**
+ * Disables/Enables multiple nav bars on {@link OrientationTouchTransformer} and then
+ * notifies system UI of the primary rotation the user is interacting with
+ *
+ * @param enable if {@code true}, this will report to sysUI the navbar of the region the gesture
+ * started in (during ACTION_DOWN), otherwise will report {@param displayRotation}
+ */
+ private void toggleSecondaryNavBarsForRotation(boolean enable) {
+ mOrientationTouchTransformer.enableMultipleRegions(enable, mDefaultDisplay.getInfo());
+ notifySysuiOfCurrentRotation(mOrientationTouchTransformer.getQuickStepStartingRotation());
+ }
+
+ public int getCurrentActiveRotation() {
if (!mMode.hasGestures) {
// touch rotation should always match that of display for 3 button
return mDisplayRotation;
diff --git a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
index 7715cca..fe5a6c9 100644
--- a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
+++ b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
@@ -445,7 +445,8 @@
}
break;
case ROTATION_270:
- if (degrees < (90 - threshold)) {
+ if (degrees < (90 - threshold) ||
+ (degrees > (270 + threshold) && degrees < 360)) {
return ROTATION_0;
}
if (degrees > (90 + threshold) && degrees < 180) {
@@ -468,7 +469,8 @@
if (degrees < (270 - threshold) && degrees > 90) {
return ROTATION_180;
}
- if (degrees > (270 + threshold) && degrees < 360) {
+ if (degrees > (270 + threshold) && degrees < 360
+ || (degrees >= 0 && degrees < threshold)) {
return ROTATION_0;
}
// flip from landscape to seascape