Merge "Don't allow swiping from overview to all apps in 3 button mode" into ub-launcher3-rvc-dev
diff --git a/quickstep/recents_ui_overrides/res/values/dimens.xml b/quickstep/recents_ui_overrides/res/values/dimens.xml
index 363840a..9266b06 100644
--- a/quickstep/recents_ui_overrides/res/values/dimens.xml
+++ b/quickstep/recents_ui_overrides/res/values/dimens.xml
@@ -20,6 +20,7 @@
<dimen name="chip_hint_start_padding">10dp</dimen>
<dimen name="chip_hint_end_padding">12dp</dimen>
<dimen name="chip_hint_horizontal_margin">20dp</dimen>
+ <dimen name="chip_hint_vertical_offset">16dp</dimen>
<dimen name="chip_hint_elevation">2dp</dimen>
<dimen name="chip_icon_size">16dp</dimen>
<dimen name="chip_text_height">26dp</dimen>
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
index 6c64bf7..79b4002 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
@@ -197,15 +197,15 @@
case INDEX_RECENTS_FADE_ANIM:
return ObjectAnimator.ofFloat(mLauncher.getOverviewPanel(),
RecentsView.CONTENT_ALPHA, values);
- case INDEX_RECENTS_TRANSLATE_X_ANIM:
- // TODO: Do not assume motion across X axis for adjacent page
- return new SpringAnimationBuilder<>(
- mLauncher.getOverviewPanel(), ADJACENT_PAGE_OFFSET)
- .setMinimumVisibleChange(1f / mLauncher.getOverviewPanel().getWidth())
+ case INDEX_RECENTS_TRANSLATE_X_ANIM: {
+ RecentsView rv = mLauncher.getOverviewPanel();
+ return new SpringAnimationBuilder(mLauncher)
+ .setMinimumVisibleChange(1f / rv.getPageOffsetScale())
.setDampingRatio(0.8f)
.setStiffness(250)
.setValues(values)
- .build(mLauncher);
+ .build(rv, ADJACENT_PAGE_OFFSET);
+ }
case INDEX_PAUSE_TO_OVERVIEW_ANIM: {
StateAnimationConfig config = new StateAnimationConfig();
config.duration = ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW;
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
index 77118d5..2b456ec 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
@@ -15,7 +15,6 @@
*/
package com.android.launcher3.uioverrides.touchcontrollers;
-import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
@@ -23,6 +22,7 @@
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.touch.AbstractStateChangeTouchController.SUCCESS_TRANSITION_PROGRESS;
+import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import android.animation.ValueAnimator;
@@ -131,12 +131,8 @@
final PendingAnimation builder = new PendingAnimation(accuracy);
if (mStartState == OVERVIEW) {
RecentsView recentsView = mLauncher.getOverviewPanel();
- float pullbackDist = mPullbackDistance;
- if (!recentsView.isRtl()) {
- pullbackDist = -pullbackDist;
- }
-
- builder.setFloat(recentsView, VIEW_TRANSLATE_X, pullbackDist, PULLBACK_INTERPOLATOR);
+ builder.setFloat(recentsView, ADJACENT_PAGE_OFFSET,
+ -mPullbackDistance / recentsView.getPageOffsetScale(), PULLBACK_INTERPOLATOR);
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
builder.addOnFrameCallback(
() -> recentsView.redrawLiveTile(false /* mightNeedToRefill */));
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 32ab98b..d22e5af 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 @@
mAppWindowAnimationHelper.updateHomeBounds(getStackBounds(dp));
}
int displayRotation = 0;
- if (mOrientedState != null && !mOrientedState.areMultipleLayoutOrientationsDisabled()) {
+ if (mOrientedState != null && mOrientedState.isMultipleOrientationSupportedByDevice()) {
// TODO(b/150300347): The first recents animation after launcher is started with the
// foreground app not in landscape will look funky until that bug is fixed
displayRotation = mOrientedState.getDisplayRotation();
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java
index 5a64382..52b40a9 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java
@@ -208,7 +208,8 @@
mTaskAnimationManager = taskAnimationManager;
mTouchTimeMs = touchTimeMs;
mContinuingLastGesture = continuingLastGesture;
- mTaskViewSimulator = new TaskViewSimulator(context, LayoutUtils::calculateLauncherTaskSize);
+ mTaskViewSimulator = new TaskViewSimulator(
+ context, LayoutUtils::calculateLauncherTaskSize, true);
initAfterSubclassConstructor();
initStateCallbacks();
@@ -1076,7 +1077,8 @@
}
private void continueComputingRecentsScrollIfNecessary() {
- if (!mGestureState.hasState(STATE_RECENTS_SCROLLING_FINISHED)) {
+ if (!mGestureState.hasState(STATE_RECENTS_SCROLLING_FINISHED)
+ && !mStateCallback.hasStates(STATE_HANDLER_INVALIDATED)) {
computeRecentsScrollIfInvisible();
mRecentsView.post(this::continueComputingRecentsScrollIfNecessary);
}
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 9b5a935..28c2b97 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.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 @@
}
private void handleOrientationSetup(InputConsumer baseInputConsumer) {
- if (!FeatureFlags.ENABLE_FIXED_ROTATION_TRANSFORM.get()) {
+ if (!isFixedRotationTransformEnabled(this)) {
return;
}
mDeviceState.enableMultipleRegions(baseInputConsumer instanceof OtherActivityInputConsumer);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
index 235ac16..3cf9b2c 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -65,7 +65,7 @@
}
public FallbackRecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
+ super(context, attrs, defStyleAttr, false);
}
@Override
@@ -195,9 +195,4 @@
}
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 00329b8..9309110 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 @@
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/StaggeredWorkspaceAnim.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
index bde6f9a..13c20f1 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
@@ -28,6 +28,7 @@
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
import android.view.View;
import android.view.ViewGroup;
@@ -185,13 +186,13 @@
ResourceProvider rp = DynamicResource.provider(v.getContext());
float stiffness = rp.getFloat(R.dimen.staggered_stiffness);
float damping = rp.getFloat(R.dimen.staggered_damping_ratio);
- ObjectAnimator springTransY = new SpringAnimationBuilder<>(v, VIEW_TRANSLATE_Y)
+ ValueAnimator springTransY = new SpringAnimationBuilder(v.getContext())
.setStiffness(stiffness)
.setDampingRatio(damping)
.setMinimumVisibleChange(1f)
.setEndValue(0)
.setStartVelocity(mVelocity)
- .build(v.getContext());
+ .build(v, VIEW_TRANSLATE_Y);
springTransY.setStartDelay(startDelay);
mAnimators.play(springTransY);
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 0131fdf..0bc021b 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.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 @@
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 @@
* @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 @@
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 @@
// 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 454223e..0b6d340 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.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 LauncherRecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
+ super(context, attrs, defStyleAttr, true);
mActivity.getStateManager().addStateListener(this);
}
@@ -265,12 +264,6 @@
}
@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 93e68c0..d160686 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 @@
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 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 b687920..3b6fd13 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.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.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.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 @@
};
protected final RecentsOrientedState mOrientationState;
- private OrientationEventListener mOrientationListener;
- private int mPreviousRotation;
protected RecentsAnimationController mRecentsAnimationController;
protected RecentsAnimationTargets mRecentsAnimationTargets;
protected AppWindowAnimationHelper mAppWindowAnimationHelper;
@@ -301,9 +297,6 @@
}
};
- private final RecentsOrientedState.SystemRotationChangeListener mSystemRotationChangeListener =
- enabled -> toggleOrientationEventListener();
-
private final PinnedStackAnimationListener mIPinnedStackAnimationListener =
new PinnedStackAnimationListener();
@@ -360,11 +353,13 @@
}
};
- 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 @@
.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 @@
SystemUiProxy.INSTANCE.get(getContext()).setPinnedStackAnimationListener(
mIPinnedStackAnimationListener);
mOrientationState.init();
- mOrientationState.addSystemRotationChangeListener(mSystemRotationChangeListener);
}
@Override
@@ -517,7 +500,6 @@
mIdp.removeOnChangeListener(this);
SystemUiProxy.INSTANCE.get(getContext()).setPinnedStackAnimationListener(null);
mIPinnedStackAnimationListener.setActivity(null);
- mOrientationState.removeSystemRotationChangeListener(mSystemRotationChangeListener);
mOrientationState.destroy();
}
@@ -576,31 +558,12 @@
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 @@
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 @@
}
private void animateRecentsRotationInPlace(int newRotation) {
- if (!supportsVerticalLandscape()) {
- return;
- }
-
AnimatorSet pa = setRecentsChangedOrientation(true);
pa.addListener(AnimationSuccessListener.forRunnable(() -> {
setLayoutRotation(newRotation, mOrientationState.getDisplayRotation());
@@ -1067,7 +1024,6 @@
return as;
}
- abstract protected boolean supportsVerticalLandscape();
private void rotateAllChildTasks() {
for (int i = 0; i < getTaskViewCount(); i++) {
@@ -1611,17 +1567,12 @@
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;
}
@@ -1719,6 +1670,13 @@
updateCurveProperties();
}
+ /**
+ * TODO: Do not assume motion across X axis for adjacent page
+ */
+ public float getPageOffsetScale() {
+ return Math.max(getWidth(), 1);
+ }
+
private void updateDeadZoneRects() {
// Get the deadzone rect surrounding the clear all button to not dismiss overview to home
mClearAllButtonDeadZoneRect.setEmpty();
@@ -2083,8 +2041,7 @@
public Consumer<MotionEvent> getEventDispatcher(float navbarRotation) {
float degreesRotated;
if (navbarRotation == 0) {
- degreesRotated = mOrientationState.areMultipleLayoutOrientationsDisabled() ? 0 :
- mOrientationHandler.getDegreesRotated();
+ degreesRotated = mOrientationHandler.getDegreesRotated();
} else {
degreesRotated = -navbarRotation;
}
@@ -2097,7 +2054,7 @@
// PagedOrientationHandler
return e -> {
if (navbarRotation != 0
- && !mOrientationState.areMultipleLayoutOrientationsDisabled()
+ && mOrientationState.isMultipleOrientationSupportedByDevice()
&& !mOrientationState.getOrientationHandler().isLayoutNaturalToLauncher()) {
mOrientationState.flipVertical(e);
super.onTouchEvent(e);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
index b0758c9..12ef521 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
@@ -174,11 +174,12 @@
// Order in which the footers appear. Lower order appear below higher order.
public static final int INDEX_DIGITAL_WELLBEING_TOAST = 0;
- public static final int INDEX_PROACTIVE_SUGGEST = 1;
private final FooterWrapper[] mFooters = new FooterWrapper[2];
private float mFooterVerticalOffset = 0;
private float mFooterAlpha = 1;
private int mStackHeight;
+ private View mContextualChipWrapper;
+ private View mContextualChip;
public TaskView(Context context) {
this(context, null);
@@ -255,8 +256,14 @@
footer.animateHide();
}
}
+ if (mContextualChip != null) {
+ mContextualChip.animate().scaleX(0f).scaleY(0f).setDuration(300);
+ }
mIconView.animate().alpha(0.0f);
} else {
+ if (mContextualChip != null) {
+ mContextualChip.animate().scaleX(1f).scaleY(1f).setDuration(300);
+ }
mIconView.animate().alpha(1.0f);
}
@@ -657,6 +664,51 @@
return oldFooter;
}
+ /**
+ * Sets the contextual chip.
+ *
+ * @param view Wrapper view containing contextual chip.
+ */
+ public void setContextualChip(View view) {
+ if (mContextualChipWrapper != null) {
+ removeView(mContextualChipWrapper);
+ }
+ if (view != null) {
+ mContextualChipWrapper = view;
+ LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT,
+ LayoutParams.WRAP_CONTENT);
+ layoutParams.gravity = BOTTOM | CENTER_HORIZONTAL;
+ layoutParams.bottomMargin = (int)
+ (((MarginLayoutParams) mSnapshotView.getLayoutParams()).bottomMargin
+ - getExpectedViewHeight(view) + getResources().getDimension(
+ R.dimen.chip_hint_vertical_offset));
+ mContextualChip = ((FrameLayout) mContextualChipWrapper).getChildAt(0);
+ mContextualChip.setScaleX(0f);
+ mContextualChip.setScaleY(0f);
+ addView(view, getChildCount(), layoutParams);
+ view.setAlpha(mFooterAlpha);
+ if (mContextualChip != null) {
+ mContextualChip.animate().scaleX(1f).scaleY(1f).setDuration(50);
+ }
+ }
+
+ }
+
+ /**
+ * Clears the contextual chip from TaskView.
+ *
+ * @return The contextual chip wrapper view to be recycled.
+ */
+ public View clearContextualChip() {
+ if (mContextualChipWrapper != null) {
+ removeView(mContextualChipWrapper);
+ }
+ View oldContextualChipWrapper = mContextualChipWrapper;
+ mContextualChipWrapper = null;
+ mContextualChip = null;
+ return oldContextualChipWrapper;
+ }
+
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
@@ -750,14 +802,7 @@
mDelegate = mOldOutlineProvider == null
? ViewOutlineProvider.BACKGROUND : mOldOutlineProvider;
- int h = view.getLayoutParams().height;
- if (h > 0) {
- mExpectedHeight = h;
- } else {
- int m = MeasureSpec.makeMeasureSpec(MeasureSpec.EXACTLY - 1, MeasureSpec.AT_MOST);
- view.measure(m, m);
- mExpectedHeight = view.getMeasuredHeight();
- }
+ mExpectedHeight = getExpectedViewHeight(view);
mOldPaddingBottom = view.getPaddingBottom();
if (mOldOutlineProvider != null) {
@@ -819,6 +864,19 @@
}
}
+ private int getExpectedViewHeight(View view) {
+ int expectedHeight;
+ int h = view.getLayoutParams().height;
+ if (h > 0) {
+ expectedHeight = h;
+ } else {
+ int m = MeasureSpec.makeMeasureSpec(MeasureSpec.EXACTLY - 1, MeasureSpec.AT_MOST);
+ view.measure(m, m);
+ expectedHeight = view.getMeasuredHeight();
+ }
+ return expectedHeight;
+ }
+
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index 65763d4..af63a25 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -161,6 +161,8 @@
@Override
protected void setupViews() {
super.setupViews();
+
+ SysUINavigationMode.INSTANCE.get(this).updateMode();
mActionsView = findViewById(R.id.overview_actions_view);
((RecentsView) getOverviewPanel()).init(mActionsView);
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 0a00a61..a6ce2b5 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.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 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 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 @@
}
private void setupOrientationSwipeHandler() {
- if (!FeatureFlags.ENABLE_FIXED_ROTATION_TRANSFORM.get()) {
+ if (!isFixedRotationTransformEnabled(mContext)) {
return;
}
diff --git a/quickstep/src/com/android/quickstep/SysUINavigationMode.java b/quickstep/src/com/android/quickstep/SysUINavigationMode.java
index 6a10b37..c715c93 100644
--- a/quickstep/src/com/android/quickstep/SysUINavigationMode.java
+++ b/quickstep/src/com/android/quickstep/SysUINavigationMode.java
@@ -74,15 +74,20 @@
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- Mode oldMode = mMode;
- initializeMode();
- if (mMode != oldMode) {
- dispatchModeChange();
- }
+ updateMode();
}
}, getPackageFilter("android", ACTION_OVERLAY_CHANGED));
}
+ /** Updates navigation mode when needed. */
+ public void updateMode() {
+ Mode oldMode = mMode;
+ initializeMode();
+ if (mMode != oldMode) {
+ dispatchModeChange();
+ }
+ }
+
private void initializeMode() {
int modeInt = getSystemIntegerRes(mContext, NAV_BAR_INTERACTION_MODE_RES_NAME);
for(Mode m : Mode.values()) {
diff --git a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
index 5be0675..74daeca 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.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 @@
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 @@
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<SystemRotationChangeListener> 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 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 @@
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 @@
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 @@
}
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);
+ setFlag(FLAG_HOME_ROTATION_ALLOWED_IN_PREFS,
+ mSharedPrefs.getBoolean(ALLOW_ROTATION_PREFERENCE_KEY, false));
}
- public void addSystemRotationChangeListener(SystemRotationChangeListener listener) {
- mSystemRotationChangeListeners.add(listener);
- listener.onSystemRotationChanged(mIsSystemRotationAllowed);
- }
-
- public void removeSystemRotationChangeListener(SystemRotationChangeListener listener) {
- mSystemRotationChangeListeners.remove(listener);
- }
-
+ /**
+ * 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 @@
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 @@
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/res/values/config.xml b/res/values/config.xml
index 0657b86..41bb909 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -125,11 +125,11 @@
<item name="all_apps_spring_damping_ratio" type="dimen" format="float">0.75</item>
<item name="all_apps_spring_stiffness" type="dimen" format="float">600</item>
- <item name="dismiss_task_trans_y_damping_ratio" type="dimen" format="float">0.5</item>
- <item name="dismiss_task_trans_y_stiffness" type="dimen" format="float">1500</item>
+ <item name="dismiss_task_trans_y_damping_ratio" type="dimen" format="float">0.73</item>
+ <item name="dismiss_task_trans_y_stiffness" type="dimen" format="float">800</item>
- <item name="dismiss_task_trans_x_damping_ratio" type="dimen" format="float">0.5</item>
- <item name="dismiss_task_trans_x_stiffness" type="dimen" format="float">1500</item>
+ <item name="dismiss_task_trans_x_damping_ratio" type="dimen" format="float">0.73</item>
+ <item name="dismiss_task_trans_x_stiffness" type="dimen" format="float">800</item>
<item name="horizontal_spring_damping_ratio" type="dimen" format="float">0.8</item>
<item name="horizontal_spring_stiffness" type="dimen" format="float">400</item>
diff --git a/src/com/android/launcher3/anim/AnimatorPlaybackController.java b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
index f12789a..e11917b 100644
--- a/src/com/android/launcher3/anim/AnimatorPlaybackController.java
+++ b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
@@ -27,7 +27,6 @@
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.content.Context;
-import android.util.FloatProperty;
import androidx.annotation.Nullable;
@@ -64,19 +63,6 @@
return new AnimatorPlaybackController(anim, duration, childAnims);
}
- private static final FloatProperty<ValueAnimator> CURRENT_PLAY_TIME =
- new FloatProperty<ValueAnimator>("current-play-time") {
- @Override
- public void setValue(ValueAnimator animator, float v) {
- animator.setCurrentPlayTime((long) v);
- }
-
- @Override
- public Float get(ValueAnimator animator) {
- return (float) animator.getCurrentPlayTime();
- }
- };
-
// Progress factor after which an animation is considered almost completed.
private static final float ANIMATION_COMPLETE_THRESHOLD = 0.95f;
@@ -177,21 +163,22 @@
long springDuration = animationDuration;
for (Holder h : mChildAnimations) {
if ((h.springProperty.flags & springFlag) != 0) {
- SpringAnimationBuilder s = new SpringAnimationBuilder(h.anim, CURRENT_PLAY_TIME)
- .setStartValue(clampDuration(mCurrentFraction))
- .setEndValue(goingToEnd ? h.anim.getDuration() : 0)
- .setStartVelocity(scaledVelocity * h.anim.getDuration())
+ SpringAnimationBuilder s = new SpringAnimationBuilder(context)
+ .setStartValue(mCurrentFraction)
+ .setEndValue(goingToEnd ? 1 : 0)
+ .setStartVelocity(scaledVelocity)
.setMinimumVisibleChange(scaleInverse)
.setDampingRatio(h.springProperty.mDampingRatio)
- .setStiffness(h.springProperty.mStiffness);
+ .setStiffness(h.springProperty.mStiffness)
+ .computeParams();
- long expectedDurationL = s.build(context).getDuration();
+ long expectedDurationL = s.getDuration();
springDuration = Math.max(expectedDurationL, springDuration);
float expectedDuration = expectedDurationL;
- h.setter = (a, l) ->
- s.setValue(a, mAnimationPlayer.getCurrentPlayTime() / expectedDuration);
- h.anim.setInterpolator(LINEAR);
+ h.setter = (a, l) -> a.setCurrentFraction(
+ mAnimationPlayer.getCurrentPlayTime() / expectedDuration);
+ h.anim.setInterpolator(s::getInterpolatedValue);
}
}
diff --git a/src/com/android/launcher3/anim/SpringAnimationBuilder.java b/src/com/android/launcher3/anim/SpringAnimationBuilder.java
index f22a9f0..bc77aab 100644
--- a/src/com/android/launcher3/anim/SpringAnimationBuilder.java
+++ b/src/com/android/launcher3/anim/SpringAnimationBuilder.java
@@ -15,7 +15,9 @@
*/
package com.android.launcher3.anim;
-import android.animation.ObjectAnimator;
+import static com.android.launcher3.anim.Interpolators.LINEAR;
+
+import android.animation.ValueAnimator;
import android.content.Context;
import android.util.FloatProperty;
@@ -28,10 +30,9 @@
* Utility class to build an object animator which follows the same path as a spring animation for
* an underdamped spring.
*/
-public class SpringAnimationBuilder<T> extends FloatProperty<T> {
+public class SpringAnimationBuilder {
- private final T mTarget;
- private final FloatProperty<T> mProperty;
+ private final Context mContext;
private float mStartValue;
private float mEndValue;
@@ -64,27 +65,23 @@
private double mValueThreshold;
private double mVelocityThreshold;
- private float mCurrentTime = 0;
+ private float mDuration = 0;
- public SpringAnimationBuilder(T target, FloatProperty<T> property) {
- super("dynamic-spring-property");
- mTarget = target;
- mProperty = property;
-
- mStartValue = mProperty.get(target);
+ public SpringAnimationBuilder(Context context) {
+ mContext = context;
}
- public SpringAnimationBuilder<T> setEndValue(float value) {
+ public SpringAnimationBuilder setEndValue(float value) {
mEndValue = value;
return this;
}
- public SpringAnimationBuilder<T> setStartValue(float value) {
+ public SpringAnimationBuilder setStartValue(float value) {
mStartValue = value;
return this;
}
- public SpringAnimationBuilder<T> setValues(float... values) {
+ public SpringAnimationBuilder setValues(float... values) {
if (values.length > 1) {
mStartValue = values[0];
mEndValue = values[values.length - 1];
@@ -94,7 +91,7 @@
return this;
}
- public SpringAnimationBuilder<T> setStiffness(
+ public SpringAnimationBuilder setStiffness(
@FloatRange(from = 0.0, fromInclusive = false) float stiffness) {
if (stiffness <= 0) {
throw new IllegalArgumentException("Spring stiffness constant must be positive.");
@@ -103,7 +100,7 @@
return this;
}
- public SpringAnimationBuilder<T> setDampingRatio(
+ public SpringAnimationBuilder setDampingRatio(
@FloatRange(from = 0.0, to = 1.0, fromInclusive = false, toInclusive = false)
float dampingRatio) {
if (dampingRatio <= 0 || dampingRatio >= 1) {
@@ -113,7 +110,7 @@
return this;
}
- public SpringAnimationBuilder<T> setMinimumVisibleChange(
+ public SpringAnimationBuilder setMinimumVisibleChange(
@FloatRange(from = 0.0, fromInclusive = false) float minimumVisibleChange) {
if (minimumVisibleChange <= 0) {
throw new IllegalArgumentException("Minimum visible change must be positive.");
@@ -122,25 +119,21 @@
return this;
}
- public SpringAnimationBuilder<T> setStartVelocity(float startVelocity) {
+ public SpringAnimationBuilder setStartVelocity(float startVelocity) {
mVelocity = startVelocity;
return this;
}
- @Override
- public void setValue(T object, float time) {
- mCurrentTime = time;
- mProperty.setValue(
- object, (float) (exponentialComponent(time) * cosSinX(time)) + mEndValue);
+ public float getInterpolatedValue(float fraction) {
+ return getValue(mDuration * fraction);
}
- @Override
- public Float get(T t) {
- return mCurrentTime;
+ private float getValue(float time) {
+ return (float) (exponentialComponent(time) * cosSinX(time)) + mEndValue;
}
- public ObjectAnimator build(Context context) {
- int singleFrameMs = DefaultDisplay.getSingleFrameMs(context);
+ public SpringAnimationBuilder computeParams() {
+ int singleFrameMs = DefaultDisplay.getSingleFrameMs(mContext);
double naturalFreq = Math.sqrt(mStiffness);
double dampedFreq = naturalFreq * Math.sqrt(1 - mDampingRatio * mDampingRatio);
@@ -187,12 +180,21 @@
}
} while (true);
+ mDuration = (float) duration;
+ return this;
+ }
- long durationMs = (long) (1000.0 * duration);
- ObjectAnimator animator = ObjectAnimator.ofFloat(mTarget, this, 0, (float) duration);
- animator.setDuration(durationMs).setInterpolator(Interpolators.LINEAR);
- animator.addListener(AnimationSuccessListener.forRunnable(
- () -> mProperty.setValue(mTarget, mEndValue)));
+ public long getDuration() {
+ return (long) (1000.0 * mDuration);
+ }
+
+ public <T> ValueAnimator build(T target, FloatProperty<T> property) {
+ computeParams();
+
+ ValueAnimator animator = ValueAnimator.ofFloat(0, mDuration);
+ animator.setDuration(getDuration()).setInterpolator(LINEAR);
+ animator.addUpdateListener(anim ->
+ property.set(target, getInterpolatedValue(anim.getAnimatedFraction())));
return animator;
}
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 2b91cb1..65d3cd2 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -159,10 +159,6 @@
"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/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 12d88df..c287190 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -332,7 +332,7 @@
.map(info -> info.suggestedFolderNames)
.map(folderNames -> (FolderNameInfo[]) folderNames
.getParcelableArrayExtra(FolderInfo.EXTRA_FOLDER_SUGGESTIONS))
- .ifPresent(nameInfos -> showLabelSuggestions(nameInfos));
+ .ifPresent(this::showLabelSuggestions);
}
mFolderName.setHint("");
mIsEditingName = true;
@@ -1450,7 +1450,7 @@
if (hasFocus) {
startEditingFolderName();
} else {
- logEditFolderLabel();
+ logCurrentFolderLabelState();
mFolderName.dispatchBackKey();
}
}
@@ -1649,7 +1649,7 @@
return mContent;
}
- private void logEditFolderLabel() {
+ protected void logCurrentFolderLabelState() {
LauncherEvent launcherEvent = LauncherEvent.newBuilder()
.setAction(Action.newBuilder().setType(Action.Type.SOFT_KEYBOARD))
.addSrcTarget(newEditTextTargetBuilder()
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index 96bdc2a..7fc6d54 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -416,6 +416,7 @@
mPreviewItemManager.hidePreviewItem(finalIndex, false);
mFolder.showItem(item);
setLabelSuggestion(nameInfos);
+ mFolder.logCurrentFolderLabelState();
invalidate();
}, DROP_IN_ANIMATION_DURATION);
}
@@ -438,7 +439,6 @@
onTitleChanged(mInfo.title);
mFolder.mFolderName.setText(mInfo.title);
mFolder.mLauncher.getModelWriter().updateItemInDatabase(mInfo);
- // TODO: Add logging while folder creation.
}
diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java
index 0d97596..2fa6051 100644
--- a/src/com/android/launcher3/model/PackageUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageUpdatedTask.java
@@ -42,7 +42,6 @@
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.shortcuts.ShortcutRequest;
-import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.FlagOp;
import com.android.launcher3.util.IntSparseArrayMap;
import com.android.launcher3.util.ItemInfoMatcher;
@@ -86,10 +85,6 @@
@Override
public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList appsList) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.APP_NOT_DISABLED, "PackageUpdatedTask: " + mOp + ", " +
- Arrays.toString(mPackages));
- }
final Context context = app.getContext();
final IconCache iconCache = app.getIconCache();
diff --git a/src/com/android/launcher3/model/data/ItemInfo.java b/src/com/android/launcher3/model/data/ItemInfo.java
index bd843e7..14f9a3e 100644
--- a/src/com/android/launcher3/model/data/ItemInfo.java
+++ b/src/com/android/launcher3/model/data/ItemInfo.java
@@ -37,6 +37,8 @@
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.util.ContentWriter;
+import java.util.Optional;
+
/**
* Represents an item in the launcher.
*/
@@ -248,24 +250,29 @@
LauncherAtom.ItemInfo.Builder itemBuilder = LauncherAtom.ItemInfo.newBuilder();
itemBuilder.setIsWork(user != Process.myUserHandle());
- ComponentName cn = getTargetComponent();
+ Optional<ComponentName> nullableComponent = Optional.ofNullable(getTargetComponent());
switch (itemType) {
case ITEM_TYPE_APPLICATION:
- itemBuilder.setApplication(LauncherAtom.Application.newBuilder()
- .setComponentName(cn.flattenToShortString())
- .setPackageName(cn.getPackageName()));
+ itemBuilder
+ .setApplication(nullableComponent
+ .map(component -> LauncherAtom.Application.newBuilder()
+ .setComponentName(component.flattenToShortString())
+ .setPackageName(component.getPackageName()))
+ .orElse(LauncherAtom.Application.newBuilder()));
break;
case ITEM_TYPE_DEEP_SHORTCUT:
case ITEM_TYPE_SHORTCUT:
- itemBuilder.setShortcut(LauncherAtom.Shortcut.newBuilder()
- .setShortcutName(cn.flattenToShortString()));
+ itemBuilder
+ .setShortcut(nullableComponent
+ .map(component -> LauncherAtom.Shortcut.newBuilder()
+ .setShortcutName(component.flattenToShortString()))
+ .orElse(LauncherAtom.Shortcut.newBuilder()));
break;
case ITEM_TYPE_APPWIDGET:
setItemBuilder(itemBuilder);
break;
default:
break;
-
}
if (fInfo != null) {
LauncherAtom.FolderContainer.Builder folderBuilder =
diff --git a/src/com/android/launcher3/states/RotationHelper.java b/src/com/android/launcher3/states/RotationHelper.java
index 3640d8b..5a60f53 100644
--- a/src/com/android/launcher3/states/RotationHelper.java
+++ b/src/com/android/launcher3/states/RotationHelper.java
@@ -43,7 +43,6 @@
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;
diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
index 82f2eb4..a5a06b4 100644
--- a/src/com/android/launcher3/testing/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -96,6 +96,4 @@
public static final String REQUEST_MOCK_SENSOR_ROTATION = "mock-sensor-rotation";
public static final String PERMANENT_DIAG_TAG = "TaplTarget";
-
- public static final String APP_NOT_DISABLED = "b/139891609";
}