Merge "Fix bug where taskbar jumps when double swiping up." into tm-qpr-dev
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 225bdcc..599095b 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -300,6 +300,8 @@
<dimen name="transient_taskbar_key_shadow_distance">10dp</dimen>
<dimen name="transient_taskbar_stashed_size">32dp</dimen>
<dimen name="transient_taskbar_all_apps_button_translation_x_offset">4dp</dimen>
+ <dimen name="transient_taskbar_stash_spring_velocity_dp_per_s">400dp</dimen>
+
<!-- An additional touch slop to prevent x-axis movement during the swipe up to show taskbar -->
<dimen name="transient_taskbar_clamped_offset_bound">16dp</dimen>
<!-- Taskbar swipe up thresholds -->
diff --git a/quickstep/src/com/android/launcher3/taskbar/BaseTaskbarContext.java b/quickstep/src/com/android/launcher3/taskbar/BaseTaskbarContext.java
index 48352a2..331184a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/BaseTaskbarContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/BaseTaskbarContext.java
@@ -65,4 +65,10 @@
/** Callback invoked when a popup is shown or closed within this context. */
public abstract void onPopupVisibilityChanged(boolean isVisible);
+
+ /**
+ * Callback invoked when user attempts to split the screen through a long-press menu in Taskbar
+ * or AllApps.
+ */
+ public abstract void onSplitScreenMenuButtonClicked();
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
index f082fc6..48b3f72 100644
--- a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
@@ -84,6 +84,9 @@
private boolean mIsStashed;
private boolean mTaskbarHidden;
+ private float mTranslationYForSwipe;
+ private float mTranslationYForStash;
+
public StashedHandleViewController(TaskbarActivityContext activity,
StashedHandleView stashedHandleView) {
mActivity = activity;
@@ -254,7 +257,20 @@
* Sets the translation of the stashed handle during the swipe up gesture.
*/
protected void setTranslationYForSwipe(float transY) {
- mStashedHandleView.setTranslationY(transY);
+ mTranslationYForSwipe = transY;
+ updateTranslationY();
+ }
+
+ /**
+ * Sets the translation of the stashed handle during the spring on stash animation.
+ */
+ protected void setTranslationYForStash(float transY) {
+ mTranslationYForStash = transY;
+ updateTranslationY();
+ }
+
+ private void updateTranslationY() {
+ mStashedHandleView.setTranslationY(mTranslationYForSwipe + mTranslationYForStash);
}
/**
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 62713ca..6bf83bb 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -56,7 +56,6 @@
import android.view.RoundedCorner;
import android.view.View;
import android.view.WindowManager;
-import android.view.WindowManagerGlobal;
import android.widget.FrameLayout;
import android.widget.Toast;
@@ -80,6 +79,7 @@
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.popup.PopupContainerWithArrow;
import com.android.launcher3.popup.PopupDataProvider;
import com.android.launcher3.taskbar.TaskbarAutohideSuspendController.AutohideSuspendFlag;
import com.android.launcher3.taskbar.TaskbarTranslationController.TransitionCallback;
@@ -233,6 +233,7 @@
new TaskbarInsetsController(this),
new VoiceInteractionWindowController(this),
new TaskbarTranslationController(this),
+ new TaskbarSpringOnStashController(this),
isDesktopMode
? new DesktopTaskbarRecentAppsController(this)
: TaskbarRecentAppsController.DEFAULT,
@@ -524,6 +525,16 @@
setTaskbarWindowFocusable(isVisible);
}
+ @Override
+ public void onSplitScreenMenuButtonClicked() {
+ PopupContainerWithArrow popup = PopupContainerWithArrow.getOpen(this);
+ if (popup != null) {
+ popup.addOnCloseCallback(() -> {
+ mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true);
+ });
+ }
+ }
+
/**
* Sets a new data-source for this taskbar instance
*/
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
index 3375877..82b455d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
@@ -35,6 +35,7 @@
val lastDrawnTransientRect = RectF()
var backgroundHeight = context.deviceProfile.taskbarSize.toFloat()
var translationYForSwipe = 0f
+ var translationYForStash = 0f
private var maxBackgroundHeight = context.deviceProfile.taskbarSize.toFloat()
private val transientBackgroundBounds = context.transientTaskbarBounds
@@ -136,7 +137,9 @@
val bottom =
canvas.height - bottomMargin +
bottomMarginProgress +
- (-mapRange(1f - progress, 0f, stashedHandleHeight / 2f) + translationYForSwipe)
+ translationYForSwipe +
+ translationYForStash +
+ -mapRange(1f - progress, 0f, stashedHandleHeight / 2f)
// Draw shadow.
val shadowAlpha =
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
index 931d79f..fb919ee 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
@@ -57,6 +57,7 @@
public final VoiceInteractionWindowController voiceInteractionWindowController;
public final TaskbarRecentAppsController taskbarRecentAppsController;
public final TaskbarTranslationController taskbarTranslationController;
+ public final TaskbarSpringOnStashController taskbarSpringOnStashController;
public final TaskbarOverlayController taskbarOverlayController;
public final TaskbarEduTooltipController taskbarEduTooltipController;
public final KeyboardQuickSwitchController keyboardQuickSwitchController;
@@ -103,6 +104,7 @@
TaskbarInsetsController taskbarInsetsController,
VoiceInteractionWindowController voiceInteractionWindowController,
TaskbarTranslationController taskbarTranslationController,
+ TaskbarSpringOnStashController taskbarSpringOnStashController,
TaskbarRecentAppsController taskbarRecentAppsController,
TaskbarEduTooltipController taskbarEduTooltipController,
KeyboardQuickSwitchController keyboardQuickSwitchController) {
@@ -127,6 +129,7 @@
this.taskbarInsetsController = taskbarInsetsController;
this.voiceInteractionWindowController = voiceInteractionWindowController;
this.taskbarTranslationController = taskbarTranslationController;
+ this.taskbarSpringOnStashController = taskbarSpringOnStashController;
this.taskbarRecentAppsController = taskbarRecentAppsController;
this.taskbarEduTooltipController = taskbarEduTooltipController;
this.keyboardQuickSwitchController = keyboardQuickSwitchController;
@@ -149,6 +152,7 @@
taskbarScrimViewController.init(this);
taskbarUnfoldAnimationController.init(this);
taskbarKeyguardController.init(navbarButtonsViewController);
+ taskbarSpringOnStashController.init(this);
stashedHandleViewController.init(this);
taskbarStashController.init(this, sharedState.setupUIVisible);
taskbarEduController.init(this);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
index 58d6244..6b9297d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
@@ -184,6 +184,14 @@
invalidate();
}
+ /*
+ * Sets the translation of the background during the spring on stash animation.
+ */
+ protected void setBackgroundTranslationYForStash(float translationY) {
+ mBackgroundRenderer.setTranslationYForStash(translationY);
+ invalidate();
+ }
+
/** Returns the bounds in DragLayer coordinates of where the transient background was drawn. */
protected RectF getLastDrawnTransientRect() {
return mBackgroundRenderer.getLastDrawnTransientRect();
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
index 7c3d14d..2badc24 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
@@ -161,6 +161,13 @@
mTaskbarDragLayer.setBackgroundTranslationYForSwipe(transY);
}
+ /**
+ * Sets the translation of the background during the spring on stash animation.
+ */
+ public void setTranslationYForStash(float transY) {
+ mTaskbarDragLayer.setBackgroundTranslationYForStash(transY);
+ }
+
private void updateBackgroundOffset() {
mTaskbarDragLayer.setTaskbarBackgroundOffset(mBgOffset.value);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
index 115b99e..0ed4538 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
@@ -65,6 +65,7 @@
/**
* Implements interfaces required to show and allow interacting with a PopupContainerWithArrow.
+ * Controls the long-press menu on Taskbar and AllApps icons.
*/
public class TaskbarPopupController implements TaskbarControllers.LoggableTaskbarController {
@@ -174,6 +175,7 @@
deepShortcutCount,
mPopupDataProvider.getNotificationKeysForItem(item),
systemShortcuts);
+ icon.clearAccessibilityFocus();
}
container.addOnAttachStateChangeListener(
@@ -190,9 +192,8 @@
// Make focusable to receive back events
context.onPopupVisibilityChanged(true);
- container.setOnCloseCallback(() -> {
+ container.addOnCloseCallback(() -> {
context.getDragLayer().post(() -> context.onPopupVisibilityChanged(false));
- container.setOnCloseCallback(null);
});
return container;
@@ -293,13 +294,19 @@
@Override
public void onClick(View view) {
+ // Add callbacks depending on what type of Taskbar context we're in (Taskbar or AllApps)
+ mTarget.onSplitScreenMenuButtonClicked();
AbstractFloatingView.closeAllOpenViews(mTarget);
+
+ // Depending on what app state we're in, we either want to initiate the split screen
+ // staging process or immediately launch a split with an existing app.
+ // - Initiate the split screen staging process
if (mAllowInitialSplitSelection) {
super.onClick(view);
return;
}
- // Initiate splitscreen from the in-app Taskbar or Taskbar All Apps
+ // - Immediately launch split with the running app
Pair<InstanceId, com.android.launcher3.logging.InstanceId> instanceIds =
LogUtils.getShellShareableInstanceId();
mTarget.getStatsLogManager().logger()
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarSpringOnStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarSpringOnStashController.java
new file mode 100644
index 0000000..d65b5c0
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarSpringOnStashController.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2023 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.launcher3.taskbar;
+
+import static com.android.launcher3.anim.AnimatedFloat.VALUE;
+
+import android.animation.ValueAnimator;
+
+import androidx.annotation.Nullable;
+import androidx.dynamicanimation.animation.SpringForce;
+
+import com.android.launcher3.R;
+import com.android.launcher3.anim.AnimatedFloat;
+import com.android.launcher3.anim.SpringAnimationBuilder;
+import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController;
+import com.android.launcher3.util.DisplayController;
+
+import java.io.PrintWriter;
+
+/**
+ * Manages the spring animation when stashing the transient taskbar.
+ */
+public class TaskbarSpringOnStashController implements LoggableTaskbarController {
+
+ private final TaskbarActivityContext mContext;
+ private TaskbarControllers mControllers;
+ private final AnimatedFloat mTranslationForStash = new AnimatedFloat(
+ this::updateTranslationYForStash);
+
+ private final boolean mIsTransientTaskbar;
+
+ private final float mStartVelocityPxPerS;
+
+ public TaskbarSpringOnStashController(TaskbarActivityContext context) {
+ mContext = context;
+ mIsTransientTaskbar = DisplayController.isTransientTaskbar(mContext);
+ mStartVelocityPxPerS = context.getResources()
+ .getDimension(R.dimen.transient_taskbar_stash_spring_velocity_dp_per_s);
+ }
+
+ /**
+ * Initialization method.
+ */
+ public void init(TaskbarControllers controllers) {
+ mControllers = controllers;
+ }
+
+ private void updateTranslationYForStash() {
+ if (!mIsTransientTaskbar) {
+ return;
+ }
+
+ float transY = mTranslationForStash.value;
+ mControllers.stashedHandleViewController.setTranslationYForStash(transY);
+ mControllers.taskbarViewController.setTranslationYForStash(transY);
+ mControllers.taskbarDragLayerController.setTranslationYForStash(transY);
+ }
+
+ /**
+ * Returns a spring animation to be used when stashing the transient taskbar.
+ */
+ public @Nullable ValueAnimator createSpringToStash() {
+ if (!mIsTransientTaskbar) {
+ return null;
+ }
+ return new SpringAnimationBuilder(mContext)
+ .setStartValue(mTranslationForStash.value)
+ .setEndValue(0)
+ .setDampingRatio(SpringForce.DAMPING_RATIO_MEDIUM_BOUNCY)
+ .setStiffness(SpringForce.STIFFNESS_LOW)
+ .setStartVelocity(mStartVelocityPxPerS)
+ .build(mTranslationForStash, VALUE);
+ }
+
+
+ @Override
+ public void dumpLogs(String prefix, PrintWriter pw) {
+ pw.println(prefix + "TaskbarSpringOnStashController:");
+
+ pw.println(prefix + "\tmTranslationForStash=" + mTranslationForStash.value);
+ pw.println(prefix + "\tmStartVelocityPxPerS=" + mStartVelocityPxPerS);
+ }
+}
+
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index cbc1672..30cfcdf 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -712,6 +712,9 @@
play(as, mTaskbarStashedHandleAlpha.animateToValue(1), alphaStartDelay,
Math.max(0, duration - alphaStartDelay), LINEAR);
+ play(as, mControllers.taskbarSpringOnStashController.createSpringToStash(), 0, duration,
+ LINEAR);
+
if (skipStashAnimation) {
skipInterpolator = INSTANT;
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index 0116e16..c5b6cdf 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -47,6 +47,7 @@
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.LauncherBindableItemsContainer;
+import com.android.launcher3.util.Themes;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.DoubleShadowBubbleTextView;
import com.android.launcher3.views.IconButtonView;
@@ -66,6 +67,7 @@
private final int mIconTouchSize;
private final int mItemMarginLeftRight;
private final int mItemPadding;
+ private final int mFolderLeaveBehindColor;
private final boolean mIsRtl;
private final TaskbarActivityContext mActivityContext;
@@ -132,6 +134,9 @@
mItemMarginLeftRight = actualMargin - (mIconTouchSize - actualIconSize) / 2;
mItemPadding = (mIconTouchSize - actualIconSize) / 2;
+ mFolderLeaveBehindColor = Themes.getAttrColor(mActivityContext,
+ android.R.attr.textColorTertiary);
+
// Needed to draw folder leave-behind when opening one.
setWillNotDraw(false);
@@ -523,7 +528,8 @@
if (mLeaveBehindFolderIcon != null) {
canvas.save();
canvas.translate(mLeaveBehindFolderIcon.getLeft(), mLeaveBehindFolderIcon.getTop());
- mLeaveBehindFolderIcon.getFolderBackground().drawLeaveBehind(canvas);
+ mLeaveBehindFolderIcon.getFolderBackground().drawLeaveBehind(canvas,
+ mFolderLeaveBehindColor);
canvas.restore();
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 4d92a9e..ad16eed 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -103,6 +103,7 @@
private AnimatedFloat mTaskbarNavButtonTranslationY;
private AnimatedFloat mTaskbarNavButtonTranslationYForInAppDisplay;
private float mTaskbarIconTranslationYForSwipe;
+ private float mTaskbarIconTranslationYForSpringOnStash;
private final int mTaskbarBottomMargin;
private final int mStashedHandleHeight;
@@ -291,10 +292,19 @@
updateTranslationY();
}
+ /**
+ * Sets the translation of the TaskbarView during the spring on stash animation.
+ */
+ public void setTranslationYForStash(float transY) {
+ mTaskbarIconTranslationYForSpringOnStash = transY;
+ updateTranslationY();
+ }
+
private void updateTranslationY() {
mTaskbarView.setTranslationY(mTaskbarIconTranslationYForHome.value
+ mTaskbarIconTranslationYForStash.value
- + mTaskbarIconTranslationYForSwipe);
+ + mTaskbarIconTranslationYForSwipe
+ + mTaskbarIconTranslationYForSpringOnStash);
}
/**
diff --git a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java
index 3edb375..66d5918 100644
--- a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java
@@ -15,8 +15,6 @@
*/
package com.android.launcher3.taskbar.overlay;
-import static android.app.ActivityTaskManager.INVALID_TASK_ID;
-
import android.content.Context;
import android.view.View;
@@ -33,10 +31,6 @@
import com.android.launcher3.taskbar.TaskbarUIController;
import com.android.launcher3.taskbar.allapps.TaskbarAllAppsContainerView;
import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource;
-import com.android.quickstep.views.RecentsView;
-import com.android.systemui.shared.recents.model.Task;
-
-import java.util.function.Consumer;
/**
* Window context for the taskbar overlays such as All Apps and EDU.
@@ -141,4 +135,8 @@
@Override
public void onPopupVisibilityChanged(boolean isVisible) {}
+
+ @Override
+ public void onSplitScreenMenuButtonClicked() {
+ }
}
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt
index 4cca24e..172cb46 100644
--- a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt
@@ -50,6 +50,7 @@
@Mock lateinit var voiceInteractionWindowController: VoiceInteractionWindowController
@Mock lateinit var taskbarRecentAppsController: TaskbarRecentAppsController
@Mock lateinit var taskbarTranslationController: TaskbarTranslationController
+ @Mock lateinit var taskbarSpringOnStashController: TaskbarSpringOnStashController
@Mock lateinit var taskbarOverlayController: TaskbarOverlayController
@Mock lateinit var taskbarEduTooltipController: TaskbarEduTooltipController
@Mock lateinit var keyboardQuickSwitchController: KeyboardQuickSwitchController
@@ -89,6 +90,7 @@
taskbarInsetsController,
voiceInteractionWindowController,
taskbarTranslationController,
+ taskbarSpringOnStashController,
taskbarRecentAppsController,
taskbarEduTooltipController,
keyboardQuickSwitchController
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 38b0e08..37194b1 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -92,6 +92,9 @@
private static final String TAG = "CellLayout";
private static final boolean LOGD = false;
+ /** The color of the "leave-behind" shape when a folder is opened from Hotseat. */
+ private static final int FOLDER_LEAVE_BEHIND_COLOR = Color.argb(160, 245, 245, 245);
+
protected final ActivityContext mActivity;
@ViewDebug.ExportedProperty(category = "launcher")
@Thunk int mCellWidth;
@@ -528,7 +531,7 @@
mFolderLeaveBehind.mDelegateCellY, mTempLocation);
canvas.save();
canvas.translate(mTempLocation[0], mTempLocation[1]);
- mFolderLeaveBehind.drawLeaveBehind(canvas);
+ mFolderLeaveBehind.drawLeaveBehind(canvas, FOLDER_LEAVE_BEHIND_COLOR);
canvas.restore();
}
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index c81ad01..abf5866 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -31,7 +31,11 @@
import android.content.pm.LauncherApps;
import android.os.UserHandle;
import android.util.Log;
+import android.util.SparseArray;
+import android.widget.RemoteViews;
+import androidx.annotation.GuardedBy;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.config.FeatureFlags;
@@ -70,6 +74,12 @@
private final InvariantDeviceProfile mInvariantDeviceProfile;
private final RunnableList mOnTerminateCallback = new RunnableList();
+ // WORKAROUND: b/269335387 remove this after widget background listener is enabled
+ /* Array of RemoteViews cached by Launcher process */
+ @GuardedBy("itself")
+ @NonNull
+ public final SparseArray<RemoteViews> mCachedRemoteViews = new SparseArray<>();
+
public static LauncherAppState getInstance(final Context context) {
return INSTANCE.get(context);
}
diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
index 3c316b8..27119ae 100644
--- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
@@ -174,7 +174,7 @@
mContext.getDragLayer().getDescendantRectRelativeToSelf(host, pos);
ArrowPopup popup = OptionsPopupView.show(mContext, new RectF(pos), actions, false);
popup.requestFocus();
- popup.setOnCloseCallback(() -> {
+ popup.addOnCloseCallback(() -> {
host.requestFocus();
host.sendAccessibilityEvent(TYPE_VIEW_FOCUSED);
host.performAccessibilityAction(ACTION_ACCESSIBILITY_FOCUS, null);
diff --git a/src/com/android/launcher3/folder/PreviewBackground.java b/src/com/android/launcher3/folder/PreviewBackground.java
index 8f9fa8a..2465745 100644
--- a/src/com/android/launcher3/folder/PreviewBackground.java
+++ b/src/com/android/launcher3/folder/PreviewBackground.java
@@ -333,12 +333,15 @@
getOffsetX() + inset, getOffsetY() + inset, getScaledRadius() - inset, mPaint);
}
- public void drawLeaveBehind(Canvas canvas) {
+ /**
+ * Draws the leave-behind circle on the given canvas and in the given color.
+ */
+ public void drawLeaveBehind(Canvas canvas, int color) {
float originalScale = mScale;
mScale = 0.5f;
mPaint.setStyle(Paint.Style.FILL);
- mPaint.setColor(Color.argb(160, 245, 245, 245));
+ mPaint.setColor(color);
getShape().drawShape(canvas, getOffsetX(), getOffsetY(), getScaledRadius(), mPaint);
mScale = originalScale;
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index be3a09b..9d06d4a 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -48,14 +48,13 @@
import android.view.animation.PathInterpolator;
import android.widget.FrameLayout;
-import androidx.annotation.Nullable;
-
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.InsettableFrameLayout;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.shortcuts.DeepShortcutView;
+import com.android.launcher3.util.RunnableList;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.BaseDragLayer;
@@ -124,7 +123,7 @@
private final GradientDrawable mRoundedTop;
private final GradientDrawable mRoundedBottom;
- @Nullable private Runnable mOnCloseCallback = null;
+ private RunnableList mOnCloseCallbacks = new RunnableList();
// The rect string of the view that the arrow is attached to, in screen reference frame.
protected int mArrowColor;
@@ -785,16 +784,14 @@
mDeferContainerRemoval = false;
getPopupContainer().removeView(this);
getPopupContainer().removeView(mArrow);
- if (mOnCloseCallback != null) {
- mOnCloseCallback.run();
- }
+ mOnCloseCallbacks.executeAllAndClear();
}
/**
- * Callback to be called when the popup is closed
+ * Callbacks to be called when the popup is closed
*/
- public void setOnCloseCallback(@Nullable Runnable callback) {
- mOnCloseCallback = callback;
+ public void addOnCloseCallback(Runnable callback) {
+ mOnCloseCallbacks.add(callback);
}
protected BaseDragLayer getPopupContainer() {
diff --git a/src/com/android/launcher3/widget/LauncherWidgetHolder.java b/src/com/android/launcher3/widget/LauncherWidgetHolder.java
index 8e67eb1..2ca825c 100644
--- a/src/com/android/launcher3/widget/LauncherWidgetHolder.java
+++ b/src/com/android/launcher3/widget/LauncherWidgetHolder.java
@@ -36,6 +36,7 @@
import com.android.launcher3.BaseActivity;
import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
@@ -74,8 +75,6 @@
private final SparseArray<PendingAppWidgetHostView> mPendingViews = new SparseArray<>();
@NonNull
private final SparseArray<LauncherAppWidgetHostView> mDeferredViews = new SparseArray<>();
- @NonNull
- private final SparseArray<RemoteViews> mCachedRemoteViews = new SparseArray<>();
protected int mFlags = FLAG_STATE_IS_NORMAL;
@@ -174,6 +173,12 @@
public void deleteAppWidgetId(int appWidgetId) {
mWidgetHost.deleteAppWidgetId(appWidgetId);
mViews.remove(appWidgetId);
+ if (FeatureFlags.ENABLE_CACHED_WIDGET.get()) {
+ final LauncherAppState state = LauncherAppState.getInstance(mContext);
+ synchronized (state.mCachedRemoteViews) {
+ state.mCachedRemoteViews.delete(appWidgetId);
+ }
+ }
}
/**
@@ -308,7 +313,17 @@
if (WidgetsModel.GO_DISABLE_WIDGETS) {
return;
}
-
+ if (FeatureFlags.ENABLE_CACHED_WIDGET.get()) {
+ // Cache the content from the widgets when Launcher stops listening to widget updates
+ final LauncherAppState state = LauncherAppState.getInstance(mContext);
+ synchronized (state.mCachedRemoteViews) {
+ for (int i = 0; i < mViews.size(); i++) {
+ final int appWidgetId = mViews.keyAt(i);
+ final LauncherAppWidgetHostView view = mViews.get(appWidgetId);
+ state.mCachedRemoteViews.put(appWidgetId, view.mLastRemoteViews);
+ }
+ }
+ }
mWidgetHost.stopListening();
setListeningFlag(false);
}
@@ -350,23 +365,24 @@
// RemoteViews from system process.
// TODO: have launcher always listens to widget updates in background so that this
// check can be removed altogether.
- if (FeatureFlags.ENABLE_CACHED_WIDGET.get()
- && mCachedRemoteViews.get(appWidgetId) != null) {
- // We've found RemoteViews from cache for this widget, so we will instantiate a
- // widget host view and populate it with the cached RemoteViews.
- final LauncherAppWidgetHostView view = new LauncherAppWidgetHostView(context);
- view.setAppWidget(appWidgetId, appWidget);
- view.updateAppWidget(mCachedRemoteViews.get(appWidgetId));
- mDeferredViews.put(appWidgetId, view);
- mViews.put(appWidgetId, view);
- return view;
- } else {
- // When cache misses, a placeholder for the widget will be returned instead.
- DeferredAppWidgetHostView view = new DeferredAppWidgetHostView(context);
- view.setAppWidget(appWidgetId, appWidget);
- mViews.put(appWidgetId, view);
- return view;
+ if (FeatureFlags.ENABLE_CACHED_WIDGET.get()) {
+ final RemoteViews cachedRemoteViews = getCachedRemoteViews(appWidgetId);
+ if (cachedRemoteViews != null) {
+ // We've found RemoteViews from cache for this widget, so we will instantiate a
+ // widget host view and populate it with the cached RemoteViews.
+ final LauncherAppWidgetHostView view = new LauncherAppWidgetHostView(context);
+ view.setAppWidget(appWidgetId, appWidget);
+ view.updateAppWidget(cachedRemoteViews);
+ mDeferredViews.put(appWidgetId, view);
+ mViews.put(appWidgetId, view);
+ return view;
+ }
}
+ // If cache misses or not enabled, a placeholder for the widget will be returned.
+ DeferredAppWidgetHostView view = new DeferredAppWidgetHostView(context);
+ view.setAppWidget(appWidgetId, appWidget);
+ mViews.put(appWidgetId, view);
+ return view;
} else {
try {
return mWidgetHost.createView(context, appWidgetId, appWidget);
@@ -432,15 +448,8 @@
LauncherAppWidgetHost tempHost = (LauncherAppWidgetHost) mWidgetHost;
tempHost.clearViews();
if (FeatureFlags.ENABLE_CACHED_WIDGET.get()) {
- // First, we clear any previously cached content from existing widgets
- mCachedRemoteViews.clear();
+ // Clear previously cached content from existing widgets
mDeferredViews.clear();
- // Then we proceed to cache the content from the widgets
- for (int i = 0; i < mViews.size(); i++) {
- final int appWidgetId = mViews.keyAt(i);
- final LauncherAppWidgetHostView view = mViews.get(appWidgetId);
- mCachedRemoteViews.put(appWidgetId, view.mLastRemoteViews);
- }
}
mViews.clear();
}
@@ -481,6 +490,14 @@
return (flags & FLAGS_SHOULD_LISTEN) == FLAGS_SHOULD_LISTEN;
}
+ @Nullable
+ private RemoteViews getCachedRemoteViews(int appWidgetId) {
+ final LauncherAppState state = LauncherAppState.getInstance(mContext);
+ synchronized (state.mCachedRemoteViews) {
+ return state.mCachedRemoteViews.get(appWidgetId);
+ }
+ }
+
/**
* Returns the new LauncherWidgetHolder instance
*/