Merge "Import translations. DO NOT MERGE ANYWHERE" into main
diff --git a/quickstep/res/values-tr/strings.xml b/quickstep/res/values-tr/strings.xml
index c50c1f8..6a0b78f 100644
--- a/quickstep/res/values-tr/strings.xml
+++ b/quickstep/res/values-tr/strings.xml
@@ -89,7 +89,7 @@
<string name="gesture_tutorial_try_again" msgid="65962545858556697">"Tekrar deneyin"</string>
<string name="gesture_tutorial_nice" msgid="2936275692616928280">"Güzel!"</string>
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Eğitim <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
- <string name="allset_title" msgid="5021126669778966707">"İşlem tamam!"</string>
+ <string name="allset_title" msgid="5021126669778966707">"Kurulum tamamlandı"</string>
<string name="allset_hint" msgid="459504134589971527">"Ana ekrana gitmek için yukarı kaydırın"</string>
<string name="allset_button_hint" msgid="2395219947744706291">"Ana ekranınıza gitmek için ana sayfa düğmesine dokunun"</string>
<string name="allset_description_generic" msgid="5385500062202019855">"<xliff:g id="DEVICE">%1$s</xliff:g> adlı cihazınızı kullanmaya hazırsınız"</string>
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index e624be7..7d193aa 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -19,6 +19,7 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static android.app.role.RoleManager.ROLE_HOME;
import static android.provider.Settings.Secure.LAUNCHER_TASKBAR_EDUCATION_SHOWING;
import static android.view.RemoteAnimationTarget.MODE_CLOSING;
import static android.view.RemoteAnimationTarget.MODE_OPENING;
@@ -74,6 +75,7 @@
import android.animation.ValueAnimator;
import android.app.ActivityOptions;
import android.app.WindowConfiguration;
+import android.app.role.RoleManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Resources;
@@ -1194,7 +1196,9 @@
.registerRemoteTransition(mLauncherOpenTransition, homeCheck);
if (mBackAnimationController != null) {
mBackAnimationController.registerComponentCallbacks();
- mBackAnimationController.registerBackCallbacks(mHandler);
+ if (isHomeRoleHeld()) {
+ mBackAnimationController.registerBackCallbacks(mHandler);
+ }
}
}
@@ -1207,6 +1211,22 @@
.unregisterContentObserver(mAnimationRemovalObserver));
}
+ /**
+ * Called when the overview-target changes. Updates the back callback registration state.
+ */
+ public void onOverviewTargetChange() {
+ if (isHomeRoleHeld()) {
+ mBackAnimationController.registerBackCallbacks(mHandler);
+ } else {
+ mBackAnimationController.unregisterBackCallbacks();
+ }
+ }
+
+ private boolean isHomeRoleHeld() {
+ RoleManager roleManager = mLauncher.getSystemService(RoleManager.class);
+ return roleManager == null || roleManager.isRoleHeld(ROLE_HOME);
+ }
+
private void unregisterRemoteAnimations() {
if (SEPARATE_RECENTS_ACTIVITY.get()) {
return;
diff --git a/quickstep/src/com/android/launcher3/taskbar/ManageWindowsTaskbarShortcut.kt b/quickstep/src/com/android/launcher3/taskbar/ManageWindowsTaskbarShortcut.kt
index 860e822..aaa4044 100644
--- a/quickstep/src/com/android/launcher3/taskbar/ManageWindowsTaskbarShortcut.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/ManageWindowsTaskbarShortcut.kt
@@ -34,7 +34,7 @@
import com.android.quickstep.SystemUiProxy
import com.android.quickstep.util.GroupTask
import com.android.systemui.shared.recents.model.ThumbnailData
-import com.android.wm.shell.shared.desktopmode.ManageWindowsViewContainer
+import com.android.wm.shell.shared.multiinstance.ManageWindowsViewContainer
import java.util.Collections
import java.util.function.Predicate
@@ -130,6 +130,22 @@
onOutsideClickListener,
controllers,
)
+
+ // If the view is removed from elsewhere, reset the state to allow the taskbar to auto-stash
+ taskbarShortcutAllWindowsView.menuView.rootView.addOnAttachStateChangeListener(
+ object : View.OnAttachStateChangeListener {
+ override fun onViewAttachedToWindow(v: View) {
+ return
+ }
+
+ override fun onViewDetachedFromWindow(v: View) {
+ controllers.taskbarAutohideSuspendController.updateFlag(
+ FLAG_AUTOHIDE_SUSPEND_MULTI_INSTANCE_MENU_OPEN,
+ false,
+ )
+ }
+ }
+ )
}
/**
@@ -214,7 +230,6 @@
FLAG_AUTOHIDE_SUSPEND_MULTI_INSTANCE_MENU_OPEN,
false,
)
- controllers.taskbarStashController.updateAndAnimateTransientTaskbar(true)
taskbarOverlayContext.dragLayer?.removeView(menuView.rootView)
taskbarOverlayContext.dragLayer.removeTouchController(this)
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index f9e7cf0..f346e19 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -66,6 +66,7 @@
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
+import android.graphics.RectF;
import android.graphics.Region;
import android.graphics.Region.Op;
import android.graphics.drawable.Drawable;
@@ -75,6 +76,7 @@
import android.os.Handler;
import android.util.Property;
import android.view.Gravity;
+import android.view.HapticFeedbackConstants;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
@@ -862,15 +864,21 @@
private void setBackButtonTouchListener(View buttonView,
TaskbarNavButtonController navButtonController) {
+ final RectF rect = new RectF();
buttonView.setOnTouchListener((v, event) -> {
- if (event.getAction() == MotionEvent.ACTION_MOVE) return false;
+ if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ rect.set(0, 0, v.getWidth(), v.getHeight());
+ }
+ boolean isCancelled = event.getAction() == MotionEvent.ACTION_CANCEL
+ || !rect.contains(event.getX(), event.getY());
+ if (event.getAction() == MotionEvent.ACTION_MOVE && !isCancelled) return false;
int motionEventAction = event.getAction();
int keyEventAction = motionEventAction == MotionEvent.ACTION_DOWN
? KeyEvent.ACTION_DOWN : ACTION_UP;
- boolean isCancelled = event.getAction() == MotionEvent.ACTION_CANCEL;
navButtonController.sendBackKeyEvent(keyEventAction, isCancelled);
- if (motionEventAction == MotionEvent.ACTION_UP) {
+ if (motionEventAction == MotionEvent.ACTION_UP && !isCancelled) {
buttonView.performClick();
+ buttonView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
}
return false;
});
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index d4814d3..4498fea 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -116,7 +116,6 @@
private final Context mContext;
private final @Nullable Context mNavigationBarPanelContext;
private WindowManager mWindowManager;
- private FrameLayout mDefaultRootLayout;
private boolean mAddedWindow;
private final TaskbarNavButtonController mDefaultNavButtonController;
private final ComponentCallbacks mDefaultComponentCallbacks;
@@ -132,6 +131,8 @@
new NonDestroyableScopedUnfoldTransitionProgressProvider();
/** DisplayId - {@link TaskbarActivityContext} map for Connected Display. */
private final SparseArray<TaskbarActivityContext> mTaskbars = new SparseArray<>();
+ /** DisplayId - {@link FrameLayout} map for Connected Display. */
+ private final SparseArray<FrameLayout> mRootLayouts = new SparseArray<>();
private StatefulActivity mActivity;
private RecentsViewContainer mRecentsViewContainer;
@@ -240,7 +241,7 @@
mDesktopVisibilityController = desktopVisibilityController;
if (enableTaskbarNoRecreate()) {
mWindowManager = mContext.getSystemService(WindowManager.class);
- mDefaultRootLayout = new FrameLayout(mContext) {
+ FrameLayout taskbarRootLayout = new FrameLayout(mContext) {
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
// The motion events can be outside the view bounds of task bar, and hence
@@ -252,6 +253,7 @@
return super.dispatchTouchEvent(ev);
}
};
+ addTaskbarRootLayoutToMap(getDefaultDisplayId(), taskbarRootLayout);
}
mDefaultNavButtonController = new TaskbarNavButtonController(
context,
@@ -340,6 +342,7 @@
for (int i = 0; i < mTaskbars.size(); i++) {
int displayId = mTaskbars.keyAt(i);
destroyTaskbarForDisplay(displayId);
+ removeTaskbarRootViewFromWindow(displayId);
}
}
@@ -359,7 +362,7 @@
DeviceProfile dp = mUserUnlocked ?
LauncherAppState.getIDP(mContext).getDeviceProfile(mContext) : null;
if (dp == null || !isTaskbarEnabled(dp)) {
- removeTaskbarRootViewFromWindow();
+ removeTaskbarRootViewFromWindow(displayId);
}
}
@@ -552,8 +555,9 @@
if (enableTaskbarNoRecreate()) {
addTaskbarRootViewToWindow(displayId);
- mDefaultRootLayout.removeAllViews();
- mDefaultRootLayout.addView(taskbar.getDragLayer());
+ FrameLayout taskbarRootLayout = getTaskbarRootLayoutForDisplay(displayId);
+ taskbarRootLayout.removeAllViews();
+ taskbarRootLayout.addView(taskbar.getDragLayer());
taskbar.notifyUpdateLayoutParams();
}
addTaskbarToMap(displayId, taskbar);
@@ -714,7 +718,6 @@
removeActivityCallbacksAndListeners();
mTaskbarBroadcastReceiver.unregisterReceiverSafely(mContext);
destroyAllTaskbars();
- removeTaskbarRootViewFromWindow();
if (mUserUnlocked) {
DisplayController.INSTANCE.get(mContext).removeChangeListener(mRecreationListener);
}
@@ -744,15 +747,18 @@
private void addTaskbarRootViewToWindow(int displayId) {
TaskbarActivityContext taskbar = getTaskbarForDisplay(displayId);
if (enableTaskbarNoRecreate() && !mAddedWindow && taskbar != null) {
- mWindowManager.addView(mDefaultRootLayout, taskbar.getWindowLayoutParams());
+ mWindowManager.addView(getTaskbarRootLayoutForDisplay(displayId),
+ taskbar.getWindowLayoutParams());
mAddedWindow = true;
}
}
- private void removeTaskbarRootViewFromWindow() {
- if (enableTaskbarNoRecreate() && mAddedWindow) {
- mWindowManager.removeViewImmediate(mDefaultRootLayout);
+ private void removeTaskbarRootViewFromWindow(int displayId) {
+ FrameLayout rootLayout = getTaskbarRootLayoutForDisplay(displayId);
+ if (enableTaskbarNoRecreate() && mAddedWindow && rootLayout != null) {
+ mWindowManager.removeViewImmediate(rootLayout);
mAddedWindow = false;
+ removeTaskbarRootLayoutFromMap(displayId);
}
}
@@ -767,16 +773,61 @@
return mTaskbars.get(displayId);
}
+ /**
+ * Adds the {@link TaskbarActivityContext} associated with the given display ID to taskbar
+ * map if there is not already a taskbar mapped to that displayId.
+ *
+ * @param displayId The ID of the display to retrieve the taskbar for.
+ * @param newTaskbar The new {@link TaskbarActivityContext} to add to the map.
+ */
private void addTaskbarToMap(int displayId, TaskbarActivityContext newTaskbar) {
if (!mTaskbars.contains(displayId)) {
mTaskbars.put(displayId, newTaskbar);
}
}
+ /**
+ * Removes the taskbar associated with the given display ID from the taskbar map.
+ *
+ * @param displayId The ID of the display for which to remove the taskbar.
+ */
private void removeTaskbarFromMap(int displayId) {
mTaskbars.delete(displayId);
}
+ /**
+ * Retrieves the root layout of the taskbar for the specified display.
+ *
+ * @param displayId The ID of the display for which to retrieve the taskbar root layout.
+ * @return The taskbar root layout {@link FrameLayout} for a given display or {@code null}.
+ */
+ private FrameLayout getTaskbarRootLayoutForDisplay(int displayId) {
+ return mRootLayouts.get(displayId);
+ }
+
+ /**
+ * Adds the taskbar root layout {@link FrameLayout} to taskbar map, mapped to display ID.
+ *
+ * @param displayId The ID of the display to associate with the taskbar root layout.
+ * @param rootLayout The taskbar root layout {@link FrameLayout} to add to the map.
+ */
+ private void addTaskbarRootLayoutToMap(int displayId, FrameLayout rootLayout) {
+ if (!mRootLayouts.contains(displayId)) {
+ mRootLayouts.put(displayId, rootLayout);
+ }
+ }
+
+ /**
+ * Removes taskbar root layout {@link FrameLayout} for given display ID from the taskbar map.
+ *
+ * @param displayId The ID of the display for which to remove the taskbar root layout.
+ */
+ private void removeTaskbarRootLayoutFromMap(int displayId) {
+ if (mRootLayouts.contains(displayId)) {
+ mRootLayouts.delete(displayId);
+ }
+ }
+
private int getDefaultDisplayId() {
return mContext.getDisplayId();
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index b609511..f2355b8 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -199,7 +199,8 @@
// TODO: Disable touch events on QSB otherwise it can crash.
mQsb = LayoutInflater.from(context).inflate(R.layout.search_container_hotseat, this, false);
- mNumStaticViews = taskbarRecentsLayoutTransition() ? addStaticViews() : 0;
+ mNumStaticViews = taskbarRecentsLayoutTransition() && !mActivityContext.isPhoneMode()
+ ? addStaticViews() : 0;
}
/**
@@ -501,16 +502,20 @@
}
private void updateAllAppsDivider() {
- final int allAppsDividerIndex =
- mIsRtl ? getChildCount() - mNumStaticViews : mNumStaticViews;
- if (getChildAt(allAppsDividerIndex) == mTaskbarDividerContainer
+ // Index where All Apps divider would be if it is already in Taskbar.
+ final int expectedAllAppsDividerIndex =
+ mIsRtl ? getChildCount() - mNumStaticViews - 1 : mNumStaticViews;
+ if (getChildAt(expectedAllAppsDividerIndex) == mTaskbarDividerContainer
&& getChildCount() == mNumStaticViews + 1) {
// Only static views with divider so remove divider.
removeView(mTaskbarDividerContainer);
- } else if (getChildAt(allAppsDividerIndex) != mTaskbarDividerContainer
+ } else if (getChildAt(expectedAllAppsDividerIndex) != mTaskbarDividerContainer
&& getChildCount() >= mNumStaticViews + 1) {
- // Static views with at least one app icon so add divider.
- addView(mTaskbarDividerContainer, allAppsDividerIndex);
+ // Static views with at least one app icon so add divider. For RTL, add it after the
+ // icon that is at the expected index.
+ addView(
+ mTaskbarDividerContainer,
+ mIsRtl ? expectedAllAppsDividerIndex + 1 : expectedAllAppsDividerIndex);
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 1baba74..cc51adc 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -264,6 +264,8 @@
private boolean mIsOverlayVisible;
+ private final Runnable mOverviewTargetChangeRunnable = this::onOverviewTargetChanged;
+
public static QuickstepLauncher getLauncher(Context context) {
return fromContext(context);
}
@@ -550,6 +552,10 @@
mUnfoldTransitionProgressProvider.destroy();
}
+ TISBinder binder = mTISBindHelper.getBinder();
+ if (binder != null) {
+ binder.unregisterOverviewTargetChangeListener(mOverviewTargetChangeRunnable);
+ }
mTISBindHelper.onDestroy();
if (mLauncherUnfoldAnimationController != null) {
@@ -1025,12 +1031,20 @@
}
}
+ private void onOverviewTargetChanged() {
+ QuickstepTransitionManager transitionManager = getAppTransitionManager();
+ if (transitionManager != null) {
+ transitionManager.onOverviewTargetChange();
+ }
+ }
+
private void onTISConnected(TISBinder binder) {
TaskbarManager taskbarManager = mTISBindHelper.getTaskbarManager();
if (taskbarManager != null) {
taskbarManager.setActivity(this);
}
mTISBindHelper.setPredictiveBackToHomeInProgress(mIsPredictiveBackToHomeInProgress);
+ binder.registerOverviewTargetChangeListener(mOverviewTargetChangeRunnable);
}
@Override
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 5648dad..bf8cff6 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -80,6 +80,8 @@
import android.os.SystemClock;
import android.util.Log;
import android.util.Pair;
+import android.util.TimeUtils;
+import android.view.Choreographer;
import android.view.MotionEvent;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
@@ -784,7 +786,7 @@
&& recentsAttachedToAppWindow) {
// Only move running task if RecentsView has never been attached before, to avoid
// TaskView jumping to new position as we move the tasks.
- mRecentsView.moveRunningTaskToFront();
+ mRecentsView.moveRunningTaskToExpectedPosition();
}
mAnimationFactory.setRecentsAttachedToAppWindow(
recentsAttachedToAppWindow, animate, updateRunningTaskAlpha);
@@ -1453,8 +1455,21 @@
onPageTransitionEnd.run();
}
}
+ long finalDuration = duration;
+ runOnRecentsAnimationAndLauncherBound(() -> animateGestureEnd(
+ startShift, endShift, finalDuration, interpolator, endTarget, velocityPxPerMs));
+ }
- animateToProgress(startShift, endShift, duration, interpolator, endTarget, velocityPxPerMs);
+ @UiThread
+ protected void animateGestureEnd(
+ float startShift,
+ float endShift,
+ long duration,
+ @NonNull Interpolator interpolator,
+ @NonNull GestureEndTarget endTarget,
+ @NonNull PointF velocityPxPerMs) {
+ animateToProgressInternal(
+ startShift, endShift, duration, interpolator, endTarget, velocityPxPerMs);
}
private void doLogGesture(GestureEndTarget endTarget, @Nullable TaskView targetTask) {
@@ -1497,14 +1512,6 @@
logger.log(event);
}
- /** Animates to the given progress, where 0 is the current app and 1 is overview. */
- @UiThread
- private void animateToProgress(float start, float end, long duration, Interpolator interpolator,
- GestureEndTarget target, PointF velocityPxPerMs) {
- runOnRecentsAnimationAndLauncherBound(() -> animateToProgressInternal(start, end, duration,
- interpolator, target, velocityPxPerMs));
- }
-
protected abstract HomeAnimationFactory createHomeAnimationFactory(
List<IBinder> launchCookies,
long duration,
@@ -1729,13 +1736,30 @@
}
private void handOffAnimation(PointF velocityPxPerMs) {
- if (!TransitionAnimator.Companion.longLivedReturnAnimationsEnabled()
- || mRecentsAnimationController == null) {
+ if (!TransitionAnimator.Companion.longLivedReturnAnimationsEnabled()) {
+ return;
+ }
+
+ // This function is not guaranteed to be called inside a frame. We try to access the frame
+ // time immediately, but if we're not inside a frame we must post a callback to be run at
+ // the beginning of the next frame.
+ try {
+ handOffAnimationInternal(Choreographer.getInstance().getFrameTime(), velocityPxPerMs);
+ } catch (IllegalStateException e) {
+ Choreographer.getInstance().postFrameCallback(
+ frameTimeNanos -> handOffAnimationInternal(
+ frameTimeNanos / TimeUtils.NANOS_PER_MS, velocityPxPerMs));
+ }
+ }
+
+ private void handOffAnimationInternal(long timestamp, PointF velocityPxPerMs) {
+ if (mRecentsAnimationController == null) {
return;
}
Pair<RemoteAnimationTarget[], WindowAnimationState[]> targetsAndStates =
- extractTargetsAndStates(mRemoteTargetHandles, velocityPxPerMs);
+ extractTargetsAndStates(
+ mRemoteTargetHandles, timestamp, velocityPxPerMs);
mRecentsAnimationController.handOffAnimation(
targetsAndStates.first, targetsAndStates.second);
ActiveGestureProtoLogProxy.logHandOffAnimation();
diff --git a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
index 7abcfb8..9b56fd4 100644
--- a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
@@ -64,8 +64,6 @@
import com.android.launcher3.util.DisplayController;
import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.fallback.RecentsState;
-import com.android.quickstep.fallback.window.RecentsWindowManager;
-import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.SurfaceTransaction.SurfaceProperties;
import com.android.quickstep.util.TransformParams;
@@ -172,16 +170,14 @@
}
@Override
- protected boolean handleTaskAppeared(@NonNull RemoteAnimationTarget[] appearedTaskTarget,
- @NonNull ActiveGestureLog.CompoundString failureReason) {
- if (mActiveAnimationFactory != null
- && mActiveAnimationFactory.handleHomeTaskAppeared(appearedTaskTarget)) {
+ public void onTasksAppeared(@NonNull RemoteAnimationTarget[] appearedTaskTargets) {
+ if (mActiveAnimationFactory != null && mActiveAnimationFactory.handleHomeTaskAppeared(
+ appearedTaskTargets)) {
mActiveAnimationFactory = null;
- failureReason.append("(FallbackSwipeHandler) should be handled as home task appeared");
- return false;
+ return;
}
- return super.handleTaskAppeared(appearedTaskTarget, failureReason);
+ super.onTasksAppeared(appearedTaskTargets);
}
@Override
diff --git a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
index a03c0f8..ef103c4 100644
--- a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
+++ b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
@@ -37,6 +37,7 @@
import com.android.launcher3.util.DisplayController.Info;
import com.android.launcher3.util.NavigationMode;
import com.android.launcher3.util.window.CachedDisplayInfo;
+import com.android.quickstep.util.ActiveGestureProtoLogProxy;
import com.android.systemui.shared.Flags;
import java.io.PrintWriter;
@@ -111,13 +112,13 @@
mNavBarGesturalHeight);
}
- private void refreshTouchRegion(Info info, Resources newRes) {
+ private void refreshTouchRegion(Info info, Resources newRes, String reason) {
// Swipe touch regions are independent of nav mode, so we have to clear them explicitly
// here to avoid, for ex, a nav region for 2-button rotation 0 being used for 3-button mode
// It tries to cache and reuse swipe regions whenever possible based only on rotation
mResources = newRes;
mSwipeTouchRegions.clear();
- resetSwipeRegions(info);
+ resetSwipeRegions(info, reason);
}
void setNavigationMode(NavigationMode newMode, Info info, Resources newRes) {
@@ -128,7 +129,7 @@
return;
}
this.mMode = newMode;
- refreshTouchRegion(info, newRes);
+ refreshTouchRegion(info, newRes, "setNavigationMode");
}
void setGesturalHeight(int newGesturalHeight, Info info, Resources newRes) {
@@ -136,7 +137,7 @@
return;
}
mNavBarGesturalHeight = newGesturalHeight;
- refreshTouchRegion(info, newRes);
+ refreshTouchRegion(info, newRes, "setGesturalHeight");
}
/**
@@ -147,14 +148,14 @@
*
* @see #enableMultipleRegions(boolean, Info)
*/
- void createOrAddTouchRegion(Info info) {
+ void createOrAddTouchRegion(Info info, String reason) {
mCachedDisplayInfo = new CachedDisplayInfo(info.currentSize, info.rotation);
if (mQuickStepStartingRotation > QUICKSTEP_ROTATION_UNINITIALIZED
&& mCachedDisplayInfo.rotation == mQuickStepStartingRotation) {
// User already was swiping and the current screen is same rotation as the starting one
// Remove active nav bars in other rotations except for the one we started out in
- resetSwipeRegions(info);
+ resetSwipeRegions(info, reason);
return;
}
OrientationRectF region = mSwipeTouchRegions.get(mCachedDisplayInfo);
@@ -163,9 +164,9 @@
}
if (mEnableMultipleRegions) {
- mSwipeTouchRegions.put(mCachedDisplayInfo, createRegionForDisplay(info));
+ mSwipeTouchRegions.put(mCachedDisplayInfo, createRegionForDisplay(info, reason));
} else {
- resetSwipeRegions(info);
+ resetSwipeRegions(info, reason);
}
}
@@ -184,7 +185,7 @@
mActiveTouchRotation = 0;
mQuickStepStartingRotation = QUICKSTEP_ROTATION_UNINITIALIZED;
}
- resetSwipeRegions(info);
+ resetSwipeRegions(info, "enableMultipleRegions");
}
/**
@@ -198,7 +199,7 @@
*/
void setSingleActiveRegion(Info displayInfo) {
mActiveTouchRotation = displayInfo.rotation;
- resetSwipeRegions(displayInfo);
+ resetSwipeRegions(displayInfo, "setSingleActiveRegion");
}
/**
@@ -207,19 +208,21 @@
* To be called whenever we want to stop tracking more than one swipe region.
* Ok to call multiple times.
*/
- private void resetSwipeRegions(Info region) {
+ private void resetSwipeRegions(Info region, String reason) {
if (enableLog()) {
- Log.d(TAG, "clearing all regions except rotation: " + mCachedDisplayInfo.rotation);
+ Log.d(TAG, "clearing all regions except rotation: " + mCachedDisplayInfo.rotation
+ + " reason=" + reason);
}
mCachedDisplayInfo = new CachedDisplayInfo(region.currentSize, region.rotation);
OrientationRectF regionToKeep = mSwipeTouchRegions.get(mCachedDisplayInfo);
if (regionToKeep == null) {
- regionToKeep = createRegionForDisplay(region);
+ regionToKeep = createRegionForDisplay(region, reason);
}
mSwipeTouchRegions.clear();
mSwipeTouchRegions.put(mCachedDisplayInfo, regionToKeep);
updateAssistantRegions(regionToKeep);
+ updateOneHandedRegions(regionToKeep);
}
private void resetSwipeRegions() {
@@ -228,15 +231,17 @@
if (regionToKeep != null) {
mSwipeTouchRegions.put(mCachedDisplayInfo, regionToKeep);
updateAssistantRegions(regionToKeep);
+ updateOneHandedRegions(regionToKeep);
}
}
- private OrientationRectF createRegionForDisplay(Info display) {
+ private OrientationRectF createRegionForDisplay(Info display, String reason) {
if (enableLog()) {
Log.d(TAG, "creating rotation region for: " + mCachedDisplayInfo.rotation
+ " with mode: " + mMode + " displayRotation: " + display.rotation +
" displaySize: " + display.currentSize +
- " navBarHeight: " + mNavBarGesturalHeight);
+ " navBarHeight: " + mNavBarGesturalHeight +
+ " reason: " + reason);
}
Point size = display.currentSize;
@@ -264,9 +269,10 @@
orientationRectF.top = orientationRectF.bottom - touchHeight;
}
}
- // One handed gestural only active on portrait mode
- mOneHandedModeRegion.set(0, orientationRectF.bottom - mNavBarLargerGesturalHeight,
- size.x, size.y);
+ updateOneHandedRegions(orientationRectF);
+ ActiveGestureProtoLogProxy.logCreateTouchRegionForDisplay(rotation, size, orientationRectF,
+ mOneHandedModeRegion, mNavBarGesturalHeight, mNavBarLargerGesturalHeight,
+ reason);
return orientationRectF;
}
@@ -286,6 +292,12 @@
mAssistantRightRegion.left = orientationRectF.right - assistantWidth;
}
+ private void updateOneHandedRegions(OrientationRectF orientationRectF) {
+ // One handed gestural only active on portrait mode
+ mOneHandedModeRegion.set(0, orientationRectF.bottom - mNavBarLargerGesturalHeight,
+ orientationRectF.right, orientationRectF.bottom);
+ }
+
boolean touchInAssistantRegion(MotionEvent ev) {
return mAssistantLeftRegion.contains(ev.getX(), ev.getY())
|| mAssistantRightRegion.contains(ev.getX(), ev.getY());
@@ -411,9 +423,11 @@
OrientationRectF rectF = mSwipeTouchRegions.get(key);
regions.append(rectF).append(" ");
}
- pw.println(regions.toString());
+ pw.println(regions);
pw.println(" mNavBarGesturalHeight=" + mNavBarGesturalHeight);
pw.println(" mNavBarLargerGesturalHeight=" + mNavBarLargerGesturalHeight);
+ pw.println(" mAssistantLeftRegion=" + mAssistantLeftRegion);
+ pw.println(" mAssistantRightRegion=" + mAssistantRightRegion);
pw.println(" mOneHandedModeRegion=" + mOneHandedModeRegion);
}
}
diff --git a/quickstep/src/com/android/quickstep/RotationTouchHelper.java b/quickstep/src/com/android/quickstep/RotationTouchHelper.java
index 79abc0f..909cc35 100644
--- a/quickstep/src/com/android/quickstep/RotationTouchHelper.java
+++ b/quickstep/src/com/android/quickstep/RotationTouchHelper.java
@@ -236,7 +236,8 @@
return;
}
- mOrientationTouchTransformer.createOrAddTouchRegion(mDisplayController.getInfo());
+ mOrientationTouchTransformer.createOrAddTouchRegion(mDisplayController.getInfo(),
+ "RTH.updateGestureTouchRegions");
}
/**
@@ -273,7 +274,8 @@
if (hasGestures(mMode)) {
updateGestureTouchRegions();
- mOrientationTouchTransformer.createOrAddTouchRegion(info);
+ mOrientationTouchTransformer.createOrAddTouchRegion(info,
+ "RTH.onDisplayInfoChanged");
mCurrentAppRotation = mDisplayRotation;
/* Update nav bars on the following:
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index 783c87c..084cede 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -795,14 +795,15 @@
* second applies to the target in the same index of the first.
*
* @param handles The handles wrapping each target.
+ * @param timestamp The start time of the current frame.
* @param velocityPxPerMs The current velocity of the target animations.
*/
@NonNull
public static Pair<RemoteAnimationTarget[], WindowAnimationState[]> extractTargetsAndStates(
- @NonNull RemoteTargetHandle[] handles, @NonNull PointF velocityPxPerMs) {
+ @NonNull RemoteTargetHandle[] handles, long timestamp,
+ @NonNull PointF velocityPxPerMs) {
RemoteAnimationTarget[] targets = new RemoteAnimationTarget[handles.length];
WindowAnimationState[] animationStates = new WindowAnimationState[handles.length];
- long timestamp = System.currentTimeMillis();
for (int i = 0; i < handles.length; i++) {
targets[i] = handles[i].getTransformParams().getTargetSet().apps[i];
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index d38eaf3..8edb16f 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -137,6 +137,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
+import java.util.HashSet;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -163,7 +164,7 @@
private final WeakReference<TouchInteractionService> mTis;
- @Nullable private Runnable mOnOverviewTargetChangeListener = null;
+ private final Set<Runnable> mOnOverviewTargetChangeListeners = new HashSet<>();
private TISBinder(TouchInteractionService tis) {
mTis = new WeakReference<>(tis);
@@ -512,15 +513,19 @@
tis -> tis.mDeviceState.setGestureBlockingTaskId(taskId));
}
- /** Sets a listener to be run on Overview Target updates. */
- public void setOverviewTargetChangeListener(@Nullable Runnable listener) {
- mOnOverviewTargetChangeListener = listener;
+ /** Registers a listener to be run on Overview Target updates. */
+ public void registerOverviewTargetChangeListener(@NonNull Runnable listener) {
+ mOnOverviewTargetChangeListeners.add(listener);
+ }
+
+ /** Unregisters an OverviewTargetChange listener. */
+ public void unregisterOverviewTargetChangeListener(@NonNull Runnable listener) {
+ mOnOverviewTargetChangeListeners.remove(listener);
}
protected void onOverviewTargetChange() {
- if (mOnOverviewTargetChangeListener != null) {
- mOnOverviewTargetChangeListener.run();
- mOnOverviewTargetChangeListener = null;
+ for (Runnable listener : mOnOverviewTargetChangeListeners) {
+ listener.run();
}
}
diff --git a/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowManager.kt b/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowManager.kt
index 843ef6c..e158975 100644
--- a/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowManager.kt
+++ b/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowManager.kt
@@ -163,9 +163,19 @@
}
override fun startHome() {
+ startHome(/* finishRecentsAnimation= */ true)
+ }
+
+ fun startHome(finishRecentsAnimation: Boolean) {
val recentsView: RecentsView<*, *> = getOverviewPanel()
+
+ if (!finishRecentsAnimation) {
+ recentsView.switchToScreenshot(/* onFinishRunnable= */ null)
+ startHomeInternal()
+ return
+ }
recentsView.switchToScreenshot {
- recentsView.finishRecentsAnimation(true) { startHomeInternal() }
+ recentsView.finishRecentsAnimation(/* toRecents= */ true) { startHomeInternal() }
}
}
diff --git a/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowSwipeHandler.java b/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowSwipeHandler.java
index c1d3f6e..be71385 100644
--- a/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowSwipeHandler.java
@@ -31,6 +31,7 @@
import android.content.Context;
import android.content.Intent;
import android.graphics.Matrix;
+import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Bundle;
@@ -47,9 +48,11 @@
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
+import android.view.animation.Interpolator;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.UiThread;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Utilities;
@@ -144,6 +147,29 @@
}
}
+ @UiThread
+ @Override
+ protected void animateGestureEnd(
+ float startShift,
+ float endShift,
+ long duration,
+ @NonNull Interpolator interpolator,
+ @NonNull GestureState.GestureEndTarget endTarget,
+ @NonNull PointF velocityPxPerMs) {
+ boolean fromHomeToHome = mRunningOverHome
+ && endTarget == GestureState.GestureEndTarget.HOME;
+ if (fromHomeToHome) {
+ mRecentsWindowManager.startHome(/* finishRecentsAnimation= */ false);
+ }
+ super.animateGestureEnd(
+ startShift,
+ endShift,
+ fromHomeToHome ? 0 : duration,
+ interpolator,
+ endTarget,
+ velocityPxPerMs);
+ }
+
private void updateHomeActivityTransformDuringSwipeUp(SurfaceProperties builder,
RemoteAnimationTarget app, TransformParams params) {
if (mActiveAnimationFactory != null) {
diff --git a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
index f7f3157..3eba9c0 100644
--- a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
@@ -121,6 +121,8 @@
private TextView mHintView;
+ private final Runnable mOverviewTargetChangeRunnable = this::onOverviewTargetChanged;
+
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -285,7 +287,7 @@
private void onTISConnected(TISBinder binder) {
setSetupUIVisible(isResumed());
binder.setSwipeUpProxy(isResumed() ? this::createSwipeUpProxy : null);
- binder.setOverviewTargetChangeListener(binder::preloadOverviewForSUWAllSet);
+ binder.registerOverviewTargetChangeListener(mOverviewTargetChangeRunnable);
binder.preloadOverviewForSUWAllSet();
TaskbarManager taskbarManager = binder.getTaskbarManager();
if (taskbarManager != null) {
@@ -293,6 +295,14 @@
}
}
+ private void onOverviewTargetChanged() {
+ TISBinder binder = mTISBindHelper.getBinder();
+ if (binder != null) {
+ binder.preloadOverviewForSUWAllSet();
+ binder.unregisterOverviewTargetChangeListener(mOverviewTargetChangeRunnable);
+ }
+ }
+
@Override
protected void onPause() {
super.onPause();
@@ -309,7 +319,7 @@
if (binder != null) {
setSetupUIVisible(false);
binder.setSwipeUpProxy(null);
- binder.setOverviewTargetChangeListener(null);
+ binder.unregisterOverviewTargetChangeListener(mOverviewTargetChangeRunnable);
}
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 9cc42b4..743fa40 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -1768,26 +1768,17 @@
}
/**
- * Moves the running task to the front of the carousel in tablets, to minimize animation
- * required to move the running task in grid.
+ * Moves the running task to the expected position in the carousel. In tablets, this minimize
+ * animation required to move the running task into focused task position.
*/
- public void moveRunningTaskToFront() {
- if (!mContainer.getDeviceProfile().isTablet) {
- return;
- }
-
+ public void moveRunningTaskToExpectedPosition() {
TaskView runningTaskView = getRunningTaskView();
- if (runningTaskView == null) {
+ if (runningTaskView == null || mCurrentPage != indexOfChild(runningTaskView)) {
return;
}
- if (indexOfChild(runningTaskView) != mCurrentPage) {
- return;
- }
-
- int frontIndex = enableLargeDesktopWindowingTile() ? getDesktopTaskViewCount() : 0;
-
- if (mCurrentPage <= frontIndex) {
+ int runningTaskExpectedIndex = getRunningTaskExpectedIndex(runningTaskView);
+ if (mCurrentPage == runningTaskExpectedIndex) {
return;
}
@@ -1800,12 +1791,31 @@
mMovingTaskView = null;
runningTaskView.resetPersistentViewTransforms();
- addView(runningTaskView, frontIndex);
- setCurrentPage(frontIndex);
+ addView(runningTaskView, runningTaskExpectedIndex);
+ setCurrentPage(runningTaskExpectedIndex);
updateTaskSize();
}
+ private int getRunningTaskExpectedIndex(TaskView runningTaskView) {
+ if (mContainer.getDeviceProfile().isTablet) {
+ if (runningTaskView instanceof DesktopTaskView) {
+ return 0; // Desktop running task is always in front.
+ } else if (enableLargeDesktopWindowingTile()) {
+ return getDesktopTaskViewCount(); // Other running task is behind desktop tasks.
+ } else {
+ return 0;
+ }
+ } else {
+ int currentIndex = indexOfChild(runningTaskView);
+ if (currentIndex != -1) {
+ return currentIndex; // Keep the position if running task already in layout.
+ } else {
+ return 0; // New running task are added to the front to begin with.
+ }
+ }
+ }
+
@Override
protected void onScrollerAnimationAborted() {
ActiveGestureProtoLogProxy.logOnScrollerAnimationAborted();
@@ -2971,7 +2981,7 @@
taskView = getTaskViewFromPool(TaskViewType.SINGLE);
taskView.bind(runningTasks[0], mOrientationState, mTaskOverlayFactory);
}
- addView(taskView, 0);
+ addView(taskView, getRunningTaskExpectedIndex(taskView));
runningTaskViewId = taskView.getTaskViewId();
if (wasEmpty) {
addView(mClearAllButton);
@@ -5689,43 +5699,6 @@
updateCurrentTaskActionsVisibility();
loadVisibleTaskData(TaskView.FLAG_UPDATE_ALL);
updateEnabledOverlays();
-
- if (enableRefactorTaskThumbnail()) {
- int screenStart = 0;
- int screenEnd = 0;
- int centerPageIndex = 0;
- if (showAsGrid()) {
- screenStart = getPagedOrientationHandler().getPrimaryScroll(this);
- int pageOrientedSize = getPagedOrientationHandler().getMeasuredSize(this);
- screenEnd = screenStart + pageOrientedSize;
- } else {
- centerPageIndex = getPageNearestToCenterOfScreen();
- }
-
- Set<Integer> fullyVisibleTaskIds = new HashSet<>();
-
- // Update the task data for the in/visible children
- for (int i = 0; i < getTaskViewCount(); i++) {
- TaskView taskView = requireTaskViewAt(i);
- List<TaskContainer> containers = taskView.getTaskContainers();
- if (containers.isEmpty()) {
- continue;
- }
- boolean isFullyVisible;
- if (showAsGrid()) {
- isFullyVisible = isTaskViewFullyWithinBounds(taskView, screenStart,
- screenEnd);
- } else {
- isFullyVisible = i == centerPageIndex;
- }
- if (isFullyVisible) {
- List<Integer> taskIds = containers.stream().map(
- taskContainer -> taskContainer.getTask().key.id).toList();
- fullyVisibleTaskIds.addAll(taskIds);
- }
- }
- mRecentsViewModel.updateTasksFullyVisible(fullyVisibleTaskIds);
- }
}
@Override
@@ -6284,17 +6257,27 @@
}
private void updateEnabledOverlays() {
- TaskView focusedTaskView = getFocusedTaskView();
- for (TaskView taskView : getTaskViews()) {
- if (taskView == focusedTaskView) {
- continue;
+ if (enableRefactorTaskThumbnail()) {
+ Set<Integer> fullyVisibleTaskIds = new HashSet<>();
+ for (TaskView taskView : getTaskViews()) {
+ if (isTaskViewFullyVisible(taskView)) {
+ fullyVisibleTaskIds.addAll(taskView.getTaskIdSet());
+ }
}
- taskView.setOverlayEnabled(mOverlayEnabled && isTaskViewFullyVisible(taskView));
- }
- // Focus task overlay should be enabled and refreshed at last
- if (focusedTaskView != null) {
- focusedTaskView.setOverlayEnabled(
- mOverlayEnabled && isTaskViewFullyVisible(focusedTaskView));
+ mRecentsViewModel.updateTasksFullyVisible(fullyVisibleTaskIds);
+ } else {
+ TaskView focusedTaskView = getFocusedTaskView();
+ for (TaskView taskView : getTaskViews()) {
+ if (taskView == focusedTaskView) {
+ continue;
+ }
+ taskView.setOverlayEnabled(mOverlayEnabled && isTaskViewFullyVisible(taskView));
+ }
+ // Focus task overlay should be enabled and refreshed at last
+ if (focusedTaskView != null) {
+ focusedTaskView.setOverlayEnabled(
+ mOverlayEnabled && isTaskViewFullyVisible(focusedTaskView));
+ }
}
}
diff --git a/quickstep/src_protolog/com/android/quickstep/util/ActiveGestureProtoLogProxy.java b/quickstep/src_protolog/com/android/quickstep/util/ActiveGestureProtoLogProxy.java
index 0091036..f25f6f4 100644
--- a/quickstep/src_protolog/com/android/quickstep/util/ActiveGestureProtoLogProxy.java
+++ b/quickstep/src_protolog/com/android/quickstep/util/ActiveGestureProtoLogProxy.java
@@ -38,6 +38,8 @@
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.START_RECENTS_ANIMATION;
import static com.android.quickstep.util.QuickstepProtoLogGroup.ACTIVE_GESTURE_LOG;
+import android.graphics.Point;
+import android.graphics.RectF;
import android.view.MotionEvent;
import androidx.annotation.NonNull;
@@ -505,4 +507,16 @@
taskId,
packageName);
}
+
+ public static void logCreateTouchRegionForDisplay(int displayRotation,
+ @NonNull Point displaySize, @NonNull RectF swipeRegion, @NonNull RectF ohmRegion,
+ int gesturalHeight, int largerGesturalHeight, @NonNull String reason) {
+ if (!enableActiveGestureProtoLog()) return;
+ ProtoLog.d(ACTIVE_GESTURE_LOG,
+ "OrientationTouchTransformer.createRegionForDisplay: "
+ + "dispRot=%d, dispSize=%s, swipeRegion=%s, ohmRegion=%s, "
+ + "gesturalHeight=%d, largerGesturalHeight=%d, reason=%s",
+ displayRotation, displaySize.flattenToString(), swipeRegion.toShortString(),
+ ohmRegion.toShortString(), gesturalHeight, largerGesturalHeight, reason);
+ }
}
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarViewWithLayoutTransitionTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarViewWithLayoutTransitionTest.kt
index 15ded8d..78d8e5d 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarViewWithLayoutTransitionTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarViewWithLayoutTransitionTest.kt
@@ -84,7 +84,17 @@
@Test
@ForceRtl
- fun testUpdateItems_rtl_addHotseatItem_updatesHotseat() {
+ fun testUpdateItems_rtl_addHotseatItemWithoutRecents_updatesHotseat() {
+ runOnMainSync {
+ taskbarView.updateItems(createHotseatItems(1), emptyList())
+ taskbarView.updateItems(createHotseatItems(2), emptyList())
+ }
+ assertThat(taskbarView).hasIconTypes(*HOTSEAT * 2, DIVIDER, ALL_APPS)
+ }
+
+ @Test
+ @ForceRtl
+ fun testUpdateItems_rtl_addHotseatItemWithRecents_updatesHotseat() {
runOnMainSync {
taskbarView.updateItems(createHotseatItems(1), createRecents(1))
taskbarView.updateItems(createHotseatItems(2), createRecents(1))
diff --git a/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java b/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
index f5d082d..ff0ad53 100644
--- a/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
+++ b/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
@@ -90,7 +90,7 @@
float landscapeRegionY =
generateTouchRegionHeight(NORMAL_SCREEN_SIZE, Surface.ROTATION_90) + 1;
- mTouchTransformer.createOrAddTouchRegion(mInfo);
+ mTouchTransformer.createOrAddTouchRegion(mInfo, "test");
tapAndAssertTrue(100, portraitRegionY,
event -> mTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY()));
tapAndAssertFalse(100, landscapeRegionY,
@@ -102,7 +102,8 @@
// Override region
mTouchTransformer
- .createOrAddTouchRegion(createDisplayInfo(NORMAL_SCREEN_SIZE, Surface.ROTATION_90));
+ .createOrAddTouchRegion(createDisplayInfo(NORMAL_SCREEN_SIZE, Surface.ROTATION_90),
+ "test");
tapAndAssertFalse(100, portraitRegionY,
event -> mTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY()));
tapAndAssertTrue(100, landscapeRegionY,
@@ -113,7 +114,7 @@
event -> mTouchTransformer.touchInAssistantRegion(event));
// Override region again
- mTouchTransformer.createOrAddTouchRegion(mInfo);
+ mTouchTransformer.createOrAddTouchRegion(mInfo, "test");
tapAndAssertTrue(100, portraitRegionY,
event -> mTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY()));
tapAndAssertFalse(100, landscapeRegionY,
@@ -132,7 +133,8 @@
generateTouchRegionHeight(NORMAL_SCREEN_SIZE, Surface.ROTATION_90) + 1;
mTouchTransformer
- .createOrAddTouchRegion(createDisplayInfo(NORMAL_SCREEN_SIZE, Surface.ROTATION_90));
+ .createOrAddTouchRegion(createDisplayInfo(NORMAL_SCREEN_SIZE, Surface.ROTATION_90),
+ "test");
tapAndAssertFalse(100, portraitRegionY,
event -> mTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY()));
tapAndAssertTrue(100, landscapeRegionY,
@@ -144,7 +146,7 @@
// We have to add 0 rotation second so that gets set as the current rotation, otherwise
// matrix transform will fail (tests only work in Portrait at the moment)
mTouchTransformer.enableMultipleRegions(true, mInfo);
- mTouchTransformer.createOrAddTouchRegion(mInfo);
+ mTouchTransformer.createOrAddTouchRegion(mInfo, "test");
tapAndAssertTrue(100, portraitRegionY,
event -> mTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY()));
@@ -165,8 +167,9 @@
mTouchTransformer.enableMultipleRegions(true, mInfo);
mTouchTransformer
- .createOrAddTouchRegion(createDisplayInfo(NORMAL_SCREEN_SIZE, Surface.ROTATION_90));
- mTouchTransformer.createOrAddTouchRegion(mInfo);
+ .createOrAddTouchRegion(createDisplayInfo(NORMAL_SCREEN_SIZE, Surface.ROTATION_90),
+ "test");
+ mTouchTransformer.createOrAddTouchRegion(mInfo, "test");
tapAndAssertTrue(0, portraitRegionY,
event -> mTouchTransformer.touchInAssistantRegion(event));
tapAndAssertFalse(0, landscapeRegionY,
@@ -181,9 +184,10 @@
generateTouchRegionHeight(NORMAL_SCREEN_SIZE, Surface.ROTATION_90) + 1;
mTouchTransformer.enableMultipleRegions(true, mInfo);
- mTouchTransformer.createOrAddTouchRegion(mInfo);
+ mTouchTransformer.createOrAddTouchRegion(mInfo, "test");
mTouchTransformer
- .createOrAddTouchRegion(createDisplayInfo(NORMAL_SCREEN_SIZE, Surface.ROTATION_90));
+ .createOrAddTouchRegion(createDisplayInfo(NORMAL_SCREEN_SIZE, Surface.ROTATION_90),
+ "test");
mTouchTransformer.enableMultipleRegions(false, mInfo);
tapAndAssertTrue(0, portraitRegionY,
event -> mTouchTransformer.touchInAssistantRegion(event));
@@ -213,14 +217,14 @@
@Test
public void applyTransform_taskNotFrozen_notInRegion() {
- mTouchTransformer.createOrAddTouchRegion(mInfo);
+ mTouchTransformer.createOrAddTouchRegion(mInfo, "test");
tapAndAssertFalse(100, 100,
event -> mTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY()));
}
@Test
public void applyTransform_taskFrozen_noRotate_outOfRegion() {
- mTouchTransformer.createOrAddTouchRegion(mInfo);
+ mTouchTransformer.createOrAddTouchRegion(mInfo, "test");
mTouchTransformer.enableMultipleRegions(true, mInfo);
tapAndAssertFalse(100, 100,
event -> mTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY()));
@@ -228,7 +232,7 @@
@Test
public void applyTransform_taskFrozen_noRotate_inRegion() {
- mTouchTransformer.createOrAddTouchRegion(mInfo);
+ mTouchTransformer.createOrAddTouchRegion(mInfo, "test");
mTouchTransformer.enableMultipleRegions(true, mInfo);
float y = generateTouchRegionHeight(NORMAL_SCREEN_SIZE, Surface.ROTATION_0) + 1;
tapAndAssertTrue(100, y,
@@ -237,7 +241,7 @@
@Test
public void applyTransform_taskNotFrozen_noRotate_inDefaultRegion() {
- mTouchTransformer.createOrAddTouchRegion(mInfo);
+ mTouchTransformer.createOrAddTouchRegion(mInfo, "test");
float y = generateTouchRegionHeight(NORMAL_SCREEN_SIZE, Surface.ROTATION_0) + 1;
tapAndAssertTrue(100, y,
event -> mTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY()));
@@ -246,7 +250,8 @@
@Test
public void applyTransform_taskNotFrozen_90Rotate_inRegion() {
mTouchTransformer
- .createOrAddTouchRegion(createDisplayInfo(NORMAL_SCREEN_SIZE, Surface.ROTATION_90));
+ .createOrAddTouchRegion(createDisplayInfo(NORMAL_SCREEN_SIZE, Surface.ROTATION_90),
+ "test");
float y = generateTouchRegionHeight(NORMAL_SCREEN_SIZE, Surface.ROTATION_90) + 1;
tapAndAssertTrue(100, y,
event -> mTouchTransformer.touchInValidSwipeRegions(event.getX(), event.getY()));
@@ -254,10 +259,11 @@
@Test
public void applyTransform_taskNotFrozen_90Rotate_withTwoRegions() {
- mTouchTransformer.createOrAddTouchRegion(mInfo);
+ mTouchTransformer.createOrAddTouchRegion(mInfo, "test");
mTouchTransformer.enableMultipleRegions(true, mInfo);
mTouchTransformer
- .createOrAddTouchRegion(createDisplayInfo(NORMAL_SCREEN_SIZE, Surface.ROTATION_90));
+ .createOrAddTouchRegion(createDisplayInfo(NORMAL_SCREEN_SIZE, Surface.ROTATION_90),
+ "test");
// Landscape point
float y1 = generateTouchRegionHeight(NORMAL_SCREEN_SIZE, Surface.ROTATION_90) + 1;
MotionEvent inRegion1_down = generateMotionEvent(MotionEvent.ACTION_DOWN, 10, y1);
@@ -278,10 +284,11 @@
@Test
public void applyTransform_90Rotate_inRotatedRegion() {
// Create regions for both 0 Rotation and 90 Rotation
- mTouchTransformer.createOrAddTouchRegion(mInfo);
+ mTouchTransformer.createOrAddTouchRegion(mInfo, "test");
mTouchTransformer.enableMultipleRegions(true, mInfo);
mTouchTransformer
- .createOrAddTouchRegion(createDisplayInfo(NORMAL_SCREEN_SIZE, Surface.ROTATION_90));
+ .createOrAddTouchRegion(createDisplayInfo(NORMAL_SCREEN_SIZE, Surface.ROTATION_90),
+ "test");
// Portrait point in landscape orientation axis
float x1 = generateTouchRegionHeight(NORMAL_SCREEN_SIZE, Surface.ROTATION_0);
// bottom of screen, from landscape perspective right side of screen
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 0d4e79b..326ee06 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -568,4 +568,8 @@
<!-- WindowManagerProxy -->
<dimen name="max_width_and_height_of_small_display_cutout">136px</dimen>
+
+ <!-- App Title Pill -->
+ <dimen name="app_title_pill_horizontal_padding">4dp</dimen>
+ <dimen name="app_title_pill_round_rect_padding">2dp</dimen>
</resources>
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 817cc40..ed2ab81 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -127,8 +127,6 @@
private static final int[] STATE_PRESSED = new int[]{android.R.attr.state_pressed};
- private static final int APP_PILL_TITLE_PADDING = 8;
-
private float mScaleForReorderBounce = 1f;
private IntArray mBreakPointsIntArray;
@@ -734,12 +732,18 @@
getDrawingRect(tmpRect);
CharSequence text = getText();
+ int mAppTitleHorizontalPadding = getResources().getDimensionPixelSize(
+ R.dimen.app_title_pill_horizontal_padding);
+ int mRoundRectPadding = getResources().getDimensionPixelSize(
+ R.dimen.app_title_pill_round_rect_padding);
+
float titleLength = (getPaint().measureText(text, 0, text.length())
- + APP_PILL_TITLE_PADDING * 2);
+ + (mAppTitleHorizontalPadding + mRoundRectPadding) * 2);
titleLength = Math.min(titleLength, tmpRect.width());
appTitleBounds = new RectF((tmpRect.width() - titleLength) / 2.f - getCompoundPaddingLeft(),
0, (tmpRect.width() + titleLength) / 2.f + getCompoundPaddingRight(),
(int) Math.ceil(fm.bottom - fm.top));
+ appTitleBounds.inset(mRoundRectPadding * 2, 0);
if (mIcon != null) {
@@ -859,8 +863,13 @@
getPaddingBottom());
}
if (shouldDrawAppContrastTile()) {
- setPadding(getPaddingLeft() + APP_PILL_TITLE_PADDING, getPaddingTop(),
- getPaddingRight() + APP_PILL_TITLE_PADDING,
+ int mAppTitleHorizontalPadding = getResources().getDimensionPixelSize(
+ R.dimen.app_title_pill_horizontal_padding);
+ int mRoundRectPadding = getResources().getDimensionPixelSize(
+ R.dimen.app_title_pill_round_rect_padding);
+
+ setPadding(mAppTitleHorizontalPadding + mRoundRectPadding, getPaddingTop(),
+ mAppTitleHorizontalPadding + mRoundRectPadding,
getPaddingBottom());
}
// Only apply two line for all_apps and device search only if necessary.
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java
index 867bf98..18619f5 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -65,7 +65,7 @@
protected final ActivityContext mActivityContext;
protected final DropTargetHandler mDropTargetHandler;
protected DropTargetBar mDropTargetBar;
- private final MSDLPlayerWrapper mMSDLPlayerWrapper;
+ private MSDLPlayerWrapper mMSDLPlayerWrapper;
/** Whether this drop target is active for the current drag */
protected boolean mActive;
@@ -438,6 +438,11 @@
return textHeight + getPaddingTop() + getPaddingBottom() >= availableHeight;
}
+ @VisibleForTesting
+ public void setMSDLPlayerWrapper(MSDLPlayerWrapper wrapper) {
+ mMSDLPlayerWrapper = wrapper;
+ }
+
/**
* Reduce the size of the text until it fits the measured width or reaches a minimum.
*
diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java
index 58789fd..425f277 100644
--- a/src/com/android/launcher3/DeleteDropTarget.java
+++ b/src/com/android/launcher3/DeleteDropTarget.java
@@ -130,7 +130,6 @@
public void completeDrop(DragObject d) {
ItemInfo item = d.dragInfo;
if (canRemove(item)) {
- onAccessibilityDrop(null, item);
mDropTargetHandler.onDeleteComplete(item);
}
}
diff --git a/src/com/android/launcher3/DropTargetHandler.kt b/src/com/android/launcher3/DropTargetHandler.kt
index f1029b1..4d3fe52 100644
--- a/src/com/android/launcher3/DropTargetHandler.kt
+++ b/src/com/android/launcher3/DropTargetHandler.kt
@@ -65,6 +65,7 @@
}
fun onDeleteComplete(item: ItemInfo) {
+ removeItemAndStripEmptyScreens(null /* view */, item)
var pageItem: ItemInfo = item
if (item.container <= 0) {
val v = mLauncher.workspace.getHomescreenIconByItemId(item.container)
@@ -90,11 +91,7 @@
}
fun onAccessibilityDelete(view: View?, item: ItemInfo, announcement: CharSequence) {
- // Remove the item from launcher and the db, we can ignore the containerInfo in this call
- // because we already remove the drag view from the folder (if the drag originated from
- // a folder) in Folder.beginDrag()
- mLauncher.removeItem(view, item, true /* deleteFromDb */, "removed by accessibility drop")
- mLauncher.workspace.stripEmptyScreens()
+ removeItemAndStripEmptyScreens(view, item)
mLauncher.dragLayer.announceForAccessibility(announcement)
}
@@ -105,4 +102,12 @@
fun onClick(buttonDropTarget: ButtonDropTarget) {
mLauncher.accessibilityDelegate.handleAccessibleDrop(buttonDropTarget, null, null)
}
+
+ private fun removeItemAndStripEmptyScreens(view: View?, item: ItemInfo) {
+ // Remove the item from launcher and the db, we can ignore the containerInfo in this call
+ // because we already remove the drag view from the folder (if the drag originated from
+ // a folder) in Folder.beginDrag()
+ mLauncher.removeItem(view, item, true /* deleteFromDb */, "removed by accessibility drop")
+ mLauncher.workspace.stripEmptyScreens()
+ }
}
diff --git a/src/com/android/launcher3/model/GridSizeMigrationLogic.kt b/src/com/android/launcher3/model/GridSizeMigrationLogic.kt
index 3f52d8a..75fd31e 100644
--- a/src/com/android/launcher3/model/GridSizeMigrationLogic.kt
+++ b/src/com/android/launcher3/model/GridSizeMigrationLogic.kt
@@ -58,12 +58,17 @@
}
val isFirstLoad = get(context).get(LauncherPrefs.IS_FIRST_LOAD_AFTER_RESTORE)
- Log.d(TAG, "Begin grid migration. First load: $isFirstLoad")
+ Log.d(
+ TAG,
+ "Begin grid migration. First load: $isFirstLoad\n srcDeviceState: " +
+ "$srcDeviceState\ndestDeviceState: $destDeviceState\nisDestNewDb: $isDestNewDb",
+ )
// This is a special case where if the grid is the same amount of columns but a larger
// amount of rows we simply copy over the source grid to the destination grid, rather
// than undergoing the general grid migration.
if (shouldMigrateToStrictlyTallerGrid(isDestNewDb, srcDeviceState, destDeviceState)) {
+ Log.d(TAG, "Migrating to strictly taller grid")
copyTable(source, TABLE_NAME, target.writableDatabase, TABLE_NAME, context)
if (oneGridSpecs()) {
val destReader = DbReader(target.writableDatabase, TABLE_NAME, context)
diff --git a/src/com/android/launcher3/util/MSDLPlayerWrapper.java b/src/com/android/launcher3/util/MSDLPlayerWrapper.java
index eccccc7..8a1d923 100644
--- a/src/com/android/launcher3/util/MSDLPlayerWrapper.java
+++ b/src/com/android/launcher3/util/MSDLPlayerWrapper.java
@@ -69,6 +69,7 @@
/** Print the latest history of MSDL tokens played */
public void dump(String prefix, PrintWriter writer) {
+ writer.println(prefix + mMSDLPlayer.toString());
writer.println(prefix + "MSDLPlayerWrapper history of latest events:");
List<MSDLEvent> events = getHistory();
for (MSDLEvent event: events) {
diff --git a/tests/multivalentTests/src/com/android/launcher3/DeleteDropTargetTest.kt b/tests/multivalentTests/src/com/android/launcher3/DeleteDropTargetTest.kt
index 42374a5..fa368e5 100644
--- a/tests/multivalentTests/src/com/android/launcher3/DeleteDropTargetTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/DeleteDropTargetTest.kt
@@ -16,7 +16,12 @@
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
+import org.mockito.kotlin.times
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.verifyNoMoreInteractions
@SmallTest
@RunWith(AndroidJUnit4::class)
@@ -24,6 +29,8 @@
@get:Rule val mSetFlagsRule = SetFlagsRule()
+ @Mock private val msdlPlayerWrapper = mock<MSDLPlayerWrapper>()
+
private var mContext: Context = ActivityContextWrapper(getApplicationContext())
// Use a non-abstract class implementation
@@ -50,13 +57,12 @@
@Test
@EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
fun onDragEnter_performsMSDLSwipeThresholdFeedback() {
+ buttonDropTarget.setMSDLPlayerWrapper(msdlPlayerWrapper)
val target = DropTarget.DragObject(mContext)
target.dragView = mock<DragView<*>>()
buttonDropTarget.onDragEnter(target)
- val wrapper = MSDLPlayerWrapper.INSTANCE.get(mContext)
- val history = wrapper.history
- assertThat(history.size).isEqualTo(1)
- assertThat(history[0].tokenName).isEqualTo(MSDLToken.SWIPE_THRESHOLD_INDICATOR.name)
+ verify(msdlPlayerWrapper, times(1)).playToken(eq(MSDLToken.SWIPE_THRESHOLD_INDICATOR))
+ verifyNoMoreInteractions(msdlPlayerWrapper)
}
}