Merge "[DO NOT MERGE][NPE] check RecentsView exists before using it" into ub-launcher3-rvc-qpr-dev
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index 085b9b3..5ccc1e8 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -17,6 +17,7 @@
import static com.android.launcher3.LauncherState.OVERVIEW_BUTTONS;
import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_ACTIONS_FADE;
import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
import static com.android.quickstep.views.RecentsView.TASK_MODALNESS;
@@ -57,7 +58,7 @@
mRecentsView.updateEmptyMessage();
mRecentsView.resetTaskVisuals();
}
- setAlphas(PropertySetter.NO_ANIM_PROPERTY_SETTER, state);
+ setAlphas(PropertySetter.NO_ANIM_PROPERTY_SETTER, new StateAnimationConfig(), state);
mRecentsView.setFullscreenProgress(state.getOverviewFullscreenProgress());
}
@@ -75,17 +76,19 @@
AnimationSuccessListener.forRunnable(mRecentsView::resetTaskVisuals));
}
- setAlphas(builder, toState);
+ setAlphas(builder, config, toState);
builder.setFloat(mRecentsView, FULLSCREEN_PROGRESS,
toState.getOverviewFullscreenProgress(), LINEAR);
}
- private void setAlphas(PropertySetter propertySetter, LauncherState state) {
+ private void setAlphas(PropertySetter propertySetter, StateAnimationConfig config,
+ LauncherState state) {
float buttonAlpha = (state.getVisibleElements(mLauncher) & OVERVIEW_BUTTONS) != 0 ? 1 : 0;
propertySetter.setFloat(mRecentsView.getClearAllButton(), ClearAllButton.VISIBILITY_ALPHA,
buttonAlpha, LINEAR);
propertySetter.setFloat(mLauncher.getActionsView().getVisibilityAlpha(),
- MultiValueAlpha.VALUE, buttonAlpha, LINEAR);
+ MultiValueAlpha.VALUE, buttonAlpha, config.getInterpolator(
+ ANIM_OVERVIEW_ACTIONS_FADE, LINEAR));
}
@Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
index 131fcbf..daa1aad 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
@@ -25,6 +25,7 @@
import static com.android.launcher3.LauncherState.OVERVIEW_PEEK;
import static com.android.launcher3.WorkspaceStateTransitionAnimation.getSpringScaleAnimator;
import static com.android.launcher3.anim.Interpolators.ACCEL;
+import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7;
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
@@ -163,10 +164,15 @@
config.setInterpolator(ANIM_WORKSPACE_FADE, ACCEL);
config.setInterpolator(ANIM_ALL_APPS_FADE, ACCEL);
config.setInterpolator(ANIM_OVERVIEW_SCALE, clampToProgress(ACCEL, 0, 0.9f));
- config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, ACCEL);
- config.setInterpolator(ANIM_OVERVIEW_FADE, DEACCEL_1_7);
- Workspace workspace = mActivity.getWorkspace();
+ config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, ACCEL_DEACCEL);
+ if (SysUINavigationMode.getMode(mActivity) == NO_BUTTON) {
+ config.setInterpolator(ANIM_OVERVIEW_FADE, FINAL_FRAME);
+ } else {
+ config.setInterpolator(ANIM_OVERVIEW_FADE, DEACCEL_1_7);
+ }
+
+ Workspace workspace = mActivity.getWorkspace();
// Start from a higher workspace scale, but only if we're invisible so we don't jump.
boolean isWorkspaceVisible = workspace.getVisibility() == VISIBLE;
if (isWorkspaceVisible) {
@@ -206,8 +212,10 @@
config.setInterpolator(ANIM_WORKSPACE_SCALE,
fromState == NORMAL ? ACCEL : OVERSHOOT_1_2);
config.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCEL);
+ config.setInterpolator(ANIM_OVERVIEW_FADE, INSTANT);
} else {
config.setInterpolator(ANIM_WORKSPACE_SCALE, OVERSHOOT_1_2);
+ config.setInterpolator(ANIM_OVERVIEW_FADE, OVERSHOOT_1_2);
// Scale up the recents, if it is not coming from the side
RecentsView overview = mActivity.getOverviewPanel();
@@ -225,7 +233,6 @@
: OVERSHOOT_1_7;
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, translationInterpolator);
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, translationInterpolator);
- config.setInterpolator(ANIM_OVERVIEW_FADE, OVERSHOOT_1_2);
} else if (fromState == HINT_STATE && toState == NORMAL) {
config.setInterpolator(ANIM_DEPTH, DEACCEL_3);
if (mHintToNormalDuration == -1) {
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 c1a585e..c6aaa43 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
@@ -25,7 +25,6 @@
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOME_GESTURE;
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;
@@ -45,6 +44,7 @@
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.graphics.OverviewScrim;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.testing.TestProtocol;
@@ -52,7 +52,9 @@
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.util.TouchController;
+import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.AssistantUtilities;
+import com.android.quickstep.util.OverviewToHomeAnim;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -63,6 +65,8 @@
SingleAxisSwipeDetector.Listener {
private static final Interpolator PULLBACK_INTERPOLATOR = DEACCEL_3;
+ // The min amount of overview scrim we keep during the transition.
+ private static final float OVERVIEW_TO_HOME_SCRIM_MULTIPLIER = 0.5f;
private final Launcher mLauncher;
private final SingleAxisSwipeDetector mSwipeDetector;
@@ -156,8 +160,13 @@
final PendingAnimation builder = new PendingAnimation(accuracy);
if (mStartState.overviewUi) {
RecentsView recentsView = mLauncher.getOverviewPanel();
- builder.setFloat(recentsView, ADJACENT_PAGE_OFFSET,
- -mPullbackDistance / recentsView.getPageOffsetScale(), PULLBACK_INTERPOLATOR);
+ AnimatorControllerWithResistance.createRecentsResistanceFromOverviewAnim(mLauncher,
+ builder);
+
+ builder.setFloat(mLauncher.getDragLayer().getOverviewScrim(),
+ OverviewScrim.SCRIM_MULTIPLIER, OVERVIEW_TO_HOME_SCRIM_MULTIPLIER,
+ PULLBACK_INTERPOLATOR);
+
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
builder.addOnFrameCallback(
() -> recentsView.redrawLiveTile(false /* mightNeedToRefill */));
@@ -212,8 +221,13 @@
recentsView.switchToScreenshot(null,
() -> recentsView.finishRecentsAnimation(true /* toRecents */, null));
}
- mLauncher.getStateManager().goToState(mEndState, true,
- () -> onSwipeInteractionCompleted(mEndState));
+ if (mStartState.overviewUi) {
+ new OverviewToHomeAnim(mLauncher, () -> onSwipeInteractionCompleted(mEndState))
+ .animateWithVelocity(velocity);
+ } else {
+ mLauncher.getStateManager().goToState(mEndState, true,
+ () -> onSwipeInteractionCompleted(mEndState));
+ }
if (mStartState != mEndState) {
logStateChange(mStartState.containerType, logAction);
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
index 9316938..8f0f683 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
@@ -21,11 +21,8 @@
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
-import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_PEEK;
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
-import android.animation.Animator;
-import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.graphics.PointF;
@@ -35,14 +32,15 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.Utilities;
-import com.android.launcher3.anim.AnimationSuccessListener;
+import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.graphics.OverviewScrim;
import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.util.VibratorWrapper;
-import com.android.quickstep.util.StaggeredWorkspaceAnim;
+import com.android.quickstep.util.AnimatorControllerWithResistance;
+import com.android.quickstep.util.OverviewToHomeAnim;
import com.android.quickstep.views.RecentsView;
/**
@@ -62,10 +60,10 @@
private boolean mDidTouchStartInNavBar;
private boolean mReachedOverview;
- private boolean mIsOverviewRehidden;
- private boolean mIsHomeStaggeredAnimFinished;
// The last recorded displacement before we reached overview.
private PointF mStartDisplacement = new PointF();
+ private float mStartY;
+ private AnimatorPlaybackController mOverviewResistYAnim;
// Normal to Hint animation has flag SKIP_OVERVIEW, so we update this scrim with this animator.
private ObjectAnimator mNormalToHintOverviewScrimAnimator;
@@ -123,6 +121,7 @@
mToState.getOverviewScrimAlpha(mLauncher));
}
mReachedOverview = false;
+ mOverviewResistYAnim = null;
}
@Override
@@ -137,6 +136,11 @@
public void onDragEnd(float velocity) {
super.onDragEnd(velocity);
mNormalToHintOverviewScrimAnimator = null;
+ if (mLauncher.isInState(OVERVIEW)) {
+ // Normally we would cleanup the state based on mCurrentAnimation, but since we stop
+ // using that when we pause to go to Overview, we need to clean up ourselves.
+ clearState();
+ }
}
@Override
@@ -160,6 +164,9 @@
mNormalToHintOverviewScrimAnimator = null;
mCurrentAnimation.dispatchOnCancelWithoutCancelRunnable(() -> {
mLauncher.getStateManager().goToState(OVERVIEW, true, () -> {
+ mOverviewResistYAnim = AnimatorControllerWithResistance
+ .createRecentsResistanceFromOverviewAnim(mLauncher, null)
+ .createPlaybackController();
mReachedOverview = true;
maybeSwipeInteractionToOverviewComplete();
});
@@ -173,13 +180,6 @@
}
}
- // Used if flinging back to home after reaching overview
- private void maybeSwipeInteractionToHomeComplete() {
- if (mIsHomeStaggeredAnimFinished && mIsOverviewRehidden) {
- onSwipeInteractionCompleted(NORMAL, Touch.FLING);
- }
- }
-
@Override
protected boolean handlingOverviewAnim() {
return mDidTouchStartInNavBar && super.handlingOverviewAnim();
@@ -193,11 +193,17 @@
if (mMotionPauseDetector.isPaused()) {
if (!mReachedOverview) {
mStartDisplacement.set(xDisplacement, yDisplacement);
+ mStartY = event.getY();
} else {
mRecentsView.setTranslationX((xDisplacement - mStartDisplacement.x)
* OVERVIEW_MOVEMENT_FACTOR);
- mRecentsView.setTranslationY((yDisplacement - mStartDisplacement.y)
- * OVERVIEW_MOVEMENT_FACTOR);
+ float yProgress = (mStartDisplacement.y - yDisplacement) / mStartY;
+ if (yProgress > 0 && mOverviewResistYAnim != null) {
+ mOverviewResistYAnim.setPlayFraction(yProgress);
+ } else {
+ mRecentsView.setTranslationY((yDisplacement - mStartDisplacement.y)
+ * OVERVIEW_MOVEMENT_FACTOR);
+ }
}
// Stay in Overview.
return true;
@@ -212,35 +218,8 @@
StateManager<LauncherState> stateManager = mLauncher.getStateManager();
boolean goToHomeInsteadOfOverview = isFling;
if (goToHomeInsteadOfOverview) {
- if (velocity > 0) {
- stateManager.goToState(NORMAL, true,
- () -> onSwipeInteractionCompleted(NORMAL, Touch.FLING));
- } else {
- mIsHomeStaggeredAnimFinished = mIsOverviewRehidden = false;
-
- StaggeredWorkspaceAnim staggeredWorkspaceAnim = new StaggeredWorkspaceAnim(
- mLauncher, velocity, false /* animateOverviewScrim */);
- staggeredWorkspaceAnim.addAnimatorListener(new AnimationSuccessListener() {
- @Override
- public void onAnimationSuccess(Animator animator) {
- mIsHomeStaggeredAnimFinished = true;
- maybeSwipeInteractionToHomeComplete();
- }
- }).start();
-
- // StaggeredWorkspaceAnim doesn't animate overview, so we handle it here.
- stateManager.cancelAnimation();
- StateAnimationConfig config = new StateAnimationConfig();
- config.duration = OVERVIEW.getTransitionDuration(mLauncher);
- config.animFlags = PLAY_ATOMIC_OVERVIEW_PEEK;
- AnimatorSet anim = stateManager.createAtomicAnimation(
- stateManager.getState(), NORMAL, config);
- anim.addListener(AnimationSuccessListener.forRunnable(() -> {
- mIsOverviewRehidden = true;
- maybeSwipeInteractionToHomeComplete();
- }));
- anim.start();
- }
+ new OverviewToHomeAnim(mLauncher, ()-> onSwipeInteractionCompleted(NORMAL, Touch.FLING))
+ .animateWithVelocity(velocity);
}
if (mReachedOverview) {
float distanceDp = dpiFromPx(Math.max(
@@ -256,6 +235,13 @@
.withEndAction(goToHomeInsteadOfOverview
? null
: this::maybeSwipeInteractionToOverviewComplete);
+ if (!goToHomeInsteadOfOverview) {
+ // Return to normal properties for the overview state.
+ StateAnimationConfig config = new StateAnimationConfig();
+ config.duration = duration;
+ LauncherState state = mLauncher.getStateManager().getState();
+ mLauncher.getStateManager().createAtomicAnimation(state, state, config).start();
+ }
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
index 0ee5d04..2cfbc2b 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
@@ -25,6 +25,7 @@
import android.animation.AnimatorListenerAdapter;
import android.view.MotionEvent;
import android.view.View;
+import android.view.animation.Interpolator;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseDraggingActivity;
@@ -82,7 +83,15 @@
mDetector = new SingleAxisSwipeDetector(activity, this, dir);
}
- private boolean canInterceptTouch() {
+ private boolean canInterceptTouch(MotionEvent ev) {
+ if ((ev.getEdgeFlags() & Utilities.EDGE_NAV_BAR) != 0) {
+ // Don't intercept swipes on the nav bar, as user might be trying to go home
+ // during a task dismiss animation.
+ if (mCurrentAnimation != null) {
+ mCurrentAnimation.getAnimationPlayer().end();
+ }
+ return false;
+ }
if (mCurrentAnimation != null) {
mCurrentAnimation.forceFinishIfCloseToEnd();
}
@@ -118,7 +127,7 @@
clearState();
}
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- mNoIntercept = !canInterceptTouch();
+ mNoIntercept = !canInterceptTouch(ev);
if (mNoIntercept) {
return false;
}
@@ -206,14 +215,19 @@
long maxDuration = 2 * secondaryLayerDimension;
int verticalFactor = orientationHandler.getTaskDragDisplacementFactor(mIsRtl);
int secondaryTaskDimension = orientationHandler.getSecondaryDimension(mTaskBeingDragged);
+ // The interpolator controlling the most prominent visual movement. We use this to determine
+ // whether we passed SUCCESS_TRANSITION_PROGRESS.
+ final Interpolator currentInterpolator;
if (goingUp) {
+ currentInterpolator = Interpolators.LINEAR;
mPendingAnimation = mRecentsView.createTaskDismissAnimation(mTaskBeingDragged,
true /* animateTaskView */, true /* removeTask */, maxDuration);
mEndDisplacement = -secondaryTaskDimension;
} else {
+ currentInterpolator = Interpolators.ZOOM_IN;
mPendingAnimation = mRecentsView.createTaskLaunchAnimation(
- mTaskBeingDragged, maxDuration, Interpolators.ZOOM_IN);
+ mTaskBeingDragged, maxDuration, currentInterpolator);
// Since the thumbnail is what is filling the screen, based the end displacement on it.
View thumbnailView = mTaskBeingDragged.getThumbnail();
@@ -228,6 +242,9 @@
}
mCurrentAnimation = mPendingAnimation.createPlaybackController()
.setOnCancelRunnable(this::clearState);
+ // Setting this interpolator doesn't affect the visual motion, but is used to determine
+ // whether we successfully reached the target state in onDragEnd().
+ mCurrentAnimation.getTarget().setInterpolator(currentInterpolator);
onUserControlledAnimationCreated(mCurrentAnimation);
mCurrentAnimation.getTarget().addListener(this);
mCurrentAnimation.dispatchOnStart();
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java
index ed33532..0aa1486 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java
@@ -493,7 +493,11 @@
// much the window is bound by overscroll (vs moving freely).
if (animate) {
ValueAnimator reapplyWindowTransformAnim = ValueAnimator.ofFloat(0, 1);
- reapplyWindowTransformAnim.addUpdateListener(anim -> applyWindowTransform());
+ reapplyWindowTransformAnim.addUpdateListener(anim -> {
+ if (mRunningWindowAnim == null) {
+ applyWindowTransform();
+ }
+ });
reapplyWindowTransformAnim.setDuration(RECENTS_ATTACH_DURATION).start();
} else {
applyWindowTransform();
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/OverscrollPluginFactory.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverscrollPluginFactory.java
new file mode 100644
index 0000000..4c261ab
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverscrollPluginFactory.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep;
+
+import static com.android.launcher3.util.MainThreadInitializedObject.forOverride;
+
+import com.android.launcher3.R;
+import com.android.launcher3.util.MainThreadInitializedObject;
+import com.android.launcher3.util.ResourceBasedOverride;
+import com.android.systemui.plugins.OverscrollPlugin;
+
+/**
+ * Resource overrideable factory for forcing a local overscroll plugin.
+ * Override {@link R.string#overscroll_plugin_factory_class} to set a different class.
+ */
+public class OverscrollPluginFactory implements ResourceBasedOverride {
+ public static final MainThreadInitializedObject<OverscrollPluginFactory> INSTANCE = forOverride(
+ OverscrollPluginFactory.class,
+ R.string.overscroll_plugin_factory_class);
+
+ /**
+ * Get the plugin that is defined locally in launcher, as opposed to a dynamic side loaded one.
+ */
+ public OverscrollPlugin getLocalOverscrollPlugin() {
+ return null;
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
index db512fa..36579ec 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
@@ -18,7 +18,6 @@
import static android.view.Surface.ROTATION_0;
-import static com.android.launcher3.util.MainThreadInitializedObject.forOverride;
import static com.android.quickstep.views.OverviewActionsView.DISABLED_NO_THUMBNAIL;
import static com.android.quickstep.views.OverviewActionsView.DISABLED_ROTATED;
@@ -39,13 +38,11 @@
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.popup.SystemShortcut;
-import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.ResourceBasedOverride;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.views.OverviewActionsView;
import com.android.quickstep.views.TaskThumbnailView;
import com.android.quickstep.views.TaskView;
-import com.android.systemui.plugins.OverscrollPlugin;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -91,20 +88,22 @@
return shortcuts;
}
- public static final MainThreadInitializedObject<TaskOverlayFactory> INSTANCE =
- forOverride(TaskOverlayFactory.class, R.string.task_overlay_factory_class);
-
- /**
- * @return a launcher-provided OverscrollPlugin if available, otherwise null
- */
- public OverscrollPlugin getLocalOverscrollPlugin() {
- return null;
- }
-
public TaskOverlay createOverlay(TaskThumbnailView thumbnailView) {
return new TaskOverlay(thumbnailView);
}
+ /**
+ * Subclasses can attach any system listeners in this method, must be paired with
+ * {@link #removeListeners()}
+ */
+ public void initListeners() { }
+
+ /**
+ * Subclasses should remove any system listeners in this method, must be paired with
+ * {@link #initListeners()}
+ */
+ public void removeListeners() { }
+
/** Note that these will be shown in order from top to bottom, if available for the task. */
private static final TaskShortcutFactory[] MENU_OPTIONS = new TaskShortcutFactory[]{
TaskShortcutFactory.APP_INFO,
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 13adff5..7b91001 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -597,9 +597,8 @@
if (FeatureFlags.ENABLE_QUICK_CAPTURE_GESTURE.get()) {
OverscrollPlugin plugin = null;
if (FeatureFlags.FORCE_LOCAL_OVERSCROLL_PLUGIN.get()) {
- TaskOverlayFactory factory =
- TaskOverlayFactory.INSTANCE.get(getApplicationContext());
- plugin = factory.getLocalOverscrollPlugin(); // may be null
+ plugin = OverscrollPluginFactory.INSTANCE.get(
+ getApplicationContext()).getLocalOverscrollPlugin();
}
// If not local plugin was forced, use the actual overscroll plugin if available.
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/OverviewToHomeAnim.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/OverviewToHomeAnim.java
new file mode 100644
index 0000000..4a298d3
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/OverviewToHomeAnim.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.util;
+
+import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.LauncherState.OVERVIEW;
+import static com.android.launcher3.anim.Interpolators.DEACCEL;
+import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
+import static com.android.launcher3.anim.Interpolators.INSTANT;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_COMPONENTS;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_ACTIONS_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y;
+import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_PEEK;
+
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.util.Log;
+import android.view.animation.Interpolator;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherState;
+import com.android.launcher3.anim.AnimationSuccessListener;
+import com.android.launcher3.statemanager.StateManager;
+import com.android.launcher3.states.StateAnimationConfig;
+import com.android.quickstep.views.RecentsView;
+
+/**
+ * Runs an animation from overview to home. Currently, this animation is just a wrapper around the
+ * normal state transition, in order to keep RecentsView at the same scale and translationY that
+ * it started out at as it translates offscreen. It also scrolls RecentsView to page 0 and may play
+ * a {@link StaggeredWorkspaceAnim} if we're starting from an upward fling.
+ */
+public class OverviewToHomeAnim {
+
+ private static final String TAG = "OverviewToHomeAnim";
+
+ // Constants to specify how to scroll RecentsView to the default page if it's not already there.
+ private static final int DEFAULT_PAGE = 0;
+ private static final int PER_PAGE_SCROLL_DURATION = 150;
+ private static final int MAX_PAGE_SCROLL_DURATION = 750;
+
+ private final Launcher mLauncher;
+ private final Runnable mOnReachedHome;
+
+ // Only run mOnReachedHome when both of these are true.
+ private boolean mIsHomeStaggeredAnimFinished;
+ private boolean mIsOverviewHidden;
+
+ public OverviewToHomeAnim(Launcher launcher, Runnable onReachedHome) {
+ mLauncher = launcher;
+ mOnReachedHome = onReachedHome;
+ }
+
+ /**
+ * Starts the animation. If velocity < 0 (i.e. upwards), also plays a
+ * {@link StaggeredWorkspaceAnim}.
+ */
+ public void animateWithVelocity(float velocity) {
+ StateManager<LauncherState> stateManager = mLauncher.getStateManager();
+ LauncherState startState = stateManager.getState();
+ if (startState != OVERVIEW) {
+ Log.e(TAG, "animateFromOverviewToHome: unexpected start state " + startState);
+ }
+ AnimatorSet anim = new AnimatorSet();
+
+ boolean playStaggeredWorkspaceAnim = velocity < 0;
+ if (playStaggeredWorkspaceAnim) {
+ StaggeredWorkspaceAnim staggeredWorkspaceAnim = new StaggeredWorkspaceAnim(
+ mLauncher, velocity, false /* animateOverviewScrim */);
+ staggeredWorkspaceAnim.addAnimatorListener(new AnimationSuccessListener() {
+ @Override
+ public void onAnimationSuccess(Animator animator) {
+ mIsHomeStaggeredAnimFinished = true;
+ maybeOverviewToHomeAnimComplete();
+ }
+ });
+ anim.play(staggeredWorkspaceAnim.getAnimators());
+ } else {
+ mIsHomeStaggeredAnimFinished = true;
+ }
+
+ RecentsView recentsView = mLauncher.getOverviewPanel();
+ int numPagesToScroll = recentsView.getNextPage() - DEFAULT_PAGE;
+ int scrollDuration = Math.min(MAX_PAGE_SCROLL_DURATION,
+ numPagesToScroll * PER_PAGE_SCROLL_DURATION);
+ int duration = Math.max(scrollDuration, startState.getTransitionDuration(mLauncher));
+
+ StateAnimationConfig config = new UseFirstInterpolatorStateAnimConfig();
+ config.duration = duration;
+ config.animFlags = playStaggeredWorkspaceAnim
+ // StaggeredWorkspaceAnim doesn't animate overview, so we handle it here.
+ ? PLAY_ATOMIC_OVERVIEW_PEEK
+ : ANIM_ALL_COMPONENTS;
+ boolean isLayoutNaturalToLauncher = recentsView.getPagedOrientationHandler()
+ .isLayoutNaturalToLauncher();
+ config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, isLayoutNaturalToLauncher
+ ? DEACCEL : FINAL_FRAME);
+ config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, FINAL_FRAME);
+ config.setInterpolator(ANIM_OVERVIEW_SCALE, FINAL_FRAME);
+ config.setInterpolator(ANIM_OVERVIEW_ACTIONS_FADE, INSTANT);
+ if (!isLayoutNaturalToLauncher) {
+ config.setInterpolator(ANIM_OVERVIEW_FADE, DEACCEL);
+ }
+ AnimatorSet stateAnim = stateManager.createAtomicAnimation(
+ startState, NORMAL, config);
+ stateAnim.addListener(new AnimationSuccessListener() {
+ @Override
+ public void onAnimationSuccess(Animator animator) {
+ mIsOverviewHidden = true;
+ maybeOverviewToHomeAnimComplete();
+ }
+ });
+ anim.play(stateAnim);
+ stateManager.setCurrentAnimation(anim, NORMAL);
+ anim.start();
+ recentsView.snapToPage(DEFAULT_PAGE, duration);
+ }
+
+ private void maybeOverviewToHomeAnimComplete() {
+ if (mIsHomeStaggeredAnimFinished && mIsOverviewHidden) {
+ mOnReachedHome.run();
+ }
+ }
+
+ /**
+ * Wrapper around StateAnimationConfig that doesn't allow interpolators to be set if they are
+ * already set. This ensures they aren't overridden before being used.
+ */
+ private static class UseFirstInterpolatorStateAnimConfig extends StateAnimationConfig {
+ @Override
+ public void setInterpolator(int animId, Interpolator interpolator) {
+ if (mInterpolators[animId] == null || interpolator == null) {
+ super.setInterpolator(animId, interpolator);
+ }
+ }
+ }
+}
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 79028d1..b934c29 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
@@ -51,6 +51,7 @@
import com.android.launcher3.views.ScrimView;
import com.android.quickstep.LauncherActivityInterface;
import com.android.quickstep.SysUINavigationMode;
+import com.android.quickstep.util.OverviewToHomeAnim;
import com.android.quickstep.util.TransformParams;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.RecentsExtraCard;
@@ -105,12 +106,14 @@
@Override
public void startHome() {
+ Runnable onReachedHome = () -> mActivity.getStateManager().goToState(NORMAL, false);
+ OverviewToHomeAnim overviewToHomeAnim = new OverviewToHomeAnim(mActivity, onReachedHome);
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
switchToScreenshot(null,
() -> finishRecentsAnimation(true /* toRecents */,
- () -> mActivity.getStateManager().goToState(NORMAL)));
+ () -> overviewToHomeAnim.animateWithVelocity(0)));
} else {
- mActivity.getStateManager().goToState(NORMAL);
+ overviewToHomeAnim.animateWithVelocity(0);
}
}
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 79d57c5..1bf2fbf 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
@@ -105,6 +105,7 @@
public OverviewActionsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr, 0);
mMultiValueAlpha = new MultiValueAlpha(this, 4);
+ mMultiValueAlpha.setUpdateVisibility(true);
}
@Override
@@ -168,7 +169,6 @@
}
boolean isHidden = mHiddenFlags != 0;
mMultiValueAlpha.getProperty(INDEX_HIDDEN_FLAGS_ALPHA).setValue(isHidden ? 0 : 1);
- setVisibility(isHidden ? INVISIBLE : VISIBLE);
}
/**
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 217997d..7111b69 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
@@ -24,6 +24,7 @@
import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_ICON_PARAMS;
import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
+import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK;
import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
import static com.android.launcher3.Utilities.mapToRange;
import static com.android.launcher3.Utilities.squaredHypot;
@@ -78,7 +79,6 @@
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
-import android.view.TouchDelegate;
import android.view.View;
import android.view.ViewDebug;
import android.view.ViewGroup;
@@ -93,6 +93,7 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.LauncherState;
import com.android.launcher3.PagedView;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
@@ -115,6 +116,7 @@
import com.android.launcher3.util.DynamicResource;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.util.OverScroller;
+import com.android.launcher3.util.ResourceBasedOverride.Overrides;
import com.android.launcher3.util.Themes;
import com.android.launcher3.util.ViewPool;
import com.android.quickstep.BaseActivityInterface;
@@ -123,6 +125,7 @@
import com.android.quickstep.RecentsModel;
import com.android.quickstep.RecentsModel.TaskVisualsChangeListener;
import com.android.quickstep.SystemUiProxy;
+import com.android.quickstep.TaskOverlayFactory;
import com.android.quickstep.TaskThumbnailCache;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.ViewUtils;
@@ -277,6 +280,8 @@
private final ViewPool<TaskView> mTaskViewPool;
+ private final TaskOverlayFactory mTaskOverlayFactory;
+
private boolean mDwbToastShown;
protected boolean mDisallowScrollToClearAll;
private boolean mOverlayEnabled;
@@ -464,6 +469,11 @@
updateEmptyMessage();
mOrientationHandler = mOrientationState.getOrientationHandler();
+ mTaskOverlayFactory = Overrides.getObject(
+ TaskOverlayFactory.class,
+ context.getApplicationContext(),
+ R.string.task_overlay_factory_class);
+
// Initialize quickstep specific cache params here, as this is constructed only once
mActivity.getViewCache().setCacheSize(R.layout.digital_wellbeing_toast, 5);
}
@@ -557,6 +567,7 @@
mIPinnedStackAnimationListener);
mOrientationState.initListeners();
SplitScreenBounds.INSTANCE.addOnChangeListener(this);
+ mTaskOverlayFactory.initListeners();
}
@Override
@@ -573,6 +584,7 @@
SplitScreenBounds.INSTANCE.removeOnChangeListener(this);
mIPinnedStackAnimationListener.setActivity(null);
mOrientationState.destroyListeners();
+ mTaskOverlayFactory.removeListeners();
}
@Override
@@ -687,12 +699,9 @@
super.onTouchEvent(ev);
TaskView taskView = getCurrentPageTaskView();
- if (taskView != null) {
- TouchDelegate mChildTouchDelegate = taskView.getIconTouchDelegate(ev);
- if (mChildTouchDelegate != null && mChildTouchDelegate.onTouchEvent(ev)) {
- // Keep consuming events to pass to delegate
- return true;
- }
+ if (taskView != null && taskView.offerTouchToChildren(ev)) {
+ // Keep consuming events to pass to delegate
+ return true;
}
final int x = (int) ev.getX();
@@ -1712,6 +1721,12 @@
if (mOrientationState.setRecentsRotation(mActivity.getDisplay().getRotation())) {
updateOrientationHandler();
}
+ // If overview is in modal state when rotate, reset it to overview state without running
+ // animation.
+ if (mActivity.isInState(OVERVIEW_MODAL_TASK)) {
+ mActivity.getStateManager().goToState(LauncherState.OVERVIEW, false);
+ resetModalVisuals();
+ }
}
public void setLayoutRotation(int touchRotation, int displayRotation) {
@@ -2424,6 +2439,10 @@
*/
public void setModalStateEnabled(boolean isModalState) { }
+ public TaskOverlayFactory getTaskOverlayFactory() {
+ return mTaskOverlayFactory;
+ }
+
public BaseActivityInterface getSizeStrategy() {
return mSizeStrategy;
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java
index 8b49f2c..fb799a8 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java
@@ -251,7 +251,7 @@
setScaleX(taskView.getScaleX());
setScaleY(taskView.getScaleY());
boolean canActivityRotate = taskView.getRecentsView()
- .mOrientationState.canRecentsActivityRotate();
+ .mOrientationState.isRecentsActivityRotationAllowed();
mOptionLayout.setOrientation(orientationHandler
.getTaskMenuLayoutOrientation(canActivityRotate, mOptionLayout));
setPosition(sTempRect.left - insets.left, sTempRect.top - insets.top,
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
index fad6427..607672a 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -52,7 +52,6 @@
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.util.Themes;
-import com.android.quickstep.TaskOverlayFactory;
import com.android.quickstep.TaskOverlayFactory.TaskOverlay;
import com.android.quickstep.views.TaskView.FullscreenDrawParams;
import com.android.systemui.plugins.OverviewScreenshotActions;
@@ -85,7 +84,7 @@
};
private final BaseActivity mActivity;
- private final TaskOverlay mOverlay;
+ private TaskOverlay mOverlay;
private final boolean mIsDarkTextTheme;
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
@@ -118,7 +117,6 @@
public TaskThumbnailView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
- mOverlay = TaskOverlayFactory.INSTANCE.get(context).createOverlay(this);
mPaint.setFilterBitmap(true);
mBackgroundPaint.setColor(Color.WHITE);
mClearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
@@ -134,7 +132,7 @@
* @param task
*/
public void bind(Task task) {
- mOverlay.reset();
+ getTaskOverlay().reset();
mTask = task;
int color = task == null ? Color.BLACK : task.colorBackground | 0xFF000000;
mPaint.setColor(color);
@@ -176,7 +174,7 @@
mBitmapShader = null;
mThumbnailData = null;
mPaint.setShader(null);
- mOverlay.reset();
+ getTaskOverlay().reset();
}
if (mOverviewScreenshotActionsPlugin != null) {
mOverviewScreenshotActionsPlugin.setupActions(getTaskView(), getThumbnail(), mActivity);
@@ -200,6 +198,9 @@
}
public TaskOverlay getTaskOverlay() {
+ if (mOverlay == null) {
+ mOverlay = getTaskView().getRecentsView().getTaskOverlayFactory().createOverlay(this);
+ }
return mOverlay;
}
@@ -357,10 +358,10 @@
private void updateOverlay() {
if (mOverlayEnabled) {
- mOverlay.initOverlay(mTask, mThumbnailData, mPreviewPositionHelper.mMatrix,
+ getTaskOverlay().initOverlay(mTask, mThumbnailData, mPreviewPositionHelper.mMatrix,
mPreviewPositionHelper.mIsOrientationChanged);
} else {
- mOverlay.reset();
+ getTaskOverlay().reset();
}
}
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 3621658..0d755b8 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
@@ -135,6 +135,7 @@
* delegated bounds only to be updated.
*/
private TransformingTouchDelegate mIconTouchDelegate;
+ private TransformingTouchDelegate mChipTouchDelegate;
private static final List<Rect> SYSTEM_GESTURE_EXCLUSION_RECT =
Collections.singletonList(new Rect());
@@ -200,6 +201,7 @@
private View mContextualChipWrapper;
private View mContextualChip;
private final float[] mIconCenterCoords = new float[2];
+ private final float[] mChipCenterCoords = new float[2];
public TaskView(Context context) {
this(context, null);
@@ -263,11 +265,22 @@
mIconTouchDelegate = new TransformingTouchDelegate(mIconView);
}
- public TouchDelegate getIconTouchDelegate(MotionEvent event) {
+ /**
+ * Whether the taskview should take the touch event from parent. Events passed to children
+ * that might require special handling.
+ */
+ public boolean offerTouchToChildren(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
computeAndSetIconTouchDelegate();
+ computeAndSetChipTouchDelegate();
}
- return mIconTouchDelegate;
+ if (mIconTouchDelegate != null && mIconTouchDelegate.onTouchEvent(event)) {
+ return true;
+ }
+ if (mChipTouchDelegate != null && mChipTouchDelegate.onTouchEvent(event)) {
+ return true;
+ }
+ return false;
}
private void computeAndSetIconTouchDelegate() {
@@ -282,6 +295,23 @@
(int) (mIconCenterCoords[1] + iconHalfSize));
}
+ private void computeAndSetChipTouchDelegate() {
+ if (mContextualChipWrapper != null) {
+ float chipHalfWidth = mContextualChipWrapper.getWidth() / 2f;
+ float chipHalfHeight = mContextualChipWrapper.getHeight() / 2f;
+ mChipCenterCoords[0] = chipHalfWidth;
+ mChipCenterCoords[1] = chipHalfHeight;
+ getDescendantCoordRelativeToAncestor(mContextualChipWrapper, mActivity.getDragLayer(),
+ mChipCenterCoords,
+ false);
+ mChipTouchDelegate.setBounds(
+ (int) (mChipCenterCoords[0] - chipHalfWidth),
+ (int) (mChipCenterCoords[1] - chipHalfHeight),
+ (int) (mChipCenterCoords[0] + chipHalfWidth),
+ (int) (mChipCenterCoords[1] + chipHalfHeight));
+ }
+ }
+
/**
* The modalness of this view is how it should be displayed when it is shown on its own in the
* modal state of overview.
@@ -289,6 +319,9 @@
* @param modalness [0, 1] 0 being in context with other tasks, 1 being shown on its own.
*/
public void setModalness(float modalness) {
+ if (mModalness == modalness) {
+ return;
+ }
mModalness = modalness;
mIconView.setAlpha(comp(modalness));
if (mContextualChip != null) {
@@ -298,7 +331,6 @@
if (mContextualChipWrapper != null) {
mContextualChipWrapper.setAlpha(comp(modalness));
}
-
updateFooterVerticalOffset(mFooterVerticalOffset);
}
@@ -549,7 +581,11 @@
.getInterpolation(progress);
mIconView.setScaleX(scale);
mIconView.setScaleY(scale);
-
+ if (mContextualChip != null && mContextualChipWrapper != null) {
+ mContextualChipWrapper.setAlpha(scale);
+ mContextualChip.setScaleX(scale);
+ mContextualChip.setScaleY(scale);
+ }
updateFooterVerticalOffset(1.0f - scale);
}
@@ -728,6 +764,7 @@
mContextualChip.animate().scaleX(1f).scaleY(1f).setDuration(50);
}
if (mContextualChipWrapper != null) {
+ mChipTouchDelegate = new TransformingTouchDelegate(mContextualChipWrapper);
mContextualChipWrapper.animate().alpha(1f).setDuration(50);
}
}
@@ -749,6 +786,7 @@
View oldContextualChipWrapper = mContextualChipWrapper;
mContextualChipWrapper = null;
mContextualChip = null;
+ mChipTouchDelegate = null;
return oldContextualChipWrapper;
}
diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml
index 1191bec..d1ae0fe 100644
--- a/quickstep/res/values-es-rUS/strings.xml
+++ b/quickstep/res/values-es-rUS/strings.xml
@@ -33,9 +33,9 @@
<string name="all_apps_label" msgid="8542784161730910663">"Todas las apps"</string>
<string name="all_apps_prediction_tip" msgid="2672336544844936186">"Predicción de tus apps"</string>
<string name="hotseat_edu_title_migrate" msgid="306578144424489980">"Obtén sugerencias de aplicaciones en la fila inferior de la pantalla principal"</string>
- <string name="hotseat_edu_title_migrate_landscape" msgid="3633942953997845243">"Obtén sugerencias de apps en la fila de favoritos de la Pantalla principal"</string>
+ <string name="hotseat_edu_title_migrate_landscape" msgid="3633942953997845243">"Obtén sugerencias de apps en la fila de favoritos de la pantalla principal"</string>
<string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"Accede fácilmente en la pantalla principal a las apps que más usas. Las sugerencias cambiarán según tus rutinas. Las apps de la fila inferior se desplazarán hacia arriba en la pantalla principal."</string>
- <string name="hotseat_edu_message_migrate_landscape" msgid="4248943380443387697">"Accede fácilmente en la pantalla principal a las apps que más usas. Las sugerencias cambiarán según tus rutinas. Se moverán a la Pantalla principal las apps que estén en la fila de favoritos."</string>
+ <string name="hotseat_edu_message_migrate_landscape" msgid="4248943380443387697">"Accede fácilmente en la pantalla principal a las apps que más usas. Las sugerencias cambiarán según tus rutinas. Se moverán a la pantalla principal las apps que estén en la fila de favoritos."</string>
<string name="hotseat_edu_message_migrate_alt" msgid="3042360119039646356">"Accede fácilmente a las apps que más usas en la pantalla principal. Las sugerencias cambiarán según tus rutinas. Las apps de la fila inferior se moverán a una nueva carpeta."</string>
<string name="hotseat_edu_accept" msgid="1611544083278999837">"Obtén sugerencias de aplicaciones"</string>
<string name="hotseat_edu_dismiss" msgid="2781161822780201689">"No, gracias"</string>
diff --git a/quickstep/res/values-hu/strings.xml b/quickstep/res/values-hu/strings.xml
index 75983c4..f81355e 100644
--- a/quickstep/res/values-hu/strings.xml
+++ b/quickstep/res/values-hu/strings.xml
@@ -20,7 +20,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Osztott képernyő"</string>
- <string name="recent_task_option_pin" msgid="7929860679018978258">"Rögzítés"</string>
+ <string name="recent_task_option_pin" msgid="7929860679018978258">"Kitűzés"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Szabad forma"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nincsenek mostanában használt elemek"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Alkalmazáshasználati beállítások"</string>
diff --git a/quickstep/res/values-in/strings.xml b/quickstep/res/values-in/strings.xml
index a85ea4e..d7437d0 100644
--- a/quickstep/res/values-in/strings.xml
+++ b/quickstep/res/values-in/strings.xml
@@ -25,7 +25,7 @@
<string name="recents_empty_message" msgid="7040467240571714191">"Tidak ada item yang baru dibuka"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Setelan penggunaan aplikasi"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Hapus semua"</string>
- <string name="accessibility_recent_apps" msgid="4058661986695117371">"Aplikasi baru-baru ini"</string>
+ <string name="accessibility_recent_apps" msgid="4058661986695117371">"Aplikasi terbaru"</string>
<string name="task_contents_description_with_remaining_time" msgid="4479688746574672685">"<xliff:g id="TASK_DESCRIPTION">%1$s</xliff:g>, <xliff:g id="REMAINING_TIME">%2$s</xliff:g>"</string>
<string name="shorter_duration_less_than_one_minute" msgid="4722015666335015336">"< 1 menit"</string>
<string name="time_left_for_app" msgid="3111996412933644358">"<xliff:g id="TIME">%1$s</xliff:g> tersisa hari ini"</string>
diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml
index 0f2955b..a57112b 100644
--- a/quickstep/res/values/config.xml
+++ b/quickstep/res/values/config.xml
@@ -16,6 +16,8 @@
<resources>
<string name="task_overlay_factory_class" translatable="false"/>
+ <string name="overscroll_plugin_factory_class" translatable="false" />
+
<!-- Activities which block home gesture -->
<string-array name="gesture_blocking_activities" translatable="false">
<item>com.android.launcher3/com.android.quickstep.interaction.GestureSandboxActivity</item>
diff --git a/quickstep/src/com/android/launcher3/model/WellbeingModel.java b/quickstep/src/com/android/launcher3/model/WellbeingModel.java
index cc7b712..810f4e3 100644
--- a/quickstep/src/com/android/launcher3/model/WellbeingModel.java
+++ b/quickstep/src/com/android/launcher3/model/WellbeingModel.java
@@ -43,9 +43,13 @@
import android.util.Log;
import androidx.annotation.MainThread;
+import androidx.annotation.NonNull;
import androidx.annotation.WorkerThread;
import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.LauncherProvider;
+import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.data.ItemInfo;
@@ -74,6 +78,9 @@
private static final int MSG_PACKAGE_REMOVED = 2;
private static final int MSG_FULL_REFRESH = 3;
+ private static final int UNKNOWN_MINIMAL_DEVICE_STATE = 0;
+ private static final int IN_MINIMAL_DEVICE = 2;
+
// Welbeing contract
private static final String PATH_ACTIONS = "actions";
private static final String PATH_MINIMAL_DEVICE = "minimal_device";
@@ -84,6 +91,8 @@
private static final String EXTRA_MAX_NUM_ACTIONS_SHOWN = "max_num_actions_shown";
private static final String EXTRA_PACKAGES = "packages";
private static final String EXTRA_SUCCESS = "success";
+ private static final String EXTRA_MINIMAL_DEVICE_STATE = "minimal_device_state";
+ private static final String DB_NAME_MINIMAL_DEVICE = "minimal.db";
public static final MainThreadInitializedObject<WellbeingModel> INSTANCE =
new MainThreadInitializedObject<>(WellbeingModel::new);
@@ -121,11 +130,12 @@
updateWellbeingData();
} else if (uri.getPath().contains(PATH_MINIMAL_DEVICE)) {
// Wellbeing reports that minimal device state or config is changed.
- updateLauncherModel();
+ updateLauncherModel(context);
}
}
};
- FeatureFlags.ENABLE_MINIMAL_DEVICE.addChangeListener(mContext, this::updateLauncherModel);
+ FeatureFlags.ENABLE_MINIMAL_DEVICE.addChangeListener(mContext, () ->
+ updateLauncherModel(context));
if (!TextUtils.isEmpty(mWellbeingProviderPkg)) {
context.registerReceiver(
@@ -170,7 +180,6 @@
Log.e(TAG, "Failed to register content observer for " + actionsUri + ": " + e);
if (mIsInTest) throw new RuntimeException(e);
}
-
updateWellbeingData();
}
@@ -208,10 +217,34 @@
mWorkerHandler.sendEmptyMessage(MSG_FULL_REFRESH);
}
- private void updateLauncherModel() {
- if (!FeatureFlags.ENABLE_MINIMAL_DEVICE.get()) return;
+ private void updateLauncherModel(@NonNull final Context context) {
+ if (!FeatureFlags.ENABLE_MINIMAL_DEVICE.get()) {
+ reloadLauncherInNormalMode(context);
+ return;
+ }
+ runWithMinimalDeviceConfigs((bundle) -> {
+ if (bundle.getInt(EXTRA_MINIMAL_DEVICE_STATE, UNKNOWN_MINIMAL_DEVICE_STATE)
+ == IN_MINIMAL_DEVICE) {
+ reloadLauncherInMinimalMode(context);
+ } else {
+ reloadLauncherInNormalMode(context);
+ }
+ });
+ }
- // TODO: init Launcher in minimal device / normal mode
+ private void reloadLauncherInNormalMode(@NonNull final Context context) {
+ LauncherSettings.Settings.call(context.getContentResolver(),
+ LauncherSettings.Settings.METHOD_SWITCH_DATABASE,
+ InvariantDeviceProfile.INSTANCE.get(context).dbFile);
+ }
+
+ private void reloadLauncherInMinimalMode(@NonNull final Context context) {
+ final Bundle extras = new Bundle();
+ extras.putString(LauncherProvider.KEY_LAYOUT_PROVIDER_AUTHORITY,
+ mWellbeingProviderPkg + ".api");
+ LauncherSettings.Settings.call(context.getContentResolver(),
+ LauncherSettings.Settings.METHOD_SWITCH_DATABASE,
+ DB_NAME_MINIMAL_DEVICE, extras);
}
private Uri.Builder apiBuilder() {
@@ -225,6 +258,9 @@
*/
@WorkerThread
private void runWithMinimalDeviceConfigs(Consumer<Bundle> consumer) {
+ if (!FeatureFlags.ENABLE_MINIMAL_DEVICE.get()) {
+ return;
+ }
if (DEBUG || mIsInTest) {
Log.d(TAG, "runWithMinimalDeviceConfigs() called");
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
index 1b8e244..aad7e17 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
@@ -18,6 +18,7 @@
import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE_IN_OUT;
import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.graphics.OverviewScrim.SCRIM_MULTIPLIER;
import static com.android.launcher3.graphics.Scrim.SCRIM_PROGRESS;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_MODAL;
@@ -70,6 +71,7 @@
getContentAlphaProperty().set(mRecentsView, state.overviewUi ? 1f : 0);
OverviewScrim scrim = mLauncher.getDragLayer().getOverviewScrim();
SCRIM_PROGRESS.set(scrim, state.getOverviewScrimAlpha(mLauncher));
+ SCRIM_MULTIPLIER.set(scrim, 1f);
getTaskModalnessProperty().set(mRecentsView, state.getOverviewModalness());
}
@@ -108,6 +110,8 @@
OverviewScrim scrim = mLauncher.getDragLayer().getOverviewScrim();
setter.setFloat(scrim, SCRIM_PROGRESS, toState.getOverviewScrimAlpha(mLauncher),
config.getInterpolator(ANIM_OVERVIEW_SCRIM_FADE, LINEAR));
+ setter.setFloat(scrim, SCRIM_MULTIPLIER, 1f,
+ config.getInterpolator(ANIM_OVERVIEW_SCRIM_FADE, LINEAR));
setter.setFloat(
mRecentsView, getTaskModalnessProperty(),
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
index e7cd393..29a6be0 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -18,6 +18,7 @@
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
+import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
import android.content.Context;
@@ -92,7 +93,8 @@
@Override
public float[] getOverviewScaleAndOffset(Launcher launcher) {
- return new float[] {0.9f, 0};
+ float offset = ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(launcher) ? 1 : 0;
+ return new float[] {0.9f, offset};
}
@Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
index 20ee61d..a684b9d 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
@@ -142,6 +142,10 @@
Log.d(TestProtocol.OVERIEW_NOT_ALLAPPS,
"PortraitStatesTouchController.getTargetState 1");
}
+ if (ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(mLauncher)) {
+ // Don't allow swiping down to overview.
+ return NORMAL;
+ }
return TouchInteractionService.isConnected() ?
mLauncher.getStateManager().getLastState() : NORMAL;
} else if (fromState == OVERVIEW) {
diff --git a/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java b/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java
index 23b02d5..deb70e0 100644
--- a/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java
+++ b/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java
@@ -18,6 +18,8 @@
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS;
+import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
+import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION;
import android.animation.TimeInterpolator;
import android.content.Context;
@@ -27,12 +29,17 @@
import android.graphics.RectF;
import android.util.FloatProperty;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Launcher;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
+import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.quickstep.LauncherActivityInterface;
import com.android.quickstep.SysUINavigationMode;
+import com.android.quickstep.views.RecentsView;
/**
* Controls an animation that can go beyond progress = 1, at which point resistance should be
@@ -48,15 +55,33 @@
*/
public static final float TWO_BUTTON_EXTRA_DRAG_FACTOR = 0.25f;
- /**
- * Start slowing down the rate of scaling down when recents view is smaller than this scale.
- */
- private static final float RECENTS_SCALE_START_RESIST = 0.75f;
+ private enum RecentsResistanceParams {
+ FROM_APP(0.75f, 0.5f, 1f),
+ FROM_OVERVIEW(1f, 0.75f, 0.5f);
- /**
- * Recents view will reach this scale at the very end of the drag.
- */
- private static final float RECENTS_SCALE_MAX_RESIST = 0.5f;
+ RecentsResistanceParams(float scaleStartResist, float scaleMaxResist,
+ float translationFactor) {
+ this.scaleStartResist = scaleStartResist;
+ this.scaleMaxResist = scaleMaxResist;
+ this.translationFactor = translationFactor;
+ }
+
+ /**
+ * Start slowing down the rate of scaling down when recents view is smaller than this scale.
+ */
+ public final float scaleStartResist;
+
+ /**
+ * Recents view will reach this scale at the very end of the drag.
+ */
+ public final float scaleMaxResist;
+
+ /**
+ * How much translation to apply to RecentsView when the drag reaches the top of the screen,
+ * where 0 will keep it centered and 1 will have it barely touch the top of the screen.
+ */
+ public final float translationFactor;
+ }
private static final TimeInterpolator RECENTS_SCALE_RESIST_INTERPOLATOR = DEACCEL;
private static final TimeInterpolator RECENTS_TRANSLATE_RESIST_INTERPOLATOR = LINEAR;
@@ -115,25 +140,44 @@
RecentsOrientedState recentsOrientedState, DeviceProfile dp, SCALE scaleTarget,
FloatProperty<SCALE> scaleProperty, TRANSLATION translationTarget,
FloatProperty<TRANSLATION> translationProperty) {
+
+ RecentsParams params = new RecentsParams(context, recentsOrientedState, dp, scaleTarget,
+ scaleProperty, translationTarget, translationProperty);
+ PendingAnimation resistAnim = createRecentsResistanceAnim(params);
+
+ AnimatorPlaybackController resistanceController = resistAnim.createPlaybackController();
+ return new AnimatorControllerWithResistance(normalController, resistanceController);
+ }
+
+ /**
+ * Creates the resistance animation for {@link #createForRecents}, or can be used separately
+ * when starting from recents, i.e. {@link #createRecentsResistanceFromOverviewAnim}.
+ */
+ public static <SCALE, TRANSLATION> PendingAnimation createRecentsResistanceAnim(
+ RecentsParams<SCALE, TRANSLATION> params) {
Rect startRect = new Rect();
- LauncherActivityInterface.INSTANCE.calculateTaskSize(context, dp, startRect,
- recentsOrientedState.getOrientationHandler());
+ PagedOrientationHandler orientationHandler = params.recentsOrientedState
+ .getOrientationHandler();
+ LauncherActivityInterface.INSTANCE.calculateTaskSize(params.context, params.dp, startRect,
+ orientationHandler);
long distanceToCover = startRect.bottom;
- boolean isTwoButtonMode = SysUINavigationMode.getMode(context) == TWO_BUTTONS;
+ boolean isTwoButtonMode = SysUINavigationMode.getMode(params.context) == TWO_BUTTONS;
if (isTwoButtonMode) {
// We can only drag a small distance past overview, not to the top of the screen.
distanceToCover = (long)
- ((dp.heightPx - startRect.bottom) * TWO_BUTTON_EXTRA_DRAG_FACTOR);
+ ((params.dp.heightPx - startRect.bottom) * TWO_BUTTON_EXTRA_DRAG_FACTOR);
}
- PendingAnimation resistAnim = new PendingAnimation(distanceToCover * 2);
+ PendingAnimation resistAnim = params.resistAnim != null
+ ? params.resistAnim
+ : new PendingAnimation(distanceToCover * 2);
PointF pivot = new PointF();
- float fullscreenScale = recentsOrientedState.getFullScreenScaleAndPivot(
- startRect, dp, pivot);
- float startScale = 1;
- float prevScaleRate = (fullscreenScale - startScale) / (dp.heightPx - startRect.bottom);
+ float fullscreenScale = params.recentsOrientedState.getFullScreenScaleAndPivot(
+ startRect, params.dp, pivot);
+ float prevScaleRate = (fullscreenScale - params.startScale)
+ / (params.dp.heightPx - startRect.bottom);
// This is what the scale would be at the end of the drag if we didn't apply resistance.
- float endScale = startScale - prevScaleRate * distanceToCover;
+ float endScale = params.startScale - prevScaleRate * distanceToCover;
final TimeInterpolator scaleInterpolator;
if (isTwoButtonMode) {
// We are bounded by the distance of the drag, so we don't need to apply resistance.
@@ -141,9 +185,10 @@
} else {
// Create an interpolator that resists the scale so the scale doesn't get smaller than
// RECENTS_SCALE_MAX_RESIST.
- float startResist = Utilities.getProgress(RECENTS_SCALE_START_RESIST, startScale,
- endScale);
- float maxResist = Utilities.getProgress(RECENTS_SCALE_MAX_RESIST, startScale, endScale);
+ float startResist = Utilities.getProgress(params.resistanceParams.scaleStartResist,
+ params.startScale, endScale);
+ float maxResist = Utilities.getProgress(params.resistanceParams.scaleMaxResist,
+ params.startScale, endScale);
scaleInterpolator = t -> {
if (t < startResist) {
return t;
@@ -153,24 +198,92 @@
return startResist + resistProgress * (maxResist - startResist);
};
}
- resistAnim.addFloat(scaleTarget, scaleProperty, startScale, endScale,
+ resistAnim.addFloat(params.scaleTarget, params.scaleProperty, params.startScale, endScale,
scaleInterpolator);
if (!isTwoButtonMode) {
// Compute where the task view would be based on the end scale, if we didn't translate.
RectF endRectF = new RectF(startRect);
Matrix temp = new Matrix();
- temp.setScale(RECENTS_SCALE_MAX_RESIST, RECENTS_SCALE_MAX_RESIST, pivot.x, pivot.y);
+ temp.setScale(params.resistanceParams.scaleMaxResist,
+ params.resistanceParams.scaleMaxResist, pivot.x, pivot.y);
temp.mapRect(endRectF);
// Translate such that the task view touches the top of the screen when drag does.
- float endTranslation = endRectF.top * recentsOrientedState.getOrientationHandler()
- .getSecondaryTranslationDirectionFactor();
- resistAnim.addFloat(translationTarget, translationProperty, 0, endTranslation,
- RECENTS_TRANSLATE_RESIST_INTERPOLATOR);
+ float endTranslation = endRectF.top
+ * orientationHandler.getSecondaryTranslationDirectionFactor()
+ * params.resistanceParams.translationFactor;
+ resistAnim.addFloat(params.translationTarget, params.translationProperty,
+ params.startTranslation, endTranslation, RECENTS_TRANSLATE_RESIST_INTERPOLATOR);
}
- AnimatorPlaybackController resistanceController = resistAnim.createPlaybackController();
- return new AnimatorControllerWithResistance(normalController, resistanceController);
+ return resistAnim;
}
+ /**
+ * Helper method to update or create a PendingAnimation suitable for animating
+ * a RecentsView interaction that started from the overview state.
+ */
+ public static PendingAnimation createRecentsResistanceFromOverviewAnim(
+ Launcher launcher, @Nullable PendingAnimation resistanceAnim) {
+ RecentsView recentsView = launcher.getOverviewPanel();
+ RecentsParams params = new RecentsParams(launcher, recentsView.getPagedViewOrientedState(),
+ launcher.getDeviceProfile(), recentsView, RECENTS_SCALE_PROPERTY, recentsView,
+ TASK_SECONDARY_TRANSLATION)
+ .setResistAnim(resistanceAnim)
+ .setResistanceParams(RecentsResistanceParams.FROM_OVERVIEW)
+ .setStartScale(recentsView.getScaleX());
+ return createRecentsResistanceAnim(params);
+ }
+
+ /**
+ * Params to compute resistance when scaling/translating recents.
+ */
+ private static class RecentsParams<SCALE, TRANSLATION> {
+ // These are all required and can't have default values, hence are final.
+ public final Context context;
+ public final RecentsOrientedState recentsOrientedState;
+ public final DeviceProfile dp;
+ public final SCALE scaleTarget;
+ public final FloatProperty<SCALE> scaleProperty;
+ public final TRANSLATION translationTarget;
+ public final FloatProperty<TRANSLATION> translationProperty;
+
+ // These are not required, or can have a default value that is generally correct.
+ @Nullable public PendingAnimation resistAnim = null;
+ public RecentsResistanceParams resistanceParams = RecentsResistanceParams.FROM_APP;
+ public float startScale = 1f;
+ public float startTranslation = 0f;
+
+ private RecentsParams(Context context, RecentsOrientedState recentsOrientedState,
+ DeviceProfile dp, SCALE scaleTarget, FloatProperty<SCALE> scaleProperty,
+ TRANSLATION translationTarget, FloatProperty<TRANSLATION> translationProperty) {
+ this.context = context;
+ this.recentsOrientedState = recentsOrientedState;
+ this.dp = dp;
+ this.scaleTarget = scaleTarget;
+ this.scaleProperty = scaleProperty;
+ this.translationTarget = translationTarget;
+ this.translationProperty = translationProperty;
+ }
+
+ private RecentsParams setResistAnim(PendingAnimation resistAnim) {
+ this.resistAnim = resistAnim;
+ return this;
+ }
+
+ private RecentsParams setResistanceParams(RecentsResistanceParams resistanceParams) {
+ this.resistanceParams = resistanceParams;
+ return this;
+ }
+
+ private RecentsParams setStartScale(float startScale) {
+ this.startScale = startScale;
+ return this;
+ }
+
+ private RecentsParams setStartTranslation(float startTranslation) {
+ this.startTranslation = startTranslation;
+ return this;
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
index 969fa50..f60f7ad 100644
--- a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
+++ b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
@@ -276,7 +276,7 @@
private static final int HISTORY_SIZE = 20;
// Position history are stored in a circular array
- private final float[] mHistoricTimes = new float[HISTORY_SIZE];
+ private final long[] mHistoricTimes = new long[HISTORY_SIZE];
private final float[] mHistoricPos = new float[HISTORY_SIZE];
private int mHistoryCount = 0;
private int mHistoryStart = 0;
@@ -292,7 +292,7 @@
mHistoryCount = mHistoryStart = 0;
}
- private void addPositionAndTime(float eventTime, float eventPosition) {
+ private void addPositionAndTime(long eventTime, float eventPosition) {
mHistoricTimes[mHistoryStart] = eventTime;
mHistoricPos[mHistoryStart] = eventPosition;
mHistoryStart++;
@@ -322,7 +322,7 @@
* Based on solveUnweightedLeastSquaresDeg2 in VelocityTracker.cpp
*/
private Float solveUnweightedLeastSquaresDeg2(final int pointPos) {
- final float eventTime = mHistoricTimes[pointPos];
+ final long eventTime = mHistoricTimes[pointPos];
float sxi = 0, sxiyi = 0, syi = 0, sxi2 = 0, sxi3 = 0, sxi2yi = 0, sxi4 = 0;
int count = 0;
@@ -332,8 +332,8 @@
index += HISTORY_SIZE;
}
- float time = mHistoricTimes[index];
- float age = eventTime - time;
+ long time = mHistoricTimes[index];
+ long age = eventTime - time;
if (age > HORIZON_MS) {
break;
}
@@ -364,7 +364,7 @@
if (endPos < 0) {
endPos += HISTORY_SIZE;
}
- float denominator = eventTime - mHistoricTimes[endPos];
+ long denominator = eventTime - mHistoricTimes[endPos];
if (denominator != 0) {
return (mHistoricPos[pointPos] - mHistoricPos[endPos]) / denominator;
}
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index f19d121..c39a9dc 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -53,7 +53,7 @@
<string name="app_info_drop_target_label" msgid="692894985365717661">"Programinligting"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Installeer"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Moenie program voorstel nie"</string>
- <string name="pin_prediction" msgid="4196423321649756498">"PIN-voorspelling"</string>
+ <string name="pin_prediction" msgid="4196423321649756498">"Vasspeldvoorspelling"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"installeer kortpaaie"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Laat \'n program toe om kortpaaie by te voeg sonder gebruikerinmenging."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"lees Tuis-instellings en -kortpaaie"</string>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
index a6967b7..8e9aafc 100644
--- a/res/values-as/strings.xml
+++ b/res/values-as/strings.xml
@@ -98,7 +98,7 @@
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"নতুন এপসমূহৰ বাবে"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"অজ্ঞাত"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"আঁতৰাওক"</string>
- <string name="abandoned_search" msgid="891119232568284442">"সন্ধান কৰক"</string>
+ <string name="abandoned_search" msgid="891119232568284442">"Search"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"এই এপটো ইনষ্টল কৰা হোৱা নাই"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"এই আইকনৰ এপটো ইনষ্টল কৰা হোৱা নাই। আপুনি এইটো আঁতৰাব পাৰে অথবা এপটো বিচাৰি মেনুৱেলভাৱে ইনষ্টল কৰিব পাৰে।"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ডাউনল’ড কৰি থকা হৈছে, <xliff:g id="PROGRESS">%2$s</xliff:g> সম্পূৰ্ণ হ’ল"</string>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index af3dcdb..0cec9a3 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -98,7 +98,7 @@
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"नए ऐप्लिकेशन के लिए"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"अज्ञात"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"निकालें"</string>
- <string name="abandoned_search" msgid="891119232568284442">"सर्च करें"</string>
+ <string name="abandoned_search" msgid="891119232568284442">"खोजें"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"यह ऐप्लिकेशन इंस्टॉल नहीं है"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"इस आइकॉन का ऐप इंस्टॉल नहीं है. आप उसे निकाल सकते हैं या ऐप को खोज कर उसे मैन्युअल रूप से इंस्टॉल कर सकते हैं."</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> डाउनलोड हो रहा है, <xliff:g id="PROGRESS">%2$s</xliff:g> पूरी हुई"</string>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index 99b582b..c098bb3 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -48,8 +48,8 @@
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"Անձնական հավելվածների ցանկ"</string>
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Աշխատանքային հավելվածների ցանկ"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Հիմնական"</string>
- <string name="remove_drop_target_label" msgid="7812859488053230776">"Ապատեղադրել"</string>
- <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Հեռացնել"</string>
+ <string name="remove_drop_target_label" msgid="7812859488053230776">"Հեռացնել"</string>
+ <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Ապատեղադրել"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Հավելվածի մասին"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Տեղադրել"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Թաքցնել առաջարկը"</string>
@@ -97,7 +97,7 @@
<string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Ավելացնել պատկերակները հիմնական էկրանին"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Նոր հավելվածների համար"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Անհայտ է"</string>
- <string name="abandoned_clean_this" msgid="7610119707847920412">"Ապատեղադրել"</string>
+ <string name="abandoned_clean_this" msgid="7610119707847920412">"Հեռացնել"</string>
<string name="abandoned_search" msgid="891119232568284442">"Գտնել"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Այս ծրագիրը տեղադրված չէ:"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Այս պատկերակի ծրագիրը տեղադրված չէ: Դուք կարող եք հեռացնել այն կամ գտնել ծրագիրը և տեղադրել այն ձեռքով:"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index a6e37c4..4e0181c 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -53,7 +53,7 @@
<string name="app_info_drop_target_label" msgid="692894985365717661">"アプリ情報"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"インストール"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"アプリの候補を表示しない"</string>
- <string name="pin_prediction" msgid="4196423321649756498">"アプリの候補を固定表示"</string>
+ <string name="pin_prediction" msgid="4196423321649756498">"アプリの候補を固定"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"ショートカットのインストール"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"ユーザー操作なしでショートカットを追加することをアプリに許可します。"</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"ホームの設定とショートカットの読み取り"</string>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index 1990e9e..09c1152 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn/strings.xml
@@ -98,7 +98,7 @@
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"ಹೊಸ ಅಪ್ಲಿಕೇಶನ್ಗಳಿಗೆ"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"ಅಪರಿಚಿತ"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"ತೆಗೆದುಹಾಕಿ"</string>
- <string name="abandoned_search" msgid="891119232568284442">"ಹುಡುಕಿ"</string>
+ <string name="abandoned_search" msgid="891119232568284442">"Search"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"ಈ ಅಪ್ಲಿಕೇಶನ್ ಸ್ಥಾಪನೆಗೊಂಡಿಲ್ಲ"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"ಈ ಐಕಾನ್ ಅಪ್ಲಿಕೇಶನ್ ಸ್ಥಾಪನೆಗೊಂಡಿಲ್ಲ. ನೀವು ಅದನ್ನು ತೆಗೆದುಹಾಕಬಹುದು ಅಥವಾ ಅಪ್ಲಿಕೇಶನ್ ಹುಡುಕಬಹುದು ಮತ್ತು ಹಸ್ತಚಾಲಿತವಾಗಿ ಅದನ್ನು ಸ್ಥಾಪಿಸಬಹುದು."</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ಡೌನ್ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ, <xliff:g id="PROGRESS">%2$s</xliff:g> ಪೂರ್ಣಗೊಂಡಿದೆ"</string>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
index 01d8935..8156318 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml/strings.xml
@@ -98,7 +98,7 @@
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"പുതിയ ആപ്പുകൾക്ക്"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"അജ്ഞാതം"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"നീക്കംചെയ്യുക"</string>
- <string name="abandoned_search" msgid="891119232568284442">"തിരയുക"</string>
+ <string name="abandoned_search" msgid="891119232568284442">"Search"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"ഈ അപ്ലിക്കേഷൻ ഇൻസ്റ്റാളുചെയ്തിട്ടില്ല"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"ഈ ഐക്കണുവേണ്ടി അപ്ലിക്കേഷൻ ഇൻസ്റ്റാളുചെയ്തിട്ടില്ല. നിങ്ങൾക്കത് നീക്കംചെയ്യാനാകും അല്ലെങ്കിൽ അപ്ലിക്കേഷനുവേണ്ടി തിരഞ്ഞുകൊണ്ട് അത് സ്വമേധയാ ഇൻസ്റ്റാളുചെയ്യുക."</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ഡൗൺലോഡ് ചെയ്യുന്നു, <xliff:g id="PROGRESS">%2$s</xliff:g> പൂർത്തിയായി"</string>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
index 027e780..1d680ab 100644
--- a/res/values-mn/strings.xml
+++ b/res/values-mn/strings.xml
@@ -35,7 +35,7 @@
<string name="add_item_request_drag_hint" msgid="5899764264480397019">"Гараар байршуулахын тулд дараад хүлээнэ үү"</string>
<string name="place_automatically" msgid="8064208734425456485">"Автоматаар нэмэх"</string>
<string name="all_apps_search_bar_hint" msgid="1390553134053255246">"Апп хайх"</string>
- <string name="all_apps_loading_message" msgid="5813968043155271636">"Аппыг ачааллаж байна..."</string>
+ <string name="all_apps_loading_message" msgid="5813968043155271636">"Аппыг ачаалж байна..."</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\"-д тохирох апп олдсонгүй"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Бусад апп-г хайх"</string>
<string name="label_application" msgid="8531721983832654978">"Апп"</string>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index 488f911..6f50f05 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -98,7 +98,7 @@
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"नवीन ॲप्ससाठी"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"अज्ञात"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"काढा"</string>
- <string name="abandoned_search" msgid="891119232568284442">"शोधा"</string>
+ <string name="abandoned_search" msgid="891119232568284442">"Search"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"हा अॅप इंस्टॉल केलेला नाही"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"या चिन्हासाठी अॅप इंस्टॉल केलेला नाही. तुम्ही ते काढू शकता किंवा अॅपचा शोध घेऊ शकता आणि त्यास व्यक्तिचलितपणे इंस्टॉल करू शकता."</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> डाउनलोड होत आहे , <xliff:g id="PROGRESS">%2$s</xliff:g> पूर्ण झाले"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 76f1ecb..ded05b0 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -100,7 +100,7 @@
<string name="abandoned_clean_this" msgid="7610119707847920412">"Verwijderen"</string>
<string name="abandoned_search" msgid="891119232568284442">"Zoeken"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Deze app is niet geïnstalleerd"</string>
- <string name="abandoned_promise_explanation" msgid="3990027586878167529">"De app voor dit pictogram is niet geïnstalleerd. Je kunt het pictogram verwijderen of de app zoeken en handmatig installeren."</string>
+ <string name="abandoned_promise_explanation" msgid="3990027586878167529">"De app voor dit icoon is niet geïnstalleerd. Je kunt het icoon verwijderen of de app zoeken en handmatig installeren."</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> wordt gedownload, <xliff:g id="PROGRESS">%2$s</xliff:g> voltooid"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> wacht op installatie"</string>
<string name="widgets_bottom_sheet_title" msgid="2904559530954183366">"<xliff:g id="NAME">%1$s</xliff:g>-widgets"</string>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index c6e2ba1..994b620 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -98,7 +98,7 @@
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"ନୂଆ ଆପ୍ ପାଇଁ"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"ଅଜଣା"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"ବାହାର କରନ୍ତୁ"</string>
- <string name="abandoned_search" msgid="891119232568284442">"ସର୍ଚ୍ଚ କରନ୍ତୁ"</string>
+ <string name="abandoned_search" msgid="891119232568284442">"Search"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"ଏହି ଆପ୍ ଇନଷ୍ଟଲ୍ ହୋଇନାହିଁ"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"ଏହି ଆଇକନ୍ ପାଇଁ ଆପ୍ ଇନଷ୍ଟଲ୍ ହୋଇନାହିଁ। ଏହାକୁ ଆପଣ ଆପ୍ ପାଇଁ ବାହାର କରିପାରିବେ କିମ୍ୱା ସର୍ଚ୍ଚ କରି ପାରିବେ ଏବଂ ଏହାକୁ ମାନୁଆଲ୍ ଭାବରେ ଇନଷ୍ଟଲ୍ କରିପାରିବେ।"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ଡାଉନଲୋଡ୍ ହେଉଛି, <xliff:g id="PROGRESS">%2$s</xliff:g> ସମ୍ପୂର୍ଣ୍ଣ"</string>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index 9816896..3f6f9a6 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -98,7 +98,7 @@
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"కొత్త యాప్ల కోసం"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"తెలియదు"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"తీసివేయి"</string>
- <string name="abandoned_search" msgid="891119232568284442">"వెతుకు"</string>
+ <string name="abandoned_search" msgid="891119232568284442">"సెర్చ్"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"ఈ యాప్ ఇన్స్టాల్ చేయబడలేదు"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"ఈ చిహ్నం యొక్క యాప్ ఇన్స్టాల్ చేయబడలేదు. మీరు దీన్ని తీసివేయవచ్చు లేదా ఆ యాప్ కోసం శోధించి దాన్ని మాన్యువల్గా ఇన్స్టాల్ చేయవచ్చు."</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> డౌన్లోడ్ అవుతోంది, <xliff:g id="PROGRESS">%2$s</xliff:g> పూర్తయింది"</string>
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 03e4b06..dede954 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -929,6 +929,7 @@
protected void handlePendingActivityRequest() { }
private void logStopAndResume(int command) {
+ if (mPendingExecutor != null) return;
int pageIndex = mWorkspace.isOverlayShown() ? -1 : mWorkspace.getCurrentPage();
int containerType = mStateManager.getState().containerType;
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index e8b5568..19a314f 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -100,10 +100,12 @@
public static final int SCHEMA_VERSION = 28;
public static final String AUTHORITY = BuildConfig.APPLICATION_ID + ".settings";
+ public static final String KEY_LAYOUT_PROVIDER_AUTHORITY = "KEY_LAYOUT_PROVIDER_AUTHORITY";
static final String EMPTY_DATABASE_CREATED = "EMPTY_DATABASE_CREATED";
protected DatabaseHelper mOpenHelper;
+ protected String mProviderAuthority;
private long mLastRestoreTimestamp = 0L;
@@ -367,7 +369,8 @@
case LauncherSettings.Settings.METHOD_WAS_EMPTY_DB_CREATED : {
Bundle result = new Bundle();
result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE,
- Utilities.getPrefs(getContext()).getBoolean(EMPTY_DATABASE_CREATED, false));
+ Utilities.getPrefs(getContext()).getBoolean(
+ mOpenHelper.getKey(EMPTY_DATABASE_CREATED), false));
return result;
}
case LauncherSettings.Settings.METHOD_DELETE_EMPTY_FOLDERS: {
@@ -437,6 +440,7 @@
getContext(), true /* forMigration */)));
return result;
}
+ return null;
}
case LauncherSettings.Settings.METHOD_PREP_FOR_PREVIEW: {
if (MULTI_DB_GRID_MIRATION_ALGO.get()) {
@@ -450,6 +454,23 @@
() -> mOpenHelper));
return result;
}
+ return null;
+ }
+ case LauncherSettings.Settings.METHOD_SWITCH_DATABASE: {
+ if (TextUtils.equals(arg, mOpenHelper.getDatabaseName())) return null;
+ final DatabaseHelper helper = mOpenHelper;
+ if (extras == null || !extras.containsKey(KEY_LAYOUT_PROVIDER_AUTHORITY)) {
+ mProviderAuthority = null;
+ } else {
+ mProviderAuthority = extras.getString(KEY_LAYOUT_PROVIDER_AUTHORITY);
+ }
+ mOpenHelper = DatabaseHelper.createDatabaseHelper(
+ getContext(), arg, false /* forMigration */);
+ helper.close();
+ LauncherAppState app = LauncherAppState.getInstanceNoCreate();
+ if (app == null) return null;
+ app.getModel().forceReload();
+ return null;
}
}
return null;
@@ -492,7 +513,8 @@
}
private void clearFlagEmptyDbCreated() {
- Utilities.getPrefs(getContext()).edit().remove(EMPTY_DATABASE_CREATED).commit();
+ Utilities.getPrefs(getContext()).edit()
+ .remove(mOpenHelper.getKey(EMPTY_DATABASE_CREATED)).commit();
}
/**
@@ -505,7 +527,7 @@
synchronized private void loadDefaultFavoritesIfNecessary() {
SharedPreferences sp = Utilities.getPrefs(getContext());
- if (sp.getBoolean(EMPTY_DATABASE_CREATED, false)) {
+ if (sp.getBoolean(mOpenHelper.getKey(EMPTY_DATABASE_CREATED), false)) {
Log.d(TAG, "loading default workspace");
AppWidgetHost widgetHost = mOpenHelper.newLauncherWidgetHost();
@@ -553,8 +575,13 @@
*/
private AutoInstallsLayout createWorkspaceLoaderFromAppRestriction(AppWidgetHost widgetHost) {
Context ctx = getContext();
- String authority = Settings.Secure.getString(ctx.getContentResolver(),
- "launcher3.layout.provider");
+ final String authority;
+ if (!TextUtils.isEmpty(mProviderAuthority)) {
+ authority = mProviderAuthority;
+ } else {
+ authority = Settings.Secure.getString(ctx.getContentResolver(),
+ "launcher3.layout.provider");
+ }
if (TextUtils.isEmpty(authority)) {
return null;
}
@@ -694,11 +721,25 @@
}
/**
+ * Re-composite given key in respect to database. If the current db is
+ * {@link LauncherFiles#LAUNCHER_DB}, return the key as-is. Otherwise append the db name to
+ * given key. e.g. consider key="EMPTY_DATABASE_CREATED", dbName="minimal.db", the returning
+ * string will be "EMPTY_DATABASE_CREATED@minimal.db".
+ */
+ String getKey(final String key) {
+ if (TextUtils.equals(getDatabaseName(), LauncherFiles.LAUNCHER_DB)) {
+ return key;
+ }
+ return key + "@" + getDatabaseName();
+ }
+
+ /**
* Overriden in tests.
*/
protected void onEmptyDbCreated() {
// Set the flag for empty DB
- Utilities.getPrefs(mContext).edit().putBoolean(EMPTY_DATABASE_CREATED, true).commit();
+ Utilities.getPrefs(mContext).edit().putBoolean(getKey(EMPTY_DATABASE_CREATED), true)
+ .commit();
}
public long getSerialNumberForUser(UserHandle user) {
diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java
index 5512654..58a418e 100644
--- a/src/com/android/launcher3/LauncherSettings.java
+++ b/src/com/android/launcher3/LauncherSettings.java
@@ -354,14 +354,20 @@
public static final String METHOD_PREP_FOR_PREVIEW = "prep_for_preview";
+ public static final String METHOD_SWITCH_DATABASE = "switch_database";
+
public static final String EXTRA_VALUE = "value";
public static Bundle call(ContentResolver cr, String method) {
- return call(cr, method, null);
+ return call(cr, method, null /* arg */);
}
public static Bundle call(ContentResolver cr, String method, String arg) {
- return cr.call(CONTENT_URI, method, arg, null);
+ return call(cr, method, arg, null /* extras */);
+ }
+
+ public static Bundle call(ContentResolver cr, String method, String arg, Bundle extras) {
+ return cr.call(CONTENT_URI, method, arg, extras);
}
}
}
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index bf63788..681118d 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -141,6 +141,10 @@
public static final String EXTRA_WALLPAPER_OFFSET = "com.android.launcher3.WALLPAPER_OFFSET";
public static final String EXTRA_WALLPAPER_FLAVOR = "com.android.launcher3.WALLPAPER_FLAVOR";
+ // An intent extra to indicate the launch source by launcher.
+ public static final String EXTRA_WALLPAPER_LAUNCH_SOURCE =
+ "com.android.wallpaper.LAUNCH_SOURCE";
+
public static boolean IS_RUNNING_IN_TEST_HARNESS =
ActivityManager.isRunningInTestHarness();
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 45116b6..88a9aba 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -92,7 +92,7 @@
// Keep as DeviceFlag to allow remote disable in emergency.
public static final BooleanFlag ENABLE_SUGGESTED_ACTIONS_OVERVIEW = new DeviceFlag(
- "ENABLE_SUGGESTED_ACTIONS_OVERVIEW", false, "Show chip hints on the overview screen");
+ "ENABLE_SUGGESTED_ACTIONS_OVERVIEW", true, "Show chip hints on the overview screen");
public static final BooleanFlag FOLDER_NAME_SUGGEST = new DeviceFlag(
"FOLDER_NAME_SUGGEST", true,
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index a424f84..7b769b8 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -595,7 +595,10 @@
@Override
public WorkspaceResult call() throws Exception {
List<ShortcutInfo> allShortcuts = new ArrayList<>();
- loadWorkspace(allShortcuts, LauncherSettings.Favorites.PREVIEW_CONTENT_URI);
+ loadWorkspace(allShortcuts, LauncherSettings.Favorites.PREVIEW_CONTENT_URI,
+ LauncherSettings.Favorites.SCREEN + " = 0 or "
+ + LauncherSettings.Favorites.CONTAINER + " = "
+ + LauncherSettings.Favorites.CONTAINER_HOTSEAT);
return new WorkspaceResult(mBgDataModel.workspaceItems, mBgDataModel.appWidgets,
mBgDataModel.cachedPredictedItems, null, mWidgetProvidersMap);
}
diff --git a/src/com/android/launcher3/graphics/OverviewScrim.java b/src/com/android/launcher3/graphics/OverviewScrim.java
index 94acbfd..c0c3e5e 100644
--- a/src/com/android/launcher3/graphics/OverviewScrim.java
+++ b/src/com/android/launcher3/graphics/OverviewScrim.java
@@ -22,6 +22,7 @@
import static com.android.launcher3.LauncherState.OVERVIEW;
import android.graphics.Rect;
+import android.util.FloatProperty;
import android.view.View;
import android.view.ViewGroup;
@@ -33,10 +34,25 @@
*/
public class OverviewScrim extends Scrim {
+ public static final FloatProperty<OverviewScrim> SCRIM_MULTIPLIER =
+ new FloatProperty<OverviewScrim>("scrimMultiplier") {
+ @Override
+ public Float get(OverviewScrim scrim) {
+ return scrim.mScrimMultiplier;
+ }
+
+ @Override
+ public void setValue(OverviewScrim scrim, float v) {
+ scrim.setScrimMultiplier(v);
+ }
+ };
+
private @NonNull View mStableScrimmedView;
// Might be higher up if mStableScrimmedView is invisible.
private @Nullable View mCurrentScrimmedView;
+ private float mScrimMultiplier = 1f;
+
public OverviewScrim(View view) {
super(view);
mStableScrimmedView = mCurrentScrimmedView = mLauncher.getOverviewPanel();
@@ -68,4 +84,16 @@
public @Nullable View getScrimmedView() {
return mCurrentScrimmedView;
}
+
+ private void setScrimMultiplier(float scrimMultiplier) {
+ if (Float.compare(mScrimMultiplier, scrimMultiplier) != 0) {
+ mScrimMultiplier = scrimMultiplier;
+ invalidate();
+ }
+ }
+
+ @Override
+ protected int getScrimAlpha() {
+ return Math.round(super.getScrimAlpha() * mScrimMultiplier);
+ }
}
diff --git a/src/com/android/launcher3/graphics/Scrim.java b/src/com/android/launcher3/graphics/Scrim.java
index f90962d..a151cba 100644
--- a/src/com/android/launcher3/graphics/Scrim.java
+++ b/src/com/android/launcher3/graphics/Scrim.java
@@ -61,7 +61,11 @@
}
public void draw(Canvas canvas) {
- canvas.drawColor(setColorAlphaBound(mScrimColor, mScrimAlpha));
+ canvas.drawColor(setColorAlphaBound(mScrimColor, getScrimAlpha()));
+ }
+
+ protected int getScrimAlpha() {
+ return mScrimAlpha;
}
private void setScrimProgress(float progress) {
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 4a64522..d62f8d5 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -293,10 +293,12 @@
}
private void loadWorkspace(List<ShortcutInfo> allDeepShortcuts) {
- loadWorkspace(allDeepShortcuts, LauncherSettings.Favorites.CONTENT_URI);
+ loadWorkspace(allDeepShortcuts, LauncherSettings.Favorites.CONTENT_URI,
+ null /* selection */);
}
- protected void loadWorkspace(List<ShortcutInfo> allDeepShortcuts, Uri contentUri) {
+ protected void loadWorkspace(List<ShortcutInfo> allDeepShortcuts, Uri contentUri,
+ String selection) {
final Context context = mApp.getContext();
final ContentResolver contentResolver = context.getContentResolver();
final PackageManagerHelper pmHelper = new PackageManagerHelper(context);
@@ -341,8 +343,8 @@
Map<ShortcutKey, ShortcutInfo> shortcutKeyToPinnedShortcuts = new HashMap<>();
final LoaderCursor c = new LoaderCursor(
- contentResolver.query(contentUri, null, null, null, null), contentUri, mApp,
- mUserManagerState);
+ contentResolver.query(contentUri, null, selection, null, null), contentUri,
+ mApp, mUserManagerState);
try {
final int appWidgetIdIndex = c.getColumnIndexOrThrow(
@@ -776,33 +778,35 @@
return;
}
- // Remove dead items
- if (c.commitDeleted()) {
- // Remove any empty folder
- int[] deletedFolderIds = LauncherSettings.Settings
- .call(contentResolver,
- LauncherSettings.Settings.METHOD_DELETE_EMPTY_FOLDERS)
- .getIntArray(LauncherSettings.Settings.EXTRA_VALUE);
- for (int folderId : deletedFolderIds) {
- mBgDataModel.workspaceItems.remove(mBgDataModel.folders.get(folderId));
- mBgDataModel.folders.remove(folderId);
- mBgDataModel.itemsIdMap.remove(folderId);
+ if (contentUri == LauncherSettings.Favorites.CONTENT_URI) {
+ // Remove dead items
+ if (c.commitDeleted()) {
+ // Remove any empty folder
+ int[] deletedFolderIds = LauncherSettings.Settings
+ .call(contentResolver,
+ LauncherSettings.Settings.METHOD_DELETE_EMPTY_FOLDERS)
+ .getIntArray(LauncherSettings.Settings.EXTRA_VALUE);
+ for (int folderId : deletedFolderIds) {
+ mBgDataModel.workspaceItems.remove(mBgDataModel.folders.get(folderId));
+ mBgDataModel.folders.remove(folderId);
+ mBgDataModel.itemsIdMap.remove(folderId);
+ }
+
+ // Remove any ghost widgets
+ LauncherSettings.Settings.call(contentResolver,
+ LauncherSettings.Settings.METHOD_REMOVE_GHOST_WIDGETS);
}
- // Remove any ghost widgets
- LauncherSettings.Settings.call(contentResolver,
- LauncherSettings.Settings.METHOD_REMOVE_GHOST_WIDGETS);
- }
-
- // Unpin shortcuts that don't exist on the workspace.
- HashSet<ShortcutKey> pendingShortcuts =
- InstallShortcutReceiver.getPendingShortcuts(context);
- for (ShortcutKey key : shortcutKeyToPinnedShortcuts.keySet()) {
- MutableInt numTimesPinned = mBgDataModel.pinnedShortcutCounts.get(key);
- if ((numTimesPinned == null || numTimesPinned.value == 0)
- && !pendingShortcuts.contains(key)) {
- // Shortcut is pinned but doesn't exist on the workspace; unpin it.
- mBgDataModel.unpinShortcut(context, key);
+ // Unpin shortcuts that don't exist on the workspace.
+ HashSet<ShortcutKey> pendingShortcuts =
+ InstallShortcutReceiver.getPendingShortcuts(context);
+ for (ShortcutKey key : shortcutKeyToPinnedShortcuts.keySet()) {
+ MutableInt numTimesPinned = mBgDataModel.pinnedShortcutCounts.get(key);
+ if ((numTimesPinned == null || numTimesPinned.value == 0)
+ && !pendingShortcuts.contains(key)) {
+ // Shortcut is pinned but doesn't exist on the workspace; unpin it.
+ mBgDataModel.unpinShortcut(context, key);
+ }
}
}
diff --git a/src/com/android/launcher3/statemanager/StateManager.java b/src/com/android/launcher3/statemanager/StateManager.java
index 60b87d9..2792308 100644
--- a/src/com/android/launcher3/statemanager/StateManager.java
+++ b/src/com/android/launcher3/statemanager/StateManager.java
@@ -311,7 +311,13 @@
handler.setStateWithAnimation(state, mConfig, builder);
}
}
- builder.addListener(new AnimationSuccessListener() {
+ builder.addListener(createStateAnimationListener(state));
+ mConfig.setAnimation(builder.buildAnim(), state);
+ return builder;
+ }
+
+ private AnimatorListener createStateAnimationListener(STATE_TYPE state) {
+ return new AnimationSuccessListener() {
@Override
public void onAnimationStart(Animator animation) {
@@ -326,9 +332,7 @@
}
onStateTransitionEnd(state);
}
- });
- mConfig.setAnimation(builder.buildAnim(), state);
- return builder;
+ };
}
private void onStateTransitionStart(STATE_TYPE state) {
@@ -396,6 +400,19 @@
}
/**
+ * @see #setCurrentAnimation(AnimatorSet, Animator...). Using this method tells the StateManager
+ * that this is a custom animation to the given state, and thus the StateManager will add an
+ * animation listener to call {@link #onStateTransitionStart} and {@link #onStateTransitionEnd}.
+ * @param anim The custom animation to the given state.
+ * @param toState The state we are animating towards.
+ */
+ public void setCurrentAnimation(AnimatorSet anim, STATE_TYPE toState) {
+ cancelAnimation();
+ setCurrentAnimation(anim);
+ anim.addListener(createStateAnimationListener(toState));
+ }
+
+ /**
* Sets the animation as the current state animation, i.e., canceled when
* starting another animation and may block some launcher interactions while running.
*
diff --git a/src/com/android/launcher3/states/StateAnimationConfig.java b/src/com/android/launcher3/states/StateAnimationConfig.java
index f90ad3c..8b72177 100644
--- a/src/com/android/launcher3/states/StateAnimationConfig.java
+++ b/src/com/android/launcher3/states/StateAnimationConfig.java
@@ -71,6 +71,7 @@
ANIM_ALL_APPS_HEADER_FADE,
ANIM_OVERVIEW_MODAL,
ANIM_DEPTH,
+ ANIM_OVERVIEW_ACTIONS_FADE,
})
@Retention(RetentionPolicy.SOURCE)
public @interface AnimType {}
@@ -89,10 +90,11 @@
public static final int ANIM_ALL_APPS_HEADER_FADE = 12; // e.g. predictions
public static final int ANIM_OVERVIEW_MODAL = 13;
public static final int ANIM_DEPTH = 14;
+ public static final int ANIM_OVERVIEW_ACTIONS_FADE = 15;
- private static final int ANIM_TYPES_COUNT = 15;
+ private static final int ANIM_TYPES_COUNT = 16;
- private final Interpolator[] mInterpolators = new Interpolator[ANIM_TYPES_COUNT];
+ protected final Interpolator[] mInterpolators = new Interpolator[ANIM_TYPES_COUNT];
public StateAnimationConfig() { }
diff --git a/src/com/android/launcher3/util/MultiValueAlpha.java b/src/com/android/launcher3/util/MultiValueAlpha.java
index a8642b0..5be9529 100644
--- a/src/com/android/launcher3/util/MultiValueAlpha.java
+++ b/src/com/android/launcher3/util/MultiValueAlpha.java
@@ -19,6 +19,8 @@
import android.util.FloatProperty;
import android.view.View;
+import com.android.launcher3.anim.AlphaUpdateListener;
+
import java.util.Arrays;
/**
@@ -44,6 +46,8 @@
private final AlphaProperty[] mMyProperties;
private int mValidMask;
+ // Whether we should change from INVISIBLE to VISIBLE and vice versa at low alpha values.
+ private boolean mUpdateVisibility;
public MultiValueAlpha(View view, int size) {
mView = view;
@@ -66,6 +70,11 @@
return mMyProperties[index];
}
+ /** Sets whether we should update between INVISIBLE and VISIBLE based on alpha. */
+ public void setUpdateVisibility(boolean updateVisibility) {
+ mUpdateVisibility = updateVisibility;
+ }
+
public class AlphaProperty {
private final int mMyMask;
@@ -99,6 +108,9 @@
mValue = value;
mView.setAlpha(mOthers * mValue);
+ if (mUpdateVisibility) {
+ AlphaUpdateListener.updateVisibility(mView);
+ }
}
public float getValue() {
diff --git a/src/com/android/launcher3/views/OptionsPopupView.java b/src/com/android/launcher3/views/OptionsPopupView.java
index d558781..349ba9d 100644
--- a/src/com/android/launcher3/views/OptionsPopupView.java
+++ b/src/com/android/launcher3/views/OptionsPopupView.java
@@ -16,6 +16,7 @@
package com.android.launcher3.views;
import static com.android.launcher3.Utilities.EXTRA_WALLPAPER_FLAVOR;
+import static com.android.launcher3.Utilities.EXTRA_WALLPAPER_LAUNCH_SOURCE;
import static com.android.launcher3.Utilities.EXTRA_WALLPAPER_OFFSET;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.IGNORE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SETTINGS_BUTTON_TAP_OR_LONGPRESS;
@@ -210,7 +211,8 @@
Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
.putExtra(EXTRA_WALLPAPER_OFFSET,
- launcher.getWorkspace().getWallpaperOffsetForCenterPage());
+ launcher.getWorkspace().getWallpaperOffsetForCenterPage())
+ .putExtra(EXTRA_WALLPAPER_LAUNCH_SOURCE, "app_launched_launcher");
if (!Utilities.existsStyleWallpapers(launcher)) {
intent.putExtra(EXTRA_WALLPAPER_FLAVOR, "wallpaper_only");
} else {