From b7833f8193c124fc107066c6b8d8e1d030abe23f Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Tue, 21 Apr 2020 13:50:08 -0700 Subject: [PATCH] Moving various orientation related config in RecentsOrientaedState > Fixing RecentsOrientationState values for fallback recents > Using proper rotation in task simulator Change-Id: I770e7c8850e469f5dc0ce6f89889672f2decdc0d --- .../android/quickstep/BaseSwipeUpHandler.java | 2 +- .../quickstep/LauncherSwipeHandler.java | 3 +- .../quickstep/TouchInteractionService.java | 3 +- .../fallback/FallbackRecentsView.java | 7 +- .../util/AppWindowAnimationHelper.java | 3 +- .../quickstep/util/TaskViewSimulator.java | 32 ++- .../quickstep/views/LauncherRecentsView.java | 9 +- .../quickstep/views/OverviewActionsView.java | 4 +- .../android/quickstep/views/RecentsView.java | 74 +----- .../RecentsAnimationDeviceState.java | 6 +- .../quickstep/util/RecentsOrientedState.java | 226 +++++++++++------- .../launcher3/config/FeatureFlags.java | 4 - .../launcher3/states/RotationHelper.java | 1 - 13 files changed, 188 insertions(+), 186 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java index 32ab98bd4d..d22e5afcc5 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java @@ -334,7 +334,7 @@ public abstract class BaseSwipeUpHandler mTaskAnimationManager = taskAnimationManager; mTouchTimeMs = touchTimeMs; mContinuingLastGesture = continuingLastGesture; - mTaskViewSimulator = new TaskViewSimulator(context, LayoutUtils::calculateLauncherTaskSize); + mTaskViewSimulator = new TaskViewSimulator( + context, LayoutUtils::calculateLauncherTaskSize, true); initAfterSubclassConstructor(); initStateCallbacks(); 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 9b5a935e6b..28c2b97309 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java @@ -23,6 +23,7 @@ import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TI import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import static com.android.quickstep.GestureState.DEFAULT_STATE; +import static com.android.quickstep.util.RecentsOrientedState.isFixedRotationTransformEnabled; import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_INPUT_MONITOR; import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TRACING_ENABLED; @@ -597,7 +598,7 @@ public class TouchInteractionService extends Service implements PluginListener { } public FallbackRecentsView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); + super(context, attrs, defStyleAttr, false); } @Override @@ -195,9 +195,4 @@ public class FallbackRecentsView extends RecentsView { } super.applyLoadPlan(tasks); } - - @Override - protected boolean supportsVerticalLandscape() { - return false; - } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/AppWindowAnimationHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/AppWindowAnimationHelper.java index 00329b87e0..9309110fd0 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/AppWindowAnimationHelper.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/AppWindowAnimationHelper.java @@ -267,7 +267,8 @@ public class AppWindowAnimationHelper { mTmpRectF.set(mTargetRect); Utilities.scaleRectFAboutCenter(mTmpRectF, params.mOffsetScale); mCurrentRect.set(mRectFEvaluator.evaluate(params.mProgress, mSourceRect, mTmpRectF)); - if (mOrientedState == null || mOrientedState.areMultipleLayoutOrientationsDisabled()) { + if (mOrientedState == null + || !mOrientedState.isMultipleOrientationSupportedByDevice()) { mCurrentRect.offset(params.mOffset, 0); } else { int displayRotation = mOrientedState.getDisplayRotation(); 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 0131fdf5c4..0bc021b377 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 @@ -15,9 +15,13 @@ */ package com.android.quickstep.util; +import static android.view.Surface.ROTATION_0; + import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; +import static com.android.launcher3.states.RotationHelper.deltaRotation; import static com.android.launcher3.touch.PagedOrientationHandler.MATRIX_POST_TRANSLATE; import static com.android.quickstep.util.AppWindowAnimationHelper.applySurfaceParams; +import static com.android.quickstep.util.RecentsOrientedState.isFixedRotationTransformEnabled; import static com.android.quickstep.util.RecentsOrientedState.postDisplayRotation; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING; @@ -33,7 +37,6 @@ import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.anim.Interpolators; -import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.touch.PagedOrientationHandler; import com.android.quickstep.AnimatedFloat; import com.android.quickstep.RecentsAnimationTargets; @@ -91,11 +94,17 @@ public class TaskViewSimulator { private boolean mLayoutValid = false; private boolean mScrollValid = false; - public TaskViewSimulator(Context context, TaskSizeProvider sizeProvider) { + public TaskViewSimulator(Context context, TaskSizeProvider sizeProvider, + boolean rotationSupportedByActivity) { mContext = context; mSizeProvider = sizeProvider; mPositionHelper = new PreviewPositionHelper(context); - mOrientationState = new RecentsOrientedState(context); + + mOrientationState = new RecentsOrientedState(context, rotationSupportedByActivity, + i -> { }); + // We do not need to attach listeners as the simulator is created just for the gesture + // duration, and any settings are unlikely to change during this + mOrientationState.initWithoutListeners(); mCurrentFullscreenParams = new FullscreenDrawParams(context); mPageSpacing = context.getResources().getDimensionPixelSize(R.dimen.recents_page_spacing); @@ -114,11 +123,15 @@ public class TaskViewSimulator { * @see com.android.quickstep.views.RecentsView#setLayoutRotation(int, int) */ public void setLayoutRotation(int touchRotation, int displayRotation) { - if (!FeatureFlags.ENABLE_FIXED_ROTATION_TRANSFORM.get()) { - return; + int launcherRotation; + if (!mOrientationState.isMultipleOrientationSupportedByDevice() + || mOrientationState.isHomeRotationAllowed()) { + launcherRotation = displayRotation; + } else { + launcherRotation = ROTATION_0; } - mOrientationState.update(touchRotation, displayRotation, - mOrientationState.getLauncherRotation()); + + mOrientationState.update(touchRotation, displayRotation, launcherRotation); mLayoutValid = false; } @@ -180,7 +193,7 @@ public class TaskViewSimulator { mLayoutValid = true; getFullScreenScale(); - mThumbnailData.rotation = FeatureFlags.ENABLE_FIXED_ROTATION_TRANSFORM.get() + mThumbnailData.rotation = isFixedRotationTransformEnabled(mContext) ? mOrientationState.getDisplayRotation() : mPositionHelper.getCurrentRotation(); mPositionHelper.updateThumbnailMatrix(mThumbnailPosition, mThumbnailData, @@ -226,7 +239,8 @@ public class TaskViewSimulator { // Apply recensView matrix mMatrix.postScale(recentsViewScale.value, recentsViewScale.value, mPivot.x, mPivot.y); - postDisplayRotation(mOrientationState.getDisplayRotation(), + postDisplayRotation(deltaRotation( + mOrientationState.getLauncherRotation(), mOrientationState.getDisplayRotation()), mDp.widthPx, mDp.heightPx, mMatrix); // Crop rect is the inverse of thumbnail matrix diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java index 454223e06f..0b6d340313 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java @@ -45,7 +45,6 @@ import com.android.launcher3.LauncherStateManager.StateListener; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.appprediction.PredictionUiStateManager; import com.android.launcher3.appprediction.PredictionUiStateManager.Client; -import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.statehandlers.DepthController; import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper; import com.android.launcher3.util.TraceHelper; @@ -96,7 +95,7 @@ public class LauncherRecentsView extends RecentsView } public LauncherRecentsView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); + super(context, attrs, defStyleAttr, true); mActivity.getStateManager().addStateListener(this); } @@ -264,12 +263,6 @@ public class LauncherRecentsView extends RecentsView return mTransformParams; } - @Override - protected boolean supportsVerticalLandscape() { - return FeatureFlags.ENABLE_FIXED_ROTATION_TRANSFORM.get() - && !mOrientationState.areMultipleLayoutOrientationsDisabled(); - } - @Override public void reset() { super.reset(); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java index 93e68c0f5d..d160686f73 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java @@ -48,7 +48,8 @@ public class OverviewActionsView extends FrameLayo HIDDEN_NON_ZERO_ROTATION, HIDDEN_NO_TASKS, HIDDEN_GESTURE_RUNNING, - HIDDEN_NO_RECENTS}) + HIDDEN_NO_RECENTS, + HIDDEN_FULLESCREEN_PROGRESS}) @Retention(RetentionPolicy.SOURCE) public @interface ActionsHiddenFlags { } @@ -58,6 +59,7 @@ public class OverviewActionsView extends FrameLayo public static final int HIDDEN_NO_TASKS = 1 << 3; public static final int HIDDEN_GESTURE_RUNNING = 1 << 4; public static final int HIDDEN_NO_RECENTS = 1 << 5; + public static final int HIDDEN_FULLESCREEN_PROGRESS = 1 << 6; private static final int INDEX_CONTENT_ALPHA = 0; private static final int INDEX_VISIBILITY_ALPHA = 1; 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 b687920f49..90dc5a46dd 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 @@ -38,6 +38,7 @@ import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType. import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW; import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId; +import static com.android.quickstep.views.OverviewActionsView.HIDDEN_FULLESCREEN_PROGRESS; import static com.android.quickstep.views.OverviewActionsView.HIDDEN_GESTURE_RUNNING; import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NON_ZERO_ROTATION; import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_RECENTS; @@ -75,8 +76,6 @@ import android.view.HapticFeedbackConstants; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MotionEvent; -import android.view.OrientationEventListener; -import android.view.Surface; import android.view.View; import android.view.ViewDebug; import android.view.ViewGroup; @@ -103,7 +102,6 @@ import com.android.launcher3.anim.SpringProperty; import com.android.launcher3.compat.AccessibilityManagerCompat; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.statehandlers.DepthController; -import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.touch.PagedOrientationHandler; import com.android.launcher3.touch.PagedOrientationHandler.CurveProperties; import com.android.launcher3.userevent.nano.LauncherLogProto; @@ -191,8 +189,6 @@ public abstract class RecentsView extends PagedView impl }; protected final RecentsOrientedState mOrientationState; - private OrientationEventListener mOrientationListener; - private int mPreviousRotation; protected RecentsAnimationController mRecentsAnimationController; protected RecentsAnimationTargets mRecentsAnimationTargets; protected AppWindowAnimationHelper mAppWindowAnimationHelper; @@ -301,9 +297,6 @@ public abstract class RecentsView extends PagedView impl } }; - private final RecentsOrientedState.SystemRotationChangeListener mSystemRotationChangeListener = - enabled -> toggleOrientationEventListener(); - private final PinnedStackAnimationListener mIPinnedStackAnimationListener = new PinnedStackAnimationListener(); @@ -360,11 +353,13 @@ public abstract class RecentsView extends PagedView impl } }; - public RecentsView(Context context, AttributeSet attrs, int defStyleAttr) { + public RecentsView(Context context, AttributeSet attrs, int defStyleAttr, + boolean rotationSupportedByActivity) { super(context, attrs, defStyleAttr); setPageSpacing(getResources().getDimensionPixelSize(R.dimen.recents_page_spacing)); setEnableFreeScroll(true); - mOrientationState = new RecentsOrientedState(context); + mOrientationState = new RecentsOrientedState( + context, rotationSupportedByActivity, this::animateRecentsRotationInPlace); mFastFlingVelocity = getResources() .getDimensionPixelSize(R.dimen.recents_fast_fling_velocity); @@ -399,21 +394,10 @@ public abstract class RecentsView extends PagedView impl .getDimensionPixelSize(R.dimen.recents_empty_message_text_padding); setWillNotDraw(false); updateEmptyMessage(); - disableMultipleLayoutRotations(!supportsVerticalLandscape()); + mOrientationHandler = mOrientationState.getOrientationHandler(); // Initialize quickstep specific cache params here, as this is constructed only once mActivity.getViewCache().setCacheSize(R.layout.digital_wellbeing_toast, 5); - - mOrientationListener = new OrientationEventListener(getContext()) { - @Override - public void onOrientationChanged(int i) { - int rotation = RecentsOrientedState.getRotationForUserDegreesRotated(i); - if (mPreviousRotation != rotation) { - animateRecentsRotationInPlace(rotation); - mPreviousRotation = rotation; - } - } - }; } public OverScroller getScroller() { @@ -502,7 +486,6 @@ public abstract class RecentsView extends PagedView impl SystemUiProxy.INSTANCE.get(getContext()).setPinnedStackAnimationListener( mIPinnedStackAnimationListener); mOrientationState.init(); - mOrientationState.addSystemRotationChangeListener(mSystemRotationChangeListener); } @Override @@ -517,7 +500,6 @@ public abstract class RecentsView extends PagedView impl mIdp.removeOnChangeListener(this); SystemUiProxy.INSTANCE.get(getContext()).setPinnedStackAnimationListener(null); mIPinnedStackAnimationListener.setActivity(null); - mOrientationState.removeSystemRotationChangeListener(mSystemRotationChangeListener); mOrientationState.destroy(); } @@ -576,31 +558,12 @@ public abstract class RecentsView extends PagedView impl public void setOverviewStateEnabled(boolean enabled) { mOverviewStateEnabled = enabled; updateTaskStackListenerState(); + mOrientationState.setRotationWatcherEnabled(enabled); if (!enabled) { // Reset the running task when leaving overview since it can still have a reference to // its thumbnail mTmpRunningTask = null; } - toggleOrientationEventListener(); - } - - private void toggleOrientationEventListener() { - boolean canEnable = canEnableOverviewRotationAnimation() && mOverviewStateEnabled; - UI_HELPER_EXECUTOR.execute(() -> { - if (canEnable) { - mOrientationListener.enable(); - } else { - mOrientationListener.disable(); - } - }); - } - - private boolean canEnableOverviewRotationAnimation() { - return supportsVerticalLandscape() // not 3P launcher - && !TestProtocol.sDisableSensorRotation // Ignore hardware dependency for tests.. - && mOrientationListener.canDetectOrientation() // ..but does the hardware even work? - && (mOrientationState.isSystemRotationAllowed() && - !mOrientationState.canLauncherRotate()); // launcher is going to rotate itself } public void onDigitalWellbeingToastShown() { @@ -820,9 +783,7 @@ public abstract class RecentsView extends PagedView impl for (int i = 0; i < taskCount; i++) { getTaskViewAt(i).setFullscreenProgress(mFullscreenProgress); } - if (mActionsView != null && mOrientationState.getLauncherRotation() == Surface.ROTATION_0) { - mActionsView.setVisibility(fullscreenProgress == 0 ? VISIBLE : INVISIBLE); - } + mActionsView.updateHiddenFlags(HIDDEN_FULLESCREEN_PROGRESS, fullscreenProgress > 0); } private void updateTaskStackListenerState() { @@ -1039,10 +1000,6 @@ public abstract class RecentsView extends PagedView impl } private void animateRecentsRotationInPlace(int newRotation) { - if (!supportsVerticalLandscape()) { - return; - } - AnimatorSet pa = setRecentsChangedOrientation(true); pa.addListener(AnimationSuccessListener.forRunnable(() -> { setLayoutRotation(newRotation, mOrientationState.getDisplayRotation()); @@ -1067,7 +1024,6 @@ public abstract class RecentsView extends PagedView impl return as; } - abstract protected boolean supportsVerticalLandscape(); private void rotateAllChildTasks() { for (int i = 0; i < getTaskViewCount(); i++) { @@ -1611,17 +1567,12 @@ public abstract class RecentsView extends PagedView impl setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR); mClearAllButton.setRotation(mOrientationHandler.getDegreesRotated()); mActivity.getDragLayer().recreateControllers(); - mActionsView.updateHiddenFlags(HIDDEN_NON_ZERO_ROTATION, touchRotation != 0); + mActionsView.updateHiddenFlags(HIDDEN_NON_ZERO_ROTATION, + touchRotation != 0 || launcherRotation != 0); requestLayout(); } } - public void disableMultipleLayoutRotations(boolean disable) { - mOrientationState.disableMultipleOrientations(disable); - mOrientationHandler = mOrientationState.getOrientationHandler(); - requestLayout(); - } - public RecentsOrientedState getPagedViewOrientedState() { return mOrientationState; } @@ -2083,8 +2034,7 @@ public abstract class RecentsView extends PagedView impl public Consumer getEventDispatcher(float navbarRotation) { float degreesRotated; if (navbarRotation == 0) { - degreesRotated = mOrientationState.areMultipleLayoutOrientationsDisabled() ? 0 : - mOrientationHandler.getDegreesRotated(); + degreesRotated = mOrientationHandler.getDegreesRotated(); } else { degreesRotated = -navbarRotation; } @@ -2097,7 +2047,7 @@ public abstract class RecentsView extends PagedView impl // PagedOrientationHandler return e -> { if (navbarRotation != 0 - && !mOrientationState.areMultipleLayoutOrientationsDisabled() + && mOrientationState.isMultipleOrientationSupportedByDevice() && !mOrientationState.getOrientationHandler().isLayoutNaturalToLauncher()) { mOrientationState.flipVertical(e); super.onTouchEvent(e); diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java index 0a00a61c12..a6ce2b5340 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java @@ -21,6 +21,7 @@ import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON; import static com.android.quickstep.SysUINavigationMode.Mode.THREE_BUTTONS; import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS; +import static com.android.quickstep.util.RecentsOrientedState.isFixedRotationTransformEnabled; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED; @@ -35,7 +36,6 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_S import android.app.ActivityManager; import android.content.BroadcastReceiver; import android.content.ComponentName; -import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -51,8 +51,6 @@ import androidx.annotation.BinderThread; import com.android.launcher3.R; import com.android.launcher3.Utilities; -import com.android.launcher3.config.FeatureFlags; -import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.util.DefaultDisplay; import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener; import com.android.quickstep.util.NavBarPosition; @@ -176,7 +174,7 @@ public class RecentsAnimationDeviceState implements } private void setupOrientationSwipeHandler() { - if (!FeatureFlags.ENABLE_FIXED_ROTATION_TRANSFORM.get()) { + if (!isFixedRotationTransformEnabled(mContext)) { return; } diff --git a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java index 5be0675cbb..74daeca33f 100644 --- a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java +++ b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java @@ -16,17 +16,13 @@ package com.android.quickstep.util; -import static android.Manifest.permission.WRITE_SECURE_SETTINGS; -import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.util.DisplayMetrics.DENSITY_DEVICE_STABLE; import static android.view.Surface.ROTATION_0; import static android.view.Surface.ROTATION_180; import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; -import static com.android.launcher3.config.FeatureFlags.FLAG_ENABLE_FIXED_ROTATION_TRANSFORM; import static com.android.launcher3.states.RotationHelper.ALLOW_ROTATION_PREFERENCE_KEY; -import static com.android.launcher3.states.RotationHelper.FIXED_ROTATION_TRANSFORM_SETTING_NAME; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import static java.lang.annotation.RetentionPolicy.SOURCE; @@ -44,19 +40,18 @@ import android.os.Handler; import android.provider.Settings; import android.util.Log; import android.view.MotionEvent; +import android.view.OrientationEventListener; import android.view.Surface; import androidx.annotation.IntDef; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Utilities; -import com.android.launcher3.config.FeatureFlags; +import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.touch.PagedOrientationHandler; -import com.android.launcher3.touch.PortraitPagedViewHandler; import java.lang.annotation.Retention; -import java.util.ArrayList; -import java.util.List; +import java.util.function.IntConsumer; /** * Container to hold orientation/rotation related information for Launcher. @@ -71,6 +66,8 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre private static final String TAG = "RecentsOrientedState"; private static final boolean DEBUG = false; + private static final String FIXED_ROTATION_TRANSFORM_SETTING_NAME = "fixed_rotation_transform"; + private ContentObserver mSystemAutoRotateObserver = new ContentObserver(new Handler()) { @Override public void onChange(boolean selfChange) { @@ -87,46 +84,79 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre private @SurfaceRotation int mDisplayRotation = ROTATION_0; private @SurfaceRotation int mLauncherRotation = Surface.ROTATION_0; - public interface SystemRotationChangeListener { - void onSystemRotationChanged(boolean enabled); - } + // Launcher activity supports multiple orientation, but fallback activity does not + private static final int FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_ACTIVITY = 1 << 0; + // Multiple orientation is only supported if density is < 600 + private static final int FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_DENSITY = 1 << 1; + // Feature flag controlling the multi-orientation feature + private static final int FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_FLAG = 1 << 2; + // Shared prefs for rotation, only if activity supports it + private static final int FLAG_HOME_ROTATION_ALLOWED_IN_PREFS = 1 << 3; + // If the user has enabled system rotation + private static final int FLAG_SYSTEM_ROTATION_ALLOWED = 1 << 4; + // Whether to rotation sensor is supported on the device + private static final int FLAG_ROTATION_WATCHER_SUPPORTED = 1 << 5; + // Whether to enable rotation watcher when multi-rotation is supported + private static final int FLAG_ROTATION_WATCHER_ENABLED = 1 << 6; - /** - * If {@code true} we default to {@link PortraitPagedViewHandler} and don't support any fake - * launcher orientations. - */ - private boolean mDisableMultipleOrientations; - private boolean mIsHomeRotationAllowed; - private boolean mIsSystemRotationAllowed; + private static final int MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE = + FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_ACTIVITY + | FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_DENSITY + | FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_FLAG; + + private static final int MASK_ACTIVITY_ROTATING = + FLAG_HOME_ROTATION_ALLOWED_IN_PREFS | FLAG_SYSTEM_ROTATION_ALLOWED; + + // State for which rotation watcher will be enabled. + // We skip it when home rotation is enabled as in that case, activity itself rotates + private static final int VALUE_ROTATION_WATCHER_ENABLED = + MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE | FLAG_SYSTEM_ROTATION_ALLOWED + | FLAG_ROTATION_WATCHER_SUPPORTED | FLAG_ROTATION_WATCHER_ENABLED; private final ContentResolver mContentResolver; private final SharedPreferences mSharedPrefs; - private final boolean mAllowConfigurationDefaultValue; - - private List mSystemRotationChangeListeners = new ArrayList<>(); + private final OrientationEventListener mOrientationListener; private final Matrix mTmpMatrix = new Matrix(); private final Matrix mTmpInverseMatrix = new Matrix(); - public RecentsOrientedState(Context context) { + private int mFlags; + private int mPreviousRotation = ROTATION_0; + + /** + * @param rotationChangeListener Callback for receiving rotation events when rotation watcher + * is enabled + * @see #setRotationWatcherEnabled(boolean) + */ + public RecentsOrientedState(Context context, boolean rotationSupportedByActivity, + IntConsumer rotationChangeListener) { mContentResolver = context.getContentResolver(); mSharedPrefs = Utilities.getPrefs(context); + mOrientationListener = new OrientationEventListener(context) { + @Override + public void onOrientationChanged(int degrees) { + int newRotation = getRotationForUserDegreesRotated(degrees); + if (newRotation != mPreviousRotation) { + mPreviousRotation = newRotation; + rotationChangeListener.accept(newRotation); + } + } + }; + + mFlags = rotationSupportedByActivity ? FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_ACTIVITY : 0; Resources res = context.getResources(); int originalSmallestWidth = res.getConfiguration().smallestScreenWidthDp * res.getDisplayMetrics().densityDpi / DENSITY_DEVICE_STABLE; - mAllowConfigurationDefaultValue = originalSmallestWidth >= 600; - - boolean isForcedRotation = Utilities.getFeatureFlagsPrefs(context) - .getBoolean(FLAG_ENABLE_FIXED_ROTATION_TRANSFORM, true) - && !mAllowConfigurationDefaultValue; - UI_HELPER_EXECUTOR.execute(() -> { - if (context.checkSelfPermission(WRITE_SECURE_SETTINGS) == PERMISSION_GRANTED) { - Settings.Global.putInt(mContentResolver, FIXED_ROTATION_TRANSFORM_SETTING_NAME, - isForcedRotation ? 1 : 0); - } - }); - disableMultipleOrientations(!isForcedRotation); + if (originalSmallestWidth < 600) { + mFlags |= FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_DENSITY; + } + if (isFixedRotationTransformEnabled(context)) { + mFlags |= FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_FLAG; + } + if (mOrientationListener.canDetectOrientation()) { + mFlags |= FLAG_ROTATION_WATCHER_SUPPORTED; + } } /** @@ -140,10 +170,7 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre public boolean update( @SurfaceRotation int touchRotation, @SurfaceRotation int displayRotation, @SurfaceRotation int launcherRotation) { - if (!FeatureFlags.ENABLE_FIXED_ROTATION_TRANSFORM.get()) { - return false; - } - if (mDisableMultipleOrientations) { + if (!isMultipleOrientationSupportedByDevice()) { return false; } if (mDisplayRotation == displayRotation && mTouchRotation == touchRotation @@ -155,8 +182,7 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre mDisplayRotation = displayRotation; mTouchRotation = touchRotation; - if ((mIsHomeRotationAllowed && mIsSystemRotationAllowed) || - mLauncherRotation == mTouchRotation) { + if (canLauncherRotate() || mLauncherRotation == mTouchRotation) { // TODO(b/153476489) Need to determine when launcher is rotated mOrientationHandler = PagedOrientationHandler.HOME_ROTATED; if (DEBUG) { @@ -178,14 +204,25 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre return true; } - /** - * Setting this preference renders future calls to {@link #update(int, int, int)} as a no-op. - */ - public void disableMultipleOrientations(boolean disable) { - mDisableMultipleOrientations = disable; - if (disable) { - mDisplayRotation = mTouchRotation = ROTATION_0; - mOrientationHandler = PagedOrientationHandler.PORTRAIT; + private void setFlag(int mask, boolean enabled) { + boolean wasRotationEnabled = !TestProtocol.sDisableSensorRotation + && mFlags == VALUE_ROTATION_WATCHER_ENABLED; + if (enabled) { + mFlags |= mask; + } else { + mFlags &= ~mask; + } + + boolean isRotationEnabled = !TestProtocol.sDisableSensorRotation + && mFlags == VALUE_ROTATION_WATCHER_ENABLED; + if (wasRotationEnabled != isRotationEnabled) { + UI_HELPER_EXECUTOR.execute(() -> { + if (isRotationEnabled) { + mOrientationListener.enable(); + } else { + mOrientationListener.disable(); + } + }); } } @@ -195,47 +232,49 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre } private void updateAutoRotateSetting() { - try { - mIsSystemRotationAllowed = Settings.System.getInt(mContentResolver, - Settings.System.ACCELEROMETER_ROTATION) == 1; - } catch (Settings.SettingNotFoundException e) { - Log.e(TAG, "autorotate setting not found", e); - } - - for (SystemRotationChangeListener listener : mSystemRotationChangeListeners) { - listener.onSystemRotationChanged(mIsSystemRotationAllowed); - } + setFlag(FLAG_SYSTEM_ROTATION_ALLOWED, Settings.System.getInt(mContentResolver, + Settings.System.ACCELEROMETER_ROTATION, 1) == 1); } private void updateHomeRotationSetting() { - mIsHomeRotationAllowed = mSharedPrefs.getBoolean(ALLOW_ROTATION_PREFERENCE_KEY, - mAllowConfigurationDefaultValue); - } - - public void addSystemRotationChangeListener(SystemRotationChangeListener listener) { - mSystemRotationChangeListeners.add(listener); - listener.onSystemRotationChanged(mIsSystemRotationAllowed); - } - - public void removeSystemRotationChangeListener(SystemRotationChangeListener listener) { - mSystemRotationChangeListeners.remove(listener); + setFlag(FLAG_HOME_ROTATION_ALLOWED_IN_PREFS, + mSharedPrefs.getBoolean(ALLOW_ROTATION_PREFERENCE_KEY, false)); } + /** + * Initializes aany system values and registers corresponding change listeners. It must be + * paired with {@link #destroy()} call + */ public void init() { - mSharedPrefs.registerOnSharedPreferenceChangeListener(this); - mContentResolver.registerContentObserver( - Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION), - false, mSystemAutoRotateObserver); + if (isMultipleOrientationSupportedByDevice()) { + mSharedPrefs.registerOnSharedPreferenceChangeListener(this); + mContentResolver.registerContentObserver( + Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION), + false, mSystemAutoRotateObserver); + } + initWithoutListeners(); + } + + /** + * Unregisters any previously registered listeners. + */ + public void destroy() { + if (isMultipleOrientationSupportedByDevice()) { + mSharedPrefs.unregisterOnSharedPreferenceChangeListener(this); + mContentResolver.unregisterContentObserver(mSystemAutoRotateObserver); + } + setRotationWatcherEnabled(false); + } + + /** + * Initializes the OrientationState without attaching any listeners. This can be used when + * the object is short lived. + */ + public void initWithoutListeners() { updateAutoRotateSetting(); updateHomeRotationSetting(); } - public void destroy() { - mSharedPrefs.unregisterOnSharedPreferenceChangeListener(this); - mContentResolver.unregisterContentObserver(mSystemAutoRotateObserver); - mSystemRotationChangeListeners.clear(); - } - @SurfaceRotation public int getDisplayRotation() { return mDisplayRotation; @@ -251,20 +290,24 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre return mLauncherRotation; } - public boolean areMultipleLayoutOrientationsDisabled() { - return mDisableMultipleOrientations; - } - - public boolean isSystemRotationAllowed() { - return mIsSystemRotationAllowed; + public boolean isMultipleOrientationSupportedByDevice() { + return (mFlags & MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE) + == MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE; } public boolean isHomeRotationAllowed() { - return mIsHomeRotationAllowed; + return (mFlags & FLAG_HOME_ROTATION_ALLOWED_IN_PREFS) != 0; } public boolean canLauncherRotate() { - return isSystemRotationAllowed() && isHomeRotationAllowed(); + return (mFlags & MASK_ACTIVITY_ROTATING) == MASK_ACTIVITY_ROTATING; + } + + /** + * Enables or disables the rotation watcher for listening to rotation callbacks + */ + public void setRotationWatcherEnabled(boolean isEnabled) { + setFlag(FLAG_ROTATION_WATCHER_ENABLED, isEnabled); } public int getTouchRotationDegrees() { @@ -388,4 +431,13 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre break; } } + + /** + * Returns true if system can keep Launcher fixed to portrait layout even if the + * foreground app is rotated + */ + public static boolean isFixedRotationTransformEnabled(Context context) { + return Settings.Global.getInt( + context.getContentResolver(), FIXED_ROTATION_TRANSFORM_SETTING_NAME, 1) == 1; + } } diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index 2b91cb1fa3..65d3cd2ded 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -159,10 +159,6 @@ public final class FeatureFlags { "ALWAYS_USE_HARDWARE_OPTIMIZATION_FOR_FOLDER_ANIMATIONS", false, "Always use hardware optimization for folder animations."); - public static final BooleanFlag ENABLE_FIXED_ROTATION_TRANSFORM = getDebugFlag( - FLAG_ENABLE_FIXED_ROTATION_TRANSFORM, true, - "Launch/close apps without rotation animation. Fix Launcher to portrait"); - public static void initialize(Context context) { synchronized (sDebugFlags) { for (DebugFlag flag : sDebugFlags) { diff --git a/src/com/android/launcher3/states/RotationHelper.java b/src/com/android/launcher3/states/RotationHelper.java index 3640d8bbde..5a60f5328a 100644 --- a/src/com/android/launcher3/states/RotationHelper.java +++ b/src/com/android/launcher3/states/RotationHelper.java @@ -43,7 +43,6 @@ public class RotationHelper implements OnSharedPreferenceChangeListener { public static final String ALLOW_ROTATION_PREFERENCE_KEY = "pref_allowRotation"; - public static final String FIXED_ROTATION_TRANSFORM_SETTING_NAME = "fixed_rotation_transform"; private final ContentResolver mContentResolver; private boolean mSystemAutoRotateEnabled;