Merge "Allow extra pixel for app bounds containment PiP" into main
diff --git a/Android.bp b/Android.bp
index 962f269..e358005 100644
--- a/Android.bp
+++ b/Android.bp
@@ -19,6 +19,17 @@
min_launcher3_sdk_version = "30"
+// Targets that don't inherit framework aconfig libs (i.e., those that don't set
+// `platform_apis: true`) must manually link them.
+java_defaults {
+ name: "launcher-non-platform-apis-defaults",
+ static_libs: [
+ "android.os.flags-aconfig-java",
+ "android.appwidget.flags-aconfig-java",
+ "com.android.window.flags.window-aconfig-java",
+ ]
+}
+
// Common source files used to build launcher (java and kotlin)
// All sources are split so they can be reused in many other libraries/apps in other folders
@@ -141,7 +152,6 @@
static_libs: [
"LauncherPluginLib",
"launcher_quickstep_log_protos_lite",
- "android.os.flags-aconfig-java",
"androidx-constraintlayout_constraintlayout",
"androidx.recyclerview_recyclerview",
"androidx.dynamicanimation_dynamicanimation",
@@ -163,8 +173,6 @@
"kotlinx_coroutines",
"com_android_launcher3_flags_lib",
"com_android_wm_shell_flags_lib",
- "android.appwidget.flags-aconfig-java",
- "com.android.window.flags.window-aconfig-java",
],
manifest: "AndroidManifest-common.xml",
sdk_version: "current",
@@ -179,6 +187,7 @@
//
android_app {
name: "Launcher3",
+ defaults: ["launcher-non-platform-apis-defaults"],
static_libs: [
"Launcher3ResLib",
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java
index 5d47212..0ba5de1 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java
@@ -46,6 +46,7 @@
import androidx.core.content.res.ResourcesCompat;
import com.android.app.animation.Interpolators;
+import com.android.internal.jank.Cuj;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatedFloat;
@@ -53,6 +54,7 @@
import com.android.launcher3.testing.shared.TestProtocol;
import com.android.quickstep.util.DesktopTask;
import com.android.quickstep.util.GroupTask;
+import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
import java.util.HashMap;
import java.util.List;
@@ -331,6 +333,8 @@
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
+ InteractionJankMonitorWrapper.begin(
+ KeyboardQuickSwitchView.this, Cuj.CUJ_LAUNCHER_KEYBOARD_QUICK_SWITCH_OPEN);
setClipToPadding(false);
setOutlineProvider(new ViewOutlineProvider() {
@Override
@@ -366,12 +370,19 @@
}
@Override
+ public void onAnimationCancel(Animator animation) {
+ super.onAnimationCancel(animation);
+ InteractionJankMonitorWrapper.cancel(Cuj.CUJ_LAUNCHER_KEYBOARD_QUICK_SWITCH_OPEN);
+ }
+
+ @Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
setClipToPadding(true);
setOutlineProvider(outlineProvider);
invalidateOutline();
mOpenAnimation = null;
+ InteractionJankMonitorWrapper.end(Cuj.CUJ_LAUNCHER_KEYBOARD_QUICK_SWITCH_OPEN);
}
});
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java
index 73819b3..d411ba6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java
@@ -16,6 +16,7 @@
package com.android.launcher3.taskbar;
import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.view.KeyEvent;
import android.view.animation.AnimationUtils;
import android.window.RemoteTransition;
@@ -23,6 +24,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.internal.jank.Cuj;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext;
@@ -30,6 +32,7 @@
import com.android.quickstep.util.SlideInRemoteTransition;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
+import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
import com.android.systemui.shared.system.QuickStepContract;
import java.io.PrintWriter;
@@ -93,18 +96,28 @@
protected void closeQuickSwitchView(boolean animate) {
if (isCloseAnimationRunning()) {
- // Let currently-running animation finish.
if (!animate) {
mCloseAnimation.end();
}
+ // Let currently-running animation finish.
return;
}
if (!animate) {
+ InteractionJankMonitorWrapper.begin(
+ mKeyboardQuickSwitchView, Cuj.CUJ_LAUNCHER_KEYBOARD_QUICK_SWITCH_CLOSE);
onCloseComplete();
return;
}
mCloseAnimation = mKeyboardQuickSwitchView.getCloseAnimation();
+ mCloseAnimation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ super.onAnimationStart(animation);
+ InteractionJankMonitorWrapper.begin(
+ mKeyboardQuickSwitchView, Cuj.CUJ_LAUNCHER_KEYBOARD_QUICK_SWITCH_CLOSE);
+ }
+ });
mCloseAnimation.addListener(AnimatorListeners.forEndCallback(this::onCloseComplete));
mCloseAnimation.start();
}
@@ -142,16 +155,26 @@
return -1;
}
+ Runnable onStartCallback = () -> InteractionJankMonitorWrapper.begin(
+ mKeyboardQuickSwitchView, Cuj.CUJ_LAUNCHER_KEYBOARD_QUICK_SWITCH_APP_LAUNCH);
+ Runnable onFinishCallback = () -> InteractionJankMonitorWrapper.end(
+ Cuj.CUJ_LAUNCHER_KEYBOARD_QUICK_SWITCH_APP_LAUNCH);
TaskbarActivityContext context = mControllers.taskbarActivityContext;
RemoteTransition remoteTransition = new RemoteTransition(new SlideInRemoteTransition(
Utilities.isRtl(mControllers.taskbarActivityContext.getResources()),
context.getDeviceProfile().overviewPageSpacing,
QuickStepContract.getWindowCornerRadius(context),
AnimationUtils.loadInterpolator(
- context, android.R.interpolator.fast_out_extra_slow_in)),
+ context, android.R.interpolator.fast_out_extra_slow_in),
+ onStartCallback,
+ onFinishCallback),
"SlideInTransition");
mControllers.taskbarActivityContext.handleGroupTaskLaunch(
- task, remoteTransition, mOnDesktop);
+ task,
+ remoteTransition,
+ mOnDesktop,
+ onStartCallback,
+ onFinishCallback);
return -1;
}
@@ -159,6 +182,7 @@
mCloseAnimation = null;
mOverlayContext.getDragLayer().removeView(mKeyboardQuickSwitchView);
mControllerCallbacks.onCloseComplete();
+ InteractionJankMonitorWrapper.end(Cuj.CUJ_LAUNCHER_KEYBOARD_QUICK_SWITCH_CLOSE);
}
protected void onDestroy() {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 0f17a85..6d54abd 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -1226,22 +1226,44 @@
}
}
+ public void handleGroupTaskLaunch(
+ GroupTask task,
+ @Nullable RemoteTransition remoteTransition,
+ boolean onDesktop) {
+ handleGroupTaskLaunch(task, remoteTransition, onDesktop, null, null);
+ }
+
/**
* Launches the given GroupTask with the following behavior:
* - If the GroupTask is a DesktopTask, launch the tasks in that Desktop.
* - If {@code onDesktop}, bring the given GroupTask to the front.
* - If the GroupTask is a single task, launch it via startActivityFromRecents.
* - Otherwise, we assume the GroupTask is a Split pair and launch them together.
+ * <p>
+ * Given start and/or finish callbacks, they will be run before an after the app launch
+ * respectively in cases where we can't use the remote transition, otherwise we will assume that
+ * these callbacks are included in the remote transition.
*/
- public void handleGroupTaskLaunch(GroupTask task, @Nullable RemoteTransition remoteTransition,
- boolean onDesktop) {
+ public void handleGroupTaskLaunch(
+ GroupTask task,
+ @Nullable RemoteTransition remoteTransition,
+ boolean onDesktop,
+ @Nullable Runnable onStartCallback,
+ @Nullable Runnable onFinishCallback) {
if (task instanceof DesktopTask) {
UI_HELPER_EXECUTOR.execute(() ->
SystemUiProxy.INSTANCE.get(this).showDesktopApps(getDisplay().getDisplayId(),
remoteTransition));
} else if (onDesktop) {
- UI_HELPER_EXECUTOR.execute(() ->
- SystemUiProxy.INSTANCE.get(this).showDesktopApp(task.task1.key.id));
+ UI_HELPER_EXECUTOR.execute(() -> {
+ if (onStartCallback != null) {
+ onStartCallback.run();
+ }
+ SystemUiProxy.INSTANCE.get(this).showDesktopApp(task.task1.key.id);
+ if (onFinishCallback != null) {
+ onFinishCallback.run();
+ }
+ });
} else if (task.task2 == null) {
UI_HELPER_EXECUTOR.execute(() -> {
ActivityOptions activityOptions =
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
index ad81509..0f9de16 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
@@ -400,7 +400,7 @@
addedBubble.getView().setOnClickListener(mBubbleClickListener);
mBubbleDragController.setupBubbleView(addedBubble.getView());
if (!suppressAnimation) {
- animateBubbleNotification(addedBubble, isExpanding, /* isUpdate= */ true);
+ animateBubbleNotification(addedBubble, isExpanding, /* isUpdate= */ false);
}
}
@@ -428,7 +428,7 @@
}
return;
}
- animateBubbleNotification(bubble, isExpanding, /* isUpdate= */ true);
+ animateBubbleNotification(bubble, isExpanding, /* isUpdate= */ false);
} else {
Log.w(TAG, "addBubble, bubble was null!");
}
diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
index 1048ea1..b564fa7 100644
--- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
@@ -212,6 +212,9 @@
if (launcher.isStarted() && (isInLiveTileMode() || launcher.hasBeenResumed())) {
return launcher;
}
+ if (isInMinusOne()) {
+ return launcher;
+ }
return null;
}
@@ -289,6 +292,15 @@
&& TopTaskTracker.INSTANCE.get(launcher).getCachedTopTask(false).isHomeTask();
}
+ private boolean isInMinusOne() {
+ QuickstepLauncher launcher = getCreatedContainer();
+
+ return launcher != null
+ && launcher.getStateManager().getState() == NORMAL
+ && !launcher.isStarted()
+ && TopTaskTracker.INSTANCE.get(launcher).getCachedTopTask(false).isHomeTask();
+ }
+
@Override
public void onLaunchTaskFailed() {
QuickstepLauncher launcher = getCreatedContainer();
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index 0d450c6..13b6447 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -70,6 +70,9 @@
*/
public class OtherActivityInputConsumer extends ContextWrapper implements InputConsumer {
+ private static final String TAG = "OtherActivityInputConsumer";
+ private static final boolean DEBUG = true;
+
public static final String DOWN_EVT = "OtherActivityInputConsumer.DOWN";
private static final String UP_EVT = "OtherActivityInputConsumer.UP";
@@ -230,6 +233,9 @@
// Start the window animation on down to give more time for launcher to draw if the
// user didn't start the gesture over the back button
+ if (DEBUG) {
+ Log.d(TAG, "ACTION_DOWN: mIsDeferredDownTarget=" + mIsDeferredDownTarget);
+ }
if (!mIsDeferredDownTarget) {
startTouchTrackingForWindowAnimation(ev.getEventTime());
}
@@ -284,9 +290,18 @@
float horizontalDist = Math.abs(displacementX);
float upDist = -displacement;
- boolean passedSlop = mGestureState.isTrackpadGesture()
- || (squaredHypot(displacementX, displacementY) >= mSquaredTouchSlop
- && !mGestureState.isInExtendedSlopRegion());
+ boolean isTrackpadGesture = mGestureState.isTrackpadGesture();
+ float squaredHypot = squaredHypot(displacementX, displacementY);
+ boolean isInExtendedSlopRegion = !mGestureState.isInExtendedSlopRegion();
+ boolean passedSlop = isTrackpadGesture
+ || (squaredHypot >= mSquaredTouchSlop
+ && isInExtendedSlopRegion);
+ if (DEBUG) {
+ Log.d(TAG, "ACTION_MOVE: passedSlop=" + passedSlop
+ + " ( " + isTrackpadGesture
+ + " || (" + squaredHypot + " >= " + mSquaredTouchSlop
+ + " && " + isInExtendedSlopRegion + " ))");
+ }
if (!mPassedSlopOnThisGesture && passedSlop) {
mPassedSlopOnThisGesture = true;
@@ -306,6 +321,9 @@
boolean isLikelyToStartNewTask =
haveNotPassedSlopOnContinuedGesture || swipeWithinQuickSwitchRange;
+ if (DEBUG) {
+ Log.d(TAG, "ACTION_MOVE: mPassedPilferInputSlop=" + mPassedPilferInputSlop);
+ }
if (!mPassedPilferInputSlop) {
if (passedSlop) {
// Horizontal gesture is not allowed in this region
@@ -394,6 +412,10 @@
mInteractionHandler.initWhenReady(
"OtherActivityInputConsumer.startTouchTrackingForWindowAnimation");
+ if (DEBUG) {
+ Log.d(TAG, "startTouchTrackingForWindowAnimation: isRecentsAnimationRunning="
+ + mTaskAnimationManager.isRecentsAnimationRunning());
+ }
if (mTaskAnimationManager.isRecentsAnimationRunning()) {
mActiveCallbacks = mTaskAnimationManager.continueRecentsAnimation(mGestureState);
mActiveCallbacks.removeListener(mCleanupHandler);
@@ -422,6 +444,11 @@
*/
private void finishTouchTracking(MotionEvent ev) {
TraceHelper.INSTANCE.beginSection(UP_EVT);
+ if (DEBUG) {
+ Log.d(TAG, "finishTouchTracking: mPassedWindowMoveSlop=" + mPassedWindowMoveSlop);
+ Log.d(TAG, "finishTouchTracking: mInteractionHandler=" + mInteractionHandler);
+ Log.d(TAG, "finishTouchTracking: ev=" + ev);
+ }
boolean isCanceled = ev.getActionMasked() == ACTION_CANCEL;
if (mPassedWindowMoveSlop && mInteractionHandler != null) {
@@ -444,7 +471,14 @@
// Since we start touch tracking on DOWN, we may reach this state without actually
// starting the gesture. In that case, we need to clean-up an unfinished or un-started
// animation.
+ if (DEBUG) {
+ Log.d(TAG, "finishTouchTracking: mActiveCallbacks=" + mActiveCallbacks);
+ }
if (mActiveCallbacks != null && mInteractionHandler != null) {
+ if (DEBUG) {
+ Log.d(TAG, "finishTouchTracking: isRecentsAnimationRunning="
+ + mTaskAnimationManager.isRecentsAnimationRunning());
+ }
if (mTaskAnimationManager.isRecentsAnimationRunning()) {
// The animation started, but with no movement, in this case, there will be no
// animateToProgress so we have to manually finish here. In the case of
@@ -535,7 +569,13 @@
public void onRecentsAnimationStart(RecentsAnimationController controller,
RecentsAnimationTargets targets) {
+ if (DEBUG) {
+ Log.d(TAG, "FinishImmediatelyHandler: queuing callback");
+ }
Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
+ if (DEBUG) {
+ Log.d(TAG, "FinishImmediatelyHandler: running callback");
+ }
controller.finish(false /* toRecents */, null);
});
}
diff --git a/quickstep/src/com/android/quickstep/util/SlideInRemoteTransition.kt b/quickstep/src/com/android/quickstep/util/SlideInRemoteTransition.kt
index dbeedd3..ece9583 100644
--- a/quickstep/src/com/android/quickstep/util/SlideInRemoteTransition.kt
+++ b/quickstep/src/com/android/quickstep/util/SlideInRemoteTransition.kt
@@ -36,6 +36,8 @@
private val pageSpacing: Int,
private val cornerRadius: Float,
private val interpolator: TimeInterpolator,
+ private val onStartCallback: Runnable,
+ private val onFinishCallback: Runnable,
) : RemoteTransitionStub() {
private val animationDurationMs = 500L
@@ -68,6 +70,7 @@
startT.setCrop(leash, chg.endAbsBounds).setCornerRadius(leash, cornerRadius)
}
}
+ onStartCallback.run()
startT.apply()
anim.addUpdateListener {
@@ -97,6 +100,7 @@
val t = Transaction()
try {
finishCB.onTransitionFinished(null, t)
+ onFinishCallback.run()
} catch (e: RemoteException) {
// Ignore
}
diff --git a/res/drawable/work_card.xml b/res/drawable/work_card.xml
index 4a66cac..9bf2b8d 100644
--- a/res/drawable/work_card.xml
+++ b/res/drawable/work_card.xml
@@ -16,9 +16,8 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:shape="rectangle">
- <solid android:color="?androidprv:attr/colorSurface" />
+ <solid android:color="@color/material_color_surface_container_highest" />
<corners android:radius="@dimen/work_edu_card_radius" />
</shape>
diff --git a/tests/src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java b/tests/src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java
index 405dae7..46cafa7 100644
--- a/tests/src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java
+++ b/tests/src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java
@@ -177,8 +177,6 @@
*/
@Test
@PortraitLandscape
- @ScreenRecordRule.ScreenRecord // b/338869019
- @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/338869019
public void testAddDeleteShortcutOnHotseat() {
mLauncher.getWorkspace()
.deleteAppIcon(mLauncher.getWorkspace().getHotseatAppIcon(0))