Merge "Import translations. DO NOT MERGE ANYWHERE" into main
diff --git a/aconfig/launcher.aconfig b/aconfig/launcher.aconfig
index 4ff976d..bc49146 100644
--- a/aconfig/launcher.aconfig
+++ b/aconfig/launcher.aconfig
@@ -536,4 +536,11 @@
namespace: "launcher"
description: "Add options to pin/unpin to taskbar to app context menus."
bug: "375648361"
+}
+
+flag {
+ name: "enable_launcher_icon_shapes"
+ namespace: "launcher"
+ description: "Enable launcher icon shape customizations"
+ bug: "348708061"
}
\ No newline at end of file
diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml
index f3c9467..e8c8505 100644
--- a/quickstep/res/values/config.xml
+++ b/quickstep/res/values/config.xml
@@ -35,7 +35,6 @@
<string name="launcher_restore_event_logger_class" translatable="false">com.android.quickstep.LauncherRestoreEventLoggerImpl</string>
<string name="taskbar_edu_tooltip_controller_class" translatable="false">com.android.launcher3.taskbar.TaskbarEduTooltipController</string>
<string name="nav_handle_long_press_handler_class" translatable="false"></string>
- <string name="contextual_search_invoker_class" translatable="false"></string>
<string name="contextual_search_state_manager_class" translatable="false"></string>
<!-- The number of thumbnails and icons to keep in the cache. The thumbnail cache size also
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 7d193aa..2759816 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -1567,7 +1567,8 @@
private boolean isFreeformAnimation(RemoteAnimationTarget[] appTargets) {
return DesktopModeStatus.canEnterDesktopMode(mLauncher.getApplicationContext())
- && DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS.isTrue()
+ && (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS.isTrue()
+ || DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS_BUGFIX.isTrue())
&& Arrays.stream(appTargets)
.anyMatch(app -> app.taskInfo != null && app.taskInfo.isFreeform());
}
diff --git a/quickstep/src/com/android/launcher3/desktop/DesktopAppLaunchTransitionManager.kt b/quickstep/src/com/android/launcher3/desktop/DesktopAppLaunchTransitionManager.kt
index e32bcd1..645bef6 100644
--- a/quickstep/src/com/android/launcher3/desktop/DesktopAppLaunchTransitionManager.kt
+++ b/quickstep/src/com/android/launcher3/desktop/DesktopAppLaunchTransitionManager.kt
@@ -67,7 +67,8 @@
private fun shouldRegisterTransitions(): Boolean =
DesktopModeStatus.canEnterDesktopMode(context) &&
- DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS.isTrue
+ (DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS.isTrue ||
+ DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX.isTrue)
companion object {
private fun buildAppLaunchFilter(): TransitionFilter {
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index c5be13d..f0129b4 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -18,8 +18,8 @@
import static android.window.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY;
import static com.android.launcher3.QuickstepTransitionManager.TASKBAR_TO_APP_DURATION;
-import static com.android.launcher3.QuickstepTransitionManager.getTaskbarToHomeDuration;
import static com.android.launcher3.QuickstepTransitionManager.TRANSIENT_TASKBAR_TRANSITION_DURATION;
+import static com.android.launcher3.QuickstepTransitionManager.getTaskbarToHomeDuration;
import static com.android.launcher3.statemanager.BaseState.FLAG_NON_INTERACTIVE;
import static com.android.launcher3.taskbar.TaskbarEduTooltipControllerKt.TOOLTIP_STEP_FEATURES;
import static com.android.launcher3.taskbar.TaskbarLauncherStateController.FLAG_VISIBLE;
@@ -275,7 +275,8 @@
if (mControllers.bubbleControllers.isEmpty() || hotseat == null) return;
boolean hiddenForBubbles =
mControllers.bubbleControllers.get().bubbleBarViewController.isHiddenForNoBubbles();
- hotseat.post(() -> adjustHotseatForBubbleBar(!hiddenForBubbles));
+ if (hiddenForBubbles) return;
+ hotseat.post(() -> adjustHotseatForBubbleBar(/* isBubbleBarVisible= */ true));
}
/**
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index f346e19..cb4e5e2 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -1314,7 +1314,8 @@
// If the task bar is not start aligned, the navigation bar is located in the center
// between the taskbar and screen edges, depending on the bubble bar location.
float navbarWidth = mNavButtonContainer.getWidth();
- Rect taskbarBounds = mControllers.taskbarViewController.getIconLayoutBounds();
+ Rect taskbarBounds = mControllers.taskbarViewController
+ .getTransientTaskbarIconLayoutBoundsInParent();
if (isNavbarOnRight) {
if (mNavButtonsView.isLayoutRtl()) {
float taskBarEnd = taskbarBounds.right;
@@ -1334,8 +1335,10 @@
public void onLayoutsUpdated() {
// no need to do anything if on phone, or if taskbar or navbar views were not placed on
// screen.
+ Rect transientTaskbarIconLayoutBoundsInParent = mControllers.taskbarViewController
+ .getTransientTaskbarIconLayoutBoundsInParent();
if (mContext.getDeviceProfile().isPhone
- || mControllers.taskbarViewController.getIconLayoutBounds().isEmpty()
+ || transientTaskbarIconLayoutBoundsInParent.isEmpty()
|| mNavButtonsView.getWidth() == 0) {
return;
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
index eb47bb0..b6b090c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
@@ -212,7 +212,8 @@
* morphs into the size of where the taskbar icons will be.
*/
public Animator createRevealAnimToIsStashed(boolean isStashed) {
- Rect visualBounds = mControllers.taskbarViewController.getIconLayoutVisualBounds();
+ Rect visualBounds = mControllers.taskbarViewController
+ .getTransientTaskbarIconLayoutBounds();
float startRadius = mStashedHandleRadius;
if (DisplayController.isTransientTaskbar(mActivity)) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 8149f81..0f639f9 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -301,7 +301,8 @@
BubbleStashController bubbleStashController = isTransientTaskbar
? new TransientBubbleStashController(dimensionsProvider, this)
: new PersistentBubbleStashController(dimensionsProvider);
- bubbleStashController.setHotseatVerticalCenter(launcherDp.getHotseatVerticalCenter());
+ bubbleStashController.setBubbleBarVerticalCenterForHome(
+ launcherDp.getBubbleBarVerticalCenterForHome());
bubbleControllersOptional = Optional.of(new BubbleControllers(
new BubbleBarController(this, bubbleBarView),
new BubbleBarViewController(this, bubbleBarView, bubbleBarContainer),
@@ -369,8 +370,9 @@
applyDeviceProfile(launcherDp);
mControllers.taskbarOverlayController.updateLauncherDeviceProfile(launcherDp);
mControllers.bubbleControllers.ifPresent(bubbleControllers -> {
- int hotseatVertCenter = launcherDp.getHotseatVerticalCenter();
- bubbleControllers.bubbleStashController.setHotseatVerticalCenter(hotseatVertCenter);
+ int bubbleBarVerticalCenter = launcherDp.getBubbleBarVerticalCenterForHome();
+ bubbleControllers.bubbleStashController
+ .setBubbleBarVerticalCenterForHome(bubbleBarVerticalCenter);
});
AbstractFloatingView.closeAllOpenViewsExcept(this, false, TYPE_REBIND_SAFE);
// Reapply fullscreen to take potential new screen size into account.
@@ -867,7 +869,8 @@
}
private ActivityOptionsWrapper getActivityLaunchDesktopOptions(ItemInfo info) {
- if (!DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS.isTrue()) {
+ if (!DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS.isTrue()
+ && !DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX.isTrue()) {
return null;
}
if (!areDesktopTasksVisible()) {
@@ -1136,6 +1139,10 @@
return getSetupWindowSize();
}
+ int bubbleBarTop = mControllers.bubbleControllers.map(bubbleControllers ->
+ bubbleControllers.bubbleBarViewController.getBubbleBarWithFlyoutMaximumHeight()
+ ).orElse(0);
+ int taskbarWindowSize;
boolean shouldTreatAsTransient = DisplayController.isTransientTaskbar(this)
|| (enableTaskbarPinning() && !isThreeButtonNav());
@@ -1152,16 +1159,18 @@
DeviceProfile transientTaskbarDp = mDeviceProfile.toBuilder(this)
.setIsTransientTaskbar(true).build();
- return transientTaskbarDp.taskbarHeight
+ taskbarWindowSize = transientTaskbarDp.taskbarHeight
+ (2 * transientTaskbarDp.taskbarBottomMargin)
+ Math.max(extraHeightForTaskbarTooltips, resources.getDimensionPixelSize(
R.dimen.transient_taskbar_shadow_blur));
+ return Math.max(taskbarWindowSize, bubbleBarTop);
}
- return mDeviceProfile.taskbarHeight
+ taskbarWindowSize = mDeviceProfile.taskbarHeight
+ getCornerRadius()
+ extraHeightForTaskbarTooltips;
+ return Math.max(taskbarWindowSize, bubbleBarTop);
}
public int getSetupWindowSize() {
@@ -1429,7 +1438,9 @@
BubbleTextView.RunningAppState runningAppState =
mControllers.taskbarRecentAppsController.getRunningAppState(taskId);
return runningAppState == BubbleTextView.RunningAppState.MINIMIZED
- && DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_ALTTAB_TRANSITIONS.isTrue();
+ && (DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_ALTTAB_TRANSITIONS.isTrue()
+ || DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_ALTTAB_TRANSITIONS_BUGFIX.isTrue()
+ );
}
private RemoteTransition createUnminimizeRemoteTransition() {
@@ -1634,15 +1645,6 @@
mControllers.taskbarEduTooltipController.hide();
}
- /**
- * Called when we want to open bubblebar when user performs swipes up gesture.
- */
- public void onSwipeToOpenBubblebar() {
- mControllers.bubbleControllers.ifPresent(controllers -> {
- controllers.bubbleStashController.showBubbleBar(/* expandBubbles= */ true);
- });
- }
-
/** Returns {@code true} if Taskbar All Apps is open. */
public boolean isTaskbarAllAppsOpen() {
return mControllers.taskbarAllAppsController.isOpen();
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
index db70724..826722d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
@@ -227,7 +227,9 @@
bubbleControllers.bubbleBarViewController.getBubbleBarLocation();
boolean hiddenForBubbles =
bubbleControllers.bubbleBarViewController.isHiddenForNoBubbles();
- uiController.adjustHotseatForBubbleBar(!hiddenForBubbles);
+ if (!hiddenForBubbles) {
+ uiController.adjustHotseatForBubbleBar(/* isBubbleBarVisible= */ true);
+ }
uiController.onBubbleBarLocationUpdated(location);
}, () -> uiController.onBubbleBarLocationUpdated(null));
// Notify that the ui controller has changed
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
index a89bc3a..26a552e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
@@ -83,7 +83,7 @@
protected val activityContext: TaskbarActivityContext = ActivityContext.lookupContext(context)
open val shouldShowSearchEdu: Boolean
get() =
- ContextualSearchInvoker.newInstance(activityContext)
+ ContextualSearchInvoker(activityContext)
.runContextualSearchInvocationChecksAndLogFailures()
private val isTooltipEnabled: Boolean
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index 4498fea..ff8e4a8 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -261,7 +261,7 @@
SystemUiProxy.INSTANCE.get(mContext),
ContextualEduStatsManager.INSTANCE.get(mContext),
new Handler(),
- ContextualSearchInvoker.newInstance(mContext));
+ new ContextualSearchInvoker(mContext));
mDefaultComponentCallbacks = new ComponentCallbacks() {
private Configuration mOldConfig = mContext.getResources().getConfiguration();
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index ad1a44d..130b9b7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -764,7 +764,7 @@
) {
return 0;
}
- Rect iconsBounds = getIconLayoutBounds();
+ Rect iconsBounds = getTransientTaskbarIconLayoutBoundsInParent();
return getTaskBarIconsEndForBubbleBarLocation(location) - iconsBounds.right;
}
@@ -892,26 +892,46 @@
}
/**
- * Returns whether the given MotionEvent, *in screen coorindates*, is within any Taskbar item's
+ * Returns whether the given MotionEvent, *in screen coordinates*, is within any Taskbar item's
* touch bounds.
*/
public boolean isEventOverAnyItem(MotionEvent ev) {
getLocationOnScreen(mTempOutLocation);
- int xInOurCoordinates = (int) ev.getX() - mTempOutLocation[0];
- int yInOurCoorindates = (int) ev.getY() - mTempOutLocation[1];
- return isShown() && mIconLayoutBounds.contains(xInOurCoordinates, yInOurCoorindates);
+ int xInOurCoordinates = (int) ev.getRawX() - mTempOutLocation[0];
+ int yInOurCoordinates = (int) ev.getRawY() - mTempOutLocation[1];
+ return isShown() && getTaskbarIconsActualBounds().contains(xInOurCoordinates,
+ yInOurCoordinates);
+ }
+
+ /**
+ * Returns the current visual taskbar icons bounds (unlike `mIconLayoutBounds` which contains
+ * bounds for transient mode only).
+ */
+ private Rect getTaskbarIconsActualBounds() {
+ View[] iconViews = getIconViews();
+ if (iconViews.length == 0) {
+ return new Rect();
+ }
+
+ int[] firstIconViewLocation = new int[2];
+ int[] lastIconViewLocation = new int[2];
+ iconViews[0].getLocationOnScreen(firstIconViewLocation);
+ iconViews[iconViews.length - 1].getLocationOnScreen(lastIconViewLocation);
+
+ return new Rect(firstIconViewLocation[0], 0, lastIconViewLocation[0] + mIconTouchSize,
+ getHeight());
}
/**
* Gets visual bounds of the taskbar view. The visual bounds correspond to the taskbar touch
* area, rather than layout placement in the parent view.
*/
- public Rect getIconLayoutVisualBounds() {
+ public Rect getTransientTaskbarIconLayoutBounds() {
return new Rect(mIconLayoutBounds);
}
/** Gets taskbar layout bounds in parent view. */
- public Rect getIconLayoutBounds() {
+ public Rect getTransientTaskbarIconLayoutBoundsInParent() {
Rect actualBounds = new Rect(mIconLayoutBounds);
actualBounds.top = getTop();
actualBounds.bottom = getBottom();
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
index 604d32d..4d77ab2 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
@@ -203,6 +203,10 @@
private class TaskbarViewGestureListener extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onDown(@NonNull MotionEvent event) {
+ if (event.isFromSource(InputDevice.SOURCE_MOUSE)
+ && event.getButtonState() == MotionEvent.BUTTON_SECONDARY) {
+ maybeShowPinningView(event);
+ }
return true;
}
@@ -212,11 +216,16 @@
}
@Override
- public void onLongPress(MotionEvent event) {
- if (DisplayController.isPinnedTaskbar(mActivity)) {
- mControllers.taskbarPinningController.showPinningView(mTaskbarView,
- event.getRawX());
+ public void onLongPress(@NonNull MotionEvent event) {
+ maybeShowPinningView(event);
+ }
+
+ private void maybeShowPinningView(@NonNull MotionEvent event) {
+ if (!DisplayController.isPinnedTaskbar(mActivity) || mTaskbarView.isEventOverAnyItem(
+ event)) {
+ return;
}
+ mControllers.taskbarPinningController.showPinningView(mTaskbarView, event.getRawX());
}
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacksFactory.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacksFactory.kt
index 704d6cf..17da533 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacksFactory.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacksFactory.kt
@@ -38,7 +38,7 @@
super.triggerAllAppsButtonLongClick()
val contextualSearchInvoked =
- ContextualSearchInvoker.newInstance(activity).show(ENTRYPOINT_LONG_PRESS_META)
+ ContextualSearchInvoker(activity).show(ENTRYPOINT_LONG_PRESS_META)
if (contextualSearchInvoked) {
val runningPackage =
TopTaskTracker.INSTANCE[activity].getCachedTopTask(
@@ -59,8 +59,7 @@
}
open fun longPressAllAppsToStartContextualSearch(context: Context): Boolean =
- ContextualSearchInvoker.newInstance(context)
- .runContextualSearchInvocationChecksAndLogFailures()
+ ContextualSearchInvoker(context).runContextualSearchInvocationChecksAndLogFailures()
companion object {
@JvmStatic
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index bc5f9a3..4acf2fe 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -356,12 +356,12 @@
return mTaskbarView.getMaxNumIconViews();
}
- public Rect getIconLayoutVisualBounds() {
- return mTaskbarView.getIconLayoutVisualBounds();
+ public Rect getTransientTaskbarIconLayoutBounds() {
+ return mTaskbarView.getTransientTaskbarIconLayoutBounds();
}
- public Rect getIconLayoutBounds() {
- return mTaskbarView.getIconLayoutBounds();
+ public Rect getTransientTaskbarIconLayoutBoundsInParent() {
+ return mTaskbarView.getTransientTaskbarIconLayoutBoundsInParent();
}
public View[] getIconViews() {
@@ -559,14 +559,14 @@
if (mControllers.getSharedState().startTaskbarVariantIsTransient) {
float transY =
mTransientTaskbarDp.taskbarBottomMargin + (mTransientTaskbarDp.taskbarHeight
- - mTaskbarView.getIconLayoutVisualBounds().bottom)
+ - mTaskbarView.getTransientTaskbarIconLayoutBounds().bottom)
- (mPersistentTaskbarDp.taskbarHeight
- mTransientTaskbarDp.taskbarIconSize) / 2f;
taskbarIconTranslationYForPinningValue = mapRange(scale, 0f, transY);
} else {
float transY =
-mTransientTaskbarDp.taskbarBottomMargin + (mPersistentTaskbarDp.taskbarHeight
- - mTaskbarView.getIconLayoutVisualBounds().bottom)
+ - mTaskbarView.getTransientTaskbarIconLayoutBounds().bottom)
- (mTransientTaskbarDp.taskbarHeight
- mTransientTaskbarDp.taskbarIconSize) / 2f;
taskbarIconTranslationYForPinningValue = mapRange(scale, transY, 0f);
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarParentViewHeightUpdateNotifier.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarParentViewHeightUpdateNotifier.kt
new file mode 100644
index 0000000..f69ad74
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarParentViewHeightUpdateNotifier.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2024 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.bubbles
+
+/** Controls the parent view height. */
+interface BubbleBarParentViewHeightUpdateNotifier {
+
+ /** Notify parent that top boundary should be updated. */
+ fun updateTopBoundary()
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarSwipeController.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarSwipeController.kt
index 2d3642b..4b8924c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarSwipeController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarSwipeController.kt
@@ -91,7 +91,7 @@
when {
canUnstash() && swipeState.passedUnstash -> {
swipeState.currentState = COLLAPSED
- bubbleStashController.showBubbleBar(expandBubbles = false)
+ bubbleStashController.showBubbleBar(expandBubbles = false, bubbleBarGesture = true)
}
canStash() && !swipeState.passedUnstash -> {
swipeState.currentState = STASHED
@@ -103,7 +103,7 @@
/** Finish tracking swipe gesture. Animate views back to resting state */
fun finish() {
if (swipeState.passedUnstash && swipeState.startState in setOf(STASHED, COLLAPSED)) {
- bubbleStashController.showBubbleBar(expandBubbles = true)
+ bubbleStashController.showBubbleBar(expandBubbles = true, bubbleBarGesture = true)
}
if (animatedSwipeTranslation.value == 0f) {
reset()
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
index 833be61..219a2b3 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
@@ -381,6 +381,7 @@
super.onInitializeAccessibilityNodeInfoInternal(info);
// Always show only expand action as the menu is only for collapsed bubble bar
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_EXPAND);
+ info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK);
info.addAction(new AccessibilityNodeInfo.AccessibilityAction(R.id.action_dismiss_all,
getResources().getString(R.string.bubble_bar_action_dismiss_all)));
if (mBubbleBarLocation.isOnLeft(isLayoutRtl())) {
@@ -395,10 +396,8 @@
@Override
public boolean performAccessibilityActionInternal(int action,
@androidx.annotation.Nullable Bundle arguments) {
- if (super.performAccessibilityActionInternal(action, arguments)) {
- return true;
- }
- if (action == AccessibilityNodeInfo.ACTION_EXPAND) {
+ if (action == AccessibilityNodeInfo.ACTION_EXPAND
+ || action == AccessibilityNodeInfo.ACTION_CLICK) {
mController.expandBubbleBar();
return true;
}
@@ -416,7 +415,7 @@
BubbleBarLocation.UpdateSource.A11Y_ACTION_BAR);
return true;
}
- return false;
+ return super.performAccessibilityActionInternal(action, arguments);
}
@SuppressLint("RtlHardcoded")
@@ -1307,6 +1306,10 @@
return getBubbleBarCollapsedHeight() + mPointerSize;
}
+ float getArrowHeight() {
+ return mPointerSize;
+ }
+
float getBubbleBarCollapsedHeight() {
// the pointer is invisible when collapsed
return getScaledIconSize() + mBubbleBarPadding * 2;
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
index fd08078..1e0a778 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
@@ -95,7 +95,6 @@
private TaskbarInsetsController mTaskbarInsetsController;
private TaskbarViewPropertiesProvider mTaskbarViewPropertiesProvider;
private View.OnClickListener mBubbleClickListener;
- private View.OnClickListener mBubbleBarClickListener;
private BubbleView.Controller mBubbleViewController;
private BubbleBarOverflow mOverflowBubble;
@@ -171,20 +170,18 @@
mBubbleBarContainer, createFlyoutPositioner(), createFlyoutCallbacks());
mBubbleBarViewAnimator = new BubbleBarViewAnimator(
mBarView, mBubbleStashController, mBubbleBarFlyoutController,
- mBubbleBarController::showExpandedView);
+ createBubbleBarParentViewController(), mBubbleBarController::showExpandedView);
mTaskbarViewPropertiesProvider = taskbarViewPropertiesProvider;
onBubbleBarConfigurationChanged(/* animate= */ false);
mActivity.addOnDeviceProfileChangeListener(
dp -> onBubbleBarConfigurationChanged(/* animate= */ true));
mBubbleBarScaleY.updateValue(1f);
mBubbleClickListener = v -> onBubbleClicked((BubbleView) v);
- mBubbleBarClickListener = v -> expandBubbleBar();
mBubbleDragController.setupBubbleBarView(mBarView);
mOverflowBubble = bubbleControllers.bubbleCreator.createOverflow(mBarView);
if (!Flags.enableOptionalBubbleOverflow()) {
showOverflow(true);
}
- mBarView.setOnClickListener(mBubbleBarClickListener);
mBarView.addOnLayoutChangeListener(
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
mTaskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged();
@@ -211,7 +208,8 @@
@Override
public void expandBubbleBar() {
- BubbleBarViewController.this.expandBubbleBar();
+ BubbleBarViewController.this.setExpanded(
+ /* isExpanded= */ true, /* maybeShowEdu*/ true);
}
@Override
@@ -319,20 +317,18 @@
private FlyoutCallbacks createFlyoutCallbacks() {
return new FlyoutCallbacks() {
@Override
- public void extendTopBoundary(int space) {
- int defaultSize = mActivity.getDefaultTaskbarWindowSize();
- mActivity.setTaskbarWindowSize(defaultSize + space);
- }
-
- @Override
- public void resetTopBoundary() {
- mActivity.setTaskbarWindowSize(mActivity.getDefaultTaskbarWindowSize());
- }
-
- @Override
public void flyoutClicked() {
interruptAnimationForTouch();
- expandBubbleBar();
+ setExpanded(/* isExpanded= */ true, /* maybeShowEdu*/ true);
+ }
+ };
+ }
+
+ private BubbleBarParentViewHeightUpdateNotifier createBubbleBarParentViewController() {
+ return new BubbleBarParentViewHeightUpdateNotifier() {
+ @Override
+ public void updateTopBoundary() {
+ mActivity.setTaskbarWindowSize(mActivity.getDefaultTaskbarWindowSize());
}
};
}
@@ -360,25 +356,6 @@
mBubbleStashController.onNewBubbleAnimationInterrupted(false, mBarView.getTranslationY());
}
- private void expandBubbleBar() {
- if (mShouldShowEducation) {
- mShouldShowEducation = false;
- // Get the bubble bar bounds on screen
- Rect bounds = new Rect();
- mBarView.getBoundsOnScreen(bounds);
- // Calculate user education reference position in Screen coordinates
- Point position = new Point(bounds.centerX(), bounds.top);
- // Show user education relative to the reference point
- mSystemUiProxy.showUserEducation(position);
- } else {
- // ensure that the bubble bar has the correct translation. we may have just interrupted
- // the animation by touching the bubble bar.
- mBubbleBarTranslationY.animateToValue(mBubbleStashController.getBubbleBarTranslationY())
- .start();
- setExpanded(true);
- }
- }
-
private void collapseBubbleBar() {
setExpanded(false);
mBubbleStashController.stashBubbleBar();
@@ -391,6 +368,22 @@
}
}
+ /** Shows the education view if it was previously requested. */
+ private boolean maybeShowEduView() {
+ if (mShouldShowEducation) {
+ mShouldShowEducation = false;
+ // Get the bubble bar bounds on screen
+ Rect bounds = new Rect();
+ mBarView.getBoundsOnScreen(bounds);
+ // Calculate user education reference position in Screen coordinates
+ Point position = new Point(bounds.centerX(), bounds.top);
+ // Show user education relative to the reference point
+ mSystemUiProxy.showUserEducation(position);
+ return true;
+ }
+ return false;
+ }
+
/** Notifies that the IME became visible. */
public void onImeVisible() {
if (isAnimatingNewBubble()) {
@@ -447,6 +440,11 @@
return mBarView.getBubbleBarCollapsedHeight();
}
+ /** Returns the bubble bar arrow height.*/
+ public float getBubbleBarArrowHeight() {
+ return mBarView.getArrowHeight();
+ }
+
/**
* @see BubbleBarView#getRelativePivotX()
*/
@@ -580,6 +578,19 @@
return mHiddenForNoBubbles;
}
+ /** Returns maximum height of the bubble bar with the flyout view. */
+ public int getBubbleBarWithFlyoutMaximumHeight() {
+ if (!isBubbleBarVisible()) return 0;
+ int bubbleBarTopOnHome = (int) (mBubbleStashController.getBubbleBarVerticalCenterForHome()
+ + mBarView.getBubbleBarCollapsedHeight() / 2);
+ int result = (int) (bubbleBarTopOnHome + mBarView.getArrowHeight());
+ if (isAnimatingNewBubble()) {
+ // when animating new bubble add the maximum height of the flyout view
+ result += mBubbleBarFlyoutController.getMaximumFlyoutHeight();
+ }
+ return result;
+ }
+
/**
* Sets whether the bubble bar should be hidden because there are no bubbles.
*/
@@ -946,13 +957,25 @@
mBarView.setSelectedBubble(newlySelected.getView());
}
+ /** @see #setExpanded(boolean, boolean) */
+ public void setExpanded(boolean isExpanded) {
+ setExpanded(isExpanded, /* maybeShowEdu= */ false);
+ }
+
/**
* Sets whether the bubble bar should be expanded (not unstashed, but have the contents
* within it expanded). This method notifies SystemUI that the bubble bar is expanded and
* showing a selected bubble. This method should ONLY be called from UI events originating
* from Launcher.
+ *
+ * @param isExpanded whether the bar should be expanded
+ * @param maybeShowEdu whether we should show the edu view before expanding
*/
- public void setExpanded(boolean isExpanded) {
+ public void setExpanded(boolean isExpanded, boolean maybeShowEdu) {
+ // if we're trying to expand try showing the edu view instead
+ if (maybeShowEdu && isExpanded && !mBarView.isExpanded() && maybeShowEduView()) {
+ return;
+ }
if (!mBubbleBarPinning.isAnimating() && isExpanded != mBarView.isExpanded()) {
mBarView.setExpanded(isExpanded);
adjustTaskbarAndHotseatToBubbleBarState(isExpanded);
@@ -1012,7 +1035,11 @@
}
}
- /** Marks as should show education. */
+ /**
+ * Stores a request to show the education view for later processing when appropriate.
+ *
+ * @see #maybeShowEduView()
+ */
public void prepareToShowEducation() {
mShouldShowEducation = true;
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
index cb592e6..68917ff 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
@@ -102,7 +102,8 @@
new TaskbarViewPropertiesProvider() {
@Override
public Rect getTaskbarViewBounds() {
- return taskbarControllers.taskbarViewController.getIconLayoutBounds();
+ return taskbarControllers.taskbarViewController
+ .getTransientTaskbarIconLayoutBoundsInParent();
}
@Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt
index 447dad1..f5a6655 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt
@@ -25,6 +25,7 @@
import androidx.dynamicanimation.animation.SpringForce
import com.android.launcher3.R
import com.android.launcher3.taskbar.bubbles.BubbleBarBubble
+import com.android.launcher3.taskbar.bubbles.BubbleBarParentViewHeightUpdateNotifier
import com.android.launcher3.taskbar.bubbles.BubbleBarView
import com.android.launcher3.taskbar.bubbles.BubbleView
import com.android.launcher3.taskbar.bubbles.flyout.BubbleBarFlyoutController
@@ -39,6 +40,7 @@
private val bubbleBarView: BubbleBarView,
private val bubbleStashController: BubbleStashController,
private val bubbleBarFlyoutController: BubbleBarFlyoutController,
+ private val bubbleBarParentViewHeightUpdateNotifier: BubbleBarParentViewHeightUpdateNotifier,
private val onExpanded: Runnable,
private val scheduler: Scheduler = HandlerScheduler(bubbleBarView),
) {
@@ -342,7 +344,7 @@
scheduler.post(buildHandleToBubbleBarAnimation(initialVelocity = finalVelocity))
return@addEndListener
}
- animatingBubble = null
+ clearAnimatingBubble()
if (!canceled) bubbleStashController.stashBubbleBarImmediate()
bubbleBarView.relativePivotY = 1f
bubbleBarView.scaleY = 1f
@@ -378,7 +380,7 @@
moveToState(AnimatingBubble.State.ANIMATING_OUT)
bubbleBarFlyoutController.collapseFlyout {
onFlyoutRemoved()
- animatingBubble = null
+ clearAnimatingBubble()
}
bubbleStashController.showBubbleBarImmediate()
bubbleStashController.updateTaskbarTouchRegion()
@@ -437,7 +439,7 @@
moveToState(AnimatingBubble.State.ANIMATING_OUT)
bubbleBarFlyoutController.collapseFlyout {
onFlyoutRemoved()
- animatingBubble = null
+ clearAnimatingBubble()
}
bubbleStashController.showBubbleBarImmediate()
bubbleStashController.updateTaskbarTouchRegion()
@@ -515,7 +517,7 @@
val hideAnimation = animatingBubble?.hideAnimation ?: return
scheduler.cancel(hideAnimation)
bubbleBarView.relativePivotY = 1f
- animatingBubble = null
+ clearAnimatingBubble()
}
/** Notifies the animator that the taskbar area was touched during an animation. */
@@ -523,7 +525,7 @@
cancelFlyout()
val hideAnimation = animatingBubble?.hideAnimation ?: return
scheduler.cancel(hideAnimation)
- animatingBubble = null
+ clearAnimatingBubble()
bubbleStashController.getStashedHandlePhysicsAnimator().cancelIfRunning()
bubbleBarView.relativePivotY = 1f
bubbleStashController.onNewBubbleAnimationInterrupted(
@@ -672,7 +674,7 @@
private fun cancelHideAnimation() {
val hideAnimation = animatingBubble?.hideAnimation ?: return
scheduler.cancel(hideAnimation)
- animatingBubble = null
+ clearAnimatingBubble()
bubbleBarView.relativePivotY = 1f
bubbleStashController.showBubbleBarImmediate()
}
@@ -700,6 +702,14 @@
private fun moveToState(state: AnimatingBubble.State) {
val animatingBubble = this.animatingBubble ?: return
this.animatingBubble = animatingBubble.copy(state = state)
+ if (state == AnimatingBubble.State.ANIMATING_IN) {
+ bubbleBarParentViewHeightUpdateNotifier.updateTopBoundary()
+ }
+ }
+
+ private fun clearAnimatingBubble() {
+ animatingBubble = null
+ bubbleBarParentViewHeightUpdateNotifier.updateTopBoundary()
}
private fun expandBubbleBar() {
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutController.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutController.kt
index 908e97c..63db012 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutController.kt
@@ -35,6 +35,8 @@
private val flyoutScheduler: FlyoutScheduler = HandlerScheduler(container),
) {
+ val maximumFlyoutHeight: Int = BubbleBarFlyoutView.getMaximumViewHeight(container.context)
+
private companion object {
const val EXPAND_ANIMATION_DURATION_MS = 400L
const val COLLAPSE_ANIMATION_DURATION_MS = 350L
@@ -61,6 +63,8 @@
return rect
}
+ fun getFlyoutMaxHeight(): Int = BubbleBarFlyoutView.getMaximumViewHeight(container.context)
+
fun setUpAndShowFlyout(message: BubbleBarFlyoutMessage, onInit: () -> Unit, onEnd: () -> Unit) {
flyout?.let(container::removeView)
val flyout = BubbleBarFlyoutView(container.context, positioner, flyoutScheduler)
@@ -102,11 +106,10 @@
}
}
animator.addListener(
- onStart = { extendTopBoundary() },
onEnd = {
endAction()
flyout.setOnClickListener { callbacks.flyoutClicked() }
- },
+ }
)
animator.start()
}
@@ -114,14 +117,13 @@
fun updateFlyoutFullyExpanded(message: BubbleBarFlyoutMessage, onEnd: () -> Unit) {
val flyout = flyout ?: return
hideFlyout(AnimationType.FADE) {
- callbacks.resetTopBoundary()
flyout.updateData(message) { showFlyout(AnimationType.FADE, onEnd) }
}
}
fun updateFlyoutWhileExpanding(message: BubbleBarFlyoutMessage) {
val flyout = flyout ?: return
- flyout.updateData(message) { extendTopBoundary() }
+ flyout.updateData(message) {}
}
fun updateFlyoutWhileCollapsing(message: BubbleBarFlyoutMessage, onEnd: () -> Unit) {
@@ -131,14 +133,6 @@
flyout.updateData(message) { showFlyout(AnimationType.MORPH, onEnd) }
}
- private fun extendTopBoundary() {
- val flyout = flyout ?: return
- val flyoutTop = flyout.top + flyout.translationY
- // If the top position of the flyout is negative, then it's bleeding over the
- // top boundary of its parent view
- if (flyoutTop < 0) callbacks.extendTopBoundary(space = -flyoutTop.toInt())
- }
-
fun cancelFlyout(endAction: () -> Unit) {
hideFlyout(AnimationType.FADE) {
cleanupFlyoutView()
@@ -184,7 +178,6 @@
private fun cleanupFlyoutView() {
container.removeView(flyout)
this@BubbleBarFlyoutController.flyout = null
- callbacks.resetTopBoundary()
}
fun hasFlyout() = flyout != null
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutView.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutView.kt
index 216f5e3..75bf937 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutView.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutView.kt
@@ -18,6 +18,7 @@
import android.content.Context
import android.content.res.Configuration
+import android.content.res.Resources
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Outline
@@ -44,11 +45,27 @@
scheduler: FlyoutScheduler? = null,
) : ConstraintLayout(context) {
- private companion object {
- // the minimum progress of the expansion animation before the content starts fading in.
- const val MIN_EXPANSION_PROGRESS_FOR_CONTENT_ALPHA = 0.75f
+ companion object {
// the rate multiple for the background color animation relative to the morph animation.
const val BACKGROUND_COLOR_CHANGE_RATE = 5
+ // the minimum progress of the expansion animation before the content starts fading in.
+ private const val MIN_EXPANSION_PROGRESS_FOR_CONTENT_ALPHA = 0.75f
+
+ private const val TEXT_ROW_HEIGHT_SP = 20
+ private const val MAX_ROWS_COUNT = 3
+
+ /** Returns the maximum possible height of the flyout view. */
+ fun getMaximumViewHeight(context: Context): Int {
+ val verticalPaddings = getFlyoutPadding(context) * 2
+ val textSizeSp = TEXT_ROW_HEIGHT_SP * MAX_ROWS_COUNT
+ val textSizePx = textSizeSp * Resources.getSystem().displayMetrics.scaledDensity
+ val triangleHeight =
+ context.resources.getDimensionPixelSize(R.dimen.bubblebar_flyout_triangle_height)
+ return verticalPaddings + textSizePx.toInt() + triangleHeight
+ }
+
+ private fun getFlyoutPadding(context: Context) =
+ context.resources.getDimensionPixelSize(R.dimen.bubblebar_flyout_padding)
}
private val scheduler: FlyoutScheduler = scheduler ?: HandlerScheduler(this)
@@ -61,10 +78,7 @@
private val message: TextView by
lazy(LazyThreadSafetyMode.NONE) { findViewById(R.id.bubble_flyout_text) }
- private val flyoutPadding by
- lazy(LazyThreadSafetyMode.NONE) {
- context.resources.getDimensionPixelSize(R.dimen.bubblebar_flyout_padding)
- }
+ private val flyoutPadding by lazy(LazyThreadSafetyMode.NONE) { getFlyoutPadding(context) }
private val triangleHeight by
lazy(LazyThreadSafetyMode.NONE) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/FlyoutCallbacks.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/FlyoutCallbacks.kt
index e2f010a..0804a62 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/FlyoutCallbacks.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/FlyoutCallbacks.kt
@@ -18,11 +18,6 @@
/** Callbacks that the flyout uses to notify of events. */
interface FlyoutCallbacks {
- /** Requests to extend the top boundary of the parent to fully include the flyout. */
- fun extendTopBoundary(space: Int)
-
- /** Resets the top boundary of the parent. */
- fun resetTopBoundary()
/** The flyout was clicked. */
fun flyoutClicked()
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/BubbleStashController.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/BubbleStashController.kt
index d9589bb..595dac3 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/BubbleStashController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/BubbleStashController.kt
@@ -74,6 +74,9 @@
val isBubblesShowingOnOverview: Boolean
get() = launcherState == BubbleLauncherState.OVERVIEW
+ /** Bubble bar vertical center for launcher home. */
+ var bubbleBarVerticalCenterForHome: Int
+
/** Updated when sysui locked state changes, when locked, bubble bar is not shown. */
var isSysuiLocked: Boolean
@@ -121,9 +124,6 @@
/** Set a bubble bar location */
fun setBubbleBarLocation(bubbleBarLocation: BubbleBarLocation)
- /** Set the hotseat vertical center that bubble bar will align with. */
- fun setHotseatVerticalCenter(hotseatVerticalCenter: Int)
-
/**
* Stashes the bubble bar (transform to the handle view), or just shrink width of the expanded
* bubble bar based on the controller implementation.
@@ -131,7 +131,17 @@
fun stashBubbleBar()
/** Shows the bubble bar, and expands bubbles depending on [expandBubbles]. */
- fun showBubbleBar(expandBubbles: Boolean)
+ fun showBubbleBar(expandBubbles: Boolean) {
+ showBubbleBar(expandBubbles = expandBubbles, bubbleBarGesture = false)
+ }
+
+ /**
+ * Shows the bubble bar, and expands bubbles depending on [expandBubbles].
+ *
+ * Set [bubbleBarGesture] to true if this request originates from a touch gesture on the bubble
+ * bar.
+ */
+ fun showBubbleBar(expandBubbles: Boolean, bubbleBarGesture: Boolean)
// TODO(b/354218264): Move to BubbleBarViewAnimator
/**
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/PersistentBubbleStashController.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/PersistentBubbleStashController.kt
index 45f5568..9d8c0ed 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/PersistentBubbleStashController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/PersistentBubbleStashController.kt
@@ -47,7 +47,7 @@
private lateinit var bubbleBarAlphaAnimator: MultiPropertyFactory<View>.MultiProperty
private lateinit var bubbleBarScaleAnimator: AnimatedFloat
private lateinit var controllersAfterInitAction: ControllersAfterInitAction
- private var hotseatVerticalCenter: Int = 0
+ override var bubbleBarVerticalCenterForHome: Int = 0
override var launcherState: BubbleLauncherState = BubbleLauncherState.IN_APP
set(state) {
@@ -97,7 +97,7 @@
override val bubbleBarTranslationYForHotseat: Float
get() {
val bubbleBarHeight = bubbleBarViewController.bubbleBarCollapsedHeight
- return -hotseatVerticalCenter + bubbleBarHeight / 2
+ return -bubbleBarVerticalCenterForHome + bubbleBarHeight / 2
}
override val bubbleBarTranslationY: Float
@@ -159,10 +159,6 @@
animatorSet.setDuration(BAR_STASH_DURATION).start()
}
- override fun setHotseatVerticalCenter(hotseatVerticalCenter: Int) {
- this.hotseatVerticalCenter = hotseatVerticalCenter
- }
-
override fun showBubbleBarImmediate() = showBubbleBarImmediate(bubbleBarTranslationY)
override fun showBubbleBarImmediate(bubbleBarTranslationY: Float) {
@@ -180,8 +176,8 @@
updateExpandedState(expand = false)
}
- override fun showBubbleBar(expandBubbles: Boolean) {
- updateExpandedState(expandBubbles)
+ override fun showBubbleBar(expandBubbles: Boolean, bubbleBarGesture: Boolean) {
+ updateExpandedState(expand = expandBubbles, bubbleBarGesture = bubbleBarGesture)
}
override fun stashBubbleBarImmediate() {
@@ -235,13 +231,14 @@
// no op since does not have a handle view
}
- private fun updateExpandedState(expand: Boolean) {
+ private fun updateExpandedState(expand: Boolean, bubbleBarGesture: Boolean = false) {
if (bubbleBarViewController.isHiddenForNoBubbles) {
// If there are no bubbles the bar is invisible, nothing to do here.
return
}
if (bubbleBarViewController.isExpanded != expand) {
- bubbleBarViewController.isExpanded = expand
+ val maybeShowEdu = expand && bubbleBarGesture
+ bubbleBarViewController.setExpanded(expand, maybeShowEdu)
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/TransientBubbleStashController.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/TransientBubbleStashController.kt
index 22d504f..df00696 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/TransientBubbleStashController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/TransientBubbleStashController.kt
@@ -78,7 +78,7 @@
context.resources.getDimensionPixelSize(R.dimen.bubblebar_stashed_size) / 2f
private var animator: AnimatorSet? = null
- private var hotseatVerticalCenter: Int = 0
+ override var bubbleBarVerticalCenterForHome: Int = 0
override var isStashed: Boolean = false
@VisibleForTesting set
@@ -124,7 +124,7 @@
override val bubbleBarTranslationYForHotseat: Float
get() {
val bubbleBarHeight = bubbleBarViewController.bubbleBarCollapsedHeight
- return -hotseatVerticalCenter + bubbleBarHeight / 2
+ return -bubbleBarVerticalCenterForHome + bubbleBarHeight / 2
}
override val bubbleBarTranslationYForTaskbar: Float =
@@ -182,10 +182,6 @@
.start()
}
- override fun setHotseatVerticalCenter(hotseatVerticalCenter: Int) {
- this.hotseatVerticalCenter = hotseatVerticalCenter
- }
-
override fun showBubbleBarImmediate() {
showBubbleBarImmediate(bubbleBarTranslationY)
}
@@ -250,8 +246,12 @@
updateStashedAndExpandedState(stash = true, expand = false)
}
- override fun showBubbleBar(expandBubbles: Boolean) {
- updateStashedAndExpandedState(stash = false, expandBubbles)
+ override fun showBubbleBar(expandBubbles: Boolean, bubbleBarGesture: Boolean) {
+ updateStashedAndExpandedState(
+ stash = false,
+ expand = expandBubbles,
+ bubbleBarGesture = bubbleBarGesture,
+ )
}
override fun getDiffBetweenHandleAndBarCenters(): Float {
@@ -481,7 +481,11 @@
}
@VisibleForTesting
- fun updateStashedAndExpandedState(stash: Boolean, expand: Boolean) {
+ fun updateStashedAndExpandedState(
+ stash: Boolean,
+ expand: Boolean,
+ bubbleBarGesture: Boolean = false,
+ ) {
if (bubbleBarViewController.isHiddenForNoBubbles) {
// If there are no bubbles the bar and handle are invisible, nothing to do here.
return
@@ -502,7 +506,8 @@
}
}
if (bubbleBarViewController.isExpanded != expand) {
- bubbleBarViewController.isExpanded = expand
+ val maybeShowEdu = expand && bubbleBarGesture
+ bubbleBarViewController.setExpanded(expand, maybeShowEdu)
}
}
diff --git a/quickstep/src/com/android/quickstep/OverviewComponentObserver.java b/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
index 1f6c671..3507937 100644
--- a/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
+++ b/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
@@ -87,10 +87,16 @@
mCurrentHomeIntent = createHomeIntent();
mMyHomeIntent = new Intent(mCurrentHomeIntent).setPackage(mContext.getPackageName());
ResolveInfo info = context.getPackageManager().resolveActivity(mMyHomeIntent, 0);
+ ActivityInfo myHomeActivityInfo = info == null ? null : info.activityInfo;
+ int myHomeConfigChanges = myHomeActivityInfo == null ? 0 : myHomeActivityInfo.configChanges;
ComponentName myHomeComponent =
- new ComponentName(context.getPackageName(), info.activityInfo.name);
- mMyHomeIntent.setComponent(myHomeComponent);
- mConfigChangesMap.append(myHomeComponent.hashCode(), info.activityInfo.configChanges);
+ myHomeActivityInfo == null
+ ? mMyHomeIntent.resolveActivity(context.getPackageManager())
+ : new ComponentName(context.getPackageName(), myHomeActivityInfo.name);
+ if (myHomeComponent != null) {
+ mMyHomeIntent.setComponent(myHomeComponent);
+ mConfigChangesMap.append(myHomeComponent.hashCode(), myHomeConfigChanges);
+ }
mSetupWizardPkg = context.getString(R.string.setup_wizard_pkg);
ComponentName fallbackComponent = new ComponentName(mContext, RecentsActivity.class);
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index 6c4c74c..59d4547 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -313,7 +313,7 @@
setBackToLauncherCallback(mBackToLauncherCallback, mBackToLauncherRunner);
setUnfoldAnimationListener(mUnfoldAnimationListener);
setDesktopTaskListener(mDesktopTaskListener);
- setAssistantOverridesRequested(ContextualSearchInvoker.newInstance(mContext)
+ setAssistantOverridesRequested(new ContextualSearchInvoker(mContext)
.getSysUiAssistOverrideInvocationTypes());
mStateChangeCallbacks.forEach(Runnable::run);
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 8edb16f..75e7c64 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -286,8 +286,7 @@
@Override
public void onAssistantOverrideInvoked(int invocationType) {
executeForTouchInteractionService(tis -> {
- if (!ContextualSearchInvoker.newInstance(tis)
- .tryStartAssistOverride(invocationType)) {
+ if (!new ContextualSearchInvoker(tis).tryStartAssistOverride(invocationType)) {
Log.w(TAG, "Failed to invoke Assist override");
}
});
@@ -524,7 +523,8 @@
}
protected void onOverviewTargetChange() {
- for (Runnable listener : mOnOverviewTargetChangeListeners) {
+ Set<Runnable> listeners = new HashSet<>(mOnOverviewTargetChangeListeners);
+ for (Runnable listener : listeners) {
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 e158975..86f9829 100644
--- a/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowManager.kt
+++ b/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowManager.kt
@@ -36,11 +36,13 @@
import com.android.launcher3.LauncherAnimationRunner
import com.android.launcher3.LauncherAnimationRunner.RemoteAnimationFactory
import com.android.launcher3.R
+import com.android.launcher3.compat.AccessibilityManagerCompat
import com.android.launcher3.statehandlers.DesktopVisibilityController
import com.android.launcher3.statemanager.StateManager
import com.android.launcher3.statemanager.StateManager.AtomicAnimationFactory
import com.android.launcher3.statemanager.StatefulContainer
import com.android.launcher3.taskbar.TaskbarUIController
+import com.android.launcher3.testing.shared.TestProtocol.OVERVIEW_STATE_ORDINAL
import com.android.launcher3.util.ContextTracker
import com.android.launcher3.util.DisplayController
import com.android.launcher3.util.RunnableList
@@ -355,6 +357,9 @@
if (state == HOME || state == BG_LAUNCHER) {
cleanupRecentsWindow()
}
+ if (state === DEFAULT) {
+ AccessibilityManagerCompat.sendStateEventToTest(baseContext, OVERVIEW_STATE_ORDINAL)
+ }
}
private fun getStateName(state: RecentsState?): String {
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/BubbleBarInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/BubbleBarInputConsumer.java
index 778c231..6b61298 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/BubbleBarInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/BubbleBarInputConsumer.java
@@ -114,7 +114,8 @@
if (isWithinTapTime && !swipeUpOnBubbleHandle && !mPassedTouchSlop
&& mStashedOrCollapsedOnDown) {
// Taps on the handle / collapsed state should open the bar
- mBubbleStashController.showBubbleBar(/* expandBubbles= */ true);
+ mBubbleStashController.showBubbleBar(
+ /* expandBubbles= */ true, /* bubbleBarGesture= */ true);
}
break;
}
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressHandler.java b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressHandler.java
index 155d095..107babd 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressHandler.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressHandler.java
@@ -62,7 +62,7 @@
mStatsLogManager = StatsLogManager.newInstance(context);
mVibratorWrapper = VibratorWrapper.INSTANCE.get(mContext);
mContextualSearchHapticManager = ContextualSearchHapticManager.INSTANCE.get(context);
- mContextualSearchInvoker = ContextualSearchInvoker.newInstance(mContext);
+ mContextualSearchInvoker = new ContextualSearchInvoker(mContext);
}
/** Creates NavHandleLongPressHandler as specified by overrides */
diff --git a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
index 3eba9c0..99c2c1c 100644
--- a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
@@ -195,7 +195,7 @@
LOTTIE_TERTIARY_COLOR_TOKEN, R.color.all_set_bg_tertiary),
getTheme());
- startBackgroundAnimation(getDP().isTablet);
+ setUpBackgroundAnimation(getDP().isTablet);
getIDP().addOnChangeListener(mOnIDPChangeListener);
}
@@ -220,7 +220,7 @@
Executors.UI_HELPER_EXECUTOR.execute(runnable);
}
- private void startBackgroundAnimation(boolean forTablet) {
+ private void setUpBackgroundAnimation(boolean forTablet) {
if (mVibrator == null) {
return;
}
@@ -264,7 +264,6 @@
};
}
mAnimatedBackground.addAnimatorListener(mBackgroundAnimatorListener);
- mAnimatedBackground.playAnimation();
}
private void setSetupUIVisible(boolean visible) {
diff --git a/quickstep/src/com/android/quickstep/util/ContextualSearchInvoker.kt b/quickstep/src/com/android/quickstep/util/ContextualSearchInvoker.kt
index bd454c0..3be8ea6 100644
--- a/quickstep/src/com/android/quickstep/util/ContextualSearchInvoker.kt
+++ b/quickstep/src/com/android/quickstep/util/ContextualSearchInvoker.kt
@@ -21,8 +21,8 @@
import android.app.contextualsearch.ContextualSearchManager.FEATURE_CONTEXTUAL_SEARCH
import android.content.Context
import android.util.Log
+import androidx.annotation.VisibleForTesting
import com.android.internal.app.AssistUtils
-import com.android.launcher3.R
import com.android.launcher3.logging.StatsLogManager
import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_LAUNCH_ASSISTANT_FAILED_SERVICE_ERROR
import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_LAUNCH_OMNI_ATTEMPTED_OVER_KEYGUARD
@@ -31,23 +31,26 @@
import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_LAUNCH_OMNI_FAILED_NOT_AVAILABLE
import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_LAUNCH_OMNI_FAILED_SETTING_DISABLED
import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_LAUNCH_OMNI_SUCCESSFUL_HOME
-import com.android.launcher3.util.ResourceBasedOverride
+import com.android.quickstep.BaseContainerInterface
import com.android.quickstep.DeviceConfigWrapper
+import com.android.quickstep.OverviewComponentObserver
+import com.android.quickstep.RecentsAnimationDeviceState
import com.android.quickstep.SystemUiProxy
import com.android.quickstep.TopTaskTracker
+import com.android.quickstep.views.RecentsView
import com.android.systemui.shared.system.QuickStepContract
/** Handles invocations and checks for Contextual Search. */
-open class ContextualSearchInvoker
+class ContextualSearchInvoker
internal constructor(
- protected val context: Context,
+ private val context: Context,
private val contextualSearchStateManager: ContextualSearchStateManager,
private val topTaskTracker: TopTaskTracker,
private val systemUiProxy: SystemUiProxy,
- protected val statsLogManager: StatsLogManager,
+ private val statsLogManager: StatsLogManager,
private val contextualSearchHapticManager: ContextualSearchHapticManager,
private val contextualSearchManager: ContextualSearchManager?,
-) : ResourceBasedOverride {
+) {
constructor(
context: Context
) : this(
@@ -61,7 +64,7 @@
)
/** @return Array of AssistUtils.INVOCATION_TYPE_* that we want to handle instead of SysUI. */
- open fun getSysUiAssistOverrideInvocationTypes(): IntArray {
+ fun getSysUiAssistOverrideInvocationTypes(): IntArray {
val overrideInvocationTypes = com.android.launcher3.util.IntArray()
if (context.packageManager.hasSystemFeature(FEATURE_CONTEXTUAL_SEARCH)) {
overrideInvocationTypes.add(AssistUtils.INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS)
@@ -183,7 +186,15 @@
if (contextualSearchManager == null) {
return false
}
- contextualSearchManager.startContextualSearch(entryPoint)
+ val recentsContainerInterface = getRecentsContainerInterface()
+ if (recentsContainerInterface?.isInLiveTileMode() == true) {
+ Log.i(TAG, "Contextual Search invocation attempted: live tile")
+ endLiveTileMode(recentsContainerInterface) {
+ contextualSearchManager.startContextualSearch(entryPoint)
+ }
+ } else {
+ contextualSearchManager.startContextualSearch(entryPoint)
+ }
return true
}
@@ -199,6 +210,42 @@
return systemUiProxy.lastSystemUiStateFlags and KEYGUARD_SHOWING_SYSUI_FLAGS != 0L
}
+ @VisibleForTesting
+ fun getRecentsContainerInterface(): BaseContainerInterface<*, *>? {
+ val rads = RecentsAnimationDeviceState(context)
+ val observer = OverviewComponentObserver(context, rads)
+ try {
+ return observer.containerInterface
+ } finally {
+ observer.onDestroy()
+ rads.destroy()
+ }
+ }
+
+ /**
+ * End the live tile mode.
+ *
+ * @param onCompleteRunnable Runnable to run when the live tile is paused. May run immediately.
+ */
+ private fun endLiveTileMode(
+ recentsContainerInterface: BaseContainerInterface<*, *>?,
+ onCompleteRunnable: Runnable,
+ ) {
+ val recentsViewContainer = recentsContainerInterface?.createdContainer
+ if (recentsViewContainer == null) {
+ onCompleteRunnable.run()
+ return
+ }
+ val recentsView: RecentsView<*, *> = recentsViewContainer.getOverviewPanel()
+ recentsView.switchToScreenshot {
+ recentsView.finishRecentsAnimation(
+ true, /* toRecents */
+ false, /* shouldPip */
+ onCompleteRunnable,
+ )
+ }
+ }
+
companion object {
private const val TAG = "ContextualSearchInvoker"
const val SHADE_EXPANDED_SYSUI_FLAGS =
@@ -208,14 +255,5 @@
(QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING or
QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING or
QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED)
-
- @JvmStatic
- fun newInstance(context: Context): ContextualSearchInvoker {
- return ResourceBasedOverride.Overrides.getObject(
- ContextualSearchInvoker::class.java,
- context,
- R.string.contextual_search_invoker_class,
- )
- }
}
}
diff --git a/quickstep/src/com/android/quickstep/util/ContextualSearchStateManager.java b/quickstep/src/com/android/quickstep/util/ContextualSearchStateManager.java
index 334ff06..f75d3b3 100644
--- a/quickstep/src/com/android/quickstep/util/ContextualSearchStateManager.java
+++ b/quickstep/src/com/android/quickstep/util/ContextualSearchStateManager.java
@@ -224,7 +224,7 @@
UI_HELPER_EXECUTOR.getHandler().postDelayed(
() -> {
boolean contextualSearchInvoked =
- ContextualSearchInvoker.newInstance(mContext).show(
+ new ContextualSearchInvoker(mContext).show(
ENTRYPOINT_SYSTEM_ACTION);
if (contextualSearchInvoked) {
String runningPackage =
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index ec169a8..6fc33dc 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -5322,12 +5322,12 @@
pendingAnimation.addEndListener(aBoolean -> {
mSplitSelectStateController.launchSplitTasks(
aBoolean1 -> {
+ InteractionJankMonitorWrapper.end(Cuj.CUJ_SPLIT_SCREEN_ENTER);
if (FeatureFlags.enableSplitContextually()) {
mSplitSelectStateController.resetState();
} else {
resetFromSplitSelectionState();
}
- InteractionJankMonitorWrapper.end(Cuj.CUJ_SPLIT_SCREEN_ENTER);
});
});
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.kt b/quickstep/src/com/android/quickstep/views/TaskView.kt
index 3586dfb..082971c 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.kt
+++ b/quickstep/src/com/android/quickstep/views/TaskView.kt
@@ -1566,6 +1566,7 @@
}
private fun onModalnessUpdated(modalness: Float) {
+ isClickable = modalness == 0f
taskContainers.forEach {
it.iconView.setModalAlpha(1 - modalness)
it.digitalWellBeingToast?.bannerOffsetPercentage = modalness
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/model/data/TaskViewItemInfoTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/model/data/TaskViewItemInfoTest.kt
index 0103e7e..5cee434 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/model/data/TaskViewItemInfoTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/model/data/TaskViewItemInfoTest.kt
@@ -17,14 +17,17 @@
package com.android.launcher3.model.data
import android.content.ComponentName
-import android.content.Context
import android.content.Intent
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.android.launcher3.Flags.enableRefactorTaskThumbnail
+import com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_NOT_PINNABLE
import com.android.launcher3.model.data.TaskViewItemInfo.Companion.createTaskViewAtom
+import com.android.launcher3.pm.UserCache
+import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext
import com.android.launcher3.util.SplitConfigurationOptions
import com.android.launcher3.util.TransformingTouchDelegate
+import com.android.launcher3.util.UserIconInfo
import com.android.quickstep.TaskOverlayFactory
import com.android.quickstep.TaskOverlayFactory.TaskOverlay
import com.android.quickstep.recents.di.RecentsDependencies
@@ -48,10 +51,12 @@
/** Test for [TaskViewItemInfo] */
@RunWith(AndroidJUnit4::class)
class TaskViewItemInfoTest {
- private val context = mock<Context>()
+ private val context = SandboxContext(InstrumentationRegistry.getInstrumentation().targetContext)
private val taskView = mock<TaskView>()
private val recentsView = mock<RecentsView<*, *>>()
private val overlayFactory = mock<TaskOverlayFactory>()
+ private val userCache = mock<UserCache>()
+ private val userInfo = mock<UserIconInfo>()
@Before
fun setUp() {
@@ -59,7 +64,10 @@
whenever(taskView.context).thenReturn(context)
whenever(taskView.recentsView).thenReturn(recentsView)
whenever(recentsView.indexOfChild(taskView)).thenReturn(TASK_VIEW_INDEX)
- RecentsDependencies.initialize(InstrumentationRegistry.getInstrumentation().targetContext)
+ whenever(userInfo.isPrivate).thenReturn(false)
+ whenever(userCache.getUserInfo(any())).thenReturn(userInfo)
+ context.putObject(UserCache.INSTANCE, userCache)
+ RecentsDependencies.initialize(context)
}
@Test
@@ -69,9 +77,8 @@
whenever(taskView.taskContainers).thenReturn(taskContainers)
val taskViewItemInfo = TaskViewItemInfo(taskContainers[0])
- val taskViewAtom = taskViewItemInfo.taskViewAtom
- assertThat(taskViewAtom)
+ assertThat(taskViewItemInfo.taskViewAtom)
.isEqualTo(
createTaskViewAtom(
type = 0,
@@ -80,6 +87,7 @@
cardinality = 1,
)
)
+ assertThat(taskViewItemInfo.runtimeStatusFlags and FLAG_NOT_PINNABLE).isEqualTo(0)
}
@Test
@@ -90,9 +98,8 @@
whenever(taskView.taskContainers).thenReturn(taskContainers)
val taskViewItemInfo = TaskViewItemInfo(taskContainers[0])
- val taskViewAtom = taskViewItemInfo.taskViewAtom
- assertThat(taskViewAtom)
+ assertThat(taskViewItemInfo.taskViewAtom)
.isEqualTo(
createTaskViewAtom(
type = 1,
@@ -101,6 +108,7 @@
cardinality = 2,
)
)
+ assertThat(taskViewItemInfo.runtimeStatusFlags and FLAG_NOT_PINNABLE).isEqualTo(0)
}
@Test
@@ -115,9 +123,8 @@
whenever(taskView.taskContainers).thenReturn(taskContainers)
val taskViewItemInfo = TaskViewItemInfo(taskContainers[0])
- val taskViewAtom = taskViewItemInfo.taskViewAtom
- assertThat(taskViewAtom)
+ assertThat(taskViewItemInfo.taskViewAtom)
.isEqualTo(
createTaskViewAtom(
type = 2,
@@ -126,6 +133,29 @@
cardinality = 3,
)
)
+ assertThat(taskViewItemInfo.runtimeStatusFlags and FLAG_NOT_PINNABLE).isEqualTo(0)
+ }
+
+ @Test
+ fun privateTask() {
+ val taskContainers = listOf(createTaskContainer(createTask(1)))
+ whenever(taskView.type).thenReturn(TaskViewType.SINGLE)
+ whenever(taskView.taskContainers).thenReturn(taskContainers)
+ whenever(userInfo.isPrivate).thenReturn(true)
+
+ val taskViewItemInfo = TaskViewItemInfo(taskContainers[0])
+
+ assertThat(taskViewItemInfo.taskViewAtom)
+ .isEqualTo(
+ createTaskViewAtom(
+ type = 0,
+ index = TASK_VIEW_INDEX,
+ componentName = "${PACKAGE}/${CLASS}",
+ cardinality = 1,
+ )
+ )
+ assertThat(taskViewItemInfo.runtimeStatusFlags and FLAG_NOT_PINNABLE)
+ .isEqualTo(FLAG_NOT_PINNABLE)
}
private fun createTask(id: Int) =
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarOverflowTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarOverflowTest.kt
index cc8582c..5867e77 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarOverflowTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarOverflowTest.kt
@@ -272,7 +272,8 @@
private val taskbarIconsCentered: Boolean
get() {
return getOnUiThread {
- val iconLayoutBounds = taskbarViewController.iconLayoutBounds
+ val iconLayoutBounds =
+ taskbarViewController.transientTaskbarIconLayoutBoundsInParent
val availableWidth = taskbarUnitTestRule.activityContext.deviceProfile.widthPx
iconLayoutBounds.left - (availableWidth - iconLayoutBounds.right) < 2
}
@@ -282,7 +283,7 @@
get() {
return getOnUiThread {
taskbarUnitTestRule.activityContext.deviceProfile.widthPx -
- taskbarViewController.iconLayoutBounds.right
+ taskbarViewController.transientTaskbarIconLayoutBoundsInParent.right
}
}
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/BubbleBarSwipeControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/BubbleBarSwipeControllerTest.kt
index 2e471b8..024ec4c 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/BubbleBarSwipeControllerTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/BubbleBarSwipeControllerTest.kt
@@ -36,6 +36,7 @@
import org.mockito.kotlin.any
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.atLeastOnce
+import org.mockito.kotlin.eq
import org.mockito.kotlin.never
import org.mockito.kotlin.times
import org.mockito.kotlin.verify
@@ -206,7 +207,7 @@
bubbleBarSwipeController.start()
bubbleBarSwipeController.swipeTo(UP_ABOVE_UNSTASH)
}
- verify(bubbleStashController).showBubbleBar(expandBubbles = false)
+ verify(bubbleStashController).showBubbleBar(expandBubbles = false, bubbleBarGesture = true)
}
@Test
@@ -227,11 +228,12 @@
bubbleBarSwipeController.swipeTo(UP_ABOVE_UNSTASH)
bubbleBarSwipeController.swipeTo(UP_BELOW_UNSTASH)
}
- verify(bubbleStashController).showBubbleBar(expandBubbles = false)
+ verify(bubbleStashController).showBubbleBar(expandBubbles = false, bubbleBarGesture = true)
verify(bubbleStashController).stashBubbleBar()
getInstrumentation().runOnMainSync { bubbleBarSwipeController.swipeTo(UP_ABOVE_UNSTASH) }
- verify(bubbleStashController, times(2)).showBubbleBar(expandBubbles = false)
+ verify(bubbleStashController, times(2))
+ .showBubbleBar(expandBubbles = false, bubbleBarGesture = true)
}
@Test
@@ -241,9 +243,9 @@
bubbleBarSwipeController.start()
bubbleBarSwipeController.swipeTo(UP_ABOVE_UNSTASH)
}
- verify(bubbleStashController, never()).showBubbleBar(expandBubbles = true)
+ verify(bubbleStashController, never()).showBubbleBar(expandBubbles = eq(true), any())
getInstrumentation().runOnMainSync { bubbleBarSwipeController.finish() }
- verify(bubbleStashController).showBubbleBar(expandBubbles = true)
+ verify(bubbleStashController).showBubbleBar(expandBubbles = true, bubbleBarGesture = true)
}
@Test
@@ -253,12 +255,12 @@
bubbleBarSwipeController.start()
bubbleBarSwipeController.swipeTo(UP_ABOVE_UNSTASH)
}
- verify(bubbleStashController).showBubbleBar(expandBubbles = false)
+ verify(bubbleStashController).showBubbleBar(expandBubbles = false, bubbleBarGesture = true)
getInstrumentation().runOnMainSync {
bubbleBarSwipeController.swipeTo(UP_BELOW_UNSTASH)
bubbleBarSwipeController.finish()
}
- verify(bubbleStashController, never()).showBubbleBar(expandBubbles = true)
+ verify(bubbleStashController, never()).showBubbleBar(expandBubbles = eq(true), any())
}
@Test
@@ -334,7 +336,7 @@
bubbleBarSwipeController.swipeTo(UP_ABOVE_UNSTASH)
bubbleBarSwipeController.finish()
}
- verify(bubbleStashController).showBubbleBar(expandBubbles = true)
+ verify(bubbleStashController).showBubbleBar(expandBubbles = true, bubbleBarGesture = true)
}
@Test
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt
index 8beceb0..29d142f 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt
@@ -36,6 +36,7 @@
import com.android.launcher3.R
import com.android.launcher3.taskbar.bubbles.BubbleBarBubble
import com.android.launcher3.taskbar.bubbles.BubbleBarOverflow
+import com.android.launcher3.taskbar.bubbles.BubbleBarParentViewHeightUpdateNotifier
import com.android.launcher3.taskbar.bubbles.BubbleBarView
import com.android.launcher3.taskbar.bubbles.BubbleView
import com.android.launcher3.taskbar.bubbles.flyout.BubbleBarFlyoutController
@@ -69,6 +70,7 @@
private val context = ApplicationProvider.getApplicationContext<Context>()
private lateinit var animatorScheduler: TestBubbleBarViewAnimatorScheduler
+ private lateinit var bubbleBarParentViewController: TestBubbleBarParentViewHeightUpdateNotifier
private lateinit var overflowView: BubbleView
private lateinit var bubbleView: BubbleView
private lateinit var bubble: BubbleBarBubble
@@ -84,6 +86,7 @@
@Before
fun setUp() {
animatorScheduler = TestBubbleBarViewAnimatorScheduler()
+ bubbleBarParentViewController = TestBubbleBarParentViewHeightUpdateNotifier()
PhysicsAnimatorTestUtils.prepareForTest()
setupFlyoutController()
}
@@ -102,6 +105,7 @@
bubbleBarView,
bubbleStashController,
flyoutController,
+ bubbleBarParentViewController,
onExpandedNoOp,
animatorScheduler,
)
@@ -122,7 +126,7 @@
assertThat(bubbleBarView.scaleY).isEqualTo(1)
assertThat(bubbleBarView.translationY).isEqualTo(BAR_TRANSLATION_Y_FOR_TASKBAR)
assertThat(animator.isAnimating).isTrue()
-
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(1)
waitForFlyoutToShow()
// execute the hide bubble animation
@@ -135,6 +139,7 @@
InstrumentationRegistry.getInstrumentation().runOnMainSync {}
PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(2)
assertThat(handle.alpha).isEqualTo(1)
assertThat(handle.translationY).isEqualTo(0)
assertThat(bubbleBarView.alpha).isEqualTo(0)
@@ -156,6 +161,7 @@
bubbleBarView,
bubbleStashController,
flyoutController,
+ bubbleBarParentViewController,
onExpandedNoOp,
animatorScheduler,
)
@@ -178,7 +184,7 @@
assertThat(animator.isAnimating).isTrue()
verify(bubbleStashController, atLeastOnce()).updateTaskbarTouchRegion()
-
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(1)
waitForFlyoutToShow()
// verify the hide bubble animation is pending
@@ -188,6 +194,7 @@
waitForFlyoutToHide()
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(2)
assertThat(animatorScheduler.delayedBlock).isNull()
assertThat(bubbleBarView.alpha).isEqualTo(1)
assertThat(bubbleBarView.visibility).isEqualTo(VISIBLE)
@@ -209,6 +216,7 @@
bubbleBarView,
bubbleStashController,
flyoutController,
+ bubbleBarParentViewController,
onExpandedNoOp,
animatorScheduler,
)
@@ -255,6 +263,7 @@
bubbleBarView,
bubbleStashController,
flyoutController,
+ bubbleBarParentViewController,
onExpandedNoOp,
animatorScheduler,
)
@@ -266,7 +275,7 @@
// let the animation start and wait for it to complete
InstrumentationRegistry.getInstrumentation().runOnMainSync {}
PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
-
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(1)
waitForFlyoutToShow()
// execute the hide bubble animation
@@ -282,7 +291,7 @@
InstrumentationRegistry.getInstrumentation().runOnMainSync {
animator.onStashStateChangingWhileAnimating()
}
-
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(2)
assertThat(animator.isAnimating).isFalse()
verify(bubbleStashController).onNewBubbleAnimationInterrupted(any(), any())
@@ -306,6 +315,7 @@
bubbleBarView,
bubbleStashController,
flyoutController,
+ bubbleBarParentViewController,
onExpandedNoOp,
animatorScheduler,
)
@@ -344,6 +354,7 @@
bubbleBarView,
bubbleStashController,
flyoutController,
+ bubbleBarParentViewController,
onExpanded,
animatorScheduler,
)
@@ -389,6 +400,7 @@
bubbleBarView,
bubbleStashController,
flyoutController,
+ bubbleBarParentViewController,
onExpanded,
animatorScheduler,
)
@@ -440,6 +452,7 @@
bubbleBarView,
bubbleStashController,
flyoutController,
+ bubbleBarParentViewController,
onExpanded,
animatorScheduler,
)
@@ -454,7 +467,7 @@
PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
assertThat(animator.isAnimating).isTrue()
-
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(1)
waitForFlyoutToShow()
// verify the hide bubble animation is pending
@@ -469,6 +482,7 @@
waitForFlyoutToHide()
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(2)
assertThat(handle.alpha).isEqualTo(0)
assertThat(handle.translationY)
.isEqualTo(DIFF_BETWEEN_HANDLE_AND_BAR_CENTERS + BAR_TRANSLATION_Y_FOR_TASKBAR)
@@ -495,6 +509,7 @@
bubbleBarView,
bubbleStashController,
flyoutController,
+ bubbleBarParentViewController,
onExpandedNoOp,
animatorScheduler,
)
@@ -510,7 +525,7 @@
assertThat(animator.isAnimating).isTrue()
assertThat(bubbleBarView.alpha).isEqualTo(1)
assertThat(bubbleBarView.translationY).isEqualTo(BAR_TRANSLATION_Y_FOR_TASKBAR)
-
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(1)
waitForFlyoutToShow()
assertThat(animatorScheduler.delayedBlock).isNotNull()
@@ -522,6 +537,7 @@
PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
InstrumentationRegistry.getInstrumentation().waitForIdleSync()
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(2)
assertThat(animator.isAnimating).isFalse()
assertThat(bubbleBarView.alpha).isEqualTo(0)
assertThat(handle.translationY).isEqualTo(0)
@@ -550,6 +566,7 @@
bubbleBarView,
bubbleStashController,
flyoutController,
+ bubbleBarParentViewController,
onExpanded,
animatorScheduler,
)
@@ -585,6 +602,7 @@
bubbleBarView,
bubbleStashController,
flyoutController,
+ bubbleBarParentViewController,
onExpandedNoOp,
animatorScheduler,
)
@@ -600,7 +618,7 @@
assertThat(animator.isAnimating).isTrue()
assertThat(bubbleBarView.alpha).isEqualTo(1)
assertThat(bubbleBarView.translationY).isEqualTo(BAR_TRANSLATION_Y_FOR_HOTSEAT)
-
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(1)
waitForFlyoutToShow()
assertThat(animatorScheduler.delayedBlock).isNotNull()
@@ -608,6 +626,7 @@
waitForFlyoutToHide()
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(2)
assertThat(animator.isAnimating).isFalse()
assertThat(bubbleBarView.alpha).isEqualTo(1)
assertThat(bubbleBarView.translationY).isEqualTo(BAR_TRANSLATION_Y_FOR_HOTSEAT)
@@ -629,6 +648,7 @@
bubbleBarView,
bubbleStashController,
flyoutController,
+ bubbleBarParentViewController,
onExpanded,
animatorScheduler,
)
@@ -678,6 +698,7 @@
bubbleBarView,
bubbleStashController,
flyoutController,
+ bubbleBarParentViewController,
onExpanded,
animatorScheduler,
)
@@ -689,7 +710,7 @@
// wait for the animation to start
InstrumentationRegistry.getInstrumentation().runOnMainSync {}
PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
-
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(1)
waitForFlyoutToShow()
assertThat(animator.isAnimating).isTrue()
@@ -704,6 +725,7 @@
// verify that the hide animation was canceled
assertThat(animatorScheduler.delayedBlock).isNull()
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(2)
verifyBubbleBarIsExpandedWithTranslation(BAR_TRANSLATION_Y_FOR_HOTSEAT)
assertThat(animator.isAnimating).isFalse()
@@ -724,6 +746,7 @@
bubbleBarView,
bubbleStashController,
flyoutController,
+ bubbleBarParentViewController,
onExpandedNoOp,
animatorScheduler,
)
@@ -745,7 +768,7 @@
InstrumentationRegistry.getInstrumentation().runOnMainSync {}
barAnimator.assertIsRunning()
PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
-
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(1)
waitForFlyoutToShow()
assertThat(animatorScheduler.delayedBlock).isNotNull()
@@ -754,6 +777,7 @@
waitForFlyoutToHide()
assertThat(animator.isAnimating).isFalse()
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(2)
// the bubble bar translation y should be back to its initial value
assertThat(bubbleBarView.translationY).isEqualTo(BAR_TRANSLATION_Y_FOR_HOTSEAT)
@@ -778,6 +802,7 @@
bubbleBarView,
bubbleStashController,
flyoutController,
+ bubbleBarParentViewController,
onExpanded,
animatorScheduler,
)
@@ -832,6 +857,7 @@
bubbleBarView,
bubbleStashController,
flyoutController,
+ bubbleBarParentViewController,
onExpanded,
animatorScheduler,
)
@@ -896,6 +922,7 @@
bubbleBarView,
bubbleStashController,
flyoutController,
+ bubbleBarParentViewController,
onExpanded,
animatorScheduler,
)
@@ -921,7 +948,7 @@
// verify there is a pending hide animation
assertThat(animatorScheduler.delayedBlock).isNotNull()
assertThat(animator.isAnimating).isTrue()
-
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(1)
waitForFlyoutToShow()
InstrumentationRegistry.getInstrumentation().runOnMainSync {
@@ -933,6 +960,7 @@
waitForFlyoutToHide()
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(2)
assertThat(animator.isAnimating).isFalse()
assertThat(bubbleBarView.translationY).isEqualTo(BAR_TRANSLATION_Y_FOR_HOTSEAT)
assertThat(bubbleBarView.isExpanded).isTrue()
@@ -954,6 +982,7 @@
bubbleBarView,
bubbleStashController,
flyoutController,
+ bubbleBarParentViewController,
onExpandedNoOp,
animatorScheduler,
)
@@ -986,7 +1015,7 @@
assertThat(bubbleBarView.scaleY).isEqualTo(1)
assertThat(bubbleBarView.translationY).isEqualTo(BAR_TRANSLATION_Y_FOR_TASKBAR)
assertThat(animator.isAnimating).isTrue()
-
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(1)
waitForFlyoutToShow()
assertThat(flyoutView!!.findViewById<TextView>(R.id.bubble_flyout_text).text)
.isEqualTo("updated message")
@@ -1001,6 +1030,7 @@
InstrumentationRegistry.getInstrumentation().runOnMainSync {}
PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(2)
assertThat(handle.alpha).isEqualTo(1)
assertThat(handle.translationY).isEqualTo(0)
assertThat(bubbleBarView.alpha).isEqualTo(0)
@@ -1022,6 +1052,7 @@
bubbleBarView,
bubbleStashController,
flyoutController,
+ bubbleBarParentViewController,
onExpandedNoOp,
animatorScheduler,
)
@@ -1042,7 +1073,7 @@
assertThat(bubbleBarView.scaleY).isEqualTo(1)
assertThat(bubbleBarView.translationY).isEqualTo(BAR_TRANSLATION_Y_FOR_TASKBAR)
assertThat(animator.isAnimating).isTrue()
-
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(1)
waitForFlyoutToShow()
assertThat(flyoutView!!.findViewById<TextView>(R.id.bubble_flyout_text).text)
@@ -1075,6 +1106,7 @@
InstrumentationRegistry.getInstrumentation().runOnMainSync {}
PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(2)
assertThat(handle.alpha).isEqualTo(1)
assertThat(handle.translationY).isEqualTo(0)
assertThat(bubbleBarView.alpha).isEqualTo(0)
@@ -1096,6 +1128,7 @@
bubbleBarView,
bubbleStashController,
flyoutController,
+ bubbleBarParentViewController,
onExpandedNoOp,
animatorScheduler,
)
@@ -1116,7 +1149,7 @@
assertThat(bubbleBarView.scaleY).isEqualTo(1)
assertThat(bubbleBarView.translationY).isEqualTo(BAR_TRANSLATION_Y_FOR_TASKBAR)
assertThat(animator.isAnimating).isTrue()
-
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(1)
waitForFlyoutToShow()
assertThat(flyoutView!!.findViewById<TextView>(R.id.bubble_flyout_text).text)
@@ -1137,6 +1170,7 @@
// the flyout should now reverse and expand
animatorTestRule.advanceTimeBy(400)
}
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(2)
assertThat(flyoutView!!.findViewById<TextView>(R.id.bubble_flyout_text).text)
.isEqualTo("updated message")
@@ -1159,6 +1193,7 @@
InstrumentationRegistry.getInstrumentation().runOnMainSync {}
PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(3)
assertThat(handle.alpha).isEqualTo(1)
assertThat(handle.translationY).isEqualTo(0)
assertThat(bubbleBarView.alpha).isEqualTo(0)
@@ -1180,6 +1215,7 @@
bubbleBarView,
bubbleStashController,
flyoutController,
+ bubbleBarParentViewController,
onExpandedNoOp,
animatorScheduler,
)
@@ -1200,7 +1236,7 @@
assertThat(bubbleBarView.scaleY).isEqualTo(1)
assertThat(bubbleBarView.translationY).isEqualTo(BAR_TRANSLATION_Y_FOR_TASKBAR)
assertThat(animator.isAnimating).isTrue()
-
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(1)
waitForFlyoutToShow()
assertThat(flyoutView!!.findViewById<TextView>(R.id.bubble_flyout_text).text)
@@ -1216,7 +1252,6 @@
PhysicsAnimatorTestUtils.blockUntilFirstAnimationFrameWhereTrue(handleAnimator) {
bubbleBarView.alpha < 0.5
}
-
// we're about to interrupt the animation which will cancel the current animation and start
// a new one. pause the scheduler to delay starting the new animation. this allows us to run
// the test deterministically
@@ -1229,9 +1264,11 @@
animator.animateBubbleInForStashed(updatedBubble, isExpanding = false)
}
+ // since animation was interrupted there shouldn`t be additional calls to adjust window
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(1)
+
InstrumentationRegistry.getInstrumentation().runOnMainSync {}
PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
-
// verify there's a new job scheduled and start it. this is starting the animation from the
// handle back to the bar
assertThat(animatorScheduler.pausedBlock).isNotNull()
@@ -1240,9 +1277,9 @@
InstrumentationRegistry.getInstrumentation().runOnMainSync {}
PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
-
waitForFlyoutToShow()
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(2)
assertThat(flyoutView!!.findViewById<TextView>(R.id.bubble_flyout_text).text)
.isEqualTo("updated message")
assertThat(handle.alpha).isEqualTo(0)
@@ -1258,7 +1295,6 @@
InstrumentationRegistry.getInstrumentation().runOnMainSync(animatorScheduler.delayedBlock!!)
waitForFlyoutToHide()
-
PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
// verify the hide animation was rescheduled and run it
@@ -1271,6 +1307,7 @@
InstrumentationRegistry.getInstrumentation().runOnMainSync {}
PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
+ assertThat(bubbleBarParentViewController.timesInvoked).isEqualTo(3)
assertThat(handle.alpha).isEqualTo(1)
assertThat(handle.translationY).isEqualTo(0)
assertThat(bubbleBarView.alpha).isEqualTo(0)
@@ -1292,6 +1329,7 @@
bubbleBarView,
bubbleStashController,
flyoutController,
+ bubbleBarParentViewController,
onExpandedNoOp,
animatorScheduler,
)
@@ -1392,10 +1430,6 @@
}
val flyoutCallbacks =
object : FlyoutCallbacks {
- override fun extendTopBoundary(space: Int) {}
-
- override fun resetTopBoundary() {}
-
override fun flyoutClicked() {}
}
val flyoutScheduler = FlyoutScheduler { block -> block.invoke() }
@@ -1478,6 +1512,16 @@
delayedBlock = null
}
}
+
+ private class TestBubbleBarParentViewHeightUpdateNotifier :
+ BubbleBarParentViewHeightUpdateNotifier {
+
+ var timesInvoked: Int = 0
+
+ override fun updateTopBoundary() {
+ timesInvoked++
+ }
+ }
}
private const val DIFF_BETWEEN_HANDLE_AND_BAR_CENTERS = -20f
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutControllerTest.kt
index 103c769..91fe6a6 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutControllerTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutControllerTest.kt
@@ -128,46 +128,6 @@
}
@Test
- fun showFlyout_extendsTopBoundary() {
- // set negative translation for the flyout so that it will request to extend the top
- // boundary
- flyoutTy = -50f
- InstrumentationRegistry.getInstrumentation().runOnMainSync {
- setupAndShowFlyout()
- assertThat(flyoutContainer.childCount).isEqualTo(1)
- }
- InstrumentationRegistry.getInstrumentation().waitForIdleSync()
- InstrumentationRegistry.getInstrumentation().runOnMainSync {
- animatorTestRule.advanceTimeBy(showAnimationDuration)
- }
- assertThat(flyoutCallbacks.topBoundaryExtendedSpace).isEqualTo(50)
- }
-
- @Test
- fun showFlyout_withinBoundary() {
- InstrumentationRegistry.getInstrumentation().runOnMainSync {
- setupAndShowFlyout()
- assertThat(flyoutContainer.childCount).isEqualTo(1)
- }
- InstrumentationRegistry.getInstrumentation().waitForIdleSync()
- InstrumentationRegistry.getInstrumentation().runOnMainSync {
- animatorTestRule.advanceTimeBy(showAnimationDuration)
- }
- assertThat(flyoutCallbacks.topBoundaryExtendedSpace).isEqualTo(0)
- }
-
- @Test
- fun collapseFlyout_resetsTopBoundary() {
- InstrumentationRegistry.getInstrumentation().runOnMainSync {
- setupAndShowFlyout()
- assertThat(flyoutContainer.childCount).isEqualTo(1)
- flyoutController.collapseFlyout {}
- animatorTestRule.advanceTimeBy(hideAnimationDuration)
- }
- assertThat(flyoutCallbacks.topBoundaryReset).isTrue()
- }
-
- @Test
fun cancelFlyout_fadesOutFlyout() {
InstrumentationRegistry.getInstrumentation().runOnMainSync {
setupAndShowFlyout()
@@ -178,7 +138,6 @@
animatorTestRule.advanceTimeBy(hideAnimationDuration)
assertThat(flyoutView.alpha).isEqualTo(0f)
}
- assertThat(flyoutCallbacks.topBoundaryReset).isTrue()
}
@Test
@@ -217,7 +176,6 @@
assertThat(flyout.findViewById<TextView>(R.id.bubble_flyout_text).text)
.isEqualTo("new message")
}
- assertThat(flyoutCallbacks.topBoundaryExtendedSpace).isEqualTo(50)
}
@Test
@@ -246,7 +204,6 @@
animatorTestRule.advanceTimeBy(showAnimationDuration)
assertThat(flyout.alpha).isEqualTo(1)
}
- assertThat(flyoutCallbacks.topBoundaryExtendedSpace).isEqualTo(50)
}
@Test
@@ -290,18 +247,8 @@
class FakeFlyoutCallbacks : FlyoutCallbacks {
- var topBoundaryExtendedSpace = 0
- var topBoundaryReset = false
var flyoutClicked = false
- override fun extendTopBoundary(space: Int) {
- topBoundaryExtendedSpace = space
- }
-
- override fun resetTopBoundary() {
- topBoundaryReset = true
- }
-
override fun flyoutClicked() {
flyoutClicked = true
}
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/PersistentBubbleStashControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/PersistentBubbleStashControllerTest.kt
index f795ab1..88b39d3 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/PersistentBubbleStashControllerTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/PersistentBubbleStashControllerTest.kt
@@ -37,6 +37,7 @@
import org.mockito.Mock
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule
+import org.mockito.kotlin.any
import org.mockito.kotlin.clearInvocations
import org.mockito.kotlin.never
import org.mockito.kotlin.verify
@@ -76,7 +77,7 @@
PersistentBubbleStashController(DefaultDimensionsProvider())
setUpBubbleBarView()
setUpBubbleBarController()
- persistentTaskBarStashController.setHotseatVerticalCenter(HOTSEAT_VERTICAL_CENTER)
+ persistentTaskBarStashController.bubbleBarVerticalCenterForHome = HOTSEAT_VERTICAL_CENTER
persistentTaskBarStashController.init(
taskbarInsetsController,
bubbleBarViewController,
@@ -342,6 +343,45 @@
verify(taskbarInsetsController, never()).onTaskbarOrBubblebarWindowHeightOrInsetsChanged()
}
+ @Test
+ fun showBubbleBar_expand_bubbleBarGesture() {
+ whenever(bubbleBarViewController.isHiddenForNoBubbles).thenReturn(false)
+ whenever(bubbleBarViewController.isExpanded).thenReturn(false)
+
+ persistentTaskBarStashController.showBubbleBar(
+ expandBubbles = true,
+ bubbleBarGesture = true,
+ )
+
+ verify(bubbleBarViewController).setExpanded(true, true)
+ }
+
+ @Test
+ fun showBubbleBar_expand_notBubbleBarGesture() {
+ whenever(bubbleBarViewController.isHiddenForNoBubbles).thenReturn(false)
+ whenever(bubbleBarViewController.isExpanded).thenReturn(false)
+
+ persistentTaskBarStashController.showBubbleBar(
+ expandBubbles = true,
+ bubbleBarGesture = false,
+ )
+
+ verify(bubbleBarViewController).setExpanded(true, false)
+ }
+
+ @Test
+ fun showBubbleBar_notExpanding_bubbleBarGesture() {
+ whenever(bubbleBarViewController.isHiddenForNoBubbles).thenReturn(false)
+ whenever(bubbleBarViewController.isExpanded).thenReturn(false)
+
+ persistentTaskBarStashController.showBubbleBar(
+ expandBubbles = false,
+ bubbleBarGesture = true,
+ )
+
+ verify(bubbleBarViewController, never()).setExpanded(any(), any())
+ }
+
private fun advanceTimeBy(advanceMs: Long) {
// Advance animator for on-device tests
getInstrumentation().runOnMainSync { animatorTestRule.advanceTimeBy(advanceMs) }
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/TransientBubbleStashControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/TransientBubbleStashControllerTest.kt
index 1bbd12a..f642345 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/TransientBubbleStashControllerTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/TransientBubbleStashControllerTest.kt
@@ -109,7 +109,7 @@
setUpStashedHandleView()
setUpBubbleStashedHandleViewController()
PhysicsAnimatorTestUtils.prepareForTest()
- mTransientBubbleStashController.setHotseatVerticalCenter(HOTSEAT_VERTICAL_CENTER)
+ mTransientBubbleStashController.bubbleBarVerticalCenterForHome = HOTSEAT_VERTICAL_CENTER
mTransientBubbleStashController.init(
taskbarInsetsController,
bubbleBarViewController,
@@ -362,6 +362,57 @@
}
@Test
+ fun updateStashedAndExpandedState_expand_bubbleBarGesture() {
+ mTransientBubbleStashController.isStashed = true
+ whenever(bubbleBarViewController.isHiddenForNoBubbles).thenReturn(false)
+ whenever(bubbleBarViewController.isExpanded).thenReturn(false)
+
+ getInstrumentation().runOnMainSync {
+ mTransientBubbleStashController.updateStashedAndExpandedState(
+ stash = false,
+ expand = true,
+ bubbleBarGesture = true,
+ )
+ }
+
+ verify(bubbleBarViewController).setExpanded(true, true)
+ }
+
+ @Test
+ fun updateStashedAndExpandedState_expand_notBubbleBarGesture() {
+ mTransientBubbleStashController.isStashed = true
+ whenever(bubbleBarViewController.isHiddenForNoBubbles).thenReturn(false)
+ whenever(bubbleBarViewController.isExpanded).thenReturn(false)
+
+ getInstrumentation().runOnMainSync {
+ mTransientBubbleStashController.updateStashedAndExpandedState(
+ stash = false,
+ expand = true,
+ bubbleBarGesture = false,
+ )
+ }
+
+ verify(bubbleBarViewController).setExpanded(true, false)
+ }
+
+ @Test
+ fun updateStashedAndExpandedState_notExpanding_bubbleBarGesture() {
+ mTransientBubbleStashController.isStashed = true
+ whenever(bubbleBarViewController.isHiddenForNoBubbles).thenReturn(false)
+ whenever(bubbleBarViewController.isExpanded).thenReturn(false)
+
+ getInstrumentation().runOnMainSync {
+ mTransientBubbleStashController.updateStashedAndExpandedState(
+ stash = false,
+ expand = false,
+ bubbleBarGesture = true,
+ )
+ }
+
+ verify(bubbleBarViewController, never()).setExpanded(any(), any())
+ }
+
+ @Test
fun isSysuiLockedSwitchedToFalseForOverview_unlockAnimationIsShown() {
// Given screen is locked and bubble bar has bubbles
getInstrumentation().runOnMainSync {
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/ContextualSearchInvokerTest.java b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/ContextualSearchInvokerTest.java
index 543ffe6..88774be 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/ContextualSearchInvokerTest.java
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/ContextualSearchInvokerTest.java
@@ -31,6 +31,8 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
@@ -46,13 +48,17 @@
import androidx.test.filters.SmallTest;
import com.android.launcher3.logging.StatsLogManager;
+import com.android.quickstep.BaseContainerInterface;
import com.android.quickstep.DeviceConfigWrapper;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TopTaskTracker;
+import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.RecentsViewContainer;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -73,6 +79,9 @@
private @Mock StatsLogManager.StatsLogger mMockStatsLogger;
private @Mock ContextualSearchHapticManager mMockContextualSearchHapticManager;
private @Mock ContextualSearchManager mMockContextualSearchManager;
+ private @Mock BaseContainerInterface mMockContainerInterface;
+ private @Mock RecentsViewContainer mMockRecentsViewContainer;
+ private @Mock RecentsView mMockRecentsView;
private ContextualSearchInvoker mContextualSearchInvoker;
@Before
@@ -86,10 +95,15 @@
when(mMockStateManager.isContextualSearchIntentAvailable()).thenReturn(true);
when(mMockStateManager.isContextualSearchSettingEnabled()).thenReturn(true);
when(mMockStatsLogManager.logger()).thenReturn(mMockStatsLogger);
+ when(mMockContainerInterface.getCreatedContainer()).thenReturn(mMockRecentsViewContainer);
+ when(mMockRecentsViewContainer.getOverviewPanel()).thenReturn(mMockRecentsView);
- mContextualSearchInvoker = new ContextualSearchInvoker(context, mMockStateManager,
+ mContextualSearchInvoker = spy(new ContextualSearchInvoker(context, mMockStateManager,
mMockTopTaskTracker, mMockSystemUiProxy, mMockStatsLogManager,
- mMockContextualSearchHapticManager, mMockContextualSearchManager);
+ mMockContextualSearchHapticManager, mMockContextualSearchManager
+ ));
+ doReturn(mMockContainerInterface).when(mContextualSearchInvoker)
+ .getRecentsContainerInterface();
}
@Test
@@ -244,6 +258,64 @@
}
}
+ @Test
+ public void invokeContextualSearchUncheckedWithHaptic_liveTile() {
+ when(mMockContainerInterface.isInLiveTileMode()).thenReturn(true);
+ ArgumentCaptor<Runnable> switchToScreenshotCaptor = ArgumentCaptor.forClass(Runnable.class);
+ ArgumentCaptor<Runnable> finishRecentsAnimationCaptor =
+ ArgumentCaptor.forClass(Runnable.class);
+
+ assertTrue("Expected invocation unchecked to succeed",
+ mContextualSearchInvoker.invokeContextualSearchUncheckedWithHaptic(
+ CONTEXTUAL_SEARCH_ENTRY_POINT));
+ verify(mMockRecentsView).switchToScreenshot(switchToScreenshotCaptor.capture());
+ switchToScreenshotCaptor.getValue().run();
+ verify(mMockRecentsView).finishRecentsAnimation(anyBoolean(), anyBoolean(),
+ finishRecentsAnimationCaptor.capture());
+ finishRecentsAnimationCaptor.getValue().run();
+ verify(mMockContextualSearchManager).startContextualSearch(CONTEXTUAL_SEARCH_ENTRY_POINT);
+ verifyNoMoreInteractions(mMockStatsLogManager);
+ }
+
+ @Test
+ public void invokeContextualSearchUncheckedWithHaptic_liveTile_failsToSwitchToScreenshot() {
+ when(mMockContainerInterface.isInLiveTileMode()).thenReturn(true);
+ ArgumentCaptor<Runnable> switchToScreenshotCaptor = ArgumentCaptor.forClass(Runnable.class);
+ ArgumentCaptor<Runnable> finishRecentsAnimationCaptor =
+ ArgumentCaptor.forClass(Runnable.class);
+
+ assertTrue("Expected invocation unchecked to succeed",
+ mContextualSearchInvoker.invokeContextualSearchUncheckedWithHaptic(
+ CONTEXTUAL_SEARCH_ENTRY_POINT));
+ verify(mMockRecentsView).switchToScreenshot(switchToScreenshotCaptor.capture());
+
+ // Don't run switchToScreenshot's callback. Therefore, recents animation should not finish.
+ verify(mMockRecentsView, never()).finishRecentsAnimation(anyBoolean(), anyBoolean(),
+ finishRecentsAnimationCaptor.capture());
+ // And ContextualSearch should not start.
+ verify(mMockContextualSearchManager, never()).startContextualSearch(anyInt());
+ verifyNoMoreInteractions(mMockStatsLogManager);
+ }
+
+ @Test
+ public void invokeContextualSearchUncheckedWithHaptic_liveTile_failsToFinishRecentsAnimation() {
+ when(mMockContainerInterface.isInLiveTileMode()).thenReturn(true);
+ ArgumentCaptor<Runnable> switchToScreenshotCaptor = ArgumentCaptor.forClass(Runnable.class);
+ ArgumentCaptor<Runnable> finishRecentsAnimationCaptor =
+ ArgumentCaptor.forClass(Runnable.class);
+
+ assertTrue("Expected invocation unchecked to succeed",
+ mContextualSearchInvoker.invokeContextualSearchUncheckedWithHaptic(
+ CONTEXTUAL_SEARCH_ENTRY_POINT));
+ verify(mMockRecentsView).switchToScreenshot(switchToScreenshotCaptor.capture());
+ switchToScreenshotCaptor.getValue().run();
+ verify(mMockRecentsView).finishRecentsAnimation(anyBoolean(), anyBoolean(),
+ finishRecentsAnimationCaptor.capture());
+ // Don't run finishRecentsAnimation's callback. Therefore ContextualSearch should not start.
+ verify(mMockContextualSearchManager, never()).startContextualSearch(anyInt());
+ verifyNoMoreInteractions(mMockStatsLogManager);
+ }
+
private AutoCloseable overrideSearchHapticCommitFlag(boolean value) {
return TestExtensions.overrideNavConfigFlag(
"ENABLE_SEARCH_HAPTIC_COMMIT",
diff --git a/quickstep/tests/src/com/android/quickstep/desktop/DesktopAppLaunchTransitionManagerTest.kt b/quickstep/tests/src/com/android/quickstep/desktop/DesktopAppLaunchTransitionManagerTest.kt
index 26189df..ae96c09c 100644
--- a/quickstep/tests/src/com/android/quickstep/desktop/DesktopAppLaunchTransitionManagerTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/desktop/DesktopAppLaunchTransitionManagerTest.kt
@@ -30,6 +30,7 @@
import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
import com.android.quickstep.SystemUiProxy
import com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS
+import com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
import com.google.common.truth.Truth.assertThat
import org.junit.After
@@ -74,7 +75,10 @@
}
@Test
- @EnableFlags(FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS)
+ @EnableFlags(
+ FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS,
+ FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX,
+ )
fun registerTransitions_appLaunchFlagEnabled_registersTransition() {
transitionManager.registerTransitions()
@@ -82,7 +86,10 @@
}
@Test
- @DisableFlags(FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS)
+ @DisableFlags(
+ FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS,
+ FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX,
+ )
fun registerTransitions_appLaunchFlagDisabled_doesntRegisterTransition() {
transitionManager.registerTransitions()
@@ -90,7 +97,10 @@
}
@Test
- @EnableFlags(FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS)
+ @EnableFlags(
+ FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS,
+ FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX,
+ )
fun registerTransitions_usesCorrectFilter() {
transitionManager.registerTransitions()
val filterArgumentCaptor = argumentCaptor<TransitionFilter>()
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 887a708..c477633 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -163,8 +163,8 @@
</declare-styleable>
<declare-styleable name="GridDimension">
- <attr name="minDeviceWidthPx" format="float"/>
- <attr name="minDeviceHeightPx" format="float"/>
+ <attr name="minDeviceWidthDp" format="integer"/>
+ <attr name="minDeviceHeightDp" format="integer"/>
<attr name="numGridDimension" format="integer"/>
<attr name="dbFile" />
<attr name="defaultLayoutId"/>
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index eaa720e..247ee48 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -980,7 +980,7 @@
public boolean shouldDrawAppContrastTile() {
return mDisplay == DISPLAY_WORKSPACE && shouldTextBeVisible()
&& PillColorProvider.getInstance(getContext()).isMatchaEnabled()
- && enableContrastTiles() && TextUtils.isEmpty(getText());
+ && enableContrastTiles() && !TextUtils.isEmpty(getText());
}
public void setTextVisibility(boolean visible) {
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index ee72c22..df5f520 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -71,6 +71,7 @@
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.util.CellAndSpan;
import com.android.launcher3.util.GridOccupancy;
+import com.android.launcher3.util.MSDLPlayerWrapper;
import com.android.launcher3.util.MultiTranslateDelegate;
import com.android.launcher3.util.ParcelableSparseArray;
import com.android.launcher3.util.Themes;
@@ -78,6 +79,8 @@
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
+import com.google.android.msdl.data.model.MSDLToken;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -204,6 +207,8 @@
private static final Paint sPaint = new Paint();
+ private final MSDLPlayerWrapper mMSDLPlayerWrapper;
+
// Related to accessible drag and drop
DragAndDropAccessibilityDelegate mTouchHelper;
@@ -237,6 +242,8 @@
mContainerType = a.getInteger(R.styleable.CellLayout_containerType, WORKSPACE);
a.recycle();
+ mMSDLPlayerWrapper = MSDLPlayerWrapper.INSTANCE.get(context);
+
// A ViewGroup usually does not draw, but CellLayout needs to draw a rectangle to show
// the user where a dragged item will land when dropped.
setWillNotDraw(false);
@@ -1153,6 +1160,9 @@
DropTarget.DragObject dragObject) {
if (mDragCell[0] != cellX || mDragCell[1] != cellY || mDragCellSpan[0] != spanX
|| mDragCellSpan[1] != spanY) {
+ if (Flags.msdlFeedback()) {
+ mMSDLPlayerWrapper.playToken(MSDLToken.DRAG_INDICATOR_DISCRETE);
+ }
mDragCell[0] = cellX;
mDragCell[1] = cellY;
mDragCellSpan[0] = spanX;
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 09225e7..9b6fe4e 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -1861,13 +1861,15 @@
* the bubble bar.
*
* <p>Does not check for visible bubbles persistence, so caller should call
- * {@link #shouldAdjustHotseatForBubbleBar} first.
+ * {@link #shouldAdjustHotseatOrQsbForBubbleBar} first.
*
* <p>If there's no adjustment needed, this method returns {@code 0}.
- * @see #shouldAdjustHotseatForBubbleBar(Context, boolean)
+ * @see #shouldAdjustHotseatOrQsbForBubbleBar(Context, boolean)
*/
public float getHotseatAdjustedBorderSpaceForBubbleBar(Context context) {
- if (!shouldAdjustHotseatForBubbleBar(context)) return 0;
+ if (shouldAlignBubbleBarWithQSB() || !shouldAdjustHotseatOrQsbForBubbleBar(context)) {
+ return 0;
+ }
// The adjustment is shrinking the hotseat's width by 1 icon on either side.
int iconsWidth =
iconSizePx * numShownHotseatIcons + hotseatBorderSpace * (numShownHotseatIcons - 1);
@@ -1880,27 +1882,37 @@
* Returns the hotseat icon translation X for the cellX index.
*
* <p>Does not check for visible bubbles persistence, so caller should call
- * {@link #shouldAdjustHotseatForBubbleBar} first.
+ * {@link #shouldAdjustHotseatOrQsbForBubbleBar} first.
*
* <p>If there's no adjustment needed, this method returns {@code 0}.
- * @see #shouldAdjustHotseatForBubbleBar(Context, boolean)
+ * @see #shouldAdjustHotseatOrQsbForBubbleBar(Context, boolean)
*/
public float getHotseatAdjustedTranslation(Context context, int cellX) {
- if (!shouldAdjustHotseatForBubbleBar(context)) return 0;
float borderSpace = getHotseatAdjustedBorderSpaceForBubbleBar(context);
+ if (borderSpace == 0) return borderSpace;
float borderSpaceDelta = borderSpace - hotseatBorderSpace;
return iconSizePx + cellX * borderSpaceDelta;
}
- /** Returns whether hotseat should be adjusted for the bubble bar. */
- public boolean shouldAdjustHotseatForBubbleBar(Context context, boolean hasBubbles) {
- return hasBubbles && shouldAdjustHotseatForBubbleBar(context);
+ /** Returns whether hotseat or QSB should be adjusted for the bubble bar. */
+ public boolean shouldAdjustHotseatOrQsbForBubbleBar(Context context, boolean hasBubbles) {
+ return hasBubbles && shouldAdjustHotseatOrQsbForBubbleBar(context);
}
- private boolean shouldAdjustHotseatForBubbleBar(Context context) {
- // only need to adjust if bubble bar is enabled, when QSB is on top of the hotseat and
- // there's not enough space for the bubble bar to the right of the hotseat.
- return !isQsbInline && getHotseatLayoutPadding(context).right <= mBubbleBarSpaceThresholdPx;
+ /** Returns whether hotseat should be adjusted for the bubble bar. */
+ public boolean shouldAdjustHotseatForBubbleBar(Context context, boolean hasBubbles) {
+ return shouldAlignBubbleBarWithHotseat()
+ && shouldAdjustHotseatOrQsbForBubbleBar(context, hasBubbles);
+ }
+
+ /** Returns whether hotseat or QSB should be adjusted for the bubble bar. */
+ public boolean shouldAdjustHotseatOrQsbForBubbleBar(Context context) {
+ // only need to adjust if QSB is on top of the hotseat and there's not enough space for the
+ // bubble bar to either side of the hotseat.
+ if (isQsbInline) return false;
+ Rect hotseatPadding = getHotseatLayoutPadding(context);
+ int hotseatMinHorizontalPadding = Math.min(hotseatPadding.left, hotseatPadding.right);
+ return hotseatMinHorizontalPadding <= mBubbleBarSpaceThresholdPx;
}
/**
@@ -2055,15 +2067,29 @@
}
/**
- * Returns the number of pixels the hotseat icons vertical center is translated from the bottom
- * of the screen.
+ * Returns the number of pixels the hotseat icons or QSB vertical center is translated from the
+ * bottom of the screen.
*/
- public int getHotseatVerticalCenter() {
- return hotseatBarSizePx
- - (isQsbInline ? 0 : hotseatQsbVisualHeight)
- - hotseatQsbSpace
- - (hotseatCellHeightPx / 2)
- + ((hotseatCellHeightPx - iconSizePx) / 2);
+ public int getBubbleBarVerticalCenterForHome() {
+ if (shouldAlignBubbleBarWithHotseat()) {
+ return hotseatBarSizePx
+ - (isQsbInline ? 0 : hotseatQsbVisualHeight)
+ - hotseatQsbSpace
+ - (hotseatCellHeightPx / 2)
+ + ((hotseatCellHeightPx - iconSizePx) / 2);
+ } else {
+ return hotseatBarSizePx - (hotseatQsbVisualHeight / 2);
+ }
+ }
+
+ /** Returns whether bubble bar should be aligned with the hotseat. */
+ public boolean shouldAlignBubbleBarWithQSB() {
+ return !shouldAlignBubbleBarWithHotseat();
+ }
+
+ /** Returns whether bubble bar should be aligned with the hotseat. */
+ public boolean shouldAlignBubbleBarWithHotseat() {
+ return isQsbInline || isGestureMode;
}
/**
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index b2ccba4..6be8098 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -186,9 +186,10 @@
*/
public void adjustForBubbleBar(boolean isBubbleBarVisible) {
DeviceProfile dp = mActivity.getDeviceProfile();
- float adjustedBorderSpace = dp.getHotseatAdjustedBorderSpaceForBubbleBar(getContext());
- boolean shouldAdjustHotseat = isBubbleBarVisible
- && Float.compare(adjustedBorderSpace, 0f) != 0;
+ boolean shouldAdjust = isBubbleBarVisible
+ && dp.shouldAdjustHotseatOrQsbForBubbleBar(getContext());
+ boolean shouldAdjustHotseat = shouldAdjust
+ && dp.shouldAlignBubbleBarWithHotseat();
ShortcutAndWidgetContainer icons = getShortcutsAndWidgets();
// update the translation provider for future layout passes of hotseat icons.
if (shouldAdjustHotseat) {
@@ -209,9 +210,12 @@
animatorSet.play(ObjectAnimator.ofFloat(child, VIEW_TRANSLATE_X, tx));
}
}
+ //TODO(b/381109832) refactor & simplify adjustment logic
+ boolean shouldAdjustQsb =
+ shouldAdjustHotseat || (shouldAdjust && dp.shouldAlignBubbleBarWithQSB());
if (mQsb instanceof HorizontalInsettableView horizontalInsettableQsb) {
final float currentInsetFraction = horizontalInsettableQsb.getHorizontalInsets();
- final float targetInsetFraction = shouldAdjustHotseat
+ final float targetInsetFraction = shouldAdjustQsb
? (float) dp.iconSizePx / dp.hotseatQsbWidth : 0;
ValueAnimator qsbAnimator =
ValueAnimator.ofFloat(currentInsetFraction, targetInsetFraction);
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index e1d84be..c044c52 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -654,9 +654,9 @@
* Parses through the xml to find GridDimension specs. Then calls findBestRowCount to get the
* correct row count for this GridOption.
*
- * @return the result of {@link #findBestRowCount(List, Info)}.
+ * @return the result of {@link #findBestRowCount(List, int, int)}.
*/
- public static GridDimension getRowCount(ResourceHelper resourceHelper, Context context,
+ private static GridDimension getRowCount(ResourceHelper resourceHelper, Context context,
Info displayInfo) {
ArrayList<GridDimension> rowCounts = new ArrayList<>();
@@ -674,24 +674,40 @@
throw new RuntimeException(e);
}
- return findBestRowCount(rowCounts, displayInfo);
+ // Finds the min width and height in dp for all displays.
+ int[] dimens = findMinWidthAndHeightDpForDevice(displayInfo);
+
+ return findBestRowCount(rowCounts, dimens[0], dimens[1]);
}
/**
* @return the biggest row count that fits the display dimensions spec using GridDimension to
- * determine that. If no best row count is found, return -1.
+ * determine that. If no best row count is found, return null.
*/
- public static GridDimension findBestRowCount(List<GridDimension> list, Info displayInfo) {
+ private static GridDimension findBestRowCount(List<GridDimension> list, int minWidthDp,
+ int minHeightDp) {
+ GridDimension selectedRow = null;
+ for (GridDimension item: list) {
+ if (minWidthDp >= item.mMinDeviceWidthDp && minHeightDp >= item.mMinDeviceHeightDp) {
+ if (selectedRow == null || selectedRow.mNumGridDimension < item.mNumGridDimension) {
+ selectedRow = item;
+ }
+ }
+ }
+ return selectedRow;
+ }
+
+ private static int[] findMinWidthAndHeightDpForDevice(Info displayInfo) {
int minWidthPx = Integer.MAX_VALUE;
int minHeightPx = Integer.MAX_VALUE;
for (WindowBounds bounds : displayInfo.supportedBounds) {
boolean isTablet = displayInfo.isTablet(bounds);
if (isTablet && displayInfo.getDeviceType() == TYPE_MULTI_DISPLAY) {
- // For split displays, take half width per page
+ // For split displays, take half width per page.
minWidthPx = Math.min(minWidthPx, bounds.availableSize.x / 2);
minHeightPx = Math.min(minHeightPx, bounds.availableSize.y);
} else if (!isTablet && bounds.isLandscape()) {
- // We will use transposed layout in this case
+ // We will use transposed layout in this case.
minWidthPx = Math.min(minWidthPx, bounds.availableSize.y);
minHeightPx = Math.min(minHeightPx, bounds.availableSize.x);
} else {
@@ -700,18 +716,10 @@
}
}
- GridDimension selectedRow = null;
- for (GridDimension item: list) {
- if (minWidthPx >= item.mMinDeviceWidthPx && minHeightPx >= item.mMinDeviceHeightPx) {
- if (selectedRow == null || selectedRow.mNumGridDimension < item.mNumGridDimension) {
- selectedRow = item;
- }
- }
- }
- if (selectedRow != null) {
- return selectedRow;
- }
- return null;
+ int minWidthDp = (int) dpiFromPx(minWidthPx, DisplayMetrics.DENSITY_DEVICE_STABLE);
+ int minHeightDp = (int) dpiFromPx(minHeightPx, DisplayMetrics.DENSITY_DEVICE_STABLE);
+
+ return new int[]{minWidthDp, minHeightDp};
}
/**
@@ -1237,8 +1245,8 @@
public static final class GridDimension {
final int mNumGridDimension;
- final float mMinDeviceWidthPx;
- final float mMinDeviceHeightPx;
+ final int mMinDeviceWidthDp;
+ final int mMinDeviceHeightDp;
final String mDbFile;
final int mDefaultLayoutId;
final int mDemoModeLayoutId;
@@ -1248,8 +1256,8 @@
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.GridDimension);
mNumGridDimension = (int) a.getFloat(R.styleable.GridDimension_numGridDimension, 0);
- mMinDeviceWidthPx = a.getFloat(R.styleable.GridDimension_minDeviceWidthPx, 0);
- mMinDeviceHeightPx = a.getFloat(R.styleable.GridDimension_minDeviceHeightPx, 0);
+ mMinDeviceWidthDp = a.getInt(R.styleable.GridDimension_minDeviceWidthDp, 0);
+ mMinDeviceHeightDp = a.getInt(R.styleable.GridDimension_minDeviceHeightDp, 0);
mDbFile = a.getString(R.styleable.GridDimension_dbFile);
mDefaultLayoutId = a.getResourceId(
R.styleable.GridDimension_defaultLayoutId, 0);
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 95dbf5f..69a5a83 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -116,6 +116,7 @@
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.IntSparseArrayMap;
import com.android.launcher3.util.LauncherBindableItemsContainer;
+import com.android.launcher3.util.MSDLPlayerWrapper;
import com.android.launcher3.util.OverlayEdgeEffect;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.RunnableList;
@@ -133,6 +134,8 @@
import com.android.systemui.plugins.shared.LauncherOverlayManager.LauncherOverlayCallbacks;
import com.android.systemui.plugins.shared.LauncherOverlayManager.LauncherOverlayTouchProxy;
+import com.google.android.msdl.data.model.MSDLToken;
+
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -299,6 +302,8 @@
private final StatsLogManager mStatsLogManager;
+ private final MSDLPlayerWrapper mMSDLPlayerWrapper;
+
/**
* Used to inflate the Workspace from XML.
*
@@ -331,6 +336,7 @@
setMotionEventSplittingEnabled(true);
setOnTouchListener(new WorkspaceTouchListener(mLauncher, this));
mStatsLogManager = StatsLogManager.newInstance(context);
+ mMSDLPlayerWrapper = MSDLPlayerWrapper.INSTANCE.get(context);
}
@Override
@@ -2679,7 +2685,9 @@
ItemInfo info = dragObject.dragInfo;
boolean userFolderPending = willCreateUserFolder(info, mDragOverView, false);
if (mDragMode == DRAG_MODE_NONE && userFolderPending) {
-
+ if (Flags.msdlFeedback()) {
+ mMSDLPlayerWrapper.playToken(MSDLToken.DRAG_INDICATOR_DISCRETE);
+ }
mFolderCreateBg = new PreviewBackground(getContext());
mFolderCreateBg.setup(mLauncher, mLauncher, null,
mDragOverView.getMeasuredWidth(), mDragOverView.getPaddingTop());