Handling Launcher configuration change between touchDown and Launcher.onStart
If activity rotation is allowed, Launcher/recents can rotate while swipe animation
is running leading to inconsistencies between deviceProfile and rotation
> Using activity configuration to determine the rotation instead of using display rotation
> Removing rotation watcher when rotation is enabled as it is not used anymore
Bug: 158781568
Change-Id: I107d856cae80af111c0514656fac7ab1fa0c21cb
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java
index e825c5f..8d533bb 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java
@@ -275,8 +275,7 @@
if (mActivity == activity) {
return true;
}
- mTaskViewSimulator.setLayoutRotation(mDeviceState.getCurrentActiveRotation(),
- mDeviceState.getDisplayRotation());
+
if (mActivity != null) {
// The launcher may have been recreated as a result of device rotation.
int oldState = mStateCallback.getState() & ~LAUNCHER_UI_STATES;
@@ -329,6 +328,7 @@
if (mStateCallback.hasStates(STATE_HANDLER_INVALIDATED)) {
return;
}
+ mTaskViewSimulator.setRecentsConfiguration(mActivity.getResources().getConfiguration());
// If we've already ended the gesture and are going home, don't prepare recents UI,
// as that will set the state as BACKGROUND_APP, overriding the animation to NORMAL.
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
index ed07062..01936e4 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
@@ -66,7 +66,7 @@
}
}
RecentsOrientedState orientedState = taskView.getRecentsView().getPagedViewOrientedState();
- boolean canLauncherRotate = orientedState.canLauncherRotate();
+ boolean canLauncherRotate = orientedState.canRecentsActivityRotate();
boolean isInLandscape = orientedState.getTouchRotation() != ROTATION_0;
// Add overview actions to the menu when in in-place rotate landscape mode.
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java
index 32da52e..46013d3 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -22,6 +22,7 @@
import android.animation.TimeInterpolator;
import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.PointF;
@@ -125,6 +126,14 @@
}
/**
+ * @see com.android.quickstep.views.RecentsView#onConfigurationChanged(Configuration)
+ */
+ public void setRecentsConfiguration(Configuration configuration) {
+ mOrientationState.setActivityConfiguration(configuration);
+ mLayoutValid = false;
+ }
+
+ /**
* @see com.android.quickstep.views.RecentsView#FULLSCREEN_PROGRESS
*/
public float getFullScreenScale() {
@@ -205,7 +214,8 @@
public void applyWindowToHomeRotation(Matrix matrix) {
mMatrix.postTranslate(mDp.windowX, mDp.windowY);
postDisplayRotation(deltaRotation(
- mOrientationState.getLauncherRotation(), mOrientationState.getDisplayRotation()),
+ mOrientationState.getRecentsActivityRotation(),
+ mOrientationState.getDisplayRotation()),
mDp.widthPx, mDp.heightPx, matrix);
matrix.postTranslate(-mRunningTargetWindowPosition.x, -mRunningTargetWindowPosition.y);
}
@@ -226,7 +236,7 @@
mPositionHelper.updateThumbnailMatrix(
mThumbnailPosition, mThumbnailData,
mTaskRect.width(), mTaskRect.height(),
- mDp, mOrientationState.getLauncherRotation());
+ mDp, mOrientationState.getRecentsActivityRotation());
mPositionHelper.getMatrix().invert(mInversePositionMatrix);
PagedOrientationHandler poh = mOrientationState.getOrientationHandler();
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
index cb22570..92e3746 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
@@ -59,6 +59,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.PointF;
@@ -393,6 +394,7 @@
mActivity = BaseActivity.fromContext(context);
mOrientationState = new RecentsOrientedState(
context, mSizeStrategy, this::animateRecentsRotationInPlace);
+ mOrientationState.setActivityConfiguration(context.getResources().getConfiguration());
mFastFlingVelocity = getResources()
.getDimensionPixelSize(R.dimen.recents_fast_fling_velocity);
@@ -1063,7 +1065,7 @@
}
private void animateRecentsRotationInPlace(int newRotation) {
- if (mOrientationState.canLauncherRotate()) {
+ if (mOrientationState.canRecentsActivityRotate()) {
// Let system take care of the rotation
return;
}
@@ -1646,29 +1648,41 @@
}
}
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ if (mOrientationState.setActivityConfiguration(newConfig)) {
+ updateOrientationHandler();
+ }
+ }
+
public void setLayoutRotation(int touchRotation, int displayRotation) {
if (mOrientationState.update(touchRotation, displayRotation)) {
- mOrientationHandler = mOrientationState.getOrientationHandler();
- mIsRtl = mOrientationHandler.getRecentsRtlSetting(getResources());
- setLayoutDirection(mIsRtl
- ? View.LAYOUT_DIRECTION_RTL
- : View.LAYOUT_DIRECTION_LTR);
- mClearAllButton.setLayoutDirection(mIsRtl
- ? View.LAYOUT_DIRECTION_LTR
- : View.LAYOUT_DIRECTION_RTL);
- mClearAllButton.setRotation(mOrientationHandler.getDegreesRotated());
- mActivity.getDragLayer().recreateControllers();
- boolean isInLandscape = mOrientationState.getTouchRotation() != 0
- || mOrientationState.getLauncherRotation() != ROTATION_0;
- mActionsView.updateHiddenFlags(HIDDEN_NON_ZERO_ROTATION,
- !mOrientationState.canLauncherRotate() && isInLandscape);
- resetPaddingFromTaskSize();
- requestLayout();
- // Reapply the current page to update page scrolls.
- setCurrentPage(mCurrentPage);
+ updateOrientationHandler();
}
}
+ private void updateOrientationHandler() {
+ mOrientationHandler = mOrientationState.getOrientationHandler();
+ mIsRtl = mOrientationHandler.getRecentsRtlSetting(getResources());
+ setLayoutDirection(mIsRtl
+ ? View.LAYOUT_DIRECTION_RTL
+ : View.LAYOUT_DIRECTION_LTR);
+ mClearAllButton.setLayoutDirection(mIsRtl
+ ? View.LAYOUT_DIRECTION_LTR
+ : View.LAYOUT_DIRECTION_RTL);
+ mClearAllButton.setRotation(mOrientationHandler.getDegreesRotated());
+ mActivity.getDragLayer().recreateControllers();
+ boolean isInLandscape = mOrientationState.getTouchRotation() != 0
+ || mOrientationState.getRecentsActivityRotation() != ROTATION_0;
+ mActionsView.updateHiddenFlags(HIDDEN_NON_ZERO_ROTATION,
+ !mOrientationState.canRecentsActivityRotate() && isInLandscape);
+ resetPaddingFromTaskSize();
+ requestLayout();
+ // Reapply the current page to update page scrolls.
+ setCurrentPage(mCurrentPage);
+ }
+
public RecentsOrientedState getPagedViewOrientedState() {
return mOrientationState;
}
@@ -2234,7 +2248,7 @@
getCurrentPageTaskView().setModalness(modalness);
}
// Only show actions view when it's modal for in-place landscape mode.
- boolean inPlaceLandscape = !mOrientationState.canLauncherRotate()
+ boolean inPlaceLandscape = !mOrientationState.canRecentsActivityRotate()
&& mOrientationState.getTouchRotation() != ROTATION_0;
mActionsView.updateHiddenFlags(HIDDEN_NON_ZERO_ROTATION, modalness < 1 && inPlaceLandscape);
}
diff --git a/quickstep/src/com/android/quickstep/util/LayoutUtils.java b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
index cefab1b..ae19d73 100644
--- a/quickstep/src/com/android/quickstep/util/LayoutUtils.java
+++ b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
@@ -58,21 +58,6 @@
}
/**
- * Gets the scale that should be applied to the TaskView so that it matches the target
- * TODO: Remove this method
- */
- public static float getTaskScale(RecentsOrientedState orientedState,
- float srcWidth, float srcHeight, float targetWidth, float targetHeight) {
- if (orientedState == null
- || orientedState.isHomeRotationAllowed()
- || orientedState.isDisplayPhoneNatural()) {
- return srcWidth / targetWidth;
- } else {
- return srcHeight / targetHeight;
- }
- }
-
- /**
* Recursively sets view and all children enabled/disabled.
* @param view Top most parent view to change.
* @param enabled True = enable, False = disable.
diff --git a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
index 90ee18f..b9953cb 100644
--- a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
+++ b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
@@ -33,6 +33,7 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.SharedPreferences;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.graphics.Matrix;
@@ -47,6 +48,7 @@
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
@@ -56,6 +58,7 @@
import com.android.launcher3.util.WindowBounds;
import com.android.quickstep.BaseActivityInterface;
import com.android.quickstep.SysUINavigationMode;
+import com.android.systemui.shared.system.ConfigurationCompat;
import java.lang.annotation.Retention;
import java.util.function.IntConsumer;
@@ -87,7 +90,7 @@
private @SurfaceRotation int mTouchRotation = ROTATION_0;
private @SurfaceRotation int mDisplayRotation = ROTATION_0;
- private @SurfaceRotation int mLauncherRotation = ROTATION_0;
+ private @SurfaceRotation int mRecentsActivityRotation = ROTATION_0;
// Launcher activity supports multiple orientation, but fallback activity does not
private static final int FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_ACTIVITY = 1 << 0;
@@ -130,6 +133,8 @@
private int mFlags;
private int mPreviousRotation = ROTATION_0;
+ @Nullable private Configuration mActivityConfiguration;
+
/**
* @param rotationChangeListener Callback for receiving rotation events when rotation watcher
* is enabled
@@ -165,6 +170,15 @@
}
/**
+ * Sets the configuration for the recents activity, which could affect the activity's rotation
+ * @see #update(int, int)
+ */
+ public boolean setActivityConfiguration(Configuration activityConfiguration) {
+ mActivityConfiguration = activityConfiguration;
+ return update(mTouchRotation, mDisplayRotation);
+ }
+
+ /**
* Sets if the host is in multi-window mode
*/
public void setMultiWindowMode(boolean isMultiWindow) {
@@ -188,23 +202,19 @@
*/
public boolean update(
@SurfaceRotation int touchRotation, @SurfaceRotation int displayRotation) {
- if (!isMultipleOrientationSupportedByDevice()) {
- return false;
- }
-
- int launcherRotation = inferLauncherRotation(displayRotation);
+ int recentsActivityRotation = inferRecentsActivityRotation(displayRotation);
if (mDisplayRotation == displayRotation
&& mTouchRotation == touchRotation
- && mLauncherRotation == launcherRotation) {
+ && mRecentsActivityRotation == recentsActivityRotation) {
return false;
}
- mLauncherRotation = launcherRotation;
+ mRecentsActivityRotation = recentsActivityRotation;
mDisplayRotation = displayRotation;
mTouchRotation = touchRotation;
mPreviousRotation = touchRotation;
- if (mLauncherRotation == mTouchRotation || canLauncherRotate()) {
+ if (mRecentsActivityRotation == mTouchRotation || canRecentsActivityRotate()) {
mOrientationHandler = PagedOrientationHandler.PORTRAIT;
if (DEBUG) {
Log.d(TAG, "current RecentsOrientedState: " + this);
@@ -226,9 +236,11 @@
}
@SurfaceRotation
- private int inferLauncherRotation(@SurfaceRotation int displayRotation) {
- if (!isMultipleOrientationSupportedByDevice() || isHomeRotationAllowed()) {
- return displayRotation;
+ private int inferRecentsActivityRotation(@SurfaceRotation int displayRotation) {
+ if (isRecentsActivityRotationAllowed()) {
+ return mActivityConfiguration == null
+ ? displayRotation
+ : ConfigurationCompat.getWindowConfigurationRotation(mActivityConfiguration);
} else {
return ROTATION_0;
}
@@ -236,7 +248,8 @@
private void setFlag(int mask, boolean enabled) {
boolean wasRotationEnabled = !TestProtocol.sDisableSensorRotation
- && (mFlags & VALUE_ROTATION_WATCHER_ENABLED) == VALUE_ROTATION_WATCHER_ENABLED;
+ && (mFlags & VALUE_ROTATION_WATCHER_ENABLED) == VALUE_ROTATION_WATCHER_ENABLED
+ && !canRecentsActivityRotate();
if (enabled) {
mFlags |= mask;
} else {
@@ -244,7 +257,8 @@
}
boolean isRotationEnabled = !TestProtocol.sDisableSensorRotation
- && (mFlags & VALUE_ROTATION_WATCHER_ENABLED) == VALUE_ROTATION_WATCHER_ENABLED;
+ && (mFlags & VALUE_ROTATION_WATCHER_ENABLED) == VALUE_ROTATION_WATCHER_ENABLED
+ && !canRecentsActivityRotate();
if (wasRotationEnabled != isRotationEnabled) {
UI_HELPER_EXECUTOR.execute(() -> {
if (isRotationEnabled) {
@@ -324,8 +338,8 @@
}
@SurfaceRotation
- public int getLauncherRotation() {
- return mLauncherRotation;
+ public int getRecentsActivityRotation() {
+ return mRecentsActivityRotation;
}
public boolean isMultipleOrientationSupportedByDevice() {
@@ -333,14 +347,19 @@
== MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE;
}
- public boolean isHomeRotationAllowed() {
- return (mFlags & (FLAG_HOME_ROTATION_ALLOWED_IN_PREFS | FLAG_MULTIWINDOW_ROTATION_ALLOWED))
- != 0 ||
- (mFlags & FLAG_HOME_ROTATION_FORCE_ENABLED_FOR_TESTING) != 0;
+ public boolean isRecentsActivityRotationAllowed() {
+ return ((mFlags & MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE)
+ == MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE)
+ || (mFlags & (FLAG_HOME_ROTATION_ALLOWED_IN_PREFS
+ | FLAG_MULTIWINDOW_ROTATION_ALLOWED
+ | FLAG_HOME_ROTATION_FORCE_ENABLED_FOR_TESTING)) != 0;
}
- public boolean canLauncherRotate() {
- return (mFlags & FLAG_SYSTEM_ROTATION_ALLOWED) != 0 && isHomeRotationAllowed();
+ /**
+ * Returns true if the activity can rotate, if allowed by system rotation settings
+ */
+ public boolean canRecentsActivityRotate() {
+ return (mFlags & FLAG_SYSTEM_ROTATION_ALLOWED) != 0 && isRecentsActivityRotationAllowed();
}
/**
@@ -508,8 +527,8 @@
extractObjectNameAndAddress(mOrientationHandler.toString())
+ " mDisplayRotation=" + mDisplayRotation
+ " mTouchRotation=" + mTouchRotation
- + " mLauncherRotation=" + mLauncherRotation
- + " mHomeRotation=" + isHomeRotationAllowed()
+ + " mRecentsActivityRotation=" + mRecentsActivityRotation
+ + " isRecentsActivityRotationAllowed=" + isRecentsActivityRotationAllowed()
+ " mSystemRotation=" + systemRotationOn
+ " mFlags=" + mFlags
+ "]";
@@ -521,7 +540,8 @@
public DeviceProfile getLauncherDeviceProfile() {
InvariantDeviceProfile idp = InvariantDeviceProfile.INSTANCE.get(mContext);
// TODO also check the natural orientation is landscape or portrait
- return (mLauncherRotation == ROTATION_90 || mLauncherRotation == ROTATION_270)
+ return (mRecentsActivityRotation == ROTATION_90
+ || mRecentsActivityRotation == ROTATION_270)
? idp.landscapeProfile
: idp.portraitProfile;
}