Merge "Update bubble bar flyout according to spec" into main
diff --git a/Android.bp b/Android.bp
index bcbd362..4e1c9d3 100644
--- a/Android.bp
+++ b/Android.bp
@@ -17,7 +17,7 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-min_launcher3_sdk_version = "30"
+min_launcher3_sdk_version = "31"
// Targets that don't inherit framework aconfig libs (i.e., those that don't set
// `platform_apis: true`) must manually link them.
diff --git a/aconfig/launcher.aconfig b/aconfig/launcher.aconfig
index f877fd8..4d6c7ab 100644
--- a/aconfig/launcher.aconfig
+++ b/aconfig/launcher.aconfig
@@ -398,3 +398,31 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "enable_dismiss_prediction_undo"
+ namespace: "launcher"
+ description: "Show an 'Undo' snackbar when users dismiss a predicted hotseat item"
+ bug: "270394476"
+}
+
+flag {
+ name: "enable_all_apps_button_in_hotseat"
+ namespace: "launcher"
+ description: "Enables displaying the all apps button in the hotseat."
+ bug: "270393897"
+}
+
+flag {
+ name: "taskbar_quiet_mode_change_support"
+ namespace: "launcher"
+ description: "Support changing quiet mode for user profiles in taskbar."
+ bug: "345760034"
+}
+
+flag {
+ name: "taskbar_overflow"
+ namespace: "launcher"
+ description: "Show recent apps in the taskbar overflow."
+ bug: "368119679"
+}
diff --git a/quickstep/dagger/LauncherAppComponent.java b/quickstep/dagger/LauncherAppComponent.java
index bd6008e..068f01c 100644
--- a/quickstep/dagger/LauncherAppComponent.java
+++ b/quickstep/dagger/LauncherAppComponent.java
@@ -18,6 +18,7 @@
import com.android.quickstep.dagger.QuickStepModule;
+import com.android.quickstep.dagger.QuickstepBaseAppComponent;
import dagger.Component;
@@ -26,7 +27,7 @@
*/
@LauncherAppSingleton
@Component(modules = QuickStepModule.class)
-public interface LauncherAppComponent extends LauncherBaseAppComponent {
+public interface LauncherAppComponent extends QuickstepBaseAppComponent {
/** Builder for quickstep LauncherAppComponent. */
@Component.Builder
interface Builder extends LauncherBaseAppComponent.Builder {
diff --git a/quickstep/res/layout/activity_allset.xml b/quickstep/res/layout/activity_allset.xml
index 685a151..625d9b3 100644
--- a/quickstep/res/layout/activity_allset.xml
+++ b/quickstep/res/layout/activity_allset.xml
@@ -96,7 +96,6 @@
style="@style/TextAppearance.GestureTutorial.Feedback.Subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/allset_hint"
android:textSize="@dimen/allset_page_swipe_up_text_size"
android:gravity="center_horizontal"
diff --git a/quickstep/res/values-nb/strings.xml b/quickstep/res/values-nb/strings.xml
index 4b982ef..21b5fd4 100644
--- a/quickstep/res/values-nb/strings.xml
+++ b/quickstep/res/values-nb/strings.xml
@@ -97,7 +97,7 @@
<string name="action_share" msgid="2648470652637092375">"Del"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Skjermbilde"</string>
<string name="action_split" msgid="2098009717623550676">"Del opp"</string>
- <string name="action_save_app_pair" msgid="5974823919237645229">"Lagre apptilkobling"</string>
+ <string name="action_save_app_pair" msgid="5974823919237645229">"Lagre app-paret"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Trykk på en annen app for å bruke delt skjerm"</string>
<string name="toast_contextual_split_select_app" msgid="433510957123687090">"Velg en annen app for å bruke delt skjerm"</string>
<string name="toast_split_select_app_cancel" msgid="1939025102486630426">"Avbryt"</string>
diff --git a/quickstep/res/values-night/colors.xml b/quickstep/res/values-night/colors.xml
index 2052446..98e4871 100644
--- a/quickstep/res/values-night/colors.xml
+++ b/quickstep/res/values-night/colors.xml
@@ -25,7 +25,7 @@
<color name="all_set_page_background">@android:color/system_neutral1_900</color>
<!-- Turn on work apps button -->
- <color name="work_turn_on_stroke">?androidprv:attr/colorAccentSecondaryVariant</color>
+ <color name="work_turn_on_stroke">?attr/materialColorPrimary</color>
<color name="work_fab_bg_color">?attr/materialColorPrimaryFixedDim</color>
<color name="work_fab_icon_color">?attr/materialColorOnPrimaryFixed</color>
</resources>
\ No newline at end of file
diff --git a/quickstep/res/values/colors.xml b/quickstep/res/values/colors.xml
index 0bb971e..4c48bd3 100644
--- a/quickstep/res/values/colors.xml
+++ b/quickstep/res/values/colors.xml
@@ -94,7 +94,7 @@
<color name="lottie_yellow600">#f9ab00</color>
<!-- Turn on work apps button -->
- <color name="work_turn_on_stroke">?androidprv:attr/colorAccentPrimaryVariant</color>
+ <color name="work_turn_on_stroke">?attr/materialColorPrimary</color>
<color name="work_fab_bg_color">?attr/materialColorPrimaryFixedDim</color>
<color name="work_fab_icon_color">?attr/materialColorOnPrimaryFixed</color>
</resources>
\ No newline at end of file
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index fe459d5..8957e0d 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -350,7 +350,6 @@
<dimen name="taskbar_back_button_left_margin_kids">48dp</dimen>
<dimen name="taskbar_home_button_left_margin_kids">48dp</dimen>
<dimen name="taskbar_icon_size_kids">32dp</dimen>
- <dimen name="taskbar_all_apps_button_translation_x_offset">6dp</dimen>
<dimen name="taskbar_all_apps_search_button_translation_x_offset">6dp</dimen>
<dimen name="taskbar_contextual_button_suw_margin">64dp</dimen>
<dimen name="taskbar_contextual_button_suw_height">64dp</dimen>
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java b/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
index f29980b..4e6d00a 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
@@ -16,9 +16,9 @@
package com.android.launcher3.statehandlers;
import static android.view.View.VISIBLE;
+import static android.window.flags.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-import static com.android.wm.shell.shared.desktopmode.DesktopModeFlags.WALLPAPER_ACTIVITY;
import android.content.Context;
import android.os.Debug;
@@ -167,7 +167,8 @@
notifyDesktopVisibilityListeners(areDesktopTasksVisibleNow);
}
- if (!WALLPAPER_ACTIVITY.isEnabled(mContext) && wasVisible != isVisible) {
+ if (!ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY.isTrue()
+ && wasVisible != isVisible) {
// TODO: b/333533253 - Remove after flag rollout
if (mVisibleDesktopTasksCount > 0) {
setLauncherViewsVisibility(View.INVISIBLE);
@@ -225,7 +226,7 @@
notifyDesktopVisibilityListeners(areDesktopTasksVisibleNow);
}
- if (WALLPAPER_ACTIVITY.isEnabled(mContext)) {
+ if (ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY.isTrue()) {
return;
}
// TODO: b/333533253 - Clean up after flag rollout
@@ -341,7 +342,7 @@
if (mContext == null) {
return;
}
- if (WALLPAPER_ACTIVITY.isEnabled(mContext)) {
+ if (ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY.isTrue()) {
return;
}
if (DEBUG) {
@@ -376,7 +377,7 @@
if (mContext == null) {
return;
}
- if (WALLPAPER_ACTIVITY.isEnabled(mContext)) {
+ if (ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY.isTrue()) {
return;
}
if (DEBUG) {
@@ -396,7 +397,7 @@
if (mContext == null) {
return;
}
- if (WALLPAPER_ACTIVITY.isEnabled(mContext)) {
+ if (ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY.isTrue()) {
return;
}
if (DEBUG) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 5513599..02201c0 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -15,11 +15,12 @@
*/
package com.android.launcher3.taskbar;
+import static android.window.flags.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY;
+
import static com.android.launcher3.QuickstepTransitionManager.TRANSIENT_TASKBAR_TRANSITION_DURATION;
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;
-import static com.android.wm.shell.shared.desktopmode.DesktopModeFlags.WALLPAPER_ACTIVITY;
import android.animation.Animator;
import android.animation.AnimatorSet;
@@ -50,6 +51,7 @@
import com.android.quickstep.util.TISBindHelper;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
+import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
import java.io.PrintWriter;
import java.util.Arrays;
@@ -135,11 +137,6 @@
mHomeState.removeListener(mVisibilityChangeListener);
}
- /** Returns {@code true} if launcher is currently presenting the home screen. */
- public boolean isOnHome() {
- return mTaskbarLauncherStateController.isOnHome();
- }
-
private void onInAppDisplayProgressChanged() {
if (mControllers != null) {
// Update our shared state so we can restore it if taskbar gets recreated.
@@ -163,6 +160,16 @@
shouldDelayLauncherStateAnim);
}
+ @Override
+ public void stashHotseat(boolean stash) {
+ mTaskbarLauncherStateController.stashHotseat(stash);
+ }
+
+ @Override
+ public void unStashHotseatInstantly() {
+ mTaskbarLauncherStateController.unStashHotseatInstantly();
+ }
+
/**
* Adds the Launcher resume animator to the given animator set.
*
@@ -205,6 +212,9 @@
*/
@Override
public void onLauncherVisibilityChanged(boolean isVisible) {
+ if (DesktopModeStatus.enterDesktopByDefaultOnFreeformDisplay(mLauncher)) {
+ DisplayController.handleInfoChangeForLauncherVisibilityChanged(mLauncher);
+ }
onLauncherVisibilityChanged(isVisible, false /* fromInit */);
}
@@ -233,7 +243,7 @@
return null;
}
- if (!WALLPAPER_ACTIVITY.isEnabled(mLauncher)
+ if (!ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY.isTrue()
&& mControllers.taskbarDesktopModeController.getAreDesktopTasksVisible()) {
// TODO: b/333533253 - Remove after flag rollout
isVisible = false;
@@ -476,4 +486,13 @@
protected String getTaskbarUIControllerName() {
return "LauncherTaskbarUIController";
}
+
+ @Override
+ public void onSwipeToUnstashTaskbar() {
+ // Once taskbar is unstashed, the user cannot return back to the overlay. We can
+ // clear it here to set the expected state once the user goes home.
+ if (mLauncher.getWorkspace().isOverlayShown()) {
+ mLauncher.getWorkspace().onOverlayScrollChanged(0);
+ }
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index a979d58..e9bd30a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -91,6 +91,7 @@
import com.android.launcher3.anim.AlphaUpdateListener;
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.taskbar.TaskbarNavButtonController.TaskbarButton;
+import com.android.launcher3.taskbar.bubbles.BubbleBarController;
import com.android.launcher3.taskbar.navbutton.NavButtonLayoutFactory;
import com.android.launcher3.taskbar.navbutton.NavButtonLayoutFactory.NavButtonLayoutter;
import com.android.launcher3.taskbar.navbutton.NearestTouchFrame;
@@ -106,6 +107,7 @@
import com.android.systemui.shared.statusbar.phone.BarTransitions;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
+import com.android.wm.shell.shared.bubbles.BubbleBarLocation;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -115,7 +117,8 @@
/**
* Controller for managing nav bar buttons in taskbar
*/
-public class NavbarButtonsViewController implements TaskbarControllers.LoggableTaskbarController {
+public class NavbarButtonsViewController implements TaskbarControllers.LoggableTaskbarController,
+ BubbleBarController.BubbleBarLocationListener {
private final Rect mTempRect = new Rect();
@@ -397,6 +400,12 @@
}
};
mSeparateWindowParent.recreateControllers();
+ if (com.android.wm.shell.Flags.enableBubbleBarInPersistentTaskBar()
+ && mControllers.bubbleControllers.isPresent()) {
+ BubbleBarLocation bubblesLocation = mControllers.bubbleControllers.get()
+ .bubbleBarViewController.getBubbleBarLocation();
+ onBubbleBarLocationUpdated(bubblesLocation);
+ }
}
private void initButtons(ViewGroup navContainer, ViewGroup endContainer,
@@ -1168,6 +1177,52 @@
mHitboxExtender.onAnimationProgressToOverview(alignment);
}
+ /** Adjusts navigation buttons layout accordingly to the bubble bar position. */
+ @Override
+ public void onBubbleBarLocationUpdated(BubbleBarLocation location) {
+ mNavButtonContainer.setTranslationX(getNavBarTranslationX(location));
+ }
+
+ /** Animates navigation buttons accordingly to the bubble bar position. */
+ @Override
+ public void onBubbleBarLocationAnimated(BubbleBarLocation location) {
+ // TODO(b/346381754) add the teleport animation similarly to the bubble bar
+ mNavButtonContainer.setTranslationX(getNavBarTranslationX(location));
+ }
+
+ private int getNavBarTranslationX(BubbleBarLocation location) {
+ boolean isNavbarOnRight = location.isOnLeft(mNavButtonsView.isLayoutRtl());
+ DeviceProfile dp = mContext.getDeviceProfile();
+ float navBarTargetStartX;
+ if (mContext.shouldStartAlignTaskbar()) {
+ int navBarSpacing = dp.inlineNavButtonsEndSpacingPx;
+ // If the taskbar is start aligned the navigation bar is aligned to the start or end of
+ // the container, depending on the bubble bar location
+ if (isNavbarOnRight) {
+ navBarTargetStartX = dp.widthPx - navBarSpacing - mNavButtonContainer.getWidth();
+ } else {
+ navBarTargetStartX = navBarSpacing;
+ }
+ } else {
+ // 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();
+ if (isNavbarOnRight) {
+ if (mNavButtonsView.isLayoutRtl()) {
+ float taskBarEnd = taskbarBounds.right;
+ navBarTargetStartX = (dp.widthPx + taskBarEnd - navbarWidth) / 2;
+ } else {
+ navBarTargetStartX = mNavButtonContainer.getLeft();
+ }
+ } else {
+ float taskBarStart = taskbarBounds.left;
+ navBarTargetStartX = (taskBarStart - navbarWidth) / 2;
+ }
+ }
+ return (int) navBarTargetStartX - mNavButtonContainer.getLeft();
+ }
+
private class RotationButtonListener implements RotationButton.RotationButtonUpdatesCallback {
@Override
public void onVisibilityChanged(boolean isVisible) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index a1cd7f7..b95c406 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -688,6 +688,11 @@
return mNavMode == NavigationMode.THREE_BUTTONS;
}
+ /** Returns whether taskbar should start align. */
+ public boolean shouldStartAlignTaskbar() {
+ return isThreeButtonNav() && mDeviceProfile.startAlignTaskbar;
+ }
+
public boolean isGestureNav() {
return mNavMode == NavigationMode.NO_BUTTON;
}
@@ -1554,6 +1559,8 @@
* @param delayTaskbarBackground whether we will delay the taskbar background animation
*/
public void onSwipeToUnstashTaskbar(boolean delayTaskbarBackground) {
+ mControllers.uiController.onSwipeToUnstashTaskbar();
+
boolean wasStashed = mControllers.taskbarStashController.isStashed();
mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(/* stash= */ false,
SHOULD_BUBBLES_FOLLOW_DEFAULT_VALUE, delayTaskbarBackground);
@@ -1690,7 +1697,7 @@
duration);
View allAppsButton = mControllers.taskbarViewController.getAllAppsButtonView();
- if (allAppsButton != null && !FeatureFlags.ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT.get()) {
+ if (allAppsButton != null && !FeatureFlags.enableAllAppsButtonInHotseat()) {
ValueAnimator alphaOverride = ValueAnimator.ofFloat(0, 1);
alphaOverride.setDuration(duration);
alphaOverride.addUpdateListener(a -> {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
index 221504d..685c109 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
@@ -147,7 +147,11 @@
defaultTouchableRegion.addBoundsToRegion(bubbleBarViewController.bubbleBarBounds)
}
}
- if (taskbarStashController.isInApp || taskbarStashController.isInOverview) {
+ if (
+ taskbarStashController.isInApp ||
+ taskbarStashController.isInOverview ||
+ DisplayController.showLockedTaskbarOnHome(context)
+ ) {
// only add the taskbar touch region if not on home
val bottom = windowLayoutParams.height
val top = bottom - taskbarTouchableHeight
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index 6c6bd71..876221b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -16,9 +16,13 @@
package com.android.launcher3.taskbar;
import static com.android.app.animation.Interpolators.EMPHASIZED;
+import static com.android.launcher3.Hotseat.ALPHA_CHANNEL_TASKBAR_ALIGNMENT;
+import static com.android.launcher3.Hotseat.ALPHA_CHANNEL_TASKBAR_STASH;
+import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_APP;
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_OVERVIEW;
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_STASHED_LAUNCHER_STATE;
+import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_STASHED_FOR_BUBBLES;
import static com.android.launcher3.taskbar.TaskbarViewController.ALPHA_INDEX_HOME;
import static com.android.launcher3.util.FlagDebugUtils.appendFlag;
import static com.android.launcher3.util.FlagDebugUtils.formatFlagChange;
@@ -40,6 +44,7 @@
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Hotseat.HotseatQsbAlphaId;
import com.android.launcher3.LauncherState;
import com.android.launcher3.QuickstepTransitionManager;
import com.android.launcher3.Utilities;
@@ -48,6 +53,7 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.uioverrides.QuickstepLauncher;
+import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.MultiPropertyFactory.MultiProperty;
import com.android.quickstep.RecentsAnimationCallbacks;
import com.android.quickstep.RecentsAnimationController;
@@ -144,7 +150,7 @@
private AnimatedFloat mTaskbarBackgroundAlpha;
private AnimatedFloat mTaskbarAlpha;
private AnimatedFloat mTaskbarCornerRoundness;
- private MultiProperty mIconAlphaForHome;
+ private MultiProperty mTaskbarAlphaForHome;
private QuickstepLauncher mLauncher;
private boolean mIsDestroyed = false;
@@ -174,11 +180,11 @@
if (mIsQsbInline && !dp.isQsbInline) {
// We only modify QSB alpha if isQsbInline = true. If we switch to a DP
// where isQsbInline = false, then we need to reset the alpha.
- mLauncher.getHotseat().setQsbAlpha(1f);
+ mLauncher.getHotseat().setQsbAlpha(1f, ALPHA_CHANNEL_TASKBAR_ALIGNMENT);
}
mIsQsbInline = dp.isQsbInline;
TaskbarLauncherStateController.this.updateIconAlphaForHome(
- mIconAlphaForHome.getValue());
+ mTaskbarAlphaForHome.getValue(), ALPHA_CHANNEL_TASKBAR_ALIGNMENT);
}
};
@@ -241,7 +247,7 @@
.getTaskbarBackgroundAlpha();
mTaskbarAlpha = mControllers.taskbarDragLayerController.getTaskbarAlpha();
mTaskbarCornerRoundness = mControllers.getTaskbarCornerRoundness();
- mIconAlphaForHome = mControllers.taskbarViewController
+ mTaskbarAlphaForHome = mControllers.taskbarViewController
.getTaskbarIconAlpha().get(ALPHA_INDEX_HOME);
resetIconAlignment();
@@ -265,7 +271,7 @@
mIconAlignment.finishAnimation();
- mLauncher.getHotseat().setIconsAlpha(1f);
+ mLauncher.getHotseat().setIconsAlpha(1f, ALPHA_CHANNEL_TASKBAR_ALIGNMENT);
mLauncher.getStateManager().removeStateListener(mStateListener);
mCanSyncViews = !mControllers.taskbarActivityContext.isPhoneMode();
@@ -294,6 +300,7 @@
stashController.updateStateForFlag(FLAG_IN_APP, false);
updateStateForFlag(FLAG_TRANSITION_TO_VISIBLE, true);
+ mLauncherState = toState;
animatorSet.play(stashController.createApplyStateAnimator(duration));
animatorSet.play(applyState(duration, false));
@@ -440,11 +447,6 @@
return animator;
}
- /** Returns {@code true} if launcher is currently presenting the home screen. */
- public boolean isOnHome() {
- return isInLauncher() && mLauncherState == LauncherState.NORMAL;
- }
-
private Animator onStateChangeApplied(int changedFlags, long duration, boolean start) {
final boolean isInLauncher = isInLauncher();
final boolean isIconAlignedWithHotseat = isIconAlignedWithHotseat();
@@ -456,9 +458,11 @@
+ ", toAlignment: " + toAlignment);
}
mControllers.bubbleControllers.ifPresent(controllers -> {
- // Show the bubble bar when on launcher home or in overview.
+ // Show the bubble bar when on launcher home (hotseat icons visible) or in overview
boolean onOverview = mLauncherState == LauncherState.OVERVIEW;
- controllers.bubbleStashController.setBubblesShowingOnHome(isOnHome());
+ boolean hotseatIconsVisible = isInLauncher && mLauncherState.areElementsVisible(
+ mLauncher, HOTSEAT_ICONS);
+ controllers.bubbleStashController.setBubblesShowingOnHome(hotseatIconsVisible);
controllers.bubbleStashController.setBubblesShowingOnOverview(onOverview);
});
@@ -660,6 +664,9 @@
* This refers to the intended state - a transition to this state might be in progress.
*/
public boolean isTaskbarAlignedWithHotseat() {
+ if (DisplayController.showLockedTaskbarOnHome(mLauncher) && isInLauncher()) {
+ return false;
+ }
return mLauncherState.isTaskbarAlignedWithHotseat(mLauncher);
}
@@ -671,8 +678,7 @@
boolean isInStashedState = mLauncherState.isTaskbarStashed(mLauncher);
boolean willStashVisually = isInStashedState
&& mControllers.taskbarStashController.supportsVisualStashing();
- boolean isTaskbarAlignedWithHotseat =
- mLauncherState.isTaskbarAlignedWithHotseat(mLauncher);
+ boolean isTaskbarAlignedWithHotseat = isTaskbarAlignedWithHotseat();
return isTaskbarAlignedWithHotseat && !willStashVisually;
} else {
return false;
@@ -703,14 +709,17 @@
public void onAnimationEnd(Animator animation) {
if (isInStashedState && committed) {
// Reset hotseat alpha to default
- mLauncher.getHotseat().setIconsAlpha(1);
+ mLauncher.getHotseat().setIconsAlpha(1, ALPHA_CHANNEL_TASKBAR_ALIGNMENT);
}
}
@Override
public void onAnimationStart(Animator animation) {
- if (mLauncher.getHotseat().getIconsAlpha() > 0) {
- updateIconAlphaForHome(mLauncher.getHotseat().getIconsAlpha());
+ float hotseatIconsAlpha = mLauncher.getHotseat()
+ .getIconsAlpha(ALPHA_CHANNEL_TASKBAR_ALIGNMENT)
+ .getValue();
+ if (hotseatIconsAlpha > 0) {
+ updateIconAlphaForHome(hotseatIconsAlpha, ALPHA_CHANNEL_TASKBAR_ALIGNMENT);
}
}
});
@@ -739,6 +748,33 @@
}
}
+ protected void stashHotseat(boolean stash) {
+ TaskbarStashController stashController = mControllers.taskbarStashController;
+ stashController.updateStateForFlag(FLAG_STASHED_FOR_BUBBLES, stash);
+ Runnable swapHotseatWithTaskbar = new Runnable() {
+ @Override
+ public void run() {
+ updateIconAlphaForHome(stash ? 1 : 0, ALPHA_CHANNEL_TASKBAR_STASH);
+ }
+ };
+ if (stash) {
+ stashController.applyState();
+ // if we stashing the hotseat we need to immediately swap it with the animating taskbar
+ swapHotseatWithTaskbar.run();
+ } else {
+ // if we revert stashing make swap after taskbar animation is complete
+ stashController.applyState(/* postApplyAction = */ swapHotseatWithTaskbar);
+ }
+ }
+
+ protected void unStashHotseatInstantly() {
+ TaskbarStashController stashController = mControllers.taskbarStashController;
+ stashController.updateStateForFlag(FLAG_STASHED_FOR_BUBBLES, false);
+ stashController.applyState(/* duration = */ 0);
+ updateIconAlphaForHome(/* taskbarAlpha = */ 0,
+ ALPHA_CHANNEL_TASKBAR_STASH, /* updateTaskbarAlpha = */ false);
+ }
+
/**
* Resets and updates the icon alignment.
*/
@@ -748,7 +784,7 @@
}
private void onIconAlignmentRatioChanged() {
- float currentValue = mIconAlphaForHome.getValue();
+ float currentValue = mTaskbarAlphaForHome.getValue();
boolean taskbarWillBeVisible = mIconAlignment.value < 1;
boolean firstFrameVisChanged = (taskbarWillBeVisible && Float.compare(currentValue, 1) != 0)
|| (!taskbarWillBeVisible && Float.compare(currentValue, 0) != 0);
@@ -756,8 +792,10 @@
mControllers.taskbarViewController.setLauncherIconAlignment(
mIconAlignment.value, mLauncher.getDeviceProfile());
mControllers.navbarButtonsViewController.updateTaskbarAlignment(mIconAlignment.value);
- // Switch taskbar and hotseat in last frame
- updateIconAlphaForHome(taskbarWillBeVisible ? 1 : 0);
+ // Switch taskbar and hotseat in last frame and if taskbar is not hidden for bubbles
+ boolean isHiddenForBubbles = mControllers.taskbarStashController.isHiddenForBubbles();
+ updateIconAlphaForHome(taskbarWillBeVisible ? 1 : 0, ALPHA_CHANNEL_TASKBAR_ALIGNMENT,
+ /* updateTaskbarAlpha = */ !isHiddenForBubbles);
// Sync the first frame where we swap taskbar and hotseat.
if (firstFrameVisChanged && mCanSyncViews && !Utilities.isRunningInTestHarness()) {
@@ -767,12 +805,20 @@
}
}
- private void updateIconAlphaForHome(float alpha) {
+ private void updateIconAlphaForHome(float taskbarAlpha, @HotseatQsbAlphaId int alphaChannel) {
+ updateIconAlphaForHome(taskbarAlpha, alphaChannel, /* updateTaskbarAlpha = */ true);
+ }
+
+ private void updateIconAlphaForHome(float taskbarAlpha,
+ @HotseatQsbAlphaId int alphaChannel,
+ boolean updateTaskbarAlpha) {
if (mIsDestroyed) {
return;
}
- mIconAlphaForHome.setValue(alpha);
- boolean hotseatVisible = alpha == 0
+ if (updateTaskbarAlpha) {
+ mTaskbarAlphaForHome.setValue(taskbarAlpha);
+ }
+ boolean hotseatVisible = taskbarAlpha == 0
|| mControllers.taskbarActivityContext.isPhoneMode()
|| (!mControllers.uiController.isHotseatIconOnTopWhenAligned()
&& mIconAlignment.value > 0);
@@ -780,9 +826,10 @@
* Hide Launcher Hotseat icons when Taskbar icons have opacity. Both icon sets
* should not be visible at the same time.
*/
- mLauncher.getHotseat().setIconsAlpha(hotseatVisible ? 1 : 0);
+ float targetAlpha = hotseatVisible ? 1 : 0;
+ mLauncher.getHotseat().setIconsAlpha(targetAlpha, alphaChannel);
if (mIsQsbInline) {
- mLauncher.getHotseat().setQsbAlpha(hotseatVisible ? 1 : 0);
+ mLauncher.getHotseat().setQsbAlpha(targetAlpha, alphaChannel);
}
}
@@ -870,7 +917,7 @@
pw.println(String.format(
"%s\tmTaskbarBackgroundAlpha=%.2f", prefix, mTaskbarBackgroundAlpha.value));
pw.println(String.format(
- "%s\tmIconAlphaForHome=%.2f", prefix, mIconAlphaForHome.getValue()));
+ "%s\tmTaskbarAlphaForHome=%.2f", prefix, mTaskbarAlphaForHome.getValue()));
pw.println(String.format("%s\tmPrevState=%s", prefix,
mPrevState == null ? null : getStateString(mPrevState)));
pw.println(String.format("%s\tmState=%s", prefix, getStateString(mState)));
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index 1b4db7a..78e7b47 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -60,6 +60,7 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.contextualeducation.ContextualEduStatsManager;
import com.android.launcher3.statehandlers.DesktopVisibilityController;
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.taskbar.TaskbarNavButtonController.TaskbarNavButtonCallbacks;
@@ -247,6 +248,7 @@
context,
navCallbacks,
SystemUiProxy.INSTANCE.get(mContext),
+ ContextualEduStatsManager.INSTANCE.get(mContext),
new Handler(),
AssistUtils.newInstance(mContext));
mComponentCallbacks = new ComponentCallbacks() {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
index 872a4d0..15c35b6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
@@ -45,12 +45,14 @@
import androidx.annotation.StringRes;
import com.android.launcher3.R;
+import com.android.launcher3.contextualeducation.ContextualEduStatsManager;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.util.AssistUtils;
+import com.android.systemui.contextualeducation.GestureType;
import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
import java.io.PrintWriter;
@@ -109,6 +111,7 @@
private final Context mContext;
private final TaskbarNavButtonCallbacks mCallbacks;
private final SystemUiProxy mSystemUiProxy;
+ private final ContextualEduStatsManager mContextualEduStatsManager;
private final Handler mHandler;
private final AssistUtils mAssistUtils;
@Nullable private StatsLogManager mStatsLogManager;
@@ -119,11 +122,13 @@
Context context,
TaskbarNavButtonCallbacks callbacks,
SystemUiProxy systemUiProxy,
+ ContextualEduStatsManager contextualEduStatsManager,
Handler handler,
AssistUtils assistUtils) {
mContext = context;
mCallbacks = callbacks;
mSystemUiProxy = systemUiProxy;
+ mContextualEduStatsManager = contextualEduStatsManager;
mHandler = handler;
mAssistUtils = assistUtils;
}
@@ -137,14 +142,20 @@
switch (buttonType) {
case BUTTON_BACK:
logEvent(LAUNCHER_TASKBAR_BACK_BUTTON_TAP);
+ mContextualEduStatsManager.updateEduStats(/* isTrackpadGesture= */ false,
+ GestureType.BACK);
executeBack();
break;
case BUTTON_HOME:
logEvent(LAUNCHER_TASKBAR_HOME_BUTTON_TAP);
+ mContextualEduStatsManager.updateEduStats(/* isTrackpadGesture= */ false,
+ GestureType.HOME);
navigateHome();
break;
case BUTTON_RECENTS:
logEvent(LAUNCHER_TASKBAR_OVERVIEW_BUTTON_TAP);
+ mContextualEduStatsManager.updateEduStats(/* isTrackpadGesture= */ false,
+ GestureType.OVERVIEW);
navigateToOverview();
break;
case BUTTON_IME_SWITCH:
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt
index 72bdafe..57d4dbb 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt
@@ -16,6 +16,7 @@
package com.android.launcher3.taskbar
import android.content.Context
+import android.window.flags.DesktopModeFlags
import androidx.annotation.VisibleForTesting
import com.android.launcher3.Flags.enableRecentsInTaskbar
import com.android.launcher3.model.data.ItemInfo
@@ -26,7 +27,6 @@
import com.android.quickstep.RecentsModel
import com.android.quickstep.util.DesktopTask
import com.android.quickstep.util.GroupTask
-import com.android.wm.shell.shared.desktopmode.DesktopModeFlags
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
import java.io.PrintWriter
@@ -40,7 +40,7 @@
var canShowRunningApps =
DesktopModeStatus.canEnterDesktopMode(context) &&
- DesktopModeFlags.TASKBAR_RUNNING_APPS.isEnabled(context)
+ DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_TASKBAR_RUNNING_APPS.isTrue
@VisibleForTesting
set(isEnabledFromTest) {
field = isEnabledFromTest
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
index 2370dfd..751a42a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
@@ -115,7 +115,8 @@
return bubblesExpanded && !mControllers.navbarButtonsViewController.isImeVisible()
&& !isShadeVisible
&& !mControllers.taskbarStashController.isStashed()
- && (mTaskbarVisible || showScrimForBubbles);
+ && (mTaskbarVisible || showScrimForBubbles)
+ && !mControllers.taskbarStashController.isHiddenForBubbles();
}
private float getScrimAlpha() {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 2c2f65d..7624afb 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -101,6 +101,7 @@
public static final int FLAG_IN_OVERVIEW = 1 << 11; // launcher is in overview
// An internal no-op flag to determine whether we should delay the taskbar background animation
private static final int FLAG_DELAY_TASKBAR_BG_TAG = 1 << 12;
+ public static final int FLAG_STASHED_FOR_BUBBLES = 1 << 13; // show handle for stashed hotseat
// If any of these flags are enabled, isInApp should return true.
private static final int FLAGS_IN_APP = FLAG_IN_APP | FLAG_IN_SETUP;
@@ -122,7 +123,8 @@
// If any of these flags are enabled, the taskbar must be stashed.
private static final int FLAGS_FORCE_STASHED = FLAG_STASHED_SYSUI | FLAG_STASHED_DEVICE_LOCKED
- | FLAG_STASHED_IN_TASKBAR_ALL_APPS | FLAG_STASHED_SMALL_SCREEN;
+ | FLAG_STASHED_IN_TASKBAR_ALL_APPS | FLAG_STASHED_SMALL_SCREEN
+ | FLAG_STASHED_FOR_BUBBLES;
/**
* How long to stash/unstash when manually invoked via long press.
@@ -395,6 +397,16 @@
return mIsStashed;
}
+ /** Sets the hotseat stashed. */
+ public void stashHotseat(boolean stash) {
+ mControllers.uiController.stashHotseat(stash);
+ }
+
+ /** Instantly un-stashes the hotseat. */
+ public void unStashHotseatInstantly() {
+ mControllers.uiController.unStashHotseatInstantly();
+ }
+
/**
* Returns whether the taskbar should be stashed in apps (e.g. user long pressed to stash).
*/
@@ -434,6 +446,11 @@
return hasAnyFlag(FLAG_IN_OVERVIEW);
}
+ /** Returns whether taskbar is hidden for bubbles. */
+ public boolean isHiddenForBubbles() {
+ return hasAnyFlag(FLAG_STASHED_FOR_BUBBLES);
+ }
+
/**
* Returns the height that taskbar will be touchable.
*/
@@ -995,13 +1012,29 @@
}
public void applyState() {
- applyState(hasAnyFlag(FLAG_IN_SETUP) ? 0 : TASKBAR_STASH_DURATION);
+ applyState(/* postApplyAction = */ null);
+ }
+
+ /** Applies state and performs action after state is applied. */
+ public void applyState(@Nullable Runnable postApplyAction) {
+ applyState(hasAnyFlag(FLAG_IN_SETUP) ? 0 : TASKBAR_STASH_DURATION, postApplyAction);
}
public void applyState(long duration) {
+ applyState(duration, /* postApplyAction = */ null);
+ }
+
+ private void applyState(long duration, @Nullable Runnable postApplyAction) {
Animator animator = createApplyStateAnimator(duration);
if (animator != null) {
+ if (postApplyAction != null) {
+ // performs action on animation end
+ animator.addListener(AnimatorListeners.forEndCallback(postApplyAction));
+ }
animator.start();
+ } else if (postApplyAction != null) {
+ // animator was not created, just execute the action
+ postApplyAction.run();
}
}
@@ -1019,6 +1052,9 @@
*/
@Nullable
public Animator createApplyStateAnimator(long duration) {
+ if (mActivity.isPhoneMode()) {
+ return null;
+ }
return mStatePropertyHolder.createSetStateAnimator(mState, duration);
}
@@ -1064,10 +1100,6 @@
/** Called when some system ui state has changed. (See SYSUI_STATE_... in QuickstepContract) */
public void updateStateForSysuiFlags(long systemUiStateFlags, boolean skipAnim) {
- if (mActivity.isPhoneMode()) {
- return;
- }
-
long animDuration = TASKBAR_STASH_DURATION;
long startDelay = 0;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
index 6b1173a..9c8c2a9 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
@@ -428,4 +428,18 @@
public void setSkipLauncherVisibilityChange(boolean skip) {
mSkipLauncherVisibilityChange = skip;
}
+
+ /** Sets whether the hotseat is stashed */
+ public void stashHotseat(boolean stash) {
+ }
+
+ /** Un-stash the hotseat instantly */
+ public void unStashHotseatInstantly() {
+ }
+
+ /**
+ * Called when we want to unstash taskbar when user performs swipes up gesture.
+ */
+ public void onSwipeToUnstashTaskbar() {
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index 32d6561..0389a11 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -87,6 +87,7 @@
private final boolean mIsRtl;
private final TaskbarActivityContext mActivityContext;
+ @Nullable private BubbleBarLocation mBubbleBarLocation = null;
// Initialized in init.
private TaskbarViewCallbacks mControllerCallbacks;
@@ -197,7 +198,7 @@
@Override
public void onDeviceProfileChanged(DeviceProfile dp) {
- mShouldTryStartAlign = mActivityContext.isThreeButtonNav() && dp.startAlignTaskbar;
+ mShouldTryStartAlign = mActivityContext.shouldStartAlignTaskbar();
}
@Override
@@ -494,39 +495,60 @@
icon.setOnHoverListener(mControllerCallbacks.getIconOnHoverListener(icon));
}
+ /** Updates taskbar icons accordingly to the new bubble bar location. */
+ public void onBubbleBarLocationUpdated(BubbleBarLocation location) {
+ if (mBubbleBarLocation == location) return;
+ mBubbleBarLocation = location;
+ requestLayout();
+ }
+
+ /**
+ * Returns translation X for the taskbar icons for provided {@link BubbleBarLocation}. If the
+ * bubble bar is not enabled, or location of the bubble bar is the same, or taskbar is not start
+ * aligned - returns 0.
+ */
+ public float getTranslationXForBubbleBarPosition(BubbleBarLocation location) {
+ if (!mControllerCallbacks.isBubbleBarEnabledInPersistentTaskbar()
+ || location == mBubbleBarLocation
+ || !mActivityContext.shouldStartAlignTaskbar()
+ ) {
+ return 0;
+ }
+ Rect iconsBounds = getIconLayoutBounds();
+ return getTaskBarIconsEndForBubbleBarLocation(location) - iconsBounds.right;
+ }
+
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- int count = getChildCount();
- DeviceProfile deviceProfile = mActivityContext.getDeviceProfile();
int spaceNeeded = getIconLayoutWidth();
- int navSpaceNeeded = deviceProfile.hotseatBarEndOffset;
boolean layoutRtl = isLayoutRtl();
- int centerAlignIconEnd = right - (right - left - spaceNeeded) / 2;
- int iconEnd;
-
+ DeviceProfile deviceProfile = mActivityContext.getDeviceProfile();
+ int navSpaceNeeded = deviceProfile.hotseatBarEndOffset;
+ int centerAlignIconEnd = (right + left + spaceNeeded) / 2;
+ int iconEnd = centerAlignIconEnd;
if (mShouldTryStartAlign) {
- // Taskbar is aligned to the start
int startSpacingPx = deviceProfile.inlineNavButtonsEndSpacingPx;
-
- if (layoutRtl) {
- iconEnd = right - startSpacingPx;
+ if (mControllerCallbacks.isBubbleBarEnabledInPersistentTaskbar()
+ && mBubbleBarLocation != null
+ && mActivityContext.shouldStartAlignTaskbar()) {
+ iconEnd = (int) getTaskBarIconsEndForBubbleBarLocation(mBubbleBarLocation);
} else {
- iconEnd = startSpacingPx + spaceNeeded;
+ if (layoutRtl) {
+ iconEnd = right - startSpacingPx;
+ } else {
+ iconEnd = startSpacingPx + spaceNeeded;
+ }
+ boolean needMoreSpaceForNav = layoutRtl
+ ? navSpaceNeeded > (iconEnd - spaceNeeded)
+ : iconEnd > (right - navSpaceNeeded);
+ if (needMoreSpaceForNav) {
+ // Add offset to account for nav bar when taskbar is centered
+ int offset = layoutRtl
+ ? navSpaceNeeded - (centerAlignIconEnd - spaceNeeded)
+ : (right - navSpaceNeeded) - centerAlignIconEnd;
+ iconEnd = centerAlignIconEnd + offset;
+ }
}
- } else {
- iconEnd = centerAlignIconEnd;
- }
-
- boolean needMoreSpaceForNav = layoutRtl
- ? navSpaceNeeded > (iconEnd - spaceNeeded)
- : iconEnd > (right - navSpaceNeeded);
- if (needMoreSpaceForNav) {
- // Add offset to account for nav bar when taskbar is centered
- int offset = layoutRtl
- ? navSpaceNeeded - (centerAlignIconEnd - spaceNeeded)
- : (right - navSpaceNeeded) - centerAlignIconEnd;
-
- iconEnd = centerAlignIconEnd + offset;
}
// Currently, we support only one device with display cutout and we only are concern about
@@ -558,6 +580,7 @@
mIconLayoutBounds.right = iconEnd;
mIconLayoutBounds.top = (bottom - top - mIconTouchSize) / 2;
mIconLayoutBounds.bottom = mIconLayoutBounds.top + mIconTouchSize;
+ int count = getChildCount();
for (int i = count; i > 0; i--) {
View child = getChildAt(i - 1);
if (child == mQsb) {
@@ -770,4 +793,19 @@
}
return mAllAppsButtonContainer;
}
+
+ /**
+ * This method only works for bubble bar enabled in persistent task bar and the taskbar is start
+ * aligned.
+ */
+ private float getTaskBarIconsEndForBubbleBarLocation(BubbleBarLocation location) {
+ DeviceProfile deviceProfile = mActivityContext.getDeviceProfile();
+ boolean navbarOnRight = location.isOnLeft(isLayoutRtl());
+ int navSpaceNeeded = deviceProfile.hotseatBarEndOffset;
+ if (navbarOnRight) {
+ return getWidth() - navSpaceNeeded;
+ } else {
+ return navSpaceNeeded + getIconLayoutWidth();
+ }
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
index 5ec00ac..5c8d439 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
@@ -28,6 +28,7 @@
import com.android.internal.jank.Cuj;
import com.android.launcher3.taskbar.bubbles.BubbleBarViewController;
import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
+import com.android.wm.shell.Flags;
import com.android.wm.shell.shared.bubbles.BubbleBarLocation;
/**
@@ -127,4 +128,10 @@
}
return null;
}
+
+ /** Returns true if bubble bar controllers present and enabled in persistent taskbar. */
+ public boolean isBubbleBarEnabledInPersistentTaskbar() {
+ return Flags.enableBubbleBarInPersistentTaskBar()
+ && mControllers.bubbleControllers.isPresent();
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 292b9ed..b663ccb 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -29,7 +29,10 @@
import static com.android.launcher3.config.FeatureFlags.enableTaskbarPinning;
import static com.android.launcher3.taskbar.TaskbarPinningController.PINNING_PERSISTENT;
import static com.android.launcher3.taskbar.TaskbarPinningController.PINNING_TRANSIENT;
+import static com.android.launcher3.taskbar.bubbles.BubbleBarView.FADE_IN_ANIM_ALPHA_DURATION_MS;
+import static com.android.launcher3.taskbar.bubbles.BubbleBarView.FADE_OUT_ANIM_POSITION_DURATION_MS;
import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
+import static com.android.launcher3.util.MultiTranslateDelegate.INDEX_NAV_BAR_ANIM;
import static com.android.launcher3.util.MultiTranslateDelegate.INDEX_TASKBAR_ALIGNMENT_ANIM;
import static com.android.launcher3.util.MultiTranslateDelegate.INDEX_TASKBAR_PINNING_ANIM;
import static com.android.launcher3.util.MultiTranslateDelegate.INDEX_TASKBAR_REVEAL_ANIM;
@@ -66,6 +69,7 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.TaskItemInfo;
+import com.android.launcher3.taskbar.bubbles.BubbleBarController;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.LauncherBindableItemsContainer;
@@ -74,6 +78,8 @@
import com.android.launcher3.util.MultiValueAlpha;
import com.android.quickstep.util.GroupTask;
import com.android.systemui.shared.recents.model.Task;
+import com.android.wm.shell.Flags;
+import com.android.wm.shell.shared.bubbles.BubbleBarLocation;
import java.io.PrintWriter;
import java.util.Set;
@@ -82,7 +88,8 @@
/**
* Handles properties/data collection, then passes the results to TaskbarView to render.
*/
-public class TaskbarViewController implements TaskbarControllers.LoggableTaskbarController {
+public class TaskbarViewController implements TaskbarControllers.LoggableTaskbarController,
+ BubbleBarController.BubbleBarLocationListener {
private static final String TAG = "TaskbarViewController";
@@ -122,6 +129,14 @@
private final AnimatedFloat mTaskbarIconTranslationXForPinning = new AnimatedFloat(
this::updateTaskbarIconTranslationXForPinning);
+ private final AnimatedFloat mIconsTranslationXForNavbar = new AnimatedFloat(
+ this::updateTranslationXForNavBar);
+
+ @Nullable
+ private Animator mTaskbarShiftXAnim;
+ @Nullable
+ private BubbleBarLocation mCurrentBubbleBarLocation;
+
private final AnimatedFloat mTaskbarIconTranslationYForPinning = new AnimatedFloat(
this::updateTranslationY);
@@ -227,6 +242,54 @@
}
}
+ /** Adjusts start aligned taskbar layout accordingly to the bubble bar position. */
+ @Override
+ public void onBubbleBarLocationUpdated(BubbleBarLocation location) {
+ updateCurrentBubbleBarLocation(location);
+ if (!shouldMoveTaskbarOnBubbleBarLocationUpdate()) return;
+ cancelTaskbarShiftAnimation();
+ // reset translation x, taskbar will position icons with the updated location
+ mIconsTranslationXForNavbar.updateValue(0);
+ mTaskbarView.onBubbleBarLocationUpdated(location);
+ }
+
+ /** Animates start aligned taskbar accordingly to the bubble bar position. */
+ @Override
+ public void onBubbleBarLocationAnimated(BubbleBarLocation location) {
+ if (!updateCurrentBubbleBarLocation(location)
+ || !shouldMoveTaskbarOnBubbleBarLocationUpdate()) {
+ return;
+ }
+ cancelTaskbarShiftAnimation();
+ float translationX = mTaskbarView.getTranslationXForBubbleBarPosition(location);
+ mTaskbarShiftXAnim = createTaskbarIconsShiftAnimator(translationX);
+ mTaskbarShiftXAnim.start();
+ }
+
+ /** Updates the mCurrentBubbleBarLocation, returns {@code} true if location is updated. */
+ private boolean updateCurrentBubbleBarLocation(BubbleBarLocation location) {
+ if (mCurrentBubbleBarLocation == location || location == null) {
+ return false;
+ } else {
+ mCurrentBubbleBarLocation = location;
+ return true;
+ }
+ }
+
+ /** Returns whether taskbar should be moved on the bubble bar location update. */
+ private boolean shouldMoveTaskbarOnBubbleBarLocationUpdate() {
+ return Flags.enableBubbleBarInPersistentTaskBar()
+ && mControllers.bubbleControllers.isPresent()
+ && mActivity.shouldStartAlignTaskbar()
+ && mActivity.isThreeButtonNav();
+ }
+
+ private void cancelTaskbarShiftAnimation() {
+ if (mTaskbarShiftXAnim != null) {
+ mTaskbarShiftXAnim.cancel();
+ }
+ }
+
/**
* Announcement for Accessibility when Taskbar stashes/unstashes.
*/
@@ -460,6 +523,17 @@
+ mTaskbarIconTranslationYForSpringOnStash);
}
+ private void updateTranslationXForNavBar() {
+ View[] iconViews = mTaskbarView.getIconViews();
+ float translationX = mIconsTranslationXForNavbar.value;
+ for (int iconIndex = 0; iconIndex < iconViews.length; iconIndex++) {
+ View iconView = iconViews[iconIndex];
+ MultiTranslateDelegate translateDelegate =
+ ((Reorderable) iconView).getTranslateDelegate();
+ translateDelegate.getTranslationX(INDEX_NAV_BAR_ANIM).setValue(translationX);
+ }
+ }
+
/**
* Computes translation y for taskbar pinning.
*/
@@ -763,7 +837,7 @@
// plays iconAlignment to 1 really fast, therefore moving the fading towards the end
// to avoid icons disappearing rather than fading out visually.
setter.setViewAlpha(child, 0, Interpolators.clampToProgress(LINEAR, 0.8f, 1f));
- } else if ((isAllAppsButton && !FeatureFlags.ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT.get())
+ } else if ((isAllAppsButton && !FeatureFlags.enableAllAppsButtonInHotseat())
|| (isTaskbarDividerView && enableTaskbarPinning())
|| (isRecentTask && !isRecentsInHotseat)) {
if (!isToHome
@@ -1018,4 +1092,12 @@
public static void enableModelLoadingForTests(boolean enable) {
sEnableModelLoadingForTests = enable;
}
+
+ private ObjectAnimator createTaskbarIconsShiftAnimator(float translationX) {
+ ObjectAnimator animator = mIconsTranslationXForNavbar.animateToValue(translationX);
+ animator.setStartDelay(FADE_OUT_ANIM_POSITION_DURATION_MS);
+ animator.setDuration(FADE_IN_ANIM_ALPHA_DURATION_MS);
+ animator.setInterpolator(Interpolators.EMPHASIZED);
+ return animator;
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java
index 5d91acd..a46845a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java
@@ -17,13 +17,10 @@
import android.content.Context;
import android.util.AttributeSet;
-import android.view.View;
import androidx.annotation.Nullable;
-import com.android.launcher3.R;
import com.android.launcher3.allapps.ActivityAllAppsContainerView;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext;
import java.util.Optional;
@@ -47,23 +44,6 @@
}
@Override
- protected View inflateSearchBar() {
- if (isSearchSupported()) {
- return super.inflateSearchBar();
- }
-
- // Remove top padding of header, since we do not have any search
- mHeader.setPadding(mHeader.getPaddingLeft(), 0,
- mHeader.getPaddingRight(), mHeader.getPaddingBottom());
-
- TaskbarAllAppsFallbackSearchContainer searchView =
- new TaskbarAllAppsFallbackSearchContainer(getContext(), null);
- searchView.setId(R.id.search_container_all_apps);
- searchView.setVisibility(GONE);
- return searchView;
- }
-
- @Override
public void invalidateHeader() {
super.invalidateHeader();
Optional.ofNullable(mOnInvalidateHeaderListener).ifPresent(
@@ -71,11 +51,6 @@
}
@Override
- protected boolean isSearchSupported() {
- return FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get();
- }
-
- @Override
public boolean isInAllApps() {
// All apps is always open
return true;
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsFallbackSearchContainer.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsFallbackSearchContainer.java
deleted file mode 100644
index 53fe06d..0000000
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsFallbackSearchContainer.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2022 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.allapps;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.ExtendedEditText;
-import com.android.launcher3.allapps.ActivityAllAppsContainerView;
-import com.android.launcher3.allapps.SearchUiManager;
-
-/** Empty search container for Taskbar All Apps used as a fallback if search is not supported. */
-public class TaskbarAllAppsFallbackSearchContainer extends View implements SearchUiManager {
- public TaskbarAllAppsFallbackSearchContainer(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public TaskbarAllAppsFallbackSearchContainer(
- Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
- @Override
- public void initializeSearch(ActivityAllAppsContainerView<?> containerView) {
- // Do nothing.
- }
-
- @Override
- public void resetSearch() {
- // Do nothing.
- }
-
- @Nullable
- @Override
- public ExtendedEditText getEditText() {
- return null;
- }
-}
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
index f5ac66f..5830095 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
@@ -39,7 +39,6 @@
import com.android.launcher3.R;
import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.anim.PendingAnimation;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.taskbar.allapps.TaskbarAllAppsViewController.TaskbarAllAppsCallbacks;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext;
import com.android.launcher3.util.Themes;
@@ -180,9 +179,7 @@
mContent = mAppsView;
// Setup header protection for search bar, if enabled.
- if (FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get()) {
- mAppsView.setOnInvalidateHeaderListener(this::invalidate);
- }
+ mAppsView.setOnInvalidateHeaderListener(this::invalidate);
DeviceProfile dp = mActivityContext.getDeviceProfile();
setShiftRange(dp.allAppsShiftRange);
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarSearchSessionController.kt b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarSearchSessionController.kt
index 4d0b376..6b72ab6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarSearchSessionController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarSearchSessionController.kt
@@ -21,7 +21,6 @@
import com.android.launcher3.R
import com.android.launcher3.allapps.AllAppsTransitionListener
import com.android.launcher3.anim.PendingAnimation
-import com.android.launcher3.config.FeatureFlags
import com.android.launcher3.dragndrop.DragOptions.PreDragCondition
import com.android.launcher3.model.data.ItemInfo
import com.android.launcher3.util.ResourceBasedOverride
@@ -61,16 +60,11 @@
companion object {
@JvmStatic
- fun newInstance(context: Context): TaskbarSearchSessionController {
- if (!FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get()) {
- return TaskbarSearchSessionController()
- }
-
- return Overrides.getObject(
+ fun newInstance(context: Context): TaskbarSearchSessionController =
+ Overrides.getObject(
TaskbarSearchSessionController::class.java,
context,
R.string.taskbar_search_session_controller_class,
)
- }
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
index d70a317..6860004 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
@@ -118,6 +118,7 @@
private Optional<BubbleStashedHandleViewController> mBubbleStashedHandleViewController;
private BubblePinController mBubblePinController;
private BubbleCreator mBubbleCreator;
+ private BubbleBarLocationListener mBubbleBarLocationListener;
// Cache last sent top coordinate to avoid sending duplicate updates to shell
private int mLastSentBubbleBarTop;
@@ -176,6 +177,7 @@
/** Initializes controllers. */
public void init(BubbleControllers bubbleControllers,
+ BubbleBarLocationListener bubbleBarLocationListener,
ImeVisibilityChecker imeVisibilityChecker) {
mImeVisibilityChecker = imeVisibilityChecker;
mBubbleBarViewController = bubbleControllers.bubbleBarViewController;
@@ -183,6 +185,7 @@
mBubbleStashedHandleViewController = bubbleControllers.bubbleStashedHandleViewController;
mBubblePinController = bubbleControllers.bubblePinController;
mBubbleCreator = bubbleControllers.bubbleCreator;
+ mBubbleBarLocationListener = bubbleBarLocationListener;
bubbleControllers.runAfterInit(() -> {
mBubbleBarViewController.setHiddenForBubbles(
@@ -488,12 +491,16 @@
private void updateBubbleBarLocationInternal(BubbleBarLocation location) {
mBubbleBarViewController.setBubbleBarLocation(location);
mBubbleStashController.setBubbleBarLocation(location);
+ mBubbleBarLocationListener.onBubbleBarLocationUpdated(location);
}
@Override
public void animateBubbleBarLocation(BubbleBarLocation bubbleBarLocation) {
MAIN_EXECUTOR.execute(
- () -> mBubbleBarViewController.animateBubbleBarLocation(bubbleBarLocation));
+ () -> {
+ mBubbleBarViewController.animateBubbleBarLocation(bubbleBarLocation);
+ mBubbleBarLocationListener.onBubbleBarLocationAnimated(bubbleBarLocation);
+ });
}
/** Notifies WMShell to show the expanded view. */
@@ -518,4 +525,14 @@
/** Whether the IME is visible. */
boolean isImeVisible();
}
+
+ /** Listener of {@link BubbleBarLocation} updates. */
+ public interface BubbleBarLocationListener {
+
+ /** Called when {@link BubbleBarLocation} is animated, but change is not yet final. */
+ void onBubbleBarLocationAnimated(BubbleBarLocation location);
+
+ /** Called when {@link BubbleBarLocation} is updated permanently. */
+ void onBubbleBarLocationUpdated(BubbleBarLocation location);
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarLocationCompositeListener.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarLocationCompositeListener.kt
new file mode 100644
index 0000000..8e176ac
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarLocationCompositeListener.kt
@@ -0,0 +1,35 @@
+/*
+ * 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
+
+import com.android.launcher3.taskbar.bubbles.BubbleBarController.BubbleBarLocationListener
+import com.android.wm.shell.shared.bubbles.BubbleBarLocation
+
+/** Composite implementation of [BubbleBarLocationListener] interface */
+class BubbleBarLocationCompositeListener(private val listeners: List<BubbleBarLocationListener>) :
+ BubbleBarLocationListener {
+
+ constructor(vararg listeners: BubbleBarLocationListener) : this(listOf(*listeners))
+
+ override fun onBubbleBarLocationAnimated(location: BubbleBarLocation?) {
+ listeners.forEach { it.onBubbleBarLocationAnimated(location) }
+ }
+
+ override fun onBubbleBarLocationUpdated(location: BubbleBarLocation?) {
+ listeners.forEach { it.onBubbleBarLocationUpdated(location) }
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarPinController.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarPinController.kt
index 9c34307..a34fab2 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarPinController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarPinController.kt
@@ -27,6 +27,7 @@
import android.widget.FrameLayout
import androidx.core.view.updateLayoutParams
import com.android.launcher3.R
+import com.android.launcher3.taskbar.bubbles.BubbleBarController.BubbleBarLocationListener
import com.android.launcher3.taskbar.bubbles.stashing.BubbleStashController
import com.android.wm.shell.shared.bubbles.BaseBubblePinController
import com.android.wm.shell.shared.bubbles.BubbleBarLocation
@@ -42,12 +43,17 @@
private lateinit var bubbleBarViewController: BubbleBarViewController
private lateinit var bubbleStashController: BubbleStashController
+ private lateinit var bubbleBarLocationListener: BubbleBarLocationListener
private var exclRectWidth: Float = 0f
private var exclRectHeight: Float = 0f
private var dropTargetView: View? = null
- fun init(bubbleControllers: BubbleControllers) {
+ fun init(
+ bubbleControllers: BubbleControllers,
+ bubbleBarLocationListener: BubbleBarLocationListener
+ ) {
+ this.bubbleBarLocationListener = bubbleBarLocationListener
bubbleBarViewController = bubbleControllers.bubbleBarViewController
bubbleStashController = bubbleControllers.bubbleStashController
exclRectWidth = context.resources.getDimension(R.dimen.bubblebar_dismiss_zone_width)
@@ -86,6 +92,7 @@
val bounds = bubbleBarViewController.bubbleBarBounds
val horizontalMargin = bubbleBarViewController.horizontalMargin
+ bubbleBarLocationListener.onBubbleBarLocationAnimated(location)
dropTargetView?.updateLayoutParams<FrameLayout.LayoutParams> {
width = bounds.width()
height = bounds.height()
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
index c005640..d454fd7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
@@ -95,11 +95,11 @@
private static final long FADE_OUT_ANIM_ALPHA_DURATION_MS = 50L;
private static final long FADE_OUT_ANIM_ALPHA_DELAY_MS = 50L;
- private static final long FADE_OUT_ANIM_POSITION_DURATION_MS = 100L;
+ public static final long FADE_OUT_ANIM_POSITION_DURATION_MS = 100L;
// During fade out animation we shift the bubble bar 1/80th of the screen width
private static final float FADE_OUT_ANIM_POSITION_SHIFT = 1 / 80f;
- private static final long FADE_IN_ANIM_ALPHA_DURATION_MS = 100L;
+ public static final long FADE_IN_ANIM_ALPHA_DURATION_MS = 100L;
// Use STIFFNESS_MEDIUMLOW which is not defined in the API constants
private static final float FADE_IN_ANIM_POSITION_SPRING_STIFFNESS = 400f;
// During fade in animation we shift the bubble bar 1/60th of the screen width
@@ -689,7 +689,7 @@
}
setAlphaDuringBubbleDrag(1f);
setTranslationX(0f);
- if (getBubbleChildCount() > 0) {
+ if (mIsBarExpanded && getBubbleChildCount() > 0) {
setAlpha(1f);
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
index ed08de5..025c038 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
@@ -440,7 +440,7 @@
if (hidden) {
mBarView.setAlpha(0);
mBarView.setExpanded(false);
- updatePersistentTaskbar(/* isBubbleBarExpanded = */ false);
+ adjustTaskbarAndHotseatToBubbleBarState(/* isBubbleBarExpanded = */ false);
}
mActivity.bubbleBarVisibilityChanged(!hidden);
}
@@ -735,7 +735,7 @@
public void setExpanded(boolean isExpanded) {
if (isExpanded != mBarView.isExpanded()) {
mBarView.setExpanded(isExpanded);
- updatePersistentTaskbar(isExpanded);
+ adjustTaskbarAndHotseatToBubbleBarState(isExpanded);
if (!isExpanded) {
mSystemUiProxy.collapseBubbles();
} else {
@@ -746,13 +746,25 @@
}
}
- private void updatePersistentTaskbar(boolean isBubbleBarExpanded) {
- if (mBubbleStashController.isTransientTaskBar()) return;
- boolean hideTaskbar = isBubbleBarExpanded && isIntersectingTaskbar();
- mTaskbarViewPropertiesProvider
- .getIconsAlpha()
- .animateToValue(hideTaskbar ? 0 : 1)
- .start();
+ /**
+ * Hides the persistent taskbar if it is going to intersect with the expanded bubble bar if in
+ * app or overview. Set the hotseat stashed state if on launcher home screen. If not on launcher
+ * home screen and hotseat is stashed immediately un-stashes the hotseat.
+ */
+ private void adjustTaskbarAndHotseatToBubbleBarState(boolean isBubbleBarExpanded) {
+ if (mBubbleStashController.isBubblesShowingOnHome()) {
+ mTaskbarStashController.stashHotseat(isBubbleBarExpanded);
+ } else if (!mBubbleStashController.isTransientTaskBar()) {
+ boolean hideTaskbar = isBubbleBarExpanded && isIntersectingTaskbar();
+ mTaskbarViewPropertiesProvider
+ .getIconsAlpha()
+ .animateToValue(hideTaskbar ? 0 : 1)
+ .start();
+ }
+ if (!mBubbleStashController.isBubblesShowingOnHome()
+ && mTaskbarStashController.isHiddenForBubbles()) {
+ mTaskbarStashController.unStashHotseatInstantly();
+ }
}
/** Return {@code true} if expanded bubble bar would intersect the taskbar. */
@@ -871,6 +883,11 @@
mBoundsChangeListener = listener;
}
+ /** Called when the controller is destroyed. */
+ public void onDestroy() {
+ adjustTaskbarAndHotseatToBubbleBarState(/*isBubbleBarExpanded = */false);
+ }
+
/**
* Create an animator for showing or hiding bubbles when stashed state changes
*
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
index e00916a..a66df4c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
@@ -76,7 +76,14 @@
* in constructors for now, as some controllers may still be waiting for init().
*/
public void init(TaskbarControllers taskbarControllers) {
+ // TODO(b/346381754) add TaskbarLauncherStateController implementation to adjust the hotseat
+ BubbleBarLocationCompositeListener bubbleBarLocationListeners =
+ new BubbleBarLocationCompositeListener(
+ taskbarControllers.navbarButtonsViewController,
+ taskbarControllers.taskbarViewController
+ );
bubbleBarController.init(this,
+ bubbleBarLocationListeners,
taskbarControllers.navbarButtonsViewController::isImeVisible);
bubbleStashedHandleViewController.ifPresent(
controller -> controller.init(/* bubbleControllers = */ this));
@@ -102,7 +109,7 @@
});
bubbleDragController.init(/* bubbleControllers = */ this);
bubbleDismissController.init(/* bubbleControllers = */ this);
- bubbleBarPinController.init(this);
+ bubbleBarPinController.init(this, bubbleBarLocationListeners);
bubblePinController.init(this);
mPostInitRunnables.executeAllAndDestroy();
@@ -124,6 +131,7 @@
public void onDestroy() {
bubbleStashedHandleViewController.ifPresent(BubbleStashedHandleViewController::onDestroy);
bubbleBarController.onDestroy();
+ bubbleBarViewController.onDestroy();
}
/** Dumps bubble controllers state. */
diff --git a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarAllAppsButtonContainer.kt b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarAllAppsButtonContainer.kt
index 726800c..e6c0b2f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarAllAppsButtonContainer.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarAllAppsButtonContainer.kt
@@ -30,7 +30,6 @@
import androidx.core.view.setPadding
import com.android.launcher3.R
import com.android.launcher3.Utilities.dpToPx
-import com.android.launcher3.config.FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR
import com.android.launcher3.config.FeatureFlags.enableTaskbarPinning
import com.android.launcher3.taskbar.TaskbarActivityContext
import com.android.launcher3.taskbar.TaskbarViewCallbacks
@@ -43,11 +42,8 @@
/** Taskbar all apps button container for customizable taskbar. */
class TaskbarAllAppsButtonContainer
@JvmOverloads
-constructor(
- context: Context,
- attrs: AttributeSet? = null,
- defStyleAttr: Int = 0,
-) : IconButtonView(context, attrs), TaskbarContainer {
+constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
+ IconButtonView(context, attrs), TaskbarContainer {
private val activityContext: TaskbarActivityContext = ActivityContext.lookupContext(context)
private var allAppsTouchTriggered = false
@@ -101,23 +97,16 @@
private fun getAllAppsButton(isTransientTaskbar: Boolean): Int {
val shouldSelectTransientIcon =
isTransientTaskbar || (enableTaskbarPinning() && !activityContext.isThreeButtonNav)
- return if (ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get()) {
- if (shouldSelectTransientIcon) R.drawable.ic_transient_taskbar_all_apps_search_button
- else R.drawable.ic_taskbar_all_apps_search_button
- } else {
- if (shouldSelectTransientIcon) R.drawable.ic_transient_taskbar_all_apps_button
- else R.drawable.ic_taskbar_all_apps_button
- }
+ return if (shouldSelectTransientIcon) R.drawable.ic_transient_taskbar_all_apps_search_button
+ else R.drawable.ic_taskbar_all_apps_search_button
}
@DimenRes
fun getAllAppsButtonTranslationXOffset(isTransientTaskbar: Boolean): Int {
return if (isTransientTaskbar) {
R.dimen.transient_taskbar_all_apps_button_translation_x_offset
- } else if (ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get()) {
- R.dimen.taskbar_all_apps_search_button_translation_x_offset
} else {
- R.dimen.taskbar_all_apps_button_translation_x_offset
+ R.dimen.taskbar_all_apps_search_button_translation_x_offset
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java
index 93cbdc7..26a1322 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java
@@ -29,7 +29,6 @@
import android.widget.RemoteViews;
import android.window.SplashScreen;
-import com.android.launcher3.Utilities;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.util.ActivityOptionsWrapper;
@@ -66,7 +65,7 @@
Pair<Intent, ActivityOptions> options = remoteResponse.getLaunchOptions(view);
ActivityOptionsWrapper activityOptions = mLauncher.getAppTransitionManager()
.getActivityLaunchOptions(hostView, (ItemInfo) hostView.getTag());
- if (Utilities.ATLEAST_S && !pendingIntent.isActivity()) {
+ if (!pendingIntent.isActivity()) {
// In the event this pending intent eventually launches an activity, i.e. a trampoline,
// use the Quickstep transition animation.
try {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 1f5cd3a..e80e838 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -19,6 +19,7 @@
import static android.os.Trace.TRACE_TAG_APP;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_OPTIMIZE_MEASURE;
import static android.view.accessibility.AccessibilityEvent.TYPE_VIEW_FOCUSED;
+import static android.window.flags.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY;
import static com.android.app.animation.Interpolators.EMPHASIZED;
import static com.android.internal.jank.Cuj.CUJ_LAUNCHER_LAUNCH_APP_PAIR_FROM_WORKSPACE;
@@ -64,7 +65,6 @@
import static com.android.quickstep.util.AnimUtils.completeRunnableListCallback;
import static com.android.quickstep.util.SplitAnimationTimings.TABLET_HOME_TO_SPLIT;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
-import static com.android.wm.shell.shared.desktopmode.DesktopModeFlags.WALLPAPER_ACTIVITY;
import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_50_50;
import android.animation.Animator;
@@ -1003,7 +1003,7 @@
@Override
public void setResumed() {
DesktopVisibilityController desktopVisibilityController = getDesktopVisibilityController();
- if (!WALLPAPER_ACTIVITY.isEnabled(this)
+ if (!ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY.isTrue()
&& desktopVisibilityController != null
&& desktopVisibilityController.areDesktopTasksVisible()
&& !desktopVisibilityController.isRecentsGestureInProgress()) {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
index 11e0ed5..1d9e492 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
@@ -45,6 +45,7 @@
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.contextualeducation.ContextualEduStatsManager;
import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.touch.SingleAxisSwipeDetector;
import com.android.launcher3.util.DisplayController;
@@ -53,6 +54,7 @@
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.OverviewToHomeAnim;
import com.android.quickstep.views.RecentsView;
+import com.android.systemui.contextualeducation.GestureType;
import java.util.function.BiConsumer;
@@ -219,6 +221,8 @@
}
if (mStartState != mEndState) {
logHomeGesture();
+ ContextualEduStatsManager.INSTANCE.get(mLauncher).updateEduStats(
+ mSwipeDetector.isTrackpadGesture(), GestureType.HOME);
}
AbstractFloatingView topOpenView = AbstractFloatingView.getTopOpenView(mLauncher);
if (topOpenView != null) {
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 240d6ad..a6d651c 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -92,6 +92,7 @@
import android.view.animation.Interpolator;
import android.widget.Toast;
import android.window.PictureInPictureSurfaceTransaction;
+import android.window.flags.DesktopModeFlags;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -152,7 +153,6 @@
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListeners;
import com.android.wm.shell.shared.TransactionPool;
-import com.android.wm.shell.shared.desktopmode.DesktopModeFlags;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
import com.android.wm.shell.shared.startingsurface.SplashScreenExitAnimationUtils;
@@ -1256,8 +1256,8 @@
? mRecentsView.getCurrentPageTaskView() : null;
if (DesktopModeStatus.canEnterDesktopMode(mContext)
- && !(DesktopModeFlags.WALLPAPER_ACTIVITY.isEnabled(mContext)
- && DesktopModeFlags.QUICK_SWITCH.isEnabled(mContext))) {
+ && !(DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY.isTrue()
+ && DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_QUICK_SWITCH.isTrue())) {
if ((nextPageTaskView instanceof DesktopTaskView
|| currentPageTaskView instanceof DesktopTaskView)
&& endTarget == NEW_TASK) {
@@ -1423,8 +1423,8 @@
};
if (DesktopModeStatus.canEnterDesktopMode(mContext)
- && !(DesktopModeFlags.WALLPAPER_ACTIVITY.isEnabled(mContext)
- && DesktopModeFlags.QUICK_SWITCH.isEnabled(mContext))) {
+ && !(DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY.isTrue()
+ && DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_QUICK_SWITCH.isTrue())) {
if (mRecentsView != null && (mRecentsView.getCurrentPageTaskView() != null
&& !(mRecentsView.getCurrentPageTaskView() instanceof DesktopTaskView))) {
ActiveGestureLog.INSTANCE.trackEvent(ActiveGestureErrorDetector.GestureEvent
@@ -2249,8 +2249,8 @@
});
if (DesktopModeStatus.canEnterDesktopMode(mContext)
- && !(DesktopModeFlags.WALLPAPER_ACTIVITY.isEnabled(mContext)
- && DesktopModeFlags.QUICK_SWITCH.isEnabled(mContext))) {
+ && !(DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY.isTrue()
+ && DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_QUICK_SWITCH.isTrue())) {
if (mRecentsView.getNextPageTaskView() instanceof DesktopTaskView
|| mRecentsView.getCurrentPageTaskView() instanceof DesktopTaskView) {
mRecentsViewScrollLinked = false;
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.kt b/quickstep/src/com/android/quickstep/OverviewCommandHelper.kt
index f92c557..520bec3 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.kt
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.kt
@@ -80,14 +80,6 @@
*/
private var keyboardTaskFocusIndex = -1
- /**
- * Whether we should incoming toggle commands while a previous toggle command is still ongoing.
- * This serves as a rate-limiter to prevent overlapping animations that can clobber each other
- * and prevent clean-up callbacks from running. This thus prevents a recurring set of bugs with
- * janky recents animations and unresponsive home and overview buttons.
- */
- private var waitForToggleCommandComplete = false
-
private val activityInterface: BaseActivityInterface<*, *>
get() = overviewComponentObserver.activityInterface
@@ -174,12 +166,6 @@
*/
@VisibleForTesting
fun executeCommand(command: CommandInfo, onCallbackResult: () -> Unit): Boolean {
- // This shouldn't happen if we execute 1 command per time.
- if (waitForToggleCommandComplete && command.type == TOGGLE) {
- Log.d(TAG, "executeCommand: $command - waiting for toggle command complete")
- return true
- }
-
val recentsView = visibleRecentsView
Log.d(TAG, "executeCommand: $command - visibleRecentsView: $recentsView")
return if (recentsView != null) {
@@ -251,7 +237,6 @@
): Boolean {
var callbackList: RunnableList? = null
if (taskView != null) {
- waitForToggleCommandComplete = true
taskView.isEndQuickSwitchCuj = true
callbackList = taskView.launchWithAnimation()
}
@@ -260,13 +245,11 @@
callbackList.add {
Log.d(TAG, "launching task callback: $command")
onCallbackResult()
- waitForToggleCommandComplete = false
}
Log.d(TAG, "launching task - waiting for callback: $command")
return false
} else {
recents.startHome()
- waitForToggleCommandComplete = false
return true
}
}
@@ -517,7 +500,6 @@
pw.println(" pendingCommandType=${commandQueue.first().type}")
}
pw.println(" keyboardTaskFocusIndex=$keyboardTaskFocusIndex")
- pw.println(" waitForToggleCommandComplete=$waitForToggleCommandComplete")
}
@VisibleForTesting
diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java
index a01ceb2..d073580 100644
--- a/quickstep/src/com/android/quickstep/RecentsModel.java
+++ b/quickstep/src/com/android/quickstep/RecentsModel.java
@@ -56,6 +56,7 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
@@ -76,7 +77,8 @@
private static final Executor RECENTS_MODEL_EXECUTOR = Executors.newSingleThreadExecutor(
new SimpleThreadFactory("TaskThumbnailIconCache-", THREAD_PRIORITY_BACKGROUND));
- private final List<TaskVisualsChangeListener> mThumbnailChangeListeners = new ArrayList<>();
+ private final ConcurrentLinkedQueue<TaskVisualsChangeListener> mThumbnailChangeListeners =
+ new ConcurrentLinkedQueue<>();
private final Context mContext;
private final RecentTasksList mTaskList;
@@ -239,8 +241,8 @@
public boolean onTaskSnapshotChanged(int taskId, ThumbnailData snapshot) {
mThumbnailCache.updateTaskSnapShot(taskId, snapshot);
- for (int i = mThumbnailChangeListeners.size() - 1; i >= 0; i--) {
- Task task = mThumbnailChangeListeners.get(i).onTaskThumbnailChanged(taskId, snapshot);
+ for (TaskVisualsChangeListener listener : mThumbnailChangeListeners) {
+ Task task = listener.onTaskThumbnailChanged(taskId, snapshot);
if (task != null) {
task.thumbnail = snapshot;
}
@@ -269,8 +271,8 @@
@Override
public void onAppIconChanged(String packageName, UserHandle user) {
mIconCache.invalidateCacheEntries(packageName, user);
- for (int i = mThumbnailChangeListeners.size() - 1; i >= 0; i--) {
- mThumbnailChangeListeners.get(i).onTaskIconChanged(packageName, user);
+ for (TaskVisualsChangeListener listener : mThumbnailChangeListeners) {
+ listener.onTaskIconChanged(packageName, user);
}
}
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index b4bd3e3..f9b4dab 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -51,6 +51,7 @@
import android.window.RemoteTransition;
import android.window.TaskSnapshot;
import android.window.TransitionFilter;
+import android.window.flags.DesktopModeFlags;
import androidx.annotation.MainThread;
import androidx.annotation.Nullable;
@@ -85,14 +86,13 @@
import com.android.wm.shell.desktopmode.IDesktopTaskListener;
import com.android.wm.shell.draganddrop.IDragAndDrop;
import com.android.wm.shell.onehanded.IOneHanded;
-import com.android.wm.shell.recents.IRecentsAnimationController;
-import com.android.wm.shell.recents.IRecentsAnimationRunner;
import com.android.wm.shell.recents.IRecentTasks;
import com.android.wm.shell.recents.IRecentTasksListener;
+import com.android.wm.shell.recents.IRecentsAnimationController;
+import com.android.wm.shell.recents.IRecentsAnimationRunner;
import com.android.wm.shell.shared.GroupedRecentTaskInfo;
import com.android.wm.shell.shared.IShellTransitions;
import com.android.wm.shell.shared.bubbles.BubbleBarLocation;
-import com.android.wm.shell.shared.desktopmode.DesktopModeFlags;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource;
import com.android.wm.shell.shared.split.SplitBounds;
@@ -1395,7 +1395,7 @@
private boolean shouldEnableRunningTasksForDesktopMode() {
return DesktopModeStatus.canEnterDesktopMode(mContext)
- && DesktopModeFlags.TASKBAR_RUNNING_APPS.isEnabled(mContext);
+ && DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_TASKBAR_RUNNING_APPS.isTrue();
}
private boolean handleMessageAsync(Message msg) {
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 44e55c3..178636e 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -15,7 +15,6 @@
*/
package com.android.quickstep;
-import static android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS;
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_MOVE;
@@ -26,7 +25,6 @@
import static com.android.launcher3.Flags.enableCursorHoverStates;
import static com.android.launcher3.Flags.enableHandleDelayedGestureCallbacks;
import static com.android.launcher3.Flags.useActivityOverlay;
-import static com.android.launcher3.Launcher.INTENT_ACTION_ALL_APPS_TOGGLE;
import static com.android.launcher3.LauncherPrefs.backedUpItem;
import static com.android.launcher3.MotionEventsUtils.isTrackpadMotionEvent;
import static com.android.launcher3.MotionEventsUtils.isTrackpadMultiFingerSwipe;
@@ -91,7 +89,6 @@
import com.android.launcher3.Flags;
import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.anim.AnimatedFloat;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.provider.RestoreDbTask;
import com.android.launcher3.statehandlers.DesktopVisibilityController;
import com.android.launcher3.statemanager.StatefulActivity;
@@ -774,23 +771,14 @@
}
private PendingIntent createAllAppsPendingIntent() {
- if (FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get()) {
- return new PendingIntent(new IIntentSender.Stub() {
- @Override
- public void send(int code, Intent intent, String resolvedType,
- IBinder allowlistToken, IIntentReceiver finishedReceiver,
- String requiredPermission, Bundle options) {
- MAIN_EXECUTOR.execute(() -> mTaskbarManager.toggleAllApps());
- }
- });
- } else {
- return PendingIntent.getActivity(
- this,
- GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS,
- new Intent(mOverviewComponentObserver.getHomeIntent())
- .setAction(INTENT_ACTION_ALL_APPS_TOGGLE),
- PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
- }
+ return new PendingIntent(new IIntentSender.Stub() {
+ @Override
+ public void send(int code, Intent intent, String resolvedType,
+ IBinder allowlistToken, IIntentReceiver finishedReceiver,
+ String requiredPermission, Bundle options) {
+ MAIN_EXECUTOR.execute(() -> mTaskbarManager.toggleAllApps());
+ }
+ });
}
@UiThread
diff --git a/quickstep/src/com/android/quickstep/dagger/QuickStepModule.java b/quickstep/src/com/android/quickstep/dagger/QuickStepModule.java
index db29636..08345b8 100644
--- a/quickstep/src/com/android/quickstep/dagger/QuickStepModule.java
+++ b/quickstep/src/com/android/quickstep/dagger/QuickStepModule.java
@@ -15,10 +15,8 @@
*/
package com.android.quickstep.dagger;
-import com.android.quickstep.logging.LoggingModule;
-
import dagger.Module;
-@Module(includes = {LoggingModule.class})
+@Module
public class QuickStepModule {
}
diff --git a/quickstep/src/com/android/quickstep/dagger/QuickstepBaseAppComponent.java b/quickstep/src/com/android/quickstep/dagger/QuickstepBaseAppComponent.java
new file mode 100644
index 0000000..f2d5715
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/dagger/QuickstepBaseAppComponent.java
@@ -0,0 +1,33 @@
+/*
+ * 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.quickstep.dagger;
+
+import com.android.launcher3.dagger.LauncherAppComponent;
+import com.android.launcher3.dagger.LauncherBaseAppComponent;
+import com.android.quickstep.logging.SettingsChangeLogger;
+
+/**
+ * Launcher Quickstep base component for Dagger injection.
+ *
+ * This class is not actually annotated as a Dagger component, since it is not used directly as one.
+ * Doing so generates unnecessary code bloat.
+ *
+ * See {@link LauncherAppComponent} for the one actually used.
+ */
+public interface QuickstepBaseAppComponent extends LauncherBaseAppComponent {
+ SettingsChangeLogger getSettingsChangeLogger();
+}
diff --git a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
index 1bec970..f7f3157 100644
--- a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
@@ -62,6 +62,7 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatedFloat;
@@ -103,6 +104,9 @@
private final AnimatedFloat mSwipeProgress = new AnimatedFloat(this::onSwipeProgressUpdate);
+ private final InvariantDeviceProfile.OnIDPChangeListener mOnIDPChangeListener =
+ modelPropertiesChanged -> updateHint();
+
private TISBindHelper mTISBindHelper;
private BgDrawable mBackground;
@@ -115,6 +119,8 @@
private AnimatorPlaybackController mLauncherStartAnim = null;
+ private TextView mHintView;
+
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -167,12 +173,9 @@
}
});
- TextView hint = findViewById(R.id.hint);
- DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(this).getDeviceProfile(this);
- if (!dp.isGestureMode) {
- hint.setText(R.string.allset_button_hint);
- }
- hint.setAccessibilityDelegate(new SkipButtonAccessibilityDelegate());
+ mHintView = findViewById(R.id.hint);
+ mHintView.setAccessibilityDelegate(new SkipButtonAccessibilityDelegate());
+ updateHint();
mTISBindHelper = new TISBindHelper(this, this::onTISConnected);
@@ -190,7 +193,21 @@
LOTTIE_TERTIARY_COLOR_TOKEN, R.color.all_set_bg_tertiary),
getTheme());
- startBackgroundAnimation(dp.isTablet);
+ startBackgroundAnimation(getDP().isTablet);
+ getIDP().addOnChangeListener(mOnIDPChangeListener);
+ }
+
+ private InvariantDeviceProfile getIDP() {
+ return LauncherAppState.getInstance(this).getInvariantDeviceProfile();
+ }
+
+ private DeviceProfile getDP() {
+ return getIDP().getDeviceProfile(this);
+ }
+
+ private void updateHint() {
+ mHintView.setText(
+ getDP().isGestureMode ? R.string.allset_hint : R.string.allset_button_hint);
}
private void runOnUiHelperThread(Runnable runnable) {
@@ -202,7 +219,7 @@
}
private void startBackgroundAnimation(boolean forTablet) {
- if (!Utilities.ATLEAST_S || mVibrator == null) {
+ if (mVibrator == null) {
return;
}
boolean supportsThud = mVibrator.areAllPrimitivesSupported(
@@ -311,6 +328,7 @@
@Override
protected void onDestroy() {
super.onDestroy();
+ getIDP().removeOnChangeListener(mOnIDPChangeListener);
mTISBindHelper.onDestroy();
clearBinderOverride();
if (mBackgroundAnimatorListener != null) {
diff --git a/quickstep/src/com/android/quickstep/logging/LoggingModule.java b/quickstep/src/com/android/quickstep/logging/LoggingModule.java
deleted file mode 100644
index 8fdf3c7..0000000
--- a/quickstep/src/com/android/quickstep/logging/LoggingModule.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.quickstep.logging;
-
-import android.content.Context;
-
-import com.android.launcher3.dagger.ApplicationContext;
-import com.android.launcher3.dagger.LauncherAppSingleton;
-
-import dagger.Module;
-import dagger.Provides;
-
-@Module
-public class LoggingModule {
- @Provides
- @LauncherAppSingleton
- SettingsChangeLogger provideSettingsChangeLogger(@ApplicationContext Context context) {
- return SettingsChangeLogger.INSTANCE.get(context);
- }
-}
diff --git a/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java b/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
index 717f6c8..995635f 100644
--- a/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
+++ b/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
@@ -43,16 +43,21 @@
import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.R;
+import com.android.launcher3.dagger.ApplicationContext;
+import com.android.launcher3.dagger.LauncherAppSingleton;
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.logging.StatsLogManager.StatsLogger;
import com.android.launcher3.model.DeviceGridState;
+import com.android.launcher3.util.DaggerSingletonObject;
+import com.android.launcher3.util.DaggerSingletonTracker;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.Info;
-import com.android.launcher3.util.MainThreadInitializedObject;
+import com.android.launcher3.util.ExecutorUtil;
import com.android.launcher3.util.NavigationMode;
import com.android.launcher3.util.SafeCloseable;
import com.android.launcher3.util.SettingsCache;
+import com.android.quickstep.dagger.QuickstepBaseAppComponent;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -60,9 +65,12 @@
import java.io.IOException;
import java.util.Optional;
+import javax.inject.Inject;
+
/**
* Utility class to log launcher settings changes
*/
+@LauncherAppSingleton
public class SettingsChangeLogger implements
DisplayController.DisplayInfoChangeListener, OnSharedPreferenceChangeListener,
SafeCloseable {
@@ -70,8 +78,8 @@
/**
* Singleton instance
*/
- public static MainThreadInitializedObject<SettingsChangeLogger> INSTANCE =
- new MainThreadInitializedObject<>(SettingsChangeLogger::new);
+ public static DaggerSingletonObject<SettingsChangeLogger> INSTANCE =
+ new DaggerSingletonObject<>(QuickstepBaseAppComponent::getSettingsChangeLogger);
private static final String TAG = "SettingsChangeLogger";
private static final String BOOLEAN_PREF = "SwitchPreference";
@@ -84,25 +92,31 @@
private StatsLogManager.LauncherEvent mNotificationDotsEvent;
private StatsLogManager.LauncherEvent mHomeScreenSuggestionEvent;
- private SettingsChangeLogger(Context context) {
- this(context, StatsLogManager.newInstance(context));
+ @Inject
+ SettingsChangeLogger(@ApplicationContext Context context, DaggerSingletonTracker tracker) {
+ this(context, StatsLogManager.newInstance(context), tracker);
}
@VisibleForTesting
- SettingsChangeLogger(Context context, StatsLogManager statsLogManager) {
+ SettingsChangeLogger(Context context, StatsLogManager statsLogManager,
+ DaggerSingletonTracker tracker) {
mContext = context;
mStatsLogManager = statsLogManager;
mLoggablePrefs = loadPrefKeys(context);
- DisplayController.INSTANCE.get(context).addChangeListener(this);
- mNavMode = DisplayController.getNavigationMode(context);
- getPrefs(context).registerOnSharedPreferenceChangeListener(this);
- getDevicePrefs(context).registerOnSharedPreferenceChangeListener(this);
+ ExecutorUtil.executeSyncOnMainOrFail(() -> {
+ DisplayController.INSTANCE.get(context).addChangeListener(this);
+ mNavMode = DisplayController.getNavigationMode(context);
- SettingsCache mSettingsCache = SettingsCache.INSTANCE.get(context);
- mSettingsCache.register(NOTIFICATION_BADGING_URI,
- this::onNotificationDotsChanged);
- onNotificationDotsChanged(mSettingsCache.getValue(NOTIFICATION_BADGING_URI));
+ getPrefs(context).registerOnSharedPreferenceChangeListener(this);
+ getDevicePrefs(context).registerOnSharedPreferenceChangeListener(this);
+
+ SettingsCache settingsCache = SettingsCache.INSTANCE.get(context);
+ settingsCache.register(NOTIFICATION_BADGING_URI,
+ this::onNotificationDotsChanged);
+ onNotificationDotsChanged(settingsCache.getValue(NOTIFICATION_BADGING_URI));
+ tracker.addCloseable(this);
+ });
}
private static ArrayMap<String, LoggablePref> loadPrefKeys(Context context) {
@@ -209,6 +223,8 @@
public void close() {
getPrefs(mContext).unregisterOnSharedPreferenceChangeListener(this);
getDevicePrefs(mContext).unregisterOnSharedPreferenceChangeListener(this);
+ SettingsCache settingsCache = SettingsCache.INSTANCE.get(mContext);
+ settingsCache.unregister(NOTIFICATION_BADGING_URI, this::onNotificationDotsChanged);
}
@VisibleForTesting
diff --git a/quickstep/src/com/android/quickstep/recents/data/TaskVisualsChangedDelegate.kt b/quickstep/src/com/android/quickstep/recents/data/TaskVisualsChangedDelegate.kt
index a141e89..a45d194 100644
--- a/quickstep/src/com/android/quickstep/recents/data/TaskVisualsChangedDelegate.kt
+++ b/quickstep/src/com/android/quickstep/recents/data/TaskVisualsChangedDelegate.kt
@@ -23,6 +23,7 @@
import com.android.quickstep.util.TaskVisualsChangeListener
import com.android.systemui.shared.recents.model.Task
import com.android.systemui.shared.recents.model.ThumbnailData
+import java.util.concurrent.ConcurrentHashMap
/** Delegates the checking of task visuals (thumbnails, high res changes, icons) */
interface TaskVisualsChangedDelegate :
@@ -30,7 +31,7 @@
/** Registers a callback for visuals relating to icons */
fun registerTaskIconChangedCallback(
taskKey: Task.TaskKey,
- taskIconChangedCallback: TaskIconChangedCallback
+ taskIconChangedCallback: TaskIconChangedCallback,
)
/** Unregisters a callback for visuals relating to icons */
@@ -39,7 +40,7 @@
/** Registers a callback for visuals relating to thumbnails */
fun registerTaskThumbnailChangedCallback(
taskKey: Task.TaskKey,
- taskThumbnailChangedCallback: TaskThumbnailChangedCallback
+ taskThumbnailChangedCallback: TaskThumbnailChangedCallback,
)
/** Unregisters a callback for visuals relating to thumbnails */
@@ -66,31 +67,9 @@
private val highResLoadingStateNotifier: HighResLoadingStateNotifier,
) : TaskVisualsChangedDelegate {
private val taskIconChangedCallbacks =
- mutableMapOf<Int, Pair<Task.TaskKey, TaskIconChangedCallback>>()
+ ConcurrentHashMap<Int, Pair<Task.TaskKey, TaskIconChangedCallback>>()
private val taskThumbnailChangedCallbacks =
- mutableMapOf<Int, Pair<Task.TaskKey, TaskThumbnailChangedCallback>>()
- private var isListening = false
-
- @Synchronized
- private fun onCallbackRegistered() {
- if (isListening) return
-
- taskVisualsChangeNotifier.addThumbnailChangeListener(this)
- highResLoadingStateNotifier.addCallback(this)
- isListening = true
- }
-
- @Synchronized
- private fun onCallbackUnregistered() {
- if (!isListening) return
-
- if (taskIconChangedCallbacks.size + taskThumbnailChangedCallbacks.size == 0) {
- taskVisualsChangeNotifier.removeThumbnailChangeListener(this)
- highResLoadingStateNotifier.removeCallback(this)
- }
-
- isListening = false
- }
+ ConcurrentHashMap<Int, Pair<Task.TaskKey, TaskThumbnailChangedCallback>>()
override fun onTaskIconChanged(taskId: Int) {
taskIconChangedCallbacks[taskId]?.let { (_, callback) -> callback.onTaskIconChanged() }
@@ -119,27 +98,48 @@
override fun registerTaskIconChangedCallback(
taskKey: Task.TaskKey,
- taskIconChangedCallback: TaskIconChangedCallback
+ taskIconChangedCallback: TaskIconChangedCallback,
) {
- taskIconChangedCallbacks[taskKey.id] = taskKey to taskIconChangedCallback
- onCallbackRegistered()
+ updateCallbacks {
+ taskIconChangedCallbacks[taskKey.id] = taskKey to taskIconChangedCallback
+ }
}
override fun unregisterTaskIconChangedCallback(taskKey: Task.TaskKey) {
- taskIconChangedCallbacks.remove(taskKey.id)
- onCallbackUnregistered()
+ updateCallbacks { taskIconChangedCallbacks.remove(taskKey.id) }
}
override fun registerTaskThumbnailChangedCallback(
taskKey: Task.TaskKey,
- taskThumbnailChangedCallback: TaskThumbnailChangedCallback
+ taskThumbnailChangedCallback: TaskThumbnailChangedCallback,
) {
- taskThumbnailChangedCallbacks[taskKey.id] = taskKey to taskThumbnailChangedCallback
- onCallbackRegistered()
+ updateCallbacks {
+ taskThumbnailChangedCallbacks[taskKey.id] = taskKey to taskThumbnailChangedCallback
+ }
}
override fun unregisterTaskThumbnailChangedCallback(taskKey: Task.TaskKey) {
- taskThumbnailChangedCallbacks.remove(taskKey.id)
- onCallbackUnregistered()
+ updateCallbacks { taskThumbnailChangedCallbacks.remove(taskKey.id) }
+ }
+
+ @Synchronized
+ private fun updateCallbacks(callbackModifier: () -> Unit) {
+ val prevHasCallbacks =
+ taskIconChangedCallbacks.size + taskThumbnailChangedCallbacks.size > 0
+ callbackModifier()
+
+ val currHasCallbacks =
+ taskIconChangedCallbacks.size + taskThumbnailChangedCallbacks.size > 0
+
+ when {
+ prevHasCallbacks && !currHasCallbacks -> {
+ taskVisualsChangeNotifier.removeThumbnailChangeListener(this)
+ highResLoadingStateNotifier.removeCallback(this)
+ }
+ !prevHasCallbacks && currHasCallbacks -> {
+ taskVisualsChangeNotifier.addThumbnailChangeListener(this)
+ highResLoadingStateNotifier.addCallback(this)
+ }
+ }
}
}
diff --git a/quickstep/src/com/android/quickstep/util/RecentsViewUtils.kt b/quickstep/src/com/android/quickstep/util/RecentsViewUtils.kt
index 595aa00..be1af64 100644
--- a/quickstep/src/com/android/quickstep/util/RecentsViewUtils.kt
+++ b/quickstep/src/com/android/quickstep/util/RecentsViewUtils.kt
@@ -28,9 +28,17 @@
* and extracted functions from RecentsView to facilitate the implementation of unit tests.
*/
class RecentsViewUtils {
+ /** Takes a screenshot of all [taskView] and return map of taskId to the screenshot */
+ fun screenshotTasks(
+ taskView: TaskView,
+ recentsAnimationController: RecentsAnimationController,
+ ): Map<Int, ThumbnailData> =
+ taskView.taskContainers.associate {
+ it.task.key.id to recentsAnimationController.screenshotTask(it.task.key.id)
+ }
/**
- * Sort task groups to move desktop tasks to the end of the list.
+ * Sorts task groups to move desktop tasks to the end of the list.
*
* @param tasks List of group tasks to be sorted.
* @return Sorted list of GroupTasks to be used in the RecentsView.
@@ -40,6 +48,7 @@
return otherTasks + desktopTasks
}
+ /** Returns the expected index of the focus task. */
fun getFocusedTaskIndex(taskGroups: List<GroupTask>): Int {
// The focused task index is placed after the desktop tasks views.
return if (enableLargeDesktopWindowingTile()) {
@@ -49,12 +58,8 @@
}
}
- /**
- * Counts [TaskView]s that are [DesktopTaskView] instances.
- *
- * @param taskViews List of [TaskView]s
- */
- fun getDesktopTaskViewCount(taskViews: List<TaskView>): Int =
+ /** Counts [TaskView]s that are [DesktopTaskView] instances. */
+ fun getDesktopTaskViewCount(taskViews: Iterable<TaskView>): Int =
taskViews.count { it is DesktopTaskView }
/** Returns a list of all large TaskView Ids from [TaskView]s */
@@ -66,18 +71,64 @@
*
* @param taskViews List of [TaskView]s
*/
- fun getFirstLargeTaskView(taskViews: List<TaskView>): TaskView? =
+ fun getFirstLargeTaskView(taskViews: Iterable<TaskView>): TaskView? =
taskViews.firstOrNull { it.isLargeTile }
- fun screenshotTasks(
- taskView: TaskView,
- recentsAnimationController: RecentsAnimationController,
- ): Map<Int, ThumbnailData> =
- taskView.taskContainers.associate {
- it.task.key.id to recentsAnimationController.screenshotTask(it.task.key.id)
+ /** Returns the last TaskView that should be displayed as a large tile. */
+ fun getLastLargeTaskView(taskViews: Iterable<TaskView>): TaskView? =
+ taskViews.lastOrNull { it.isLargeTile }
+
+ /** Returns the first [TaskView], with some tasks possibly hidden in the carousel. */
+ fun getFirstTaskViewInCarousel(
+ nonRunningTaskCategoryHidden: Boolean,
+ taskViews: Iterable<TaskView>,
+ runningTaskView: TaskView?,
+ ): TaskView? =
+ taskViews.firstOrNull {
+ it.isVisibleInCarousel(runningTaskView, nonRunningTaskCategoryHidden)
+ }
+
+ /** Returns the last [TaskView], with some tasks possibly hidden in the carousel. */
+ fun getLastTaskViewInCarousel(
+ nonRunningTaskCategoryHidden: Boolean,
+ taskViews: Iterable<TaskView>,
+ runningTaskView: TaskView?,
+ ): TaskView? =
+ taskViews.lastOrNull {
+ it.isVisibleInCarousel(runningTaskView, nonRunningTaskCategoryHidden)
}
/** Returns the current list of [TaskView] children. */
- fun getTaskViews(taskViewCount: Int, requireTaskViewAt: (Int) -> TaskView): List<TaskView> =
+ fun getTaskViews(taskViewCount: Int, requireTaskViewAt: (Int) -> TaskView): Iterable<TaskView> =
(0 until taskViewCount).map(requireTaskViewAt)
+
+ /** Apply attachAlpha to all [TaskView] accordingly to different conditions. */
+ fun applyAttachAlpha(
+ taskViews: Iterable<TaskView>,
+ runningTaskView: TaskView?,
+ runningTaskTileHidden: Boolean,
+ nonRunningTaskCategoryHidden: Boolean,
+ ) {
+ taskViews.forEach { taskView ->
+ val isVisible =
+ if (taskView == runningTaskView) !runningTaskTileHidden
+ else taskView.isVisibleInCarousel(runningTaskView, nonRunningTaskCategoryHidden)
+ taskView.attachAlpha = if (isVisible) 1f else 0f
+ }
+ }
+
+ private fun TaskView.isVisibleInCarousel(
+ runningTaskView: TaskView?,
+ nonRunningTaskCategoryHidden: Boolean,
+ ): Boolean =
+ if (!nonRunningTaskCategoryHidden) true
+ else if (runningTaskView == null) true else getCategory() == runningTaskView.getCategory()
+
+ private fun TaskView.getCategory(): TaskViewCategory =
+ if (this is DesktopTaskView) TaskViewCategory.DESKTOP else TaskViewCategory.FULL_SCREEN
+
+ private enum class TaskViewCategory {
+ FULL_SCREEN,
+ DESKTOP,
+ }
}
diff --git a/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java b/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
index c3270dc..f3b984b8 100644
--- a/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
+++ b/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
@@ -15,6 +15,7 @@
*/
package com.android.quickstep.util;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.view.Display.DEFAULT_DISPLAY;
import android.content.Context;
@@ -30,6 +31,8 @@
import com.android.launcher3.util.WindowBounds;
import com.android.launcher3.util.window.CachedDisplayInfo;
import com.android.launcher3.util.window.WindowManagerProxy;
+import com.android.quickstep.SystemUiProxy;
+import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
import java.util.List;
import java.util.Set;
@@ -66,6 +69,24 @@
}
@Override
+ public boolean showLockedTaskbarOnHome(Context displayInfoContext) {
+ if (!DesktopModeStatus.canEnterDesktopMode(displayInfoContext)) {
+ return false;
+ }
+ if (!DesktopModeStatus.enterDesktopByDefaultOnFreeformDisplay(displayInfoContext)) {
+ return false;
+ }
+ final boolean isFreeformDisplay = displayInfoContext.getResources().getConfiguration()
+ .windowConfiguration.getWindowingMode() == WINDOWING_MODE_FREEFORM;
+ return isFreeformDisplay;
+ }
+
+ @Override
+ public boolean isHomeVisible(Context context) {
+ return SystemUiProxy.INSTANCE.get(context).getHomeVisibilityState().isHomeVisible();
+ }
+
+ @Override
public int getRotation(Context displayInfoContext) {
return displayInfoContext.getResources().getConfiguration().windowConfiguration
.getRotation();
diff --git a/quickstep/src/com/android/quickstep/views/FloatingWidgetBackgroundView.java b/quickstep/src/com/android/quickstep/views/FloatingWidgetBackgroundView.java
index 4ea7753..f17be05 100644
--- a/quickstep/src/com/android/quickstep/views/FloatingWidgetBackgroundView.java
+++ b/quickstep/src/com/android/quickstep/views/FloatingWidgetBackgroundView.java
@@ -32,7 +32,6 @@
import com.android.launcher3.R;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
-import com.android.launcher3.widget.RoundedCornerEnforcement;
import java.util.stream.IntStream;
@@ -171,8 +170,7 @@
/** Corner radius from source view's outline, or enforced view. */
private static float getOutlineRadius(LauncherAppWidgetHostView hostView, View v) {
- if (RoundedCornerEnforcement.isRoundedCornerEnabled()
- && hostView.hasEnforcedCornerRadius()) {
+ if (hostView.hasEnforcedCornerRadius()) {
return hostView.getEnforcedCornerRadius();
} else if (v.getOutlineProvider() instanceof RemoteViewOutlineProvider
&& v.getClipToOutline()) {
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index d20d0a5..73edb9e 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -16,6 +16,7 @@
package com.android.quickstep.views;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+import static android.window.flags.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.CLEAR_ALL_BUTTON;
@@ -26,7 +27,6 @@
import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT;
import static com.android.launcher3.LauncherState.SPRING_LOADED;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SPLIT_SELECTION_EXIT_HOME;
-import static com.android.wm.shell.shared.desktopmode.DesktopModeFlags.WALLPAPER_ACTIVITY;
import android.annotation.TargetApi;
import android.content.Context;
@@ -268,7 +268,8 @@
super.onGestureAnimationStart(runningTasks, rotationTouchHelper);
DesktopVisibilityController desktopVisibilityController =
mContainer.getDesktopVisibilityController();
- if (!WALLPAPER_ACTIVITY.isEnabled(mContext) && desktopVisibilityController != null) {
+ if (!ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY.isTrue()
+ && desktopVisibilityController != null) {
// TODO: b/333533253 - Remove after flag rollout
desktopVisibilityController.setRecentsGestureStart();
}
@@ -291,7 +292,8 @@
}
}
super.onGestureAnimationEnd();
- if (!WALLPAPER_ACTIVITY.isEnabled(mContext) && desktopVisibilityController != null) {
+ if (!ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY.isTrue()
+ && desktopVisibilityController != null) {
// TODO: b/333533253 - Remove after flag rollout
desktopVisibilityController.setRecentsGestureEnd(endTarget);
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index e37e036..f502e31 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -343,7 +343,7 @@
};
public static final int SCROLL_VIBRATION_PRIMITIVE =
- Utilities.ATLEAST_S ? VibrationEffect.Composition.PRIMITIVE_LOW_TICK : -1;
+ VibrationEffect.Composition.PRIMITIVE_LOW_TICK;
public static final float SCROLL_VIBRATION_PRIMITIVE_SCALE = 0.6f;
public static final VibrationEffect SCROLL_VIBRATION_FALLBACK =
VibrationConstants.EFFECT_TEXTURE_TICK;
@@ -681,6 +681,7 @@
protected int mRunningTaskViewId = -1;
private int mTaskViewIdCount;
protected boolean mRunningTaskTileHidden;
+ private boolean mNonRunningTaskCategoryHidden;
@Nullable
private Task[] mTmpRunningTasks;
protected int mFocusedTaskViewId = INVALID_TASK_ID;
@@ -2094,14 +2095,10 @@
simulator.fullScreenProgress.value = 0;
simulator.recentsViewScale.value = 1;
});
- // Similar to setRunningTaskHidden below, reapply the state before runningTaskView is
- // null.
- if (!mRunningTaskShowScreenshot) {
- setRunningTaskViewShowScreenshot(mRunningTaskShowScreenshot);
- }
- if (mRunningTaskTileHidden) {
- setRunningTaskHidden(mRunningTaskTileHidden);
- }
+ // Reapply runningTask related attributes as they might have been reset by
+ // resetViewTransforms().
+ setRunningTaskViewShowScreenshot(mRunningTaskShowScreenshot);
+ applyAttachAlpha();
updateCurveProperties();
// Update the set of visible task's data
@@ -2650,10 +2647,6 @@
return getTaskViewFromTaskViewId(mFocusedTaskViewId);
}
- private @Nullable TaskView getFirstLargeTaskView() {
- return mUtils.getFirstLargeTaskView(getTaskViews());
- }
-
@Nullable
private TaskView getTaskViewFromTaskViewId(int taskViewId) {
if (taskViewId == -1) {
@@ -2749,7 +2742,10 @@
showCurrentTask(mActiveGestureRunningTasks);
setEnableFreeScroll(false);
setEnableDrawingLiveTile(false);
- setRunningTaskHidden(!shouldUpdateRunningTaskAlpha());
+ setRunningTaskHidden(true);
+ if (enableLargeDesktopWindowingTile()) {
+ setNonRunningTaskCategoryHidden(true);
+ }
setTaskIconScaledDown(true);
}
@@ -2888,6 +2884,9 @@
setEnableDrawingLiveTile(mCurrentGestureEndTarget == GestureState.GestureEndTarget.RECENTS);
Log.d(TAG, "onGestureAnimationEnd - mEnableDrawingLiveTile: " + mEnableDrawingLiveTile);
setRunningTaskHidden(false);
+ if (enableLargeDesktopWindowingTile()) {
+ setNonRunningTaskCategoryHidden(false);
+ }
animateUpTaskIconScale();
animateActionsViewIn();
@@ -3043,13 +3042,27 @@
if (runningTask == null) {
return;
}
- runningTask.setStableAlpha(isHidden ? 0 : mContentAlpha);
+ applyAttachAlpha();
if (!isHidden) {
AccessibilityManagerCompat.sendCustomAccessibilityEvent(
runningTask, AccessibilityEvent.TYPE_VIEW_FOCUSED, null);
}
}
+ /**
+ * Hides the tasks that has a different category (Fullscreen/Desktop) from the running task.
+ */
+ public void setNonRunningTaskCategoryHidden(boolean isHidden) {
+ mNonRunningTaskCategoryHidden = isHidden;
+ updateMinAndMaxScrollX();
+ applyAttachAlpha();
+ }
+
+ private void applyAttachAlpha() {
+ mUtils.applyAttachAlpha(getTaskViews(), getRunningTaskView(), mRunningTaskTileHidden,
+ mNonRunningTaskCategoryHidden);
+ }
+
private void setRunningTaskViewShowScreenshot(boolean showScreenshot) {
setRunningTaskViewShowScreenshot(showScreenshot, /*updatedThumbnails=*/null);
}
@@ -4447,11 +4460,7 @@
alpha = Utilities.boundToRange(alpha, 0, 1);
mContentAlpha = alpha;
- TaskView runningTaskView = getRunningTaskView();
for (TaskView taskView : getTaskViews()) {
- if (runningTaskView != null && mRunningTaskTileHidden && taskView == runningTaskView) {
- continue;
- }
taskView.setStableAlpha(alpha);
}
mClearAllButton.setContentAlpha(mContentAlpha);
@@ -4564,7 +4573,7 @@
/**
* Returns the current list of [TaskView] children.
*/
- private List<TaskView> getTaskViews() {
+ private Iterable<TaskView> getTaskViews() {
return mUtils.getTaskViews(getTaskViewCount(), this::requireTaskViewAt);
}
@@ -5794,26 +5803,42 @@
}
private int getFirstViewIndex() {
- TaskView firstTaskView = mShowAsGridLastOnLayout ? getFirstLargeTaskView() : null;
- return firstTaskView != null ? indexOfChild(firstTaskView) : 0;
+ final TaskView firstView;
+ if (mShowAsGridLastOnLayout) {
+ // For grid Overivew, it always start if a large tile (focused task or desktop task) if
+ // they exist, otherwise it start with the first task.
+ TaskView firstLargeTaskView = mUtils.getFirstLargeTaskView(getTaskViews());
+ if (firstLargeTaskView != null) {
+ firstView = firstLargeTaskView;
+ } else {
+ firstView = getTaskViewAt(0);
+ }
+ } else {
+ firstView = mUtils.getFirstTaskViewInCarousel(mNonRunningTaskCategoryHidden,
+ getTaskViews(), getRunningTaskView());
+ }
+ return indexOfChild(firstView);
}
private int getLastViewIndex() {
+ final View lastView;
if (!mDisallowScrollToClearAll) {
- return indexOfChild(mClearAllButton);
+ // When ClearAllButton is present, it always end with ClearAllButton.
+ lastView = mClearAllButton;
+ } else if (mShowAsGridLastOnLayout) {
+ // When ClearAllButton is absent, for the grid Overview, it always end with a grid task
+ // if they exist, otherwise it ends with a large tile (focused task or desktop task).
+ TaskView lastGridTaskView = getLastGridTaskView();
+ if (lastGridTaskView != null) {
+ lastView = lastGridTaskView;
+ } else {
+ lastView = mUtils.getLastLargeTaskView(getTaskViews());
+ }
+ } else {
+ lastView = mUtils.getLastTaskViewInCarousel(mNonRunningTaskCategoryHidden,
+ getTaskViews(), getRunningTaskView());
}
-
- if (!mShowAsGridLastOnLayout) {
- return getTaskViewCount() - 1;
- }
-
- TaskView lastGridTaskView = getLastGridTaskView();
- if (lastGridTaskView != null) {
- return indexOfChild(lastGridTaskView);
- }
-
- // Returns focus task if there are no grid tasks.
- return indexOfChild(getFirstLargeTaskView());
+ return indexOfChild(lastView);
}
/**
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.kt b/quickstep/src/com/android/quickstep/views/TaskView.kt
index 291ccef..2ed6ae6 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.kt
+++ b/quickstep/src/com/android/quickstep/views/TaskView.kt
@@ -82,7 +82,6 @@
import com.android.quickstep.orientation.RecentsPagedOrientationHandler
import com.android.quickstep.recents.di.RecentsDependencies
import com.android.quickstep.recents.di.get
-import com.android.quickstep.task.thumbnail.TaskThumbnailView
import com.android.quickstep.task.viewmodel.TaskViewModel
import com.android.quickstep.util.ActiveGestureErrorDetector
import com.android.quickstep.util.ActiveGestureLog
@@ -397,7 +396,7 @@
}
get() = taskViewAlpha.get(ALPHA_INDEX_STABLE).value
- protected var attachAlpha
+ var attachAlpha
set(value) {
taskViewAlpha.get(ALPHA_INDEX_ATTACH).value = value
}
@@ -606,6 +605,7 @@
override fun onRecycle() {
resetPersistentViewTransforms()
+ attachAlpha = 1f
// Clear any references to the thumbnail (it will be re-read either from the cache or the
// system on next bind)
if (!enableRefactorTaskThumbnail()) {
@@ -1587,10 +1587,7 @@
resetViewTransforms()
}
- fun getTaskContainerForTaskThumbnailView(taskThumbnailView: TaskThumbnailView): TaskContainer? =
- taskContainers.firstOrNull { it.thumbnailView == taskThumbnailView }
-
- open fun resetViewTransforms() {
+ fun resetViewTransforms() {
// fullscreenTranslation and accumulatedTranslation should not be reset, as
// resetViewTransforms is called during QuickSwitch scrolling.
dismissTranslationX = 0f
@@ -1606,7 +1603,6 @@
}
dismissScale = 1f
translationZ = 0f
- attachAlpha = 1f
setIconScaleAndDim(1f)
setColorTint(0f, 0)
}
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java
index 399aea6..02d6218 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java
@@ -20,6 +20,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@@ -33,11 +34,13 @@
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import com.android.launcher3.contextualeducation.ContextualEduStatsManager;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.taskbar.TaskbarNavButtonController.TaskbarNavButtonCallbacks;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TouchInteractionService;
import com.android.quickstep.util.AssistUtils;
+import com.android.systemui.contextualeducation.GestureType;
import org.junit.Before;
import org.junit.Test;
@@ -52,6 +55,10 @@
@Mock
SystemUiProxy mockSystemUiProxy;
+
+ @Mock
+ ContextualEduStatsManager mockContextualEduStatsManager;
+
@Mock
TouchInteractionService mockService;
@Mock
@@ -100,6 +107,7 @@
mockService,
mCallbacks,
mockSystemUiProxy,
+ mockContextualEduStatsManager,
mockHandler,
mockAssistUtils);
}
@@ -111,6 +119,13 @@
}
@Test
+ public void testPressBack_updateContextualEduData() {
+ mNavButtonController.onButtonClick(BUTTON_BACK, mockView);
+ verify(mockContextualEduStatsManager, times(1))
+ .updateEduStats(/* isTrackpad= */ eq(false), eq(GestureType.BACK));
+ }
+
+ @Test
public void testPressImeSwitcher() {
mNavButtonController.init(mockTaskbarControllers);
mNavButtonController.onButtonClick(BUTTON_IME_SWITCH, mockView);
@@ -195,12 +210,26 @@
}
@Test
+ public void testPressHome_updateContextualEduData() {
+ mNavButtonController.onButtonClick(BUTTON_HOME, mockView);
+ verify(mockContextualEduStatsManager, times(1))
+ .updateEduStats(/* isTrackpad= */ eq(false), eq(GestureType.HOME));
+ }
+
+ @Test
public void testPressRecents() {
mNavButtonController.onButtonClick(BUTTON_RECENTS, mockView);
assertThat(mOverviewToggleCount).isEqualTo(1);
}
@Test
+ public void testPressRecents_updateContextualEduData() {
+ mNavButtonController.onButtonClick(BUTTON_RECENTS, mockView);
+ verify(mockContextualEduStatsManager, times(1))
+ .updateEduStats(/* isTrackpad= */ eq(false), eq(GestureType.OVERVIEW));
+ }
+
+ @Test
public void testPressRecentsWithScreenPinned_noNavigationToOverview() {
mNavButtonController.updateSysuiFlags(SYSUI_STATE_SCREEN_PINNING);
mNavButtonController.onButtonClick(BUTTON_RECENTS, mockView);
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/logging/SettingsChangeLoggerTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/logging/SettingsChangeLoggerTest.kt
index 7c48ea4..0a60774 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/logging/SettingsChangeLoggerTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/logging/SettingsChangeLoggerTest.kt
@@ -34,6 +34,7 @@
import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NOTIFICATION_DOT_ENABLED
import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_THEMED_ICON_DISABLED
import com.android.launcher3.states.RotationHelper.ALLOW_ROTATION_PREFERENCE_KEY
+import com.android.launcher3.util.DaggerSingletonTracker
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
@@ -62,6 +63,7 @@
@Mock private lateinit var mMockLogger: StatsLogManager.StatsLogger
@Captor private lateinit var mEventCaptor: ArgumentCaptor<StatsLogManager.EventEnum>
+ @Mock private lateinit var mTracker: DaggerSingletonTracker
private var mDefaultThemedIcons = false
private var mDefaultAllowRotation = false
@@ -79,7 +81,7 @@
// To match the default value of ALLOW_ROTATION
LauncherPrefs.get(mContext).put(item = ALLOW_ROTATION, value = false)
- mSystemUnderTest = SettingsChangeLogger(mContext, mStatsLogManager)
+ mSystemUnderTest = SettingsChangeLogger(mContext, mStatsLogManager, mTracker)
}
@After
@@ -90,7 +92,7 @@
@Test
fun loggingPrefs_correctDefaultValue() {
- val systemUnderTest = SettingsChangeLogger(mContext, mStatsLogManager)
+ val systemUnderTest = SettingsChangeLogger(mContext, mStatsLogManager, mTracker)
assertThat(systemUnderTest.loggingPrefs[ALLOW_ROTATION_PREFERENCE_KEY]!!.defaultValue)
.isFalse()
@@ -117,7 +119,7 @@
LauncherPrefs.get(mContext).put(item = ALLOW_ROTATION, value = true)
// This a new object so the values of mLoggablePrefs will be different
- SettingsChangeLogger(mContext, mStatsLogManager).logSnapshot(mInstanceId)
+ SettingsChangeLogger(mContext, mStatsLogManager, mTracker).logSnapshot(mInstanceId)
verify(mMockLogger, atLeastOnce()).log(mEventCaptor.capture())
val capturedEvents = mEventCaptor.allValues
diff --git a/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java b/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java
index 23a29f7..800fd4a 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java
@@ -21,6 +21,7 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
import android.util.Log;
@@ -117,7 +118,6 @@
}
@Test
- @ScreenRecordRule.ScreenRecord // b/334946529
public void testUserInstalledAppIsShownAboveDivider() throws IOException {
// Ensure that the App is not installed in main user otherwise, it may not be found in
// PS container.
@@ -142,7 +142,6 @@
}
@Test
- @ScreenRecordRule.ScreenRecord // b/334946529
public void testPrivateSpaceAppLongPressUninstallMenu() throws IOException {
// Ensure that the App is not installed in main user otherwise, it may not be found in
// PS container.
@@ -166,8 +165,9 @@
}
@Test
- @ScreenRecordRule.ScreenRecord // b/334946529
+ @ScreenRecordRule.ScreenRecord // b/355466672
public void testPrivateSpaceLockingBehaviour() throws IOException {
+ assumeFalse(mLauncher.isTablet()); // b/367258373
// Scroll to the bottom of All Apps
executeOnLauncher(launcher -> launcher.getAppsView().resetAndScrollToPrivateSpaceHeader());
HomeAllApps homeAllApps = mLauncher.getAllApps();
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index de2c506..113b8a4 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -577,7 +577,7 @@
public void testExcludeFromRecents() throws Exception {
startExcludeFromRecentsTestActivity();
OverviewTask currentTask = getAndAssertLaunchedApp().switchToOverview().getCurrentTask();
- // TODO(b/326565120): the expected content description shouldn't be null but for now there
+ // TODO(b/342627272): the expected content description shouldn't be null but for now there
// is a bug that causes it to sometimes be for excludeForRecents tasks.
assertTrue("Can't find ExcludeFromRecentsTestActivity after entering Overview from it",
currentTask.containsContentDescription("ExcludeFromRecents")
diff --git a/res/drawable-sw720dp/ic_transient_taskbar_all_apps_button.xml b/res/drawable-sw720dp/ic_transient_taskbar_all_apps_button.xml
deleted file mode 100644
index 47f2a5d..0000000
--- a/res/drawable-sw720dp/ic_transient_taskbar_all_apps_button.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2023 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="52dp"
- android:height="52dp"
- android:viewportWidth="52"
- android:viewportHeight="52">
- <path
- android:pathData="M15.5,19C14.538,19 13.715,18.65 13.033,17.968C12.35,17.285 12,16.462 12,15.5C12,14.538 12.35,13.715 13.033,13.033C13.715,12.35 14.538,12 15.5,12C16.462,12 17.285,12.35 17.968,13.033C18.65,13.715 19,14.538 19,15.5C19,16.462 18.65,17.285 17.968,17.968C17.285,18.65 16.462,19 15.5,19Z"
- android:fillColor="#40484B"/>
- <path
- android:pathData="M26,19C25.038,19 24.215,18.65 23.532,17.968C22.85,17.285 22.5,16.462 22.5,15.5C22.5,14.538 22.85,13.715 23.532,13.033C24.215,12.35 25.038,12 26,12C26.962,12 27.785,12.35 28.468,13.033C29.15,13.715 29.5,14.538 29.5,15.5C29.5,16.462 29.15,17.285 28.468,17.968C27.785,18.65 26.962,19 26,19Z"
- android:fillColor="#40484B"/>
- <path
- android:pathData="M36.5,19C35.537,19 34.715,18.65 34.033,17.968C33.35,17.285 33,16.462 33,15.5C33,14.538 33.35,13.715 34.033,13.033C34.715,12.35 35.537,12 36.5,12C37.463,12 38.285,12.35 38.967,13.033C39.65,13.715 40,14.538 40,15.5C40,16.462 39.65,17.285 38.967,17.968C38.285,18.65 37.463,19 36.5,19Z"
- android:fillColor="#40484B"/>
- <path
- android:pathData="M15.5,29.5C14.538,29.5 13.715,29.15 13.033,28.468C12.35,27.785 12,26.962 12,26C12,25.038 12.35,24.215 13.033,23.532C13.715,22.85 14.538,22.5 15.5,22.5C16.462,22.5 17.285,22.85 17.968,23.532C18.65,24.215 19,25.038 19,26C19,26.962 18.65,27.785 17.968,28.468C17.285,29.15 16.462,29.5 15.5,29.5Z"
- android:fillColor="#40484B"/>
- <path
- android:pathData="M26,29.5C25.038,29.5 24.215,29.15 23.532,28.468C22.85,27.785 22.5,26.962 22.5,26C22.5,25.038 22.85,24.215 23.532,23.532C24.215,22.85 25.038,22.5 26,22.5C26.962,22.5 27.785,22.85 28.468,23.532C29.15,24.215 29.5,25.038 29.5,26C29.5,26.962 29.15,27.785 28.468,28.468C27.785,29.15 26.962,29.5 26,29.5Z"
- android:fillColor="#40484B"/>
- <path
- android:pathData="M36.5,29.5C35.537,29.5 34.715,29.15 34.033,28.468C33.35,27.785 33,26.962 33,26C33,25.038 33.35,24.215 34.033,23.532C34.715,22.85 35.537,22.5 36.5,22.5C37.463,22.5 38.285,22.85 38.967,23.532C39.65,24.215 40,25.038 40,26C40,26.962 39.65,27.785 38.967,28.468C38.285,29.15 37.463,29.5 36.5,29.5Z"
- android:fillColor="#40484B"/>
- <path
- android:pathData="M15.5,40C14.538,40 13.715,39.65 13.033,38.967C12.35,38.285 12,37.463 12,36.5C12,35.537 12.35,34.715 13.033,34.033C13.715,33.35 14.538,33 15.5,33C16.462,33 17.285,33.35 17.968,34.033C18.65,34.715 19,35.537 19,36.5C19,37.463 18.65,38.285 17.968,38.967C17.285,39.65 16.462,40 15.5,40Z"
- android:fillColor="#40484B"/>
- <path
- android:pathData="M26,40C25.038,40 24.215,39.65 23.532,38.967C22.85,38.285 22.5,37.463 22.5,36.5C22.5,35.537 22.85,34.715 23.532,34.033C24.215,33.35 25.038,33 26,33C26.962,33 27.785,33.35 28.468,34.033C29.15,34.715 29.5,35.537 29.5,36.5C29.5,37.463 29.15,38.285 28.468,38.967C27.785,39.65 26.962,40 26,40Z"
- android:fillColor="#40484B"/>
- <path
- android:pathData="M36.5,40C35.537,40 34.715,39.65 34.033,38.967C33.35,38.285 33,37.463 33,36.5C33,35.537 33.35,34.715 34.033,34.033C34.715,33.35 35.537,33 36.5,33C37.463,33 38.285,33.35 38.967,34.033C39.65,34.715 40,35.537 40,36.5C40,37.463 39.65,38.285 38.967,38.967C38.285,39.65 37.463,40 36.5,40Z"
- android:fillColor="#40484B"/>
-</vector>
diff --git a/res/drawable/ic_taskbar_all_apps_button.xml b/res/drawable/ic_taskbar_all_apps_button.xml
deleted file mode 100644
index 82fbbea..0000000
--- a/res/drawable/ic_taskbar_all_apps_button.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2023 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="44dp"
- android:height="44dp"
- android:viewportWidth="44"
- android:viewportHeight="44">
- <path
- android:pathData="M13,16C12.175,16 11.47,15.7 10.885,15.115C10.3,14.53 10,13.825 10,13C10,12.175 10.3,11.47 10.885,10.885C11.47,10.3 12.175,10 13,10C13.825,10 14.53,10.3 15.115,10.885C15.7,11.47 16,12.175 16,13C16,13.825 15.7,14.53 15.115,15.115C14.53,15.7 13.825,16 13,16Z"
- android:fillColor="#40484B"/>
- <path
- android:pathData="M22,16C21.175,16 20.47,15.7 19.885,15.115C19.3,14.53 19,13.825 19,13C19,12.175 19.3,11.47 19.885,10.885C20.47,10.3 21.175,10 22,10C22.825,10 23.53,10.3 24.115,10.885C24.7,11.47 25,12.175 25,13C25,13.825 24.7,14.53 24.115,15.115C23.53,15.7 22.825,16 22,16Z"
- android:fillColor="#40484B"/>
- <path
- android:pathData="M31,16C30.175,16 29.47,15.7 28.885,15.115C28.3,14.53 28,13.825 28,13C28,12.175 28.3,11.47 28.885,10.885C29.47,10.3 30.175,10 31,10C31.825,10 32.53,10.3 33.115,10.885C33.7,11.47 34,12.175 34,13C34,13.825 33.7,14.53 33.115,15.115C32.53,15.7 31.825,16 31,16Z"
- android:fillColor="#40484B"/>
- <path
- android:pathData="M13,25C12.175,25 11.47,24.7 10.885,24.115C10.3,23.53 10,22.825 10,22C10,21.175 10.3,20.47 10.885,19.885C11.47,19.3 12.175,19 13,19C13.825,19 14.53,19.3 15.115,19.885C15.7,20.47 16,21.175 16,22C16,22.825 15.7,23.53 15.115,24.115C14.53,24.7 13.825,25 13,25Z"
- android:fillColor="#40484B"/>
- <path
- android:pathData="M22,25C21.175,25 20.47,24.7 19.885,24.115C19.3,23.53 19,22.825 19,22C19,21.175 19.3,20.47 19.885,19.885C20.47,19.3 21.175,19 22,19C22.825,19 23.53,19.3 24.115,19.885C24.7,20.47 25,21.175 25,22C25,22.825 24.7,23.53 24.115,24.115C23.53,24.7 22.825,25 22,25Z"
- android:fillColor="#40484B"/>
- <path
- android:pathData="M31,25C30.175,25 29.47,24.7 28.885,24.115C28.3,23.53 28,22.825 28,22C28,21.175 28.3,20.47 28.885,19.885C29.47,19.3 30.175,19 31,19C31.825,19 32.53,19.3 33.115,19.885C33.7,20.47 34,21.175 34,22C34,22.825 33.7,23.53 33.115,24.115C32.53,24.7 31.825,25 31,25Z"
- android:fillColor="#40484B"/>
- <path
- android:pathData="M13,34C12.175,34 11.47,33.7 10.885,33.115C10.3,32.53 10,31.825 10,31C10,30.175 10.3,29.47 10.885,28.885C11.47,28.3 12.175,28 13,28C13.825,28 14.53,28.3 15.115,28.885C15.7,29.47 16,30.175 16,31C16,31.825 15.7,32.53 15.115,33.115C14.53,33.7 13.825,34 13,34Z"
- android:fillColor="#40484B"/>
- <path
- android:pathData="M22,34C21.175,34 20.47,33.7 19.885,33.115C19.3,32.53 19,31.825 19,31C19,30.175 19.3,29.47 19.885,28.885C20.47,28.3 21.175,28 22,28C22.825,28 23.53,28.3 24.115,28.885C24.7,29.47 25,30.175 25,31C25,31.825 24.7,32.53 24.115,33.115C23.53,33.7 22.825,34 22,34Z"
- android:fillColor="#40484B"/>
- <path
- android:pathData="M31,34C30.175,34 29.47,33.7 28.885,33.115C28.3,32.53 28,31.825 28,31C28,30.175 28.3,29.47 28.885,28.885C29.47,28.3 30.175,28 31,28C31.825,28 32.53,28.3 33.115,28.885C33.7,29.47 34,30.175 34,31C34,31.825 33.7,32.53 33.115,33.115C32.53,33.7 31.825,34 31,34Z"
- android:fillColor="#40484B"/>
-</vector>
diff --git a/res/drawable/ic_transient_taskbar_all_apps_button.xml b/res/drawable/ic_transient_taskbar_all_apps_button.xml
deleted file mode 100644
index 6e740ae..0000000
--- a/res/drawable/ic_transient_taskbar_all_apps_button.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2023 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48"
- android:viewportHeight="48">
- <path
- android:pathData="M13.5,17C12.538,17 11.715,16.65 11.033,15.967C10.35,15.285 10,14.462 10,13.5C10,12.538 10.35,11.715 11.033,11.033C11.715,10.35 12.538,10 13.5,10C14.462,10 15.285,10.35 15.967,11.033C16.65,11.715 17,12.538 17,13.5C17,14.462 16.65,15.285 15.967,15.967C15.285,16.65 14.462,17 13.5,17Z"
- android:fillColor="#40484B"/>
- <path
- android:pathData="M24,17C23.038,17 22.215,16.65 21.532,15.967C20.85,15.285 20.5,14.462 20.5,13.5C20.5,12.538 20.85,11.715 21.532,11.033C22.215,10.35 23.038,10 24,10C24.962,10 25.785,10.35 26.468,11.033C27.15,11.715 27.5,12.538 27.5,13.5C27.5,14.462 27.15,15.285 26.468,15.967C25.785,16.65 24.962,17 24,17Z"
- android:fillColor="#40484B"/>
- <path
- android:pathData="M34.5,17C33.537,17 32.715,16.65 32.033,15.967C31.35,15.285 31,14.462 31,13.5C31,12.538 31.35,11.715 32.033,11.033C32.715,10.35 33.537,10 34.5,10C35.463,10 36.285,10.35 36.967,11.033C37.65,11.715 38,12.538 38,13.5C38,14.462 37.65,15.285 36.967,15.967C36.285,16.65 35.463,17 34.5,17Z"
- android:fillColor="#40484B"/>
- <path
- android:pathData="M13.5,27.5C12.538,27.5 11.715,27.15 11.033,26.468C10.35,25.785 10,24.962 10,24C10,23.038 10.35,22.215 11.033,21.532C11.715,20.85 12.538,20.5 13.5,20.5C14.462,20.5 15.285,20.85 15.967,21.532C16.65,22.215 17,23.038 17,24C17,24.962 16.65,25.785 15.967,26.468C15.285,27.15 14.462,27.5 13.5,27.5Z"
- android:fillColor="#40484B"/>
- <path
- android:pathData="M24,27.5C23.038,27.5 22.215,27.15 21.532,26.468C20.85,25.785 20.5,24.962 20.5,24C20.5,23.038 20.85,22.215 21.532,21.532C22.215,20.85 23.038,20.5 24,20.5C24.962,20.5 25.785,20.85 26.468,21.532C27.15,22.215 27.5,23.038 27.5,24C27.5,24.962 27.15,25.785 26.468,26.468C25.785,27.15 24.962,27.5 24,27.5Z"
- android:fillColor="#40484B"/>
- <path
- android:pathData="M34.5,27.5C33.537,27.5 32.715,27.15 32.033,26.468C31.35,25.785 31,24.962 31,24C31,23.038 31.35,22.215 32.033,21.532C32.715,20.85 33.537,20.5 34.5,20.5C35.463,20.5 36.285,20.85 36.967,21.532C37.65,22.215 38,23.038 38,24C38,24.962 37.65,25.785 36.967,26.468C36.285,27.15 35.463,27.5 34.5,27.5Z"
- android:fillColor="#40484B"/>
- <path
- android:pathData="M13.5,38C12.538,38 11.715,37.65 11.033,36.967C10.35,36.285 10,35.463 10,34.5C10,33.537 10.35,32.715 11.033,32.033C11.715,31.35 12.538,31 13.5,31C14.462,31 15.285,31.35 15.967,32.033C16.65,32.715 17,33.537 17,34.5C17,35.463 16.65,36.285 15.967,36.967C15.285,37.65 14.462,38 13.5,38Z"
- android:fillColor="#40484B"/>
- <path
- android:pathData="M24,38C23.038,38 22.215,37.65 21.532,36.967C20.85,36.285 20.5,35.463 20.5,34.5C20.5,33.537 20.85,32.715 21.532,32.033C22.215,31.35 23.038,31 24,31C24.962,31 25.785,31.35 26.468,32.033C27.15,32.715 27.5,33.537 27.5,34.5C27.5,35.463 27.15,36.285 26.468,36.967C25.785,37.65 24.962,38 24,38Z"
- android:fillColor="#40484B"/>
- <path
- android:pathData="M34.5,38C33.537,38 32.715,37.65 32.033,36.967C31.35,36.285 31,35.463 31,34.5C31,33.537 31.35,32.715 32.033,32.033C32.715,31.35 33.537,31 34.5,31C35.463,31 36.285,31.35 36.967,32.033C37.65,32.715 38,33.537 38,34.5C38,35.463 37.65,36.285 36.967,36.967C36.285,37.65 35.463,38 34.5,38Z"
- android:fillColor="#40484B"/>
-</vector>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index d9f2072..f62384c 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -189,7 +189,7 @@
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtrirajte"</string>
<string name="remote_action_failed" msgid="1383965239183576790">"Nije uspjelo: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
<string name="private_space_label" msgid="2359721649407947001">"Privatni prostor"</string>
- <string name="private_space_secondary_label" msgid="9203933341714508907">"Dodirnite da biste postavili ili otvorili"</string>
+ <string name="private_space_secondary_label" msgid="9203933341714508907">"Dodirnite za postavljanje ili otvaranje"</string>
<string name="ps_container_title" msgid="4391796149519594205">"Privatno"</string>
<string name="ps_container_settings" msgid="6059734123353320479">"Postavke privatnog prostora"</string>
<string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Privatno, otključano."</string>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index 3c9135b..ebd68f7 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -117,7 +117,7 @@
<string name="folder_name_format_exact" msgid="8626242716117004803">"ថត៖ <xliff:g id="NAME">%1$s</xliff:g>, ធាតុ <xliff:g id="SIZE">%2$d</xliff:g>"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"ថត៖ <xliff:g id="NAME">%1$s</xliff:g>, ធាតុ <xliff:g id="SIZE">%2$d</xliff:g> ឬច្រើនជាងនេះ"</string>
<string name="app_pair_name_format" msgid="8134106404716224054">"គូកម្មវិធី៖ <xliff:g id="APP1">%1$s</xliff:g> និង <xliff:g id="APP2">%2$s</xliff:g>"</string>
- <string name="styles_wallpaper_button_text" msgid="8216961355289236794">"ផ្ទាំងរូបភាព និងរចនាប័ទ្ម"</string>
+ <string name="styles_wallpaper_button_text" msgid="8216961355289236794">"ផ្ទាំងរូបភាព និងរចនាបថ"</string>
<string name="edit_home_screen" msgid="8947858375782098427">"កែអេក្រង់ដើម"</string>
<string name="settings_button_text" msgid="8873672322605444408">"ការកំណត់ទំព័រដើម"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"បានបិទដំណើរការដោយអ្នកគ្រប់គ្រងរបស់អ្នក"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 2a6611f..e2be4ff 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -31,7 +31,7 @@
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Delt skjerm"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Appinformasjon for %1$s"</string>
<string name="split_app_usage_settings" msgid="7214375263347964093">"Bruksinnstillinger for %1$s"</string>
- <string name="save_app_pair" msgid="5647523853662686243">"Lagre apptilkoblingen"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Lagre app-paret"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Denne apptilkoblingen støttes ikke på denne enheten"</string>
<string name="app_pair_needs_unfold" msgid="4588897528143807002">"Åpne enheten for å bruke denne apptilkoblingen"</string>
diff --git a/res/values/config.xml b/res/values/config.xml
index 507ce9a..701e64a 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -67,7 +67,6 @@
<string name="main_process_initializer_class" translatable="false"></string>
<string name="app_launch_tracker_class" translatable="false"></string>
<string name="test_information_handler_class" translatable="false"></string>
- <string name="launcher_activity_logic_class" translatable="false"></string>
<string name="model_delegate_class" translatable="false"></string>
<string name="window_manager_proxy_class" translatable="false"></string>
<string name="secondary_display_predictions_class" translatable="false"></string>
diff --git a/src/com/android/launcher3/DropTargetHandler.kt b/src/com/android/launcher3/DropTargetHandler.kt
index e022159..f1029b1 100644
--- a/src/com/android/launcher3/DropTargetHandler.kt
+++ b/src/com/android/launcher3/DropTargetHandler.kt
@@ -35,8 +35,7 @@
target?.let {
deferred.mPackageName = it.packageName
mLauncher.addEventCallback(EVENT_RESUMED) { deferred.onLauncherResume() }
- }
- ?: deferred.sendFailure()
+ } ?: deferred.sendFailure()
}
}
}
@@ -47,19 +46,10 @@
mLauncher.appWidgetHolder.startConfigActivity(
mLauncher,
widgetId,
- ActivityCodes.REQUEST_RECONFIGURE_APPWIDGET
+ ActivityCodes.REQUEST_RECONFIGURE_APPWIDGET,
)
}
- fun dismissPrediction(
- announcement: CharSequence,
- onActionClicked: Runnable,
- onDismiss: Runnable?
- ) {
- mLauncher.dragLayer.announceForAccessibility(announcement)
- Snackbar.show(mLauncher, R.string.item_removed, R.string.undo, onDismiss, onActionClicked)
- }
-
fun getViewUnderDrag(info: ItemInfo): View? {
return if (
info is LauncherAppWidgetInfo &&
@@ -95,7 +85,7 @@
R.string.item_removed,
R.string.undo,
mLauncher.modelWriter::commitDelete,
- onUndoClicked
+ onUndoClicked,
)
}
diff --git a/src/com/android/launcher3/FastScrollRecyclerView.java b/src/com/android/launcher3/FastScrollRecyclerView.java
index 6622e11..17084bb 100644
--- a/src/com/android/launcher3/FastScrollRecyclerView.java
+++ b/src/com/android/launcher3/FastScrollRecyclerView.java
@@ -60,6 +60,7 @@
mScrollbar = scrollbar;
mScrollbar.setRecyclerView(this);
mScrollbar.setFastScrollerLocation(location);
+ scrollToTop();
onUpdateScrollbar(0);
}
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index 0d4ebe0..024dde4 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -33,15 +33,34 @@
import android.view.ViewGroup;
import android.widget.FrameLayout;
+import androidx.annotation.IntDef;
+
import com.android.launcher3.util.HorizontalInsettableView;
+import com.android.launcher3.util.MultiPropertyFactory.MultiProperty;
import com.android.launcher3.util.MultiTranslateDelegate;
+import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.views.ActivityContext;
+import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* View class that represents the bottom row of the home screen.
*/
public class Hotseat extends CellLayout implements Insettable {
+ public static final int ALPHA_CHANNEL_TASKBAR_ALIGNMENT = 0;
+ public static final int ALPHA_CHANNEL_PREVIEW_RENDERER = 1;
+ public static final int ALPHA_CHANNEL_TASKBAR_STASH = 2;
+ public static final int ALPHA_CHANNEL_CHANNELS_COUNT = 3;
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @IntDef({ALPHA_CHANNEL_TASKBAR_ALIGNMENT, ALPHA_CHANNEL_PREVIEW_RENDERER,
+ ALPHA_CHANNEL_TASKBAR_STASH})
+ public @interface HotseatQsbAlphaId {
+ }
+
// Ratio of empty space, qsb should take up to appear visually centered.
public static final float QSB_CENTER_FACTOR = .325f;
private static final int BUBBLE_BAR_ADJUSTMENT_ANIMATION_DURATION_MS = 250;
@@ -50,6 +69,8 @@
private boolean mHasVerticalHotseat;
private Workspace<?> mWorkspace;
private boolean mSendTouchToWorkspace;
+ private final MultiValueAlpha mIconsAlphaChannels;
+ private final MultiValueAlpha mQsbAlphaChannels;
private final View mQsb;
@@ -63,9 +84,11 @@
public Hotseat(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
-
mQsb = LayoutInflater.from(context).inflate(R.layout.search_container_hotseat, this, false);
addView(mQsb);
+ mIconsAlphaChannels = new MultiValueAlpha(getShortcutsAndWidgets(),
+ ALPHA_CHANNEL_CHANNELS_COUNT);
+ mQsbAlphaChannels = new MultiValueAlpha(mQsb, ALPHA_CHANNEL_CHANNELS_COUNT);
}
/**
@@ -270,21 +293,27 @@
}
/**
- * Sets the alpha value of just our ShortcutAndWidgetContainer.
+ * Sets the alpha value of the specified alpha channel of just our ShortcutAndWidgetContainer.
*/
- public void setIconsAlpha(float alpha) {
- getShortcutsAndWidgets().setAlpha(alpha);
+ public void setIconsAlpha(float alpha, @HotseatQsbAlphaId int channelId) {
+ getIconsAlpha(channelId).setValue(alpha);
}
/**
* Sets the alpha value of just our QSB.
*/
- public void setQsbAlpha(float alpha) {
- mQsb.setAlpha(alpha);
+ public void setQsbAlpha(float alpha, @HotseatQsbAlphaId int channelId) {
+ getQsbAlpha(channelId).setValue(alpha);
}
- public float getIconsAlpha() {
- return getShortcutsAndWidgets().getAlpha();
+ /** Returns the alpha channel for ShortcutAndWidgetContainer */
+ public MultiProperty getIconsAlpha(@HotseatQsbAlphaId int channelId) {
+ return mIconsAlphaChannels.get(channelId);
+ }
+
+ /** Returns the alpha channel for Qsb */
+ public MultiProperty getQsbAlpha(@HotseatQsbAlphaId int channelId) {
+ return mQsbAlphaChannels.get(channelId);
}
/**
@@ -294,4 +323,24 @@
return mQsb;
}
+ /** Dumps the Hotseat internal state */
+ public void dump(String prefix, PrintWriter writer) {
+ writer.println(prefix + "Hotseat:");
+ mIconsAlphaChannels.dump(
+ prefix + "\t",
+ writer,
+ "mIconsAlphaChannels",
+ "ALPHA_CHANNEL_TASKBAR_ALIGNMENT",
+ "ALPHA_CHANNEL_PREVIEW_RENDERER",
+ "ALPHA_CHANNEL_TASKBAR_STASH");
+ mQsbAlphaChannels.dump(
+ prefix + "\t",
+ writer,
+ "mQsbAlphaChannels",
+ "ALPHA_CHANNEL_TASKBAR_ALIGNMENT",
+ "ALPHA_CHANNEL_PREVIEW_RENDERER",
+ "ALPHA_CHANNEL_TASKBAR_STASH"
+ );
+ }
+
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 365e3d4..b0ec9b0 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -76,7 +76,6 @@
import static com.android.launcher3.logging.StatsLogManager.EventEnum;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_ENTRY;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_ENTRY_WITH_DEVICE_SEARCH;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_EXIT;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ONRESUME;
@@ -449,12 +448,10 @@
.logStart(LAUNCHER_LATENCY_STARTUP_TOTAL_DURATION)
.logStart(LAUNCHER_LATENCY_STARTUP_ACTIVITY_ON_CREATE);
// Only use a hard-coded cookie since we only want to trace this once.
- if (Utilities.ATLEAST_S) {
- Trace.beginAsyncSection(
- DISPLAY_WORKSPACE_TRACE_METHOD_NAME, DISPLAY_WORKSPACE_TRACE_COOKIE);
- Trace.beginAsyncSection(DISPLAY_ALL_APPS_TRACE_METHOD_NAME,
- DISPLAY_ALL_APPS_TRACE_COOKIE);
- }
+ Trace.beginAsyncSection(
+ DISPLAY_WORKSPACE_TRACE_METHOD_NAME, DISPLAY_WORKSPACE_TRACE_COOKIE);
+ Trace.beginAsyncSection(DISPLAY_ALL_APPS_TRACE_METHOD_NAME,
+ DISPLAY_ALL_APPS_TRACE_COOKIE);
TraceHelper.INSTANCE.beginSection(ON_CREATE_EVT);
if (DEBUG_STRICT_MODE) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
@@ -733,13 +730,6 @@
public void onEnterAnimationComplete() {
super.onEnterAnimationComplete();
mRotationHelper.setCurrentTransitionRequest(REQUEST_NONE);
- // Starting with Android S, onEnterAnimationComplete is sent immediately
- // causing the surface to get removed before the animation completed (b/175345344).
- // Instead we rely on next user touch event to remove the view and optionally a callback
- // from system from Android T onwards.
- if (!Utilities.ATLEAST_S) {
- AbstractFloatingView.closeOpenViews(this, false, TYPE_ICON_SURFACE);
- }
}
@Override
@@ -1251,9 +1241,7 @@
* Returns {@link EventEnum} that should be logged when Launcher enters into AllApps state.
*/
protected Optional<EventEnum> getAllAppsEntryEvent() {
- return Optional.of(FeatureFlags.ENABLE_DEVICE_SEARCH.get()
- ? LAUNCHER_ALLAPPS_ENTRY_WITH_DEVICE_SEARCH
- : LAUNCHER_ALLAPPS_ENTRY);
+ return Optional.of(LAUNCHER_ALLAPPS_ENTRY_WITH_DEVICE_SEARCH);
}
@Override
@@ -2582,10 +2570,8 @@
public void bindAllApplications(AppInfo[] apps, int flags,
Map<PackageUserKey, Integer> packageUserKeytoUidMap) {
mModelCallbacks.bindAllApplications(apps, flags, packageUserKeytoUidMap);
- if (Utilities.ATLEAST_S) {
- Trace.endAsyncSection(DISPLAY_ALL_APPS_TRACE_METHOD_NAME,
- DISPLAY_ALL_APPS_TRACE_COOKIE);
- }
+ Trace.endAsyncSection(DISPLAY_ALL_APPS_TRACE_METHOD_NAME,
+ DISPLAY_ALL_APPS_TRACE_COOKIE);
}
/**
@@ -2678,6 +2664,7 @@
}
writer.println(prefix + " Hotseat");
+ mHotseat.dump(prefix, writer);
ViewGroup layout = mHotseat.getShortcutsAndWidgets();
for (int j = 0; j < layout.getChildCount(); j++) {
Object tag = layout.getChildAt(j).getTag();
diff --git a/src/com/android/launcher3/LauncherApplication.java b/src/com/android/launcher3/LauncherApplication.java
index 490186a..4c82e56 100644
--- a/src/com/android/launcher3/LauncherApplication.java
+++ b/src/com/android/launcher3/LauncherApplication.java
@@ -18,6 +18,7 @@
import android.app.Application;
import com.android.launcher3.dagger.DaggerLauncherAppComponent;
+import com.android.launcher3.dagger.LauncherAppComponent;
import com.android.launcher3.dagger.LauncherBaseAppComponent;
/**
@@ -30,10 +31,18 @@
public void onCreate() {
super.onCreate();
MainProcessInitializer.initialize(this);
- mAppComponent = DaggerLauncherAppComponent.builder().appContext(this).build();
+ initDagger();
}
- public LauncherBaseAppComponent getAppComponent() {
- return mAppComponent;
+ public LauncherAppComponent getAppComponent() {
+ // Since supertype setters will return a supertype.builder and @Component.Builder types
+ // must not have any generic types.
+ // We need to cast mAppComponent to {@link LauncherAppComponent} since appContext()
+ // method is defined in the super class LauncherBaseComponent#Builder.
+ return (LauncherAppComponent) mAppComponent;
+ }
+
+ protected void initDagger() {
+ mAppComponent = DaggerLauncherAppComponent.builder().appContext(this).build();
}
}
diff --git a/src/com/android/launcher3/ModelCallbacks.kt b/src/com/android/launcher3/ModelCallbacks.kt
index d57f8a0..496d517 100644
--- a/src/com/android/launcher3/ModelCallbacks.kt
+++ b/src/com/android/launcher3/ModelCallbacks.kt
@@ -61,7 +61,7 @@
AbstractFloatingView.closeOpenViews(
launcher,
true,
- AbstractFloatingView.TYPE_ALL and AbstractFloatingView.TYPE_REBIND_SAFE.inv()
+ AbstractFloatingView.TYPE_ALL and AbstractFloatingView.TYPE_REBIND_SAFE.inv(),
)
workspaceLoading = true
@@ -76,7 +76,7 @@
TAG,
"startBinding: " +
"hotseat layout was vertical: ${launcher.hotseat?.isHasVerticalHotseat}" +
- " and is setting to ${launcher.deviceProfile.isVerticalBarLayout}"
+ " and is setting to ${launcher.deviceProfile.isVerticalBarLayout}",
)
launcher.hotseat?.resetLayout(launcher.deviceProfile.isVerticalBarLayout)
TraceHelper.INSTANCE.endSection()
@@ -88,14 +88,12 @@
pendingTasks: RunnableList,
onCompleteSignal: RunnableList,
workspaceItemCount: Int,
- isBindSync: Boolean
+ isBindSync: Boolean,
) {
- if (Utilities.ATLEAST_S) {
- Trace.endAsyncSection(
- TraceEvents.DISPLAY_WORKSPACE_TRACE_METHOD_NAME,
- TraceEvents.DISPLAY_WORKSPACE_TRACE_COOKIE
- )
- }
+ Trace.endAsyncSection(
+ TraceEvents.DISPLAY_WORKSPACE_TRACE_METHOD_NAME,
+ TraceEvents.DISPLAY_WORKSPACE_TRACE_COOKIE,
+ )
synchronouslyBoundPages = boundPages
pagesToBindSynchronously = LIntSet()
clearPendingBinds()
@@ -149,14 +147,14 @@
// Cache one page worth of icons
launcher.viewCache.setCacheSize(
R.layout.folder_application,
- deviceProfile.numFolderColumns * deviceProfile.numFolderRows
+ deviceProfile.numFolderColumns * deviceProfile.numFolderRows,
)
launcher.viewCache.setCacheSize(R.layout.folder_page, 2)
TraceHelper.INSTANCE.endSection()
launcher.workspace.removeExtraEmptyScreen(/* stripEmptyScreens= */ true)
launcher.workspace.pageIndicator.setPauseScroll(
/*pause=*/ false,
- deviceProfile.isTwoPanels
+ deviceProfile.isTwoPanels,
)
TestEventEmitter.INSTANCE.get(launcher).sendEvent(TestEvent.WORKSPACE_FINISH_LOADING)
}
@@ -182,7 +180,7 @@
val snackbar =
AbstractFloatingView.getOpenView<AbstractFloatingView>(
launcher,
- AbstractFloatingView.TYPE_SNACKBAR
+ AbstractFloatingView.TYPE_SNACKBAR,
)
snackbar?.post { snackbar.close(true) }
}
@@ -191,7 +189,7 @@
override fun bindAllApplications(
apps: Array<AppInfo?>?,
flags: Int,
- packageUserKeytoUidMap: Map<PackageUserKey?, Int?>?
+ packageUserKeytoUidMap: Map<PackageUserKey?, Int?>?,
) {
Preconditions.assertUIThread()
val hadWorkApps = launcher.appsView.shouldShowTabs()
@@ -312,7 +310,7 @@
val info =
PendingAddWidgetInfo(
widgetsListBaseEntry.mWidgets[0].widgetInfo,
- LauncherSettings.Favorites.CONTAINER_DESKTOP
+ LauncherSettings.Favorites.CONTAINER_DESKTOP,
)
launcher.addPendingItem(
info,
@@ -320,14 +318,14 @@
WorkspaceLayoutManager.FIRST_SCREEN_ID,
intArrayOf(0, 0),
info.spanX,
- info.spanY
+ info.spanY,
)
}
override fun bindScreens(orderedScreenIds: LIntArray) {
launcher.workspace.pageIndicator.setPauseScroll(
/*pause=*/ true,
- launcher.deviceProfile.isTwoPanels
+ launcher.deviceProfile.isTwoPanels,
)
val firstScreenPosition = 0
if (
@@ -354,7 +352,7 @@
override fun bindAppsAdded(
newScreens: LIntArray?,
addNotAnimated: java.util.ArrayList<ItemInfo?>?,
- addAnimated: java.util.ArrayList<ItemInfo?>?
+ addAnimated: java.util.ArrayList<ItemInfo?>?,
) {
// Add the new screens
if (newScreens != null) {
diff --git a/src/com/android/launcher3/SecondaryDropTarget.java b/src/com/android/launcher3/SecondaryDropTarget.java
index 0a4fb73..8d1e61f 100644
--- a/src/com/android/launcher3/SecondaryDropTarget.java
+++ b/src/com/android/launcher3/SecondaryDropTarget.java
@@ -7,7 +7,6 @@
import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.INVALID;
import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.RECONFIGURE;
import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.UNINSTALL;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_DISMISS_PREDICTION_UNDO;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROPPED_ON_UNINSTALL;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_UNINSTALL_CANCELLED;
@@ -36,7 +35,6 @@
import androidx.annotation.Nullable;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.logging.InstanceId;
@@ -242,8 +240,7 @@
@Override
public void completeDrop(final DragObject d) {
- ComponentName target = performDropAction(getViewUnderDrag(d.dragInfo), d.dragInfo,
- d.logInstanceId);
+ ComponentName target = performDropAction(getViewUnderDrag(d.dragInfo), d.dragInfo);
mDropTargetHandler.onSecondaryTargetCompleteDrop(target, d);
}
@@ -275,7 +272,7 @@
* Performs the drop action and returns the target component for the dragObject or null if
* the action was not performed.
*/
- protected ComponentName performDropAction(View view, ItemInfo info, InstanceId instanceId) {
+ protected ComponentName performDropAction(View view, ItemInfo info) {
if (mCurrentAccessibilityAction == RECONFIGURE) {
int widgetId = getReconfigurableWidgetId(view);
if (widgetId != INVALID_APPWIDGET_ID) {
@@ -283,21 +280,6 @@
}
return null;
}
- if (mCurrentAccessibilityAction == DISMISS_PREDICTION) {
- if (FeatureFlags.ENABLE_DISMISS_PREDICTION_UNDO.get()) {
- CharSequence announcement = getContext().getString(R.string.item_removed);
- mDropTargetHandler
- .dismissPrediction(announcement, () -> {
- }, () -> {
- mStatsLogManager.logger()
- .withInstanceId(instanceId)
- .withItemInfo(info)
- .log(LAUNCHER_DISMISS_PREDICTION_UNDO);
- });
- }
- return null;
- }
-
return performUninstall(getContext(), getUninstallTarget(getContext(), info), info);
}
@@ -332,9 +314,8 @@
@Override
public void onAccessibilityDrop(View view, ItemInfo item) {
- InstanceId instanceId = new InstanceIdSequence().newInstanceId();
- doLog(instanceId, item);
- performDropAction(view, item, instanceId);
+ doLog(new InstanceIdSequence().newInstanceId(), item);
+ performDropAction(view, item);
}
/**
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index fde7014..f8ac48a 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -122,9 +122,6 @@
public static final String[] EMPTY_STRING_ARRAY = new String[0];
public static final Person[] EMPTY_PERSON_ARRAY = new Person[0];
- @ChecksSdkIntAtLeast(api = VERSION_CODES.S)
- public static final boolean ATLEAST_S = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S;
-
@ChecksSdkIntAtLeast(api = VERSION_CODES.TIRAMISU, codename = "T")
public static final boolean ATLEAST_T = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU;
diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
index 6b5e3be..1094768 100644
--- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -728,9 +728,7 @@
removeCustomRules(rvContainer);
removeCustomRules(getSearchRecyclerView());
- if (!isSearchSupported()) {
- layoutWithoutSearchContainer(rvContainer, showTabs);
- } else if (isSearchBarFloating()) {
+ if (isSearchBarFloating()) {
alignParentTop(rvContainer, showTabs);
alignParentTop(getSearchRecyclerView(), /* tabs= */ false);
} else {
@@ -761,9 +759,7 @@
});
removeCustomRules(mHeader);
- if (!isSearchSupported()) {
- layoutWithoutSearchContainer(mHeader, false /* includeTabsMargin */);
- } else if (isSearchBarFloating()) {
+ if (isSearchBarFloating()) {
alignParentTop(mHeader, false /* includeTabsMargin */);
} else {
layoutBelowSearchContainer(mHeader, false /* includeTabsMargin */);
@@ -918,23 +914,6 @@
mMainAdapterProvider);
}
- // TODO(b/216683257): Remove when Taskbar All Apps supports search.
- protected boolean isSearchSupported() {
- return true;
- }
-
- private void layoutWithoutSearchContainer(View v, boolean includeTabsMargin) {
- if (!(v.getLayoutParams() instanceof RelativeLayout.LayoutParams)) {
- return;
- }
-
- RelativeLayout.LayoutParams layoutParams = (LayoutParams) v.getLayoutParams();
- layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
- layoutParams.topMargin = getContext().getResources().getDimensionPixelSize(includeTabsMargin
- ? R.dimen.all_apps_header_pill_height
- : R.dimen.all_apps_header_top_margin);
- }
-
public boolean isInAllApps() {
// TODO: Make this abstract
return true;
diff --git a/src/com/android/launcher3/allapps/AllAppsFastScrollHelper.java b/src/com/android/launcher3/allapps/AllAppsFastScrollHelper.java
index 911612f..77a0fe3 100644
--- a/src/com/android/launcher3/allapps/AllAppsFastScrollHelper.java
+++ b/src/com/android/launcher3/allapps/AllAppsFastScrollHelper.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.allapps;
+import static android.view.HapticFeedbackConstants.CLOCK_TICK;
+
import androidx.recyclerview.widget.LinearSmoothScroller;
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
@@ -71,6 +73,7 @@
@Override
protected int getVerticalSnapPreference() {
+ mRv.performHapticFeedback(CLOCK_TICK);
return SNAP_TO_ANY;
}
diff --git a/src/com/android/launcher3/allapps/FloatingHeaderView.java b/src/com/android/launcher3/allapps/FloatingHeaderView.java
index a2bd5dd..ac06ab4 100644
--- a/src/com/android/launcher3/allapps/FloatingHeaderView.java
+++ b/src/com/android/launcher3/allapps/FloatingHeaderView.java
@@ -34,7 +34,6 @@
import com.android.launcher3.Insettable;
import com.android.launcher3.R;
import com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.PluginManagerWrapper;
import com.android.launcher3.views.ActivityContext;
import com.android.systemui.plugins.AllAppsRow;
@@ -220,15 +219,12 @@
@Override
public View getFocusedChild() {
- if (FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
- for (FloatingHeaderRow row : mAllRows) {
- if (row.hasVisibleContent() && row.isVisible()) {
- return row.getFocusedChild();
- }
+ for (FloatingHeaderRow row : mAllRows) {
+ if (row.hasVisibleContent() && row.isVisible()) {
+ return row.getFocusedChild();
}
- return null;
}
- return super.getFocusedChild();
+ return null;
}
void setup(AllAppsRecyclerView mainRV, AllAppsRecyclerView workRV, SearchRecyclerView searchRV,
diff --git a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
index ec45415..de3bb9e 100644
--- a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
+++ b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
@@ -22,8 +22,6 @@
import android.text.style.SuggestionSpan;
import android.util.Log;
import android.view.KeyEvent;
-import android.view.View;
-import android.view.View.OnFocusChangeListener;
import android.view.inputmethod.EditorInfo;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
@@ -31,7 +29,6 @@
import com.android.launcher3.ExtendedEditText;
import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.search.SearchAlgorithm;
import com.android.launcher3.search.SearchCallback;
import com.android.launcher3.views.ActivityContext;
@@ -40,8 +37,7 @@
* An interface to a search box that AllApps can command.
*/
public class AllAppsSearchBarController
- implements TextWatcher, OnEditorActionListener, ExtendedEditText.OnBackKeyListener,
- OnFocusChangeListener {
+ implements TextWatcher, OnEditorActionListener, ExtendedEditText.OnBackKeyListener {
private static final String TAG = "AllAppsSearchBarController";
protected ActivityContext mLauncher;
@@ -69,7 +65,6 @@
mInput.addTextChangedListener(this);
mInput.setOnEditorActionListener(this);
mInput.setOnBackKeyListener(this);
- mInput.addOnFocusChangeListener(this);
mSearchAlgorithm = searchAlgorithm;
}
@@ -142,13 +137,6 @@
return false;
}
- @Override
- public void onFocusChange(View view, boolean hasFocus) {
- if (!hasFocus && !FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
- mInput.hideKeyboard();
- }
- }
-
/**
* Resets the search bar state.
*/
@@ -157,7 +145,6 @@
mInput.reset();
mInput.clearFocus();
mQuery = null;
- mInput.removeOnFocusChangeListener(this);
}
/**
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index eb65320..8fe1b34 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -63,10 +63,6 @@
* <p>
*/
// TODO(Block 3): Clean up flags
- public static final BooleanFlag ENABLE_DISMISS_PREDICTION_UNDO = getDebugFlag(270394476,
- "ENABLE_DISMISS_PREDICTION_UNDO", DISABLED,
- "Show an 'Undo' snackbar when users dismiss a predicted hotseat item");
-
public static final BooleanFlag ENABLE_WORKSPACE_LOADING_OPTIMIZATION = getDebugFlag(251502424,
"ENABLE_WORKSPACE_LOADING_OPTIMIZATION", DISABLED,
"load the current workspace screen visible to the user before the rest rather than "
@@ -77,16 +73,7 @@
"changes the timing of the loading and binding of delegate items during "
+ "data preparation for loading the home screen");
- // TODO(Block 4): Cleanup flags
- public static final BooleanFlag ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS = getReleaseFlag(
- 270394468, "ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS", ENABLED,
- "Enable option to show keyboard when going to all-apps");
-
// TODO(Block 6): Clean up flags
- public static final BooleanFlag ENABLE_ALL_APPS_SEARCH_IN_TASKBAR = getDebugFlag(270393900,
- "ENABLE_ALL_APPS_SEARCH_IN_TASKBAR", ENABLED,
- "Enables Search box in Taskbar All Apps.");
-
public static final BooleanFlag SECONDARY_DRAG_N_DROP_TO_PIN = getDebugFlag(270395140,
"SECONDARY_DRAG_N_DROP_TO_PIN", DISABLED,
"Enable dragging and dropping to pin apps within secondary display");
@@ -148,28 +135,11 @@
public static final BooleanFlag PROMISE_APPS_IN_ALL_APPS = getDebugFlag(270390012,
"PROMISE_APPS_IN_ALL_APPS", DISABLED, "Add promise icon in all-apps");
- public static final BooleanFlag ENABLE_DEVICE_SEARCH = getReleaseFlag(270390907,
- "ENABLE_DEVICE_SEARCH", ENABLED, "Allows on device search in all apps");
-
- public static final BooleanFlag ENABLE_HIDE_HEADER = getReleaseFlag(270390930,
- "ENABLE_HIDE_HEADER", ENABLED, "Hide header on keyboard before typing in all apps");
-
// Aconfig migration complete for ENABLE_EXPANDING_PAUSE_WORK_BUTTON.
public static final BooleanFlag ENABLE_EXPANDING_PAUSE_WORK_BUTTON = getDebugFlag(270390779,
"ENABLE_EXPANDING_PAUSE_WORK_BUTTON", DISABLED,
"Expand and collapse pause work button while scrolling");
- // Aconfig migration complete for ENABLE_TWOLINE_ALLAPPS.
- public static final BooleanFlag ENABLE_TWOLINE_ALLAPPS = getDebugFlag(270390937,
- "ENABLE_TWOLINE_ALLAPPS", DISABLED, "Enables two line label inside all apps.");
-
- public static final BooleanFlag IME_STICKY_SNACKBAR_EDU = getDebugFlag(270391693,
- "IME_STICKY_SNACKBAR_EDU", ENABLED, "Show sticky IME edu in AllApps");
-
- public static final BooleanFlag FOLDER_NAME_MAJORITY_RANKING = getDebugFlag(270391638,
- "FOLDER_NAME_MAJORITY_RANKING", ENABLED,
- "Suggests folder names based on majority based ranking.");
-
public static final BooleanFlag INJECT_FALLBACK_APP_CORPUS_RESULTS = getReleaseFlag(270391706,
"INJECT_FALLBACK_APP_CORPUS_RESULTS", DISABLED,
"Inject fallback app corpus result when AiAi fails to return it.");
@@ -194,15 +164,6 @@
return ENABLE_APP_PAIRS.get() || com.android.wm.shell.Flags.enableAppPairs();
}
- // TODO(Block 19): Clean up flags
- public static final BooleanFlag SCROLL_TOP_TO_RESET = getReleaseFlag(270395177,
- "SCROLL_TOP_TO_RESET", ENABLED,
- "Bring up IME and focus on input when scroll to top if 'Always show keyboard'"
- + " is enabled or in prefix state");
-
- public static final BooleanFlag ENABLE_SEARCH_UNINSTALLED_APPS = getReleaseFlag(270395269,
- "ENABLE_SEARCH_UNINSTALLED_APPS", ENABLED, "Search uninstalled app results.");
-
// TODO(Block 20): Clean up flags
// Aconfig migration complete for ENABLE_HOME_TRANSITION_LISTENER.
public static final BooleanFlag ENABLE_HOME_TRANSITION_LISTENER = getDebugFlag(306053414,
@@ -261,10 +222,15 @@
}
// TODO(Block 29): Clean up flags
+ // Aconfig migration complete for ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT.
public static final BooleanFlag ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT = getDebugFlag(270393897,
"ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT", DISABLED,
"Enables displaying the all apps button in the hotseat.");
+ public static boolean enableAllAppsButtonInHotseat() {
+ return ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT.get() || Flags.enableAllAppsButtonInHotseat();
+ }
+
// TODO(Block 30): Clean up flags
public static final BooleanFlag USE_SEARCH_REQUEST_TIMEOUT_OVERRIDES = getDebugFlag(270395010,
"USE_SEARCH_REQUEST_TIMEOUT_OVERRIDES", DISABLED,
diff --git a/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java b/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java
index 1a59d82..0a50e8b 100644
--- a/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java
+++ b/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java
@@ -18,6 +18,8 @@
import android.content.Context;
+import com.android.launcher3.util.DaggerSingletonTracker;
+
import dagger.BindsInstance;
/**
@@ -29,6 +31,7 @@
* See {@link LauncherAppComponent} for the one actually used by AOSP.
*/
public interface LauncherBaseAppComponent {
+ DaggerSingletonTracker getDaggerSingletonTracker();
/** Builder for LauncherBaseAppComponent. */
interface Builder {
@BindsInstance Builder appContext(@ApplicationContext Context context);
diff --git a/src/com/android/launcher3/graphics/GridCustomizationsProvider.java b/src/com/android/launcher3/graphics/GridCustomizationsProvider.java
index 374c07b..531cdfd 100644
--- a/src/com/android/launcher3/graphics/GridCustomizationsProvider.java
+++ b/src/com/android/launcher3/graphics/GridCustomizationsProvider.java
@@ -16,11 +16,13 @@
package com.android.launcher3.graphics;
import static com.android.launcher3.LauncherPrefs.THEMED_ICONS;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.Themes.isThemedIconEnabled;
import android.content.ContentProvider;
import android.content.ContentValues;
+import android.content.Context;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.MatrixCursor;
@@ -39,8 +41,15 @@
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.InvariantDeviceProfile.GridOption;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherPrefs;
+import com.android.launcher3.model.BgDataModel;
import com.android.launcher3.util.Executors;
+import com.android.launcher3.util.Preconditions;
+import com.android.systemui.shared.Flags;
+
+import java.util.concurrent.ExecutionException;
/**
* Exposes various launcher grid options and allows the caller to change them.
@@ -144,14 +153,20 @@
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
- switch (uri.getPath()) {
+ String path = uri.getPath();
+ Context context = getContext();
+ if (path == null || context == null) {
+ return 0;
+ }
+ switch (path) {
case KEY_DEFAULT_GRID: {
String gridName = values.getAsString(KEY_NAME);
- InvariantDeviceProfile idp = InvariantDeviceProfile.INSTANCE.get(getContext());
+ InvariantDeviceProfile idp = InvariantDeviceProfile.INSTANCE.get(context);
// Verify that this is a valid grid option
GridOption match = null;
- for (GridOption option : idp.parseAllGridOptions(getContext())) {
- if (option.name.equals(gridName)) {
+ for (GridOption option : idp.parseAllGridOptions(context)) {
+ String name = option.name;
+ if (name != null && name.equals(gridName)) {
match = option;
break;
}
@@ -160,15 +175,23 @@
return 0;
}
- idp.setCurrentGrid(getContext(), gridName);
- getContext().getContentResolver().notifyChange(uri, null);
+ idp.setCurrentGrid(context, gridName);
+ if (Flags.newCustomizationPickerUi()) {
+ try {
+ // Wait for device profile to be fully reloaded and applied to the launcher
+ loadModelSync(context);
+ } catch (ExecutionException | InterruptedException e) {
+ Log.e(TAG, "Fail to load model", e);
+ }
+ }
+ context.getContentResolver().notifyChange(uri, null);
return 1;
}
case ICON_THEMED:
case SET_ICON_THEMED: {
- LauncherPrefs.get(getContext())
+ LauncherPrefs.get(context)
.put(THEMED_ICONS, values.getAsBoolean(BOOLEAN_VALUE));
- getContext().getContentResolver().notifyChange(uri, null);
+ context.getContentResolver().notifyChange(uri, null);
return 1;
}
default:
@@ -176,6 +199,23 @@
}
}
+ /**
+ * Loads the model in memory synchronously
+ */
+ private void loadModelSync(Context context) throws ExecutionException, InterruptedException {
+ Preconditions.assertNonUiThread();
+ BgDataModel.Callbacks emptyCallbacks = new BgDataModel.Callbacks() { };
+ LauncherModel launcherModel = LauncherAppState.getInstance(context).getModel();
+ MAIN_EXECUTOR.submit(
+ () -> launcherModel.addCallbacksAndLoad(emptyCallbacks)
+ ).get();
+
+ Executors.MODEL_EXECUTOR.submit(() -> { }).get();
+ MAIN_EXECUTOR.submit(
+ () -> launcherModel.removeCallbacks(emptyCallbacks)
+ ).get();
+ }
+
@Override
public Bundle call(String method, String arg, Bundle extras) {
if (getContext().checkPermission("android.permission.BIND_WALLPAPER",
@@ -227,7 +267,7 @@
}
observer.destroyed = true;
observer.renderer.getHostToken().unlinkToDeath(observer, 0);
- Executors.MAIN_EXECUTOR.execute(observer.renderer::destroy);
+ MAIN_EXECUTOR.execute(observer.renderer::destroy);
PreviewLifecycleObserver cached = mActivePreviews.get(observer.getIdentifier());
if (cached == observer) {
mActivePreviews.remove(observer.getIdentifier());
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index 2408955..40c0cc6 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -23,6 +23,7 @@
import static com.android.launcher3.BubbleTextView.DISPLAY_TASKBAR;
import static com.android.launcher3.BubbleTextView.DISPLAY_WORKSPACE;
import static com.android.launcher3.DeviceProfile.DEFAULT_SCALE;
+import static com.android.launcher3.Hotseat.ALPHA_CHANNEL_PREVIEW_RENDERER;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
import static com.android.launcher3.Utilities.SHOULD_SHOW_FIRST_PAGE_WIDGET;
import static com.android.launcher3.model.ModelUtils.filterCurrentWorkspaceItems;
@@ -68,7 +69,6 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
import com.android.launcher3.WorkspaceLayoutManager;
import com.android.launcher3.apppairs.AppPairIcon;
@@ -206,15 +206,12 @@
mWorkspaceScreens.put(Workspace.SECOND_SCREEN_ID, rightPanel);
}
- if (Utilities.ATLEAST_S) {
- WallpaperColors wallpaperColors = wallpaperColorsOverride != null
- ? wallpaperColorsOverride
- : WallpaperManager.getInstance(context).getWallpaperColors(FLAG_SYSTEM);
- mWallpaperColorResources = wallpaperColors != null ? LocalColorExtractor.newInstance(
- context).generateColorsOverride(wallpaperColors) : null;
- } else {
- mWallpaperColorResources = null;
- }
+ WallpaperColors wallpaperColors = wallpaperColorsOverride != null
+ ? wallpaperColorsOverride
+ : WallpaperManager.getInstance(context).getWallpaperColors(FLAG_SYSTEM);
+ mWallpaperColorResources = wallpaperColors != null
+ ? LocalColorExtractor.newInstance(context).generateColorsOverride(wallpaperColors)
+ : null;
mAppWidgetHost = new LauncherPreviewAppWidgetHost(context);
}
@@ -320,12 +317,12 @@
mUiHandler.post(() -> {
if (mDp.isTaskbarPresent) {
// hotseat icons on bottom
- mHotseat.setIconsAlpha(hide ? 0 : 1);
+ mHotseat.setIconsAlpha(hide ? 0 : 1, ALPHA_CHANNEL_PREVIEW_RENDERER);
if (mDp.isQsbInline) {
- mHotseat.setQsbAlpha(hide ? 0 : 1);
+ mHotseat.setQsbAlpha(hide ? 0 : 1, ALPHA_CHANNEL_PREVIEW_RENDERER);
}
} else {
- mHotseat.setQsbAlpha(hide ? 0 : 1);
+ mHotseat.setQsbAlpha(hide ? 0 : 1, ALPHA_CHANNEL_PREVIEW_RENDERER);
}
});
}
diff --git a/src/com/android/launcher3/icons/ComponentWithLabel.java b/src/com/android/launcher3/icons/ComponentWithLabel.java
deleted file mode 100644
index 30575fc..0000000
--- a/src/com/android/launcher3/icons/ComponentWithLabel.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2018 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.icons;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.UserHandle;
-
-import androidx.annotation.NonNull;
-
-import com.android.launcher3.icons.cache.CachingLogic;
-
-public interface ComponentWithLabel {
-
- ComponentName getComponent();
-
- UserHandle getUser();
-
- CharSequence getLabel(PackageManager pm);
-
-
- class ComponentCachingLogic<T extends ComponentWithLabel> implements CachingLogic<T> {
-
- private final PackageManager mPackageManager;
- private final boolean mAddToMemCache;
-
- public ComponentCachingLogic(Context context, boolean addToMemCache) {
- mPackageManager = context.getPackageManager();
- mAddToMemCache = addToMemCache;
- }
-
- @Override
- @NonNull
- public ComponentName getComponent(@NonNull T object) {
- return object.getComponent();
- }
-
- @NonNull
- @Override
- public UserHandle getUser(@NonNull T object) {
- return object.getUser();
- }
-
- @NonNull
- @Override
- public CharSequence getLabel(@NonNull T object) {
- return object.getLabel(mPackageManager);
- }
-
- @NonNull
- @Override
- public BitmapInfo loadIcon(@NonNull Context context, @NonNull T object) {
- return BitmapInfo.LOW_RES_INFO;
- }
-
- @Override
- public boolean addToMemCache() {
- return mAddToMemCache;
- }
- }
-}
diff --git a/src/com/android/launcher3/icons/ComponentWithLabelAndIcon.java b/src/com/android/launcher3/icons/ComponentWithLabelAndIcon.java
deleted file mode 100644
index 0a52dd7..0000000
--- a/src/com/android/launcher3/icons/ComponentWithLabelAndIcon.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.icons;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-
-import androidx.annotation.NonNull;
-
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.icons.BaseIconFactory.IconOptions;
-
-/**
- * Extension of ComponentWithLabel to also support loading icons
- */
-public interface ComponentWithLabelAndIcon extends ComponentWithLabel {
-
- /**
- * Provide an icon for this object
- */
- Drawable getFullResIcon(IconCache cache);
-
- class ComponentWithIconCachingLogic extends ComponentCachingLogic<ComponentWithLabelAndIcon> {
-
- public ComponentWithIconCachingLogic(Context context, boolean addToMemCache) {
- super(context, addToMemCache);
- }
-
- @NonNull
- @Override
- public BitmapInfo loadIcon(@NonNull Context context,
- @NonNull ComponentWithLabelAndIcon object) {
- Drawable d = object.getFullResIcon(LauncherAppState.getInstance(context)
- .getIconCache());
- if (d == null) {
- return super.loadIcon(context, object);
- }
- try (LauncherIcons li = LauncherIcons.obtain(context)) {
- return li.createBadgedIconBitmap(d, new IconOptions().setUser(object.getUser()));
- }
- }
- }
-}
diff --git a/src/com/android/launcher3/icons/IconCache.java b/src/com/android/launcher3/icons/IconCache.java
index 44e448e..587dc27 100644
--- a/src/com/android/launcher3/icons/IconCache.java
+++ b/src/com/android/launcher3/icons/IconCache.java
@@ -54,9 +54,10 @@
import com.android.launcher3.Flags;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.Utilities;
-import com.android.launcher3.icons.ComponentWithLabel.ComponentCachingLogic;
import com.android.launcher3.icons.cache.BaseIconCache;
+import com.android.launcher3.icons.cache.CachedObjectCachingLogic;
import com.android.launcher3.icons.cache.CachingLogic;
+import com.android.launcher3.icons.cache.LauncherActivityCachingLogic;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.IconRequestInfo;
@@ -102,7 +103,6 @@
private final LauncherApps mLauncherApps;
private final UserCache mUserManager;
private final InstantAppResolver mInstantAppResolver;
- private final IconProvider mIconProvider;
private final CancellableTask mCancelledTask;
private final SparseArray<BitmapInfo> mWidgetCategoryBitmapInfos;
@@ -112,14 +112,14 @@
public IconCache(Context context, InvariantDeviceProfile idp, String dbFileName,
IconProvider iconProvider) {
super(context, dbFileName, MODEL_EXECUTOR.getLooper(),
- idp.fillResIconDpi, idp.iconBitmapSize, true /* inMemoryCache */);
- mComponentWithLabelCachingLogic = new ComponentCachingLogic(context, false);
- mLauncherActivityInfoCachingLogic = LauncherActivityCachingLogic.newInstance(context);
+ idp.fillResIconDpi, idp.iconBitmapSize, true /* inMemoryCache */, iconProvider);
+ mComponentWithLabelCachingLogic = new CachedObjectCachingLogic(
+ context, false /* loadIcons */, false /* addToMemCache */);
+ mLauncherActivityInfoCachingLogic = LauncherActivityCachingLogic.INSTANCE;
mShortcutCachingLogic = new ShortcutCachingLogic();
mLauncherApps = mContext.getSystemService(LauncherApps.class);
mUserManager = UserCache.INSTANCE.get(mContext);
mInstantAppResolver = InstantAppResolver.newInstance(mContext);
- mIconProvider = iconProvider;
mWidgetCategoryBitmapInfos = new SparseArray<>();
mCancelledTask = new CancellableTask(() -> null, MAIN_EXECUTOR, c -> { });
@@ -337,6 +337,9 @@
}
}
+ /**
+ * Loads and returns the icon for the provided object without adding it to memCache
+ */
public synchronized String getTitleNoCache(ComponentWithLabel info) {
CacheEntry entry = cacheLocked(info.getComponent(), info.getUser(), () -> info,
mComponentWithLabelCachingLogic, false /* usePackageIcon */,
@@ -629,12 +632,6 @@
info.getAppLabel());
}
- @Override
- @NonNull
- protected String getIconSystemState(String packageName) {
- return mIconProvider.getSystemStateForPackage(mSystemState, packageName);
- }
-
/**
* Interface for receiving itemInfo with high-res icon.
*/
diff --git a/src/com/android/launcher3/icons/LauncherActivityCachingLogic.java b/src/com/android/launcher3/icons/LauncherActivityCachingLogic.java
deleted file mode 100644
index de2269c..0000000
--- a/src/com/android/launcher3/icons/LauncherActivityCachingLogic.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2018 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.icons;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.LauncherActivityInfo;
-import android.os.Build;
-import android.os.UserHandle;
-
-import androidx.annotation.NonNull;
-
-import com.android.launcher3.Flags;
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.R;
-import com.android.launcher3.icons.BaseIconFactory.IconOptions;
-import com.android.launcher3.icons.cache.CachingLogic;
-import com.android.launcher3.util.ResourceBasedOverride;
-
-/**
- * Caching logic for LauncherActivityInfo.
- */
-public class LauncherActivityCachingLogic
- implements CachingLogic<LauncherActivityInfo>, ResourceBasedOverride {
-
- /**
- * Creates and returns a new instance
- */
- public static LauncherActivityCachingLogic newInstance(Context context) {
- return Overrides.getObject(LauncherActivityCachingLogic.class, context,
- R.string.launcher_activity_logic_class);
- }
-
- @NonNull
- @Override
- public ComponentName getComponent(@NonNull LauncherActivityInfo object) {
- return object.getComponentName();
- }
-
- @NonNull
- @Override
- public UserHandle getUser(@NonNull LauncherActivityInfo object) {
- return object.getUser();
- }
-
- @NonNull
- @Override
- public CharSequence getLabel(@NonNull LauncherActivityInfo object) {
- return object.getLabel();
- }
-
- @NonNull
- @Override
- public BitmapInfo loadIcon(@NonNull Context context, @NonNull LauncherActivityInfo object) {
- try (LauncherIcons li = LauncherIcons.obtain(context)) {
- IconOptions iconOptions = new IconOptions().setUser(object.getUser());
- iconOptions.mIsArchived = Flags.useNewIconForArchivedApps()
- && Build.VERSION.SDK_INT >= 35
- && object.getActivityInfo().isArchived;
- return li.createBadgedIconBitmap(
- LauncherAppState.getInstance(context)
- .getIconProvider()
- .getIcon(object, li.mFillResIconDpi),
- iconOptions
- );
- }
- }
-}
diff --git a/src/com/android/launcher3/icons/Legacy.kt b/src/com/android/launcher3/icons/Legacy.kt
new file mode 100644
index 0000000..3bf3bb2
--- /dev/null
+++ b/src/com/android/launcher3/icons/Legacy.kt
@@ -0,0 +1,31 @@
+/*
+ * 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.icons
+
+import com.android.launcher3.icons.cache.CachedObject
+
+/**
+ * This files contains some definitions used during refactoring to avoid breaking changes.
+ *
+ * TODO(b/366237794) remove this file once refactoring is complete
+ */
+
+/** Temporary interface to allow easier refactoring */
+interface ComponentWithLabel : CachedObject<IconCache>
+
+/** Temporary interface to allow easier refactoring */
+interface ComponentWithLabelAndIcon : ComponentWithLabel
diff --git a/src/com/android/launcher3/icons/ShortcutCachingLogic.java b/src/com/android/launcher3/icons/ShortcutCachingLogic.java
index f40eda6..7bb39e1 100644
--- a/src/com/android/launcher3/icons/ShortcutCachingLogic.java
+++ b/src/com/android/launcher3/icons/ShortcutCachingLogic.java
@@ -33,6 +33,7 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.icons.BaseIconFactory.IconOptions;
+import com.android.launcher3.icons.cache.BaseIconCache;
import com.android.launcher3.icons.cache.CachingLogic;
import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.util.Themes;
@@ -72,7 +73,8 @@
@NonNull
@Override
- public BitmapInfo loadIcon(@NonNull Context context, @NonNull ShortcutInfo info) {
+ public BitmapInfo loadIcon(@NonNull Context context, @NonNull BaseIconCache cache,
+ @NonNull ShortcutInfo info) {
try (LauncherIcons li = LauncherIcons.obtain(context)) {
Drawable unbadgedDrawable = ShortcutCachingLogic.getIcon(
context, info, LauncherAppState.getIDP(context).fillResIconDpi);
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 605accf..609846f 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -70,11 +70,11 @@
import com.android.launcher3.folder.FolderNameInfos;
import com.android.launcher3.folder.FolderNameProvider;
import com.android.launcher3.icons.ComponentWithLabelAndIcon;
-import com.android.launcher3.icons.ComponentWithLabelAndIcon.ComponentWithIconCachingLogic;
import com.android.launcher3.icons.IconCache;
-import com.android.launcher3.icons.LauncherActivityCachingLogic;
import com.android.launcher3.icons.ShortcutCachingLogic;
+import com.android.launcher3.icons.cache.CachedObjectCachingLogic;
import com.android.launcher3.icons.cache.IconCacheUpdateHandler;
+import com.android.launcher3.icons.cache.LauncherActivityCachingLogic;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.AppPairInfo;
@@ -298,7 +298,7 @@
IconCacheUpdateHandler updateHandler = mIconCache.getUpdateHandler();
setIgnorePackages(updateHandler);
updateHandler.updateIcons(allActivityList,
- LauncherActivityCachingLogic.newInstance(mApp.getContext()),
+ LauncherActivityCachingLogic.INSTANCE,
mApp.getModel()::onPackageIconsUpdated);
logASplit("update icon cache");
@@ -360,7 +360,7 @@
}
updateHandler.updateIcons(allWidgetsList,
- new ComponentWithIconCachingLogic(mApp.getContext(), true),
+ new CachedObjectCachingLogic(mApp.getContext()),
mApp.getModel()::onWidgetLabelsUpdated);
logASplit("save widgets in icon cache");
diff --git a/src/com/android/launcher3/model/WidgetItem.java b/src/com/android/launcher3/model/WidgetItem.java
index 3f88717..ac9f2d6 100644
--- a/src/com/android/launcher3/model/WidgetItem.java
+++ b/src/com/android/launcher3/model/WidgetItem.java
@@ -4,8 +4,6 @@
import static android.appwidget.AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD;
import static android.appwidget.AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX;
-import static com.android.launcher3.Utilities.ATLEAST_S;
-
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.ActivityInfo;
@@ -48,7 +46,7 @@
super(info.provider, info.getProfile());
label = iconCache.getTitleNoCache(info);
- description = ATLEAST_S ? info.loadDescription(context) : null;
+ description = info.loadDescription(context);
widgetInfo = info;
activityInfo = null;
@@ -107,7 +105,7 @@
/** Returns whether this {@link WidgetItem} has a preview layout that can be used. */
@SuppressLint("NewApi") // Already added API check.
public boolean hasPreviewLayout() {
- return ATLEAST_S && widgetInfo != null && widgetInfo.previewLayout != Resources.ID_NULL;
+ return widgetInfo != null && widgetInfo.previewLayout != Resources.ID_NULL;
}
/** Returns whether this {@link WidgetItem} is for a shortcut rather than an app widget. */
diff --git a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
index 90e47d6..1f1e514 100644
--- a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
+++ b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
@@ -30,7 +30,6 @@
import com.android.launcher3.InvariantDeviceProfile
import com.android.launcher3.LauncherAppState
import com.android.launcher3.LauncherSettings.Favorites
-import com.android.launcher3.Utilities
import com.android.launcher3.backuprestore.LauncherRestoreEventLogger.RestoreError
import com.android.launcher3.config.FeatureFlags
import com.android.launcher3.logging.FileLog
@@ -76,7 +75,7 @@
private val pmHelper: PackageManagerHelper,
private val iconRequestInfos: MutableList<IconRequestInfo<WorkspaceItemInfo>>,
private val unlockedUsers: LongSparseArray<Boolean>,
- private val allDeepShortcuts: MutableList<ShortcutInfo>
+ private val allDeepShortcuts: MutableList<ShortcutInfo>,
) {
private val isSafeMode = app.isSafeModeEnabled
@@ -97,7 +96,7 @@
// User has been deleted, remove the item.
c.markDeleted(
"User has been deleted for item id=${c.id}",
- RestoreError.PROFILE_DELETED
+ RestoreError.PROFILE_DELETED,
)
return
}
@@ -168,7 +167,7 @@
FileLog.d(
TAG,
"Activity not enabled for id=${c.id}, component=$cn, user=${c.user}." +
- " Will attempt to find fallback Activity for targetPkg=$targetPkg."
+ " Will attempt to find fallback Activity for targetPkg=$targetPkg.",
)
intent = pmHelper.getAppLaunchIntent(targetPkg, c.user)
if (intent != null) {
@@ -178,7 +177,7 @@
c.markDeleted(
"No Activities found for id=${c.id}, targetPkg=$targetPkg, component=$cn." +
" Unable to create launch Intent.",
- RestoreError.MISSING_INFO
+ RestoreError.MISSING_INFO,
)
return
}
@@ -213,7 +212,7 @@
else -> {
c.markDeleted(
"removing app that is not restored and not installing. package: $targetPkg",
- RestoreError.APP_NOT_INSTALLED
+ RestoreError.APP_NOT_INSTALLED,
)
return
}
@@ -238,7 +237,7 @@
// Do not wait for external media load anymore.
c.markDeleted(
"Invalid package removed: $targetPkg",
- RestoreError.APP_NOT_INSTALLED
+ RestoreError.APP_NOT_INSTALLED,
)
return
}
@@ -270,7 +269,7 @@
// The shortcut is no longer valid.
c.markDeleted(
"Pinned shortcut not found from request. package=${key.packageName}, user=${c.user}",
- RestoreError.SHORTCUT_NOT_FOUND
+ RestoreError.SHORTCUT_NOT_FOUND,
)
return
}
@@ -337,7 +336,7 @@
activityInfo,
userCache.getUserInfo(c.user),
ApiWrapper.INSTANCE[app.context],
- pmHelper
+ pmHelper,
)
}
if (
@@ -445,7 +444,7 @@
", id=${c.id}," +
", appWidgetId=${c.appWidgetId}," +
", component=${component}",
- RestoreError.INVALID_LOCATION
+ RestoreError.INVALID_LOCATION,
)
return
}
@@ -456,7 +455,7 @@
", appWidgetId=${c.appWidgetId}," +
", component=${component}," +
", container=${c.container}",
- RestoreError.INVALID_LOCATION
+ RestoreError.INVALID_LOCATION,
)
return
}
@@ -470,7 +469,7 @@
TAG,
"processWidget: id=${c.id}" +
", appWidgetId=${c.appWidgetId}" +
- ", inflationResult=$inflationResult"
+ ", inflationResult=$inflationResult",
)
when (inflationResult.type) {
WidgetInflater.TYPE_DELETE -> {
@@ -496,7 +495,7 @@
", appWidgetId=${c.appWidgetId}" +
", component=${component}" +
", restoreFlag:=${c.restoreFlag}",
- RestoreError.APP_NOT_INSTALLED
+ RestoreError.APP_NOT_INSTALLED,
)
return
} else if (
@@ -512,7 +511,7 @@
WidgetsModel.newPendingItemInfo(
app.context,
appWidgetInfo.providerName,
- appWidgetInfo.user
+ appWidgetInfo.user,
)
iconCache.getTitleAndIconForApp(appWidgetInfo.pendingItemInfo, false)
}
@@ -522,7 +521,7 @@
lapi,
app.context,
appWidgetInfo.spanX,
- appWidgetInfo.spanY
+ appWidgetInfo.spanY,
)
}
@@ -541,7 +540,7 @@
" processWidget: Widget ${lapi.component} minSizes not met: span=${appWidgetInfo.spanX}x${appWidgetInfo.spanY} minSpan=${lapi.minSpanX}x${lapi.minSpanY}," +
" id: ${c.id}," +
" appWidgetId: ${c.appWidgetId}," +
- " component=${component}"
+ " component=${component}",
)
logWidgetInfo(app.invariantDeviceProfile, lapi)
}
@@ -554,7 +553,7 @@
private fun logWidgetInfo(
idp: InvariantDeviceProfile,
- widgetProviderInfo: LauncherAppWidgetProviderInfo
+ widgetProviderInfo: LauncherAppWidgetProviderInfo,
) {
val cellSize = Point()
for (deviceProfile in idp.supportedProfiles) {
@@ -565,7 +564,7 @@
" available height: ${deviceProfile.availableHeightPx}," +
" cellLayoutBorderSpacePx Horizontal: ${deviceProfile.cellLayoutBorderSpacePx.x}," +
" cellLayoutBorderSpacePx Vertical: ${deviceProfile.cellLayoutBorderSpacePx.y}," +
- " cellSize: $cellSize"
+ " cellSize: $cellSize",
)
}
val widgetDimension = StringBuilder()
@@ -583,21 +582,19 @@
.append("defaultHeight: ")
.append(widgetProviderInfo.minHeight)
.append("\n")
- if (Utilities.ATLEAST_S) {
- widgetDimension
- .append("targetCellWidth: ")
- .append(widgetProviderInfo.targetCellWidth)
- .append("\n")
- .append("targetCellHeight: ")
- .append(widgetProviderInfo.targetCellHeight)
- .append("\n")
- .append("maxResizeWidth: ")
- .append(widgetProviderInfo.maxResizeWidth)
- .append("\n")
- .append("maxResizeHeight: ")
- .append(widgetProviderInfo.maxResizeHeight)
- .append("\n")
- }
+ widgetDimension
+ .append("targetCellWidth: ")
+ .append(widgetProviderInfo.targetCellWidth)
+ .append("\n")
+ .append("targetCellHeight: ")
+ .append(widgetProviderInfo.targetCellHeight)
+ .append("\n")
+ .append("maxResizeWidth: ")
+ .append(widgetProviderInfo.maxResizeWidth)
+ .append("\n")
+ .append("maxResizeHeight: ")
+ .append(widgetProviderInfo.maxResizeHeight)
+ .append("\n")
FileLog.d(TAG, widgetDimension.toString())
}
}
diff --git a/src/com/android/launcher3/model/data/LauncherAppWidgetInfo.java b/src/com/android/launcher3/model/data/LauncherAppWidgetInfo.java
index f4dda55..361f09d 100644
--- a/src/com/android/launcher3/model/data/LauncherAppWidgetInfo.java
+++ b/src/com/android/launcher3/model/data/LauncherAppWidgetInfo.java
@@ -21,7 +21,6 @@
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PIN_WIDGETS;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_TRAY;
-import static com.android.launcher3.Utilities.ATLEAST_S;
import android.appwidget.AppWidgetHostView;
import android.content.ComponentName;
@@ -233,16 +232,16 @@
if (providerInfo.isConfigurationOptional()) {
widgetFeatures |= FEATURE_OPTIONAL_CONFIGURATION;
}
- if (ATLEAST_S && providerInfo.previewLayout != Resources.ID_NULL) {
+ if (providerInfo.previewLayout != Resources.ID_NULL) {
widgetFeatures |= FEATURE_PREVIEW_LAYOUT;
}
- if (ATLEAST_S && providerInfo.targetCellWidth > 0 || providerInfo.targetCellHeight > 0) {
+ if (providerInfo.targetCellWidth > 0 || providerInfo.targetCellHeight > 0) {
widgetFeatures |= FEATURE_TARGET_CELL_SIZE;
}
if (providerInfo.minResizeWidth > 0 || providerInfo.minResizeHeight > 0) {
widgetFeatures |= FEATURE_MIN_SIZE;
}
- if (ATLEAST_S && providerInfo.maxResizeWidth > 0 || providerInfo.maxResizeHeight > 0) {
+ if (providerInfo.maxResizeWidth > 0 || providerInfo.maxResizeHeight > 0) {
widgetFeatures |= FEATURE_MAX_SIZE;
}
if (hostView instanceof LauncherAppWidgetHostView &&
diff --git a/src/com/android/launcher3/pm/PinRequestHelper.java b/src/com/android/launcher3/pm/PinRequestHelper.java
index 667136a..47afeef 100644
--- a/src/com/android/launcher3/pm/PinRequestHelper.java
+++ b/src/com/android/launcher3/pm/PinRequestHelper.java
@@ -77,8 +77,9 @@
WorkspaceItemInfo info = new WorkspaceItemInfo(si, context);
// Apply the unbadged icon synchronously using the caching logic directly and
// fetch the actual icon asynchronously.
- info.bitmap = new ShortcutCachingLogic().loadIcon(context, si);
- LauncherAppState.getInstance(context).getModel().updateAndBindWorkspaceItem(info, si);
+ LauncherAppState app = LauncherAppState.getInstance(context);
+ info.bitmap = new ShortcutCachingLogic().loadIcon(context, app.getIconCache(), si);
+ app.getModel().updateAndBindWorkspaceItem(info, si);
return info;
} else {
return null;
diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java
index 1b245ab..63c9d94 100644
--- a/src/com/android/launcher3/popup/SystemShortcut.java
+++ b/src/com/android/launcher3/popup/SystemShortcut.java
@@ -1,5 +1,6 @@
package com.android.launcher3.popup;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_DISMISS_PREDICTION_UNDO;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_INSTALL_SYSTEM_SHORTCUT_TAP;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_UNINSTALL_SYSTEM_SHORTCUT_TAP;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_APP_INFO_TAP;
@@ -41,6 +42,7 @@
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.views.ActivityContext;
+import com.android.launcher3.views.Snackbar;
import com.android.launcher3.widget.WidgetsBottomSheet;
import com.android.launcher3.widget.picker.model.data.WidgetPickerData;
@@ -336,6 +338,14 @@
mTarget.getStatsLogManager().logger()
.withItemInfo(mItemInfo)
.log(LAUNCHER_SYSTEM_SHORTCUT_DONT_SUGGEST_APP_TAP);
+ if (Flags.enableDismissPredictionUndo()) {
+ Snackbar.show(mTarget,
+ view.getContext().getString(R.string.item_removed), R.string.undo,
+ () -> { }, () ->
+ mTarget.getStatsLogManager().logger()
+ .withItemInfo(mItemInfo)
+ .log(LAUNCHER_DISMISS_PREDICTION_UNDO));
+ }
}
}
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index 3817563..efd1f0d 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -40,11 +40,13 @@
import com.android.launcher3.LauncherState;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.contextualeducation.ContextualEduStatsManager;
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.util.FlingBlockCheck;
import com.android.launcher3.util.TouchController;
+import com.android.systemui.contextualeducation.GestureType;
/**
* TouchController for handling state changes
@@ -388,6 +390,7 @@
} else {
logReachedState(mToState);
}
+ updateContextualEduStats(targetState);
}
protected void goToTargetState(LauncherState targetState) {
@@ -403,6 +406,21 @@
.setDuration(0).start();
}
+ private void updateContextualEduStats(LauncherState targetState) {
+ if (targetState == NORMAL) {
+ ContextualEduStatsManager.INSTANCE.get(
+ mLauncher).updateEduStats(mDetector.isTrackpadGesture(), GestureType.HOME);
+ } else if (targetState == OVERVIEW) {
+ ContextualEduStatsManager.INSTANCE.get(
+ mLauncher).updateEduStats(mDetector.isTrackpadGesture(), GestureType.OVERVIEW);
+ } else if (targetState == ALL_APPS && !mDetector.isTrackpadGesture()) {
+ // Only update if it is touch gesture as trackpad gesture is not relevant for all apps
+ // which only provides keyboard education.
+ ContextualEduStatsManager.INSTANCE.get(
+ mLauncher).updateEduStats(/* isTrackpadGesture= */ false, GestureType.ALL_APPS);
+ }
+ }
+
private void logReachedState(LauncherState targetState) {
if (mStartState == targetState) {
return;
diff --git a/src/com/android/launcher3/touch/BaseSwipeDetector.java b/src/com/android/launcher3/touch/BaseSwipeDetector.java
index 52c3581..faac4a3 100644
--- a/src/com/android/launcher3/touch/BaseSwipeDetector.java
+++ b/src/com/android/launcher3/touch/BaseSwipeDetector.java
@@ -17,6 +17,8 @@
import static android.view.MotionEvent.INVALID_POINTER_ID;
+import static com.android.launcher3.MotionEventsUtils.isTrackpadMotionEvent;
+
import android.content.Context;
import android.graphics.PointF;
import android.util.Log;
@@ -64,6 +66,7 @@
protected PointF mSubtractDisplacement = new PointF();
@VisibleForTesting ScrollState mState = ScrollState.IDLE;
private boolean mIsSettingState;
+ protected boolean mIsTrackpadGesture;
protected boolean mIgnoreSlopWhenSettling;
protected Context mContext;
@@ -122,6 +125,10 @@
return mState == ScrollState.DRAGGING || mState == ScrollState.SETTLING;
}
+ public boolean isTrackpadGesture() {
+ return mIsTrackpadGesture;
+ }
+
public void finishedScrolling() {
setState(ScrollState.IDLE);
}
@@ -147,7 +154,7 @@
mLastPos.set(mDownPos);
mLastDisplacement.set(0, 0);
mDisplacement.set(0, 0);
-
+ mIsTrackpadGesture = isTrackpadMotionEvent(ev);
if (mState == ScrollState.SETTLING && mIgnoreSlopWhenSettling) {
setState(ScrollState.DRAGGING);
}
diff --git a/src/com/android/launcher3/util/DaggerSingletonObject.java b/src/com/android/launcher3/util/DaggerSingletonObject.java
new file mode 100644
index 0000000..b8cf2ae
--- /dev/null
+++ b/src/com/android/launcher3/util/DaggerSingletonObject.java
@@ -0,0 +1,44 @@
+/*
+ * 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.util;
+
+import android.content.Context;
+
+import com.android.launcher3.LauncherApplication;
+import com.android.launcher3.dagger.LauncherAppComponent;
+
+import java.util.function.Function;
+
+/**
+ * A class to provide DaggerSingleton objects in a traditional way for
+ * {@link MainThreadInitializedObject}.
+ * We should delete this class at the end and use @Inject to get dagger provided singletons.
+ */
+
+public class DaggerSingletonObject<T extends SafeCloseable> {
+ private final Function<LauncherAppComponent, T> mFunction;
+
+ public DaggerSingletonObject(Function<LauncherAppComponent, T> function) {
+ mFunction = function;
+ }
+
+ public T get(Context context) {
+ LauncherAppComponent component =
+ ((LauncherApplication) context.getApplicationContext()).getAppComponent();
+ return mFunction.apply(component);
+ }
+}
diff --git a/src/com/android/launcher3/util/DaggerSingletonTracker.java b/src/com/android/launcher3/util/DaggerSingletonTracker.java
new file mode 100644
index 0000000..2946da1
--- /dev/null
+++ b/src/com/android/launcher3/util/DaggerSingletonTracker.java
@@ -0,0 +1,57 @@
+/*
+ * 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.util;
+
+import com.android.launcher3.dagger.LauncherAppSingleton;
+
+import java.util.ArrayList;
+
+import javax.inject.Inject;
+
+/**
+ * A tracker class for keeping track of Dagger created singletons.
+ * Dagger will take care of creating singletons. But we should take care of unregistering callbacks
+ * if at all registered during singleton construction.
+ * All singletons should be declared as SafeCloseable so that we can call close() method.
+ */
+@LauncherAppSingleton
+public class DaggerSingletonTracker implements SafeCloseable {
+
+ private final ArrayList<SafeCloseable> mLauncherAppSingletons = new ArrayList<>();
+
+ @Inject
+ DaggerSingletonTracker() {
+ }
+
+ /**
+ * Adds the SafeCloseable Singletons to the mLauncherAppSingletons list.
+ * This helps to track the singletons and close them appropriately.
+ * See {@link DaggerSingletonTracker#close()} and
+ * {@link MainThreadInitializedObject.SandboxContext#onDestroy()}
+ */
+ public void addCloseable(SafeCloseable closeable) {
+ mLauncherAppSingletons.add(closeable);
+ }
+
+ @Override
+ public void close() {
+ // Destroy in reverse order
+ for (int i = mLauncherAppSingletons.size() - 1; i >= 0; i--) {
+ mLauncherAppSingletons.get(i).close();
+ }
+ }
+}
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index 072bcdf..afa5075 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -15,7 +15,6 @@
*/
package com.android.launcher3.util;
-import static android.content.Intent.ACTION_CONFIGURATION_CHANGED;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
@@ -33,7 +32,6 @@
import static com.android.launcher3.util.window.WindowManagerProxy.MIN_TABLET_WIDTH;
import android.annotation.SuppressLint;
-import android.annotation.TargetApi;
import android.content.ComponentCallbacks;
import android.content.Context;
import android.content.Intent;
@@ -42,7 +40,6 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
-import android.os.Build;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
@@ -132,21 +129,15 @@
}
Display display = mDM.getDisplay(DEFAULT_DISPLAY);
- if (Utilities.ATLEAST_S) {
- mWindowContext = mContext.createWindowContext(display, TYPE_APPLICATION, null);
- mWindowContext.registerComponentCallbacks(this);
- } else {
- mWindowContext = null;
- mReceiver.register(mContext, ACTION_CONFIGURATION_CHANGED);
- }
+ mWindowContext = mContext.createWindowContext(display, TYPE_APPLICATION, null);
+ mWindowContext.registerComponentCallbacks(this);
// Initialize navigation mode change listener
mReceiver.registerPkgActions(mContext, TARGET_OVERLAY_PACKAGE, ACTION_OVERLAY_CHANGED);
WindowManagerProxy wmProxy = WindowManagerProxy.INSTANCE.get(context);
- Context displayInfoContext = getDisplayInfoContext(display);
- mInfo = new Info(displayInfoContext, wmProxy,
- wmProxy.estimateInternalDisplayBounds(displayInfoContext));
+ mInfo = new Info(mWindowContext, wmProxy,
+ wmProxy.estimateInternalDisplayBounds(mWindowContext));
FileLog.i(TAG, "(CTOR) perDisplayBounds: " + mInfo.mPerDisplayBounds);
}
@@ -161,7 +152,7 @@
&& mInfo.mIsTaskbarPinnedInDesktopMode != prefs.get(
TASKBAR_PINNING_IN_DESKTOP_MODE);
if (isTaskbarPinningChanged || isTaskbarPinningDesktopModeChanged) {
- handleInfoChange(mWindowContext.getDisplay());
+ handleInfoChange();
}
};
@@ -191,7 +182,14 @@
* Handles info change for desktop mode.
*/
public static void handleInfoChangeForDesktopMode(Context context) {
- INSTANCE.get(context).handleInfoChange(context.getDisplay());
+ INSTANCE.get(context).handleInfoChange();
+ }
+
+ /**
+ * Handles info change for launcher visibility.
+ */
+ public static void handleInfoChangeForLauncherVisibilityChanged(Context context) {
+ INSTANCE.get(context).handleInfoChange();
}
/**
@@ -217,6 +215,13 @@
return INSTANCE.get(context).getInfo().isPinnedTaskbar();
}
+ /**
+ * Returns whether the taskbar is forced to be pinned when home is visible.
+ */
+ public static boolean showLockedTaskbarOnHome(Context context) {
+ return INSTANCE.get(context).getInfo().showLockedTaskbarOnHome();
+ }
+
@Override
public void close() {
mDestroyed = true;
@@ -252,36 +257,22 @@
if (mDestroyed) {
return;
}
- boolean reconfigure = false;
if (ACTION_OVERLAY_CHANGED.equals(intent.getAction())) {
- reconfigure = true;
- } else if (ACTION_CONFIGURATION_CHANGED.equals(intent.getAction())) {
- Configuration config = mContext.getResources().getConfiguration();
- reconfigure = mInfo.fontScale != config.fontScale
- || mInfo.densityDpi != config.densityDpi;
- }
-
- if (reconfigure) {
- Log.d(TAG, "Configuration changed, notifying listeners");
- Display display = mDM.getDisplay(DEFAULT_DISPLAY);
- if (display != null) {
- handleInfoChange(display);
- }
+ Log.d(TAG, "Overlay changed, notifying listeners");
+ handleInfoChange();
}
}
@UiThread
@Override
- @TargetApi(Build.VERSION_CODES.S)
public final void onConfigurationChanged(Configuration config) {
Log.d(TASKBAR_NOT_DESTROYED_TAG, "DisplayController#onConfigurationChanged: " + config);
- Display display = mWindowContext.getDisplay();
if (config.densityDpi != mInfo.densityDpi
|| config.fontScale != mInfo.fontScale
- || display.getRotation() != mInfo.rotation
|| !mInfo.mScreenSizeDp.equals(
- new PortraitSize(config.screenHeightDp, config.screenWidthDp))) {
- handleInfoChange(display);
+ new PortraitSize(config.screenHeightDp, config.screenWidthDp))
+ || mWindowContext.getDisplay().getRotation() != mInfo.rotation) {
+ handleInfoChange();
}
}
@@ -304,17 +295,13 @@
return mInfo;
}
- private Context getDisplayInfoContext(Display display) {
- return Utilities.ATLEAST_S ? mWindowContext : mContext.createDisplayContext(display);
- }
-
@AnyThread
@VisibleForTesting
- public void handleInfoChange(Display display) {
+ public void handleInfoChange() {
WindowManagerProxy wmProxy = WindowManagerProxy.INSTANCE.get(mContext);
Info oldInfo = mInfo;
- Context displayInfoContext = getDisplayInfoContext(display);
+ Context displayInfoContext = mWindowContext;
Info newInfo = new Info(displayInfoContext, wmProxy, oldInfo.mPerDisplayBounds);
if (newInfo.densityDpi != oldInfo.densityDpi || newInfo.fontScale != oldInfo.fontScale
@@ -345,7 +332,8 @@
}
if ((newInfo.mIsTaskbarPinned != oldInfo.mIsTaskbarPinned)
|| (newInfo.mIsTaskbarPinnedInDesktopMode
- != oldInfo.mIsTaskbarPinnedInDesktopMode)) {
+ != oldInfo.mIsTaskbarPinnedInDesktopMode)
+ || newInfo.isPinnedTaskbar() != oldInfo.isPinnedTaskbar()) {
change |= CHANGE_TASKBAR_PINNING;
}
if (newInfo.mIsInDesktopMode != oldInfo.mIsInDesktopMode) {
@@ -399,6 +387,9 @@
private final boolean mIsInDesktopMode;
+ private final boolean mShowLockedTaskbarOnHome;
+ private final boolean mIsHomeVisible;
+
public Info(Context displayInfoContext) {
/* don't need system overrides for external displays */
this(displayInfoContext, new WindowManagerProxy(), new ArrayMap<>());
@@ -460,6 +451,8 @@
mIsTaskbarPinnedInDesktopMode = LauncherPrefs.get(displayInfoContext).get(
TASKBAR_PINNING_IN_DESKTOP_MODE);
mIsInDesktopMode = wmProxy.isInDesktopMode();
+ mShowLockedTaskbarOnHome = wmProxy.showLockedTaskbarOnHome(displayInfoContext);
+ mIsHomeVisible = wmProxy.isHomeVisible(displayInfoContext);
}
/**
@@ -476,6 +469,10 @@
return sTransientTaskbarStatusForTests;
}
if (enableTaskbarPinning()) {
+ // If Launcher is visible on the freeform display, ensure the taskbar is pinned.
+ if (mShowLockedTaskbarOnHome && mIsHomeVisible) {
+ return false;
+ }
if (mIsInDesktopMode) {
return !mIsTaskbarPinnedInDesktopMode;
}
@@ -543,6 +540,13 @@
return TYPE_PHONE;
}
}
+
+ /**
+ * Returns whether the taskbar is forced to be pinned when home is visible.
+ */
+ public boolean showLockedTaskbarOnHome() {
+ return mShowLockedTaskbarOnHome;
+ }
}
/**
diff --git a/src/com/android/launcher3/util/EdgeEffectCompat.java b/src/com/android/launcher3/util/EdgeEffectCompat.java
index ca37259..a949f50 100644
--- a/src/com/android/launcher3/util/EdgeEffectCompat.java
+++ b/src/com/android/launcher3/util/EdgeEffectCompat.java
@@ -19,8 +19,6 @@
import android.view.MotionEvent;
import android.widget.EdgeEffect;
-import com.android.launcher3.Utilities;
-
/**
* Extension of {@link EdgeEffect} to allow backwards compatibility
*/
@@ -30,21 +28,6 @@
super(context);
}
- @Override
- public float getDistance() {
- return Utilities.ATLEAST_S ? super.getDistance() : 0;
- }
-
- @Override
- public float onPullDistance(float deltaDistance, float displacement) {
- if (Utilities.ATLEAST_S) {
- return super.onPullDistance(deltaDistance, displacement);
- } else {
- onPull(deltaDistance, displacement);
- return deltaDistance;
- }
- }
-
public float onPullDistance(float deltaDistance, float displacement, MotionEvent ev) {
return onPullDistance(deltaDistance, displacement);
}
diff --git a/src/com/android/launcher3/util/ExecutorUtil.java b/src/com/android/launcher3/util/ExecutorUtil.java
new file mode 100644
index 0000000..efc0eec
--- /dev/null
+++ b/src/com/android/launcher3/util/ExecutorUtil.java
@@ -0,0 +1,37 @@
+/*
+ * 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.util;
+
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+
+import android.os.Looper;
+
+import java.util.concurrent.ExecutionException;
+
+public final class ExecutorUtil {
+
+ /**
+ * Executes runnable on {@link Looper#getMainLooper()}, otherwise fails with an exception.
+ */
+ public static void executeSyncOnMainOrFail(Runnable runnable) {
+ try {
+ MAIN_EXECUTOR.submit(runnable).get();
+ } catch (InterruptedException | ExecutionException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/src/com/android/launcher3/util/MainThreadInitializedObject.java b/src/com/android/launcher3/util/MainThreadInitializedObject.java
index 63f14bd..e12ccbc 100644
--- a/src/com/android/launcher3/util/MainThreadInitializedObject.java
+++ b/src/com/android/launcher3/util/MainThreadInitializedObject.java
@@ -18,13 +18,13 @@
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.content.Context;
-import android.content.ContextWrapper;
import android.os.Looper;
import android.util.Log;
import androidx.annotation.UiThread;
import androidx.annotation.VisibleForTesting;
+import com.android.launcher3.LauncherApplication;
import com.android.launcher3.util.ResourceBasedOverride.Overrides;
import java.util.ArrayList;
@@ -118,7 +118,7 @@
* Abstract Context which allows custom implementations for
* {@link MainThreadInitializedObject} providers
*/
- public static class SandboxContext extends ContextWrapper implements SandboxApplication {
+ public static class SandboxContext extends LauncherApplication implements SandboxApplication {
private static final String TAG = "SandboxContext";
@@ -129,7 +129,8 @@
private boolean mDestroyed = false;
public SandboxContext(Context base) {
- super(base);
+ attachBaseContext(base);
+ initDagger();
}
@Override
@@ -138,6 +139,7 @@
}
public void onDestroy() {
+ getAppComponent().getDaggerSingletonTracker().close();
synchronized (mDestroyLock) {
// Destroy in reverse order
for (int i = mOrderedObjects.size() - 1; i >= 0; i--) {
diff --git a/src/com/android/launcher3/util/MultiTranslateDelegate.java b/src/com/android/launcher3/util/MultiTranslateDelegate.java
index 84ef445..38c87c8 100644
--- a/src/com/android/launcher3/util/MultiTranslateDelegate.java
+++ b/src/com/android/launcher3/util/MultiTranslateDelegate.java
@@ -37,6 +37,7 @@
public static final int INDEX_TASKBAR_ALIGNMENT_ANIM = 3;
public static final int INDEX_TASKBAR_REVEAL_ANIM = 4;
public static final int INDEX_TASKBAR_PINNING_ANIM = 5;
+ public static final int INDEX_NAV_BAR_ANIM = 6;
// Affect all items inside of a MultipageCellLayout
public static final int INDEX_CELLAYOUT_MULTIPAGE_SPACING = 3;
@@ -47,7 +48,7 @@
// Specific for hotseat items when adjusting for bubbles
public static final int INDEX_BUBBLE_ADJUSTMENT_ANIM = 3;
- public static final int COUNT = 6;
+ public static final int COUNT = 7;
private final MultiPropertyFactory<View> mTranslationX;
private final MultiPropertyFactory<View> mTranslationY;
diff --git a/src/com/android/launcher3/util/OverlayEdgeEffect.java b/src/com/android/launcher3/util/OverlayEdgeEffect.java
index d09d801..0623af7 100644
--- a/src/com/android/launcher3/util/OverlayEdgeEffect.java
+++ b/src/com/android/launcher3/util/OverlayEdgeEffect.java
@@ -46,6 +46,7 @@
return mDistance;
}
+ @Override
public float onPullDistance(float deltaDistance, float displacement) {
// Fallback implementation, will never actually get called
if (BuildConfig.IS_DEBUG_DEVICE) {
diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java
index 469e363..b1913c0 100644
--- a/src/com/android/launcher3/util/PackageManagerHelper.java
+++ b/src/com/android/launcher3/util/PackageManagerHelper.java
@@ -303,10 +303,7 @@
/** Returns the incremental download progress for the given shortcut's app. */
public static int getLoadingProgress(LauncherActivityInfo info) {
- if (Utilities.ATLEAST_S) {
- return (int) (100 * info.getLoadingProgress());
- }
- return 100;
+ return (int) (100 * info.getLoadingProgress());
}
/** Returns true in case app is installed on the device or in archived state. */
diff --git a/src/com/android/launcher3/util/Themes.java b/src/com/android/launcher3/util/Themes.java
index 60951ba..104040a 100644
--- a/src/com/android/launcher3/util/Themes.java
+++ b/src/com/android/launcher3/util/Themes.java
@@ -52,10 +52,8 @@
}
public static int getActivityThemeRes(Context context, int wallpaperColorHints) {
- boolean supportsDarkText = Utilities.ATLEAST_S
- && (wallpaperColorHints & HINT_SUPPORTS_DARK_TEXT) != 0;
- boolean isMainColorDark = Utilities.ATLEAST_S
- && (wallpaperColorHints & HINT_SUPPORTS_DARK_THEME) != 0;
+ boolean supportsDarkText = (wallpaperColorHints & HINT_SUPPORTS_DARK_TEXT) != 0;
+ boolean isMainColorDark = (wallpaperColorHints & HINT_SUPPORTS_DARK_THEME) != 0;
if (Utilities.isDarkTheme(context)) {
return supportsDarkText ? R.style.AppTheme_Dark_DarkText
diff --git a/src/com/android/launcher3/util/VibratorWrapper.java b/src/com/android/launcher3/util/VibratorWrapper.java
index a4b8eb0..adb8f9d 100644
--- a/src/com/android/launcher3/util/VibratorWrapper.java
+++ b/src/com/android/launcher3/util/VibratorWrapper.java
@@ -31,8 +31,6 @@
import androidx.annotation.VisibleForTesting;
-import com.android.launcher3.Utilities;
-
/**
* Wrapper around {@link Vibrator} to easily perform haptic feedback where necessary.
*/
@@ -129,7 +127,7 @@
/** Indicates that Taskbar has been invoked. */
public void vibrateForTaskbarUnstash() {
- if (Utilities.ATLEAST_S && mVibrator.areAllPrimitivesSupported(PRIMITIVE_LOW_TICK)) {
+ if (mVibrator.areAllPrimitivesSupported(PRIMITIVE_LOW_TICK)) {
VibrationEffect primitiveLowTickEffect = VibrationEffect
.startComposition()
.addPrimitive(PRIMITIVE_LOW_TICK, LOW_TICK_SCALE)
diff --git a/src/com/android/launcher3/util/WallpaperColorHints.kt b/src/com/android/launcher3/util/WallpaperColorHints.kt
index 1361c1e..11d4c25 100644
--- a/src/com/android/launcher3/util/WallpaperColorHints.kt
+++ b/src/com/android/launcher3/util/WallpaperColorHints.kt
@@ -23,7 +23,6 @@
import android.content.Context
import androidx.annotation.MainThread
import androidx.annotation.VisibleForTesting
-import com.android.launcher3.Utilities
import com.android.launcher3.util.Executors.MAIN_EXECUTOR
import com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR
@@ -34,36 +33,34 @@
class WallpaperColorHints(private val context: Context) : SafeCloseable {
var hints: Int = 0
private set
+
private val wallpaperManager
get() = context.getSystemService(WallpaperManager::class.java)!!
+
private val onColorHintsChangedListeners = mutableListOf<OnColorHintListener>()
private val onClose: SafeCloseable
init {
- if (Utilities.ATLEAST_S) {
- hints = wallpaperManager.getWallpaperColors(FLAG_SYSTEM)?.colorHints ?: 0
- val onColorsChangedListener = OnColorsChangedListener { colors, which ->
- onColorsChanged(colors, which)
- }
+ hints = wallpaperManager.getWallpaperColors(FLAG_SYSTEM)?.colorHints ?: 0
+ val onColorsChangedListener = OnColorsChangedListener { colors, which ->
+ onColorsChanged(colors, which)
+ }
+ UI_HELPER_EXECUTOR.execute {
+ wallpaperManager.addOnColorsChangedListener(
+ onColorsChangedListener,
+ MAIN_EXECUTOR.handler,
+ )
+ }
+ onClose = SafeCloseable {
UI_HELPER_EXECUTOR.execute {
- wallpaperManager.addOnColorsChangedListener(
- onColorsChangedListener,
- MAIN_EXECUTOR.handler
- )
+ wallpaperManager.removeOnColorsChangedListener(onColorsChangedListener)
}
- onClose = SafeCloseable {
- UI_HELPER_EXECUTOR.execute {
- wallpaperManager.removeOnColorsChangedListener(onColorsChangedListener)
- }
- }
- } else {
- onClose = SafeCloseable {}
}
}
@MainThread
private fun onColorsChanged(colors: WallpaperColors?, which: Int) {
- if ((which and FLAG_SYSTEM) != 0 && Utilities.ATLEAST_S) {
+ if ((which and FLAG_SYSTEM) != 0) {
val newHints = colors?.colorHints ?: 0
if (newHints != hints) {
hints = newHints
@@ -86,6 +83,7 @@
@VisibleForTesting
@JvmField
val INSTANCE = MainThreadInitializedObject { WallpaperColorHints(it) }
+
@JvmStatic fun get(context: Context): WallpaperColorHints = INSTANCE.get(context)
}
}
diff --git a/src/com/android/launcher3/util/window/WindowManagerProxy.java b/src/com/android/launcher3/util/window/WindowManagerProxy.java
index 0817c0a..84b4a36 100644
--- a/src/com/android/launcher3/util/window/WindowManagerProxy.java
+++ b/src/com/android/launcher3/util/window/WindowManagerProxy.java
@@ -32,7 +32,6 @@
import static com.android.launcher3.util.RotationUtils.rotateRect;
import static com.android.launcher3.util.RotationUtils.rotateSize;
-import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -40,7 +39,6 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
-import android.os.Build;
import android.util.ArrayMap;
import android.util.Log;
import android.view.Display;
@@ -54,7 +52,6 @@
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import com.android.launcher3.testing.shared.ResourceUtils;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.NavigationMode;
@@ -122,6 +119,20 @@
}
/**
+ * Returns if the pinned taskbar should be shown when home is visible.
+ */
+ public boolean showLockedTaskbarOnHome(Context displayInfoContext) {
+ return false;
+ }
+
+ /**
+ * Returns if the home is visible.
+ */
+ public boolean isHomeVisible(Context context) {
+ return false;
+ }
+
+ /**
* Returns the real bounds for the provided display after applying any insets normalization
*/
public WindowBounds getRealBounds(Context displayInfoContext, CachedDisplayInfo info) {
@@ -216,7 +227,7 @@
int screenWidthPx,
@NonNull WindowInsets windowInsets,
@NonNull WindowInsets.Builder insetsBuilder) {
- if (!isLargeScreen || !Utilities.ATLEAST_S) {
+ if (!isLargeScreen) {
return;
}
@@ -391,25 +402,16 @@
/**
* Returns a CachedDisplayInfo initialized for the current display
*/
- @TargetApi(Build.VERSION_CODES.S)
public CachedDisplayInfo getDisplayInfo(Context displayInfoContext) {
int rotation = getRotation(displayInfoContext);
- if (Utilities.ATLEAST_S) {
- WindowMetrics windowMetrics = displayInfoContext.getSystemService(WindowManager.class)
- .getMaximumWindowMetrics();
- return getDisplayInfo(windowMetrics, rotation);
- } else {
- Point size = new Point();
- Display display = getDisplay(displayInfoContext);
- display.getRealSize(size);
- return new CachedDisplayInfo(size, rotation);
- }
+ WindowMetrics windowMetrics = displayInfoContext.getSystemService(WindowManager.class)
+ .getMaximumWindowMetrics();
+ return getDisplayInfo(windowMetrics, rotation);
}
/**
* Returns a CachedDisplayInfo initialized for the current display
*/
- @TargetApi(Build.VERSION_CODES.S)
protected CachedDisplayInfo getDisplayInfo(WindowMetrics windowMetrics, int rotation) {
Point size = new Point(windowMetrics.getBounds().right, windowMetrics.getBounds().bottom);
return new CachedDisplayInfo(size, rotation,
@@ -478,8 +480,7 @@
}
}
}
- return Utilities.ATLEAST_S ? NavigationMode.NO_BUTTON :
- NavigationMode.THREE_BUTTONS;
+ return NavigationMode.NO_BUTTON;
}
@Override
diff --git a/src/com/android/launcher3/views/RecyclerViewFastScroller.java b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
index 63648dd..6fd18be 100644
--- a/src/com/android/launcher3/views/RecyclerViewFastScroller.java
+++ b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
@@ -355,7 +355,10 @@
if (!sectionName.equals(mPopupSectionName)) {
mPopupSectionName = sectionName;
mPopupView.setText(sectionName);
- performHapticFeedback(CLOCK_TICK);
+ // AllApps haptics are taken care of by AllAppsFastScrollHelper.
+ if (mFastScrollerLocation != ALL_APPS_SCROLLER) {
+ performHapticFeedback(CLOCK_TICK);
+ }
}
animatePopupVisibility(!TextUtils.isEmpty(sectionName));
mLastTouchY = boundedY;
diff --git a/src/com/android/launcher3/views/SpringRelativeLayout.java b/src/com/android/launcher3/views/SpringRelativeLayout.java
index 923eb19..a13152e 100644
--- a/src/com/android/launcher3/views/SpringRelativeLayout.java
+++ b/src/com/android/launcher3/views/SpringRelativeLayout.java
@@ -25,8 +25,6 @@
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerView.EdgeEffectFactory;
-import com.android.launcher3.Utilities;
-
/**
* View group to allow rendering overscroll effect in a child at the parent level
*/
@@ -46,10 +44,8 @@
public SpringRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
- mEdgeGlowTop = Utilities.ATLEAST_S
- ? new EdgeEffect(context, attrs) : new EdgeEffect(context);
- mEdgeGlowBottom = Utilities.ATLEAST_S
- ? new EdgeEffect(context, attrs) : new EdgeEffect(context);
+ mEdgeGlowTop = new EdgeEffect(context, attrs);
+ mEdgeGlowBottom = new EdgeEffect(context, attrs);
setWillNotDraw(false);
}
diff --git a/src/com/android/launcher3/widget/BaseLauncherAppWidgetHostView.java b/src/com/android/launcher3/widget/BaseLauncherAppWidgetHostView.java
index 856f4b3..12a14c2 100644
--- a/src/com/android/launcher3/widget/BaseLauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/BaseLauncherAppWidgetHostView.java
@@ -104,7 +104,7 @@
@UiThread
private void enforceRoundedCorners() {
- if (mEnforcedCornerRadius <= 0 || !RoundedCornerEnforcement.isRoundedCornerEnabled()) {
+ if (mEnforcedCornerRadius <= 0) {
resetRoundedCorners();
return;
}
diff --git a/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java b/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java
index 2817299..ab42839 100644
--- a/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java
+++ b/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java
@@ -183,19 +183,14 @@
// Draw horizontal and vertical lines to represent individual columns.
final Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
+ boxRect = new RectF(/* left= */ 0, /* top= */ 0, /* right= */
+ previewWidthF, /* bottom= */ previewHeightF);
- if (Utilities.ATLEAST_S) {
- boxRect = new RectF(/* left= */ 0, /* top= */ 0, /* right= */
- previewWidthF, /* bottom= */ previewHeightF);
-
- p.setStyle(Paint.Style.FILL);
- p.setColor(Color.WHITE);
- float roundedCorner = mContext.getResources().getDimension(
- android.R.dimen.system_app_widget_background_radius);
- c.drawRoundRect(boxRect, roundedCorner, roundedCorner, p);
- } else {
- boxRect = drawBoxWithShadow(c, previewWidthF, previewHeightF);
- }
+ p.setStyle(Paint.Style.FILL);
+ p.setColor(Color.WHITE);
+ float roundedCorner = mContext.getResources().getDimension(
+ android.R.dimen.system_app_widget_background_radius);
+ c.drawRoundRect(boxRect, roundedCorner, roundedCorner, p);
p.setStyle(Paint.Style.STROKE);
p.setStrokeWidth(mContext.getResources()
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java b/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java
index 3e4fd8c..e77ba24 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java
@@ -1,7 +1,5 @@
package com.android.launcher3.widget;
-import static com.android.launcher3.Utilities.ATLEAST_S;
-
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Context;
@@ -116,15 +114,13 @@
getSpanY(widgetPadding, minResizeHeight, dp.cellLayoutBorderSpacePx.y,
cellSize.y));
- if (ATLEAST_S) {
- if (maxResizeWidth > 0) {
- maxSpanX = Math.min(maxSpanX, getSpanX(widgetPadding, maxResizeWidth,
- dp.cellLayoutBorderSpacePx.x, cellSize.x));
- }
- if (maxResizeHeight > 0) {
- maxSpanY = Math.min(maxSpanY, getSpanY(widgetPadding, maxResizeHeight,
- dp.cellLayoutBorderSpacePx.y, cellSize.y));
- }
+ if (maxResizeWidth > 0) {
+ maxSpanX = Math.min(maxSpanX, getSpanX(widgetPadding, maxResizeWidth,
+ dp.cellLayoutBorderSpacePx.x, cellSize.x));
+ }
+ if (maxResizeHeight > 0) {
+ maxSpanY = Math.min(maxSpanY, getSpanY(widgetPadding, maxResizeHeight,
+ dp.cellLayoutBorderSpacePx.y, cellSize.y));
}
spanX = Math.max(spanX,
@@ -135,18 +131,16 @@
cellSize.y));
}
- if (ATLEAST_S) {
- // Ensures maxSpan >= minSpan
- maxSpanX = Math.max(maxSpanX, minSpanX);
- maxSpanY = Math.max(maxSpanY, minSpanY);
+ // Ensures maxSpan >= minSpan
+ maxSpanX = Math.max(maxSpanX, minSpanX);
+ maxSpanY = Math.max(maxSpanY, minSpanY);
- // Use targetCellWidth/Height if it is within the min/max ranges.
- // Otherwise, use the span of minWidth/Height.
- if (targetCellWidth >= minSpanX && targetCellWidth <= maxSpanX
- && targetCellHeight >= minSpanY && targetCellHeight <= maxSpanY) {
- spanX = targetCellWidth;
- spanY = targetCellHeight;
- }
+ // Use targetCellWidth/Height if it is within the min/max ranges.
+ // Otherwise, use the span of minWidth/Height.
+ if (targetCellWidth >= minSpanX && targetCellWidth <= maxSpanX
+ && targetCellHeight >= minSpanY && targetCellHeight <= maxSpanY) {
+ spanX = targetCellWidth;
+ spanY = targetCellHeight;
}
// If minSpanX/Y > spanX/Y, ignore the minSpanX/Y to match the behavior described in
@@ -213,8 +207,7 @@
}
public boolean isConfigurationOptional() {
- return ATLEAST_S
- && isReconfigurable()
+ return isReconfigurable()
&& (getWidgetFeatures() & WIDGET_FEATURE_CONFIGURATION_OPTIONAL) != 0;
}
diff --git a/src/com/android/launcher3/widget/PendingItemDragHelper.java b/src/com/android/launcher3/widget/PendingItemDragHelper.java
index 8857774..130d533 100644
--- a/src/com/android/launcher3/widget/PendingItemDragHelper.java
+++ b/src/com/android/launcher3/widget/PendingItemDragHelper.java
@@ -136,9 +136,7 @@
Drawable p = new FastBitmapDrawable(new DatabaseWidgetPreviewLoader(launcher)
.generateWidgetPreview(
createWidgetInfo.info, maxWidth, previewSizeBeforeScale));
- if (RoundedCornerEnforcement.isRoundedCornerEnabled()) {
- p = new RoundDrawableWrapper(p, mEnforcedRoundedCornersForWidget);
- }
+ p = new RoundDrawableWrapper(p, mEnforcedRoundedCornersForWidget);
preview = p;
}
diff --git a/src/com/android/launcher3/widget/RoundedCornerEnforcement.java b/src/com/android/launcher3/widget/RoundedCornerEnforcement.java
index a2fac46..cadaf89 100644
--- a/src/com/android/launcher3/widget/RoundedCornerEnforcement.java
+++ b/src/com/android/launcher3/widget/RoundedCornerEnforcement.java
@@ -28,7 +28,6 @@
import androidx.annotation.Nullable;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import java.util.ArrayList;
import java.util.List;
@@ -70,11 +69,6 @@
return background.getId() == android.R.id.background && background.getClipToOutline();
}
- /** Check if the app widget is in the deny list. */
- public static boolean isRoundedCornerEnabled() {
- return Utilities.ATLEAST_S;
- }
-
/**
* Computes the rounded rectangle needed for this app widget.
*
@@ -101,9 +95,6 @@
* in the given context.
*/
public static float computeEnforcedRadius(@NonNull Context context) {
- if (!Utilities.ATLEAST_S) {
- return 0;
- }
Resources res = context.getResources();
float systemRadius = res.getDimension(android.R.dimen.system_app_widget_background_radius);
float defaultRadius = res.getDimension(R.dimen.enforced_rounded_corner_max_radius);
diff --git a/tests/multivalentTests/src/com/android/launcher3/util/DisplayControllerTest.kt b/tests/multivalentTests/src/com/android/launcher3/util/DisplayControllerTest.kt
index 41effa2..d2cce12 100644
--- a/tests/multivalentTests/src/com/android/launcher3/util/DisplayControllerTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/util/DisplayControllerTest.kt
@@ -38,7 +38,10 @@
import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext
import com.android.launcher3.util.window.CachedDisplayInfo
import com.android.launcher3.util.window.WindowManagerProxy
+import junit.framework.Assert.assertFalse
+import junit.framework.Assert.assertTrue
import kotlin.math.min
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -79,7 +82,7 @@
WindowBounds(Rect(0, 0, width, height), Rect(0, inset, 0, 0), Surface.ROTATION_0),
WindowBounds(Rect(0, 0, height, width), Rect(0, inset, 0, 0), Surface.ROTATION_90),
WindowBounds(Rect(0, 0, width, height), Rect(0, inset, 0, 0), Surface.ROTATION_180),
- WindowBounds(Rect(0, 0, height, width), Rect(0, inset, 0, 0), Surface.ROTATION_270)
+ WindowBounds(Rect(0, 0, height, width), Rect(0, inset, 0, 0), Surface.ROTATION_270),
)
private val configuration =
Configuration(appContext.resources.configuration).apply {
@@ -111,6 +114,7 @@
whenever(windowManagerProxy.getRealBounds(any(), any())).thenAnswer { i ->
bounds[i.getArgument<CachedDisplayInfo>(1).rotation]
}
+ whenever(windowManagerProxy.showLockedTaskbarOnHome(any())).thenReturn(false)
whenever(windowManagerProxy.getNavigationMode(any())).thenReturn(NavigationMode.NO_BUTTON)
// Mock context
@@ -134,6 +138,13 @@
displayController.addChangeListener(displayInfoChangeListener)
}
+ @After
+ fun tearDown() {
+ // We need to reset the taskbar mode preference override even if a test throws an exception.
+ // Otherwise, it may break the following tests' assumptions.
+ DisplayController.enableTaskbarModePreferenceForTests(false)
+ }
+
@Test
@UiThreadTest
fun testRotation() {
@@ -167,7 +178,7 @@
@UiThreadTest
fun testTaskbarPinning() {
whenever(launcherPrefs.get(TASKBAR_PINNING)).thenReturn(true)
- displayController.handleInfoChange(display)
+ displayController.handleInfoChange()
verify(displayInfoChangeListener)
.onDisplayInfoChanged(any(), any(), eq(CHANGE_TASKBAR_PINNING))
}
@@ -176,8 +187,24 @@
@UiThreadTest
fun testTaskbarPinningChangeInDesktopMode() {
whenever(launcherPrefs.get(TASKBAR_PINNING_IN_DESKTOP_MODE)).thenReturn(false)
- displayController.handleInfoChange(display)
+ displayController.handleInfoChange()
verify(displayInfoChangeListener)
.onDisplayInfoChanged(any(), any(), eq(CHANGE_TASKBAR_PINNING))
}
+
+ @Test
+ @UiThreadTest
+ fun testTaskbarPinningChangeInLockedTaskbarChange() {
+ whenever(windowManagerProxy.showLockedTaskbarOnHome(any())).thenReturn(true)
+ whenever(windowManagerProxy.isHomeVisible(any())).thenReturn(true)
+ whenever(windowManagerProxy.isInDesktopMode()).thenReturn(false)
+ whenever(launcherPrefs.get(TASKBAR_PINNING)).thenReturn(false)
+ DisplayController.enableTaskbarModePreferenceForTests(true)
+
+ assertTrue(displayController.getInfo().isTransientTaskbar())
+ displayController.handleInfoChange()
+ verify(displayInfoChangeListener)
+ .onDisplayInfoChanged(any(), any(), eq(CHANGE_TASKBAR_PINNING))
+ assertFalse(displayController.getInfo().isTransientTaskbar())
+ }
}
diff --git a/tests/src/com/android/launcher3/popup/SystemShortcutTest.java b/tests/src/com/android/launcher3/popup/SystemShortcutTest.java
index dcfcad5..f54668c 100644
--- a/tests/src/com/android/launcher3/popup/SystemShortcutTest.java
+++ b/tests/src/com/android/launcher3/popup/SystemShortcutTest.java
@@ -19,19 +19,26 @@
import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+import static com.android.launcher3.AbstractFloatingView.TYPE_SNACKBAR;
+import static com.android.launcher3.Flags.FLAG_ENABLE_DISMISS_PREDICTION_UNDO;
import static com.android.launcher3.Flags.FLAG_ENABLE_PRIVATE_SPACE;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_ALL_APPS;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_DISMISS_PREDICTION_UNDO;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_DONT_SUGGEST_APP_TAP;
import static com.android.launcher3.model.data.WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -50,8 +57,13 @@
import androidx.test.annotation.UiThreadTest;
import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.launcher3.AbstractFloatingView;
+import com.android.launcher3.R;
import com.android.launcher3.allapps.PrivateProfileManager;
+import com.android.launcher3.logging.StatsLogManager;
+import com.android.launcher3.logging.StatsLogManager.StatsLogger;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -61,8 +73,9 @@
import com.android.launcher3.util.LauncherModelHelper.SandboxModelContext;
import com.android.launcher3.util.LauncherMultivalentJUnit;
import com.android.launcher3.util.TestSandboxModelContextWrapper;
+import com.android.launcher3.util.TestUtil;
import com.android.launcher3.util.UserIconInfo;
-import com.android.launcher3.views.BaseDragLayer;
+import com.android.launcher3.views.Snackbar;
import com.android.launcher3.widget.picker.model.WidgetPickerDataProvider;
import com.android.launcher3.widget.picker.model.data.WidgetPickerData;
@@ -72,6 +85,7 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -88,25 +102,31 @@
private PrivateProfileManager mPrivateProfileManager;
private WidgetPickerDataProvider mWidgetPickerDataProvider;
private AppInfo mAppInfo;
+
@Mock UserCache mUserCache;
@Mock ApiWrapper mApiWrapper;
- @Mock BaseDragLayer mBaseDragLayer;
@Mock UserIconInfo mUserIconInfo;
@Mock LauncherActivityInfo mLauncherActivityInfo;
@Mock ApplicationInfo mApplicationInfo;
@Mock Intent mIntent;
+ @Mock StatsLogManager mStatsLogManager;
+ @Mock(answer = Answers.RETURNS_SELF) StatsLogger mStatsLogger;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mSandboxContext.putObject(UserCache.INSTANCE, mUserCache);
mSandboxContext.putObject(ApiWrapper.INSTANCE, mApiWrapper);
- mTestContext = new TestSandboxModelContextWrapper(mSandboxContext);
- mView = new View(mSandboxContext);
- spyOn(mTestContext);
+ mTestContext = new TestSandboxModelContextWrapper(mSandboxContext) {
+ @Override
+ public StatsLogManager getStatsLogManager() {
+ return mStatsLogManager;
+ }
+ };
spyOn(mSandboxContext);
- doReturn(mBaseDragLayer).when(mTestContext).getDragLayer();
+ doReturn(mStatsLogger).when(mStatsLogManager).logger();
+ mView = new View(mTestContext);
mItemInfo = new ItemInfo();
LauncherApps mLauncherApps = mSandboxContext.spyService(LauncherApps.class);
@@ -114,7 +134,6 @@
when(mLauncherActivityInfo.getApplicationInfo()).thenReturn(mApplicationInfo);
when(mUserCache.getUserInfo(any())).thenReturn(mUserIconInfo);
- when(mBaseDragLayer.getChildCount()).thenReturn(0);
mPrivateProfileManager = mTestContext.getAppsView().getPrivateProfileManager();
spyOn(mPrivateProfileManager);
when(mPrivateProfileManager.getProfileUser()).thenReturn(PRIVATE_HANDLE);
@@ -168,6 +187,7 @@
}
@Test
+ @DisableFlags(FLAG_ENABLE_DISMISS_PREDICTION_UNDO)
public void testDontSuggestAppForPredictedItem() {
mAppInfo = new AppInfo();
mAppInfo.componentName = new ComponentName(mTestContext, getClass());
@@ -176,7 +196,36 @@
SystemShortcut systemShortcut = SystemShortcut.DONT_SUGGEST_APP
.getShortcut(mTestContext, mAppInfo, mView);
assertNotNull(systemShortcut);
- systemShortcut.onClick(mView);
+
+ TestUtil.runOnExecutorSync(MAIN_EXECUTOR, () -> systemShortcut.onClick(mView));
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+ verify(mStatsLogger).log(eq(LAUNCHER_SYSTEM_SHORTCUT_DONT_SUGGEST_APP_TAP));
+ assertFalse(AbstractFloatingView.hasOpenView(mTestContext, TYPE_SNACKBAR));
+ }
+
+ @Test
+ @EnableFlags(FLAG_ENABLE_DISMISS_PREDICTION_UNDO)
+ public void testDontSuggestAppForPredictedItemWithUndo() {
+ mAppInfo = new AppInfo();
+ mAppInfo.componentName = new ComponentName(mTestContext, getClass());
+ mAppInfo.container = CONTAINER_HOTSEAT_PREDICTION;
+ assertTrue(mAppInfo.isPredictedItem());
+ SystemShortcut systemShortcut = SystemShortcut.DONT_SUGGEST_APP
+ .getShortcut(mTestContext, mAppInfo, mView);
+ assertNotNull(systemShortcut);
+
+ TestUtil.runOnExecutorSync(MAIN_EXECUTOR, () -> systemShortcut.onClick(mView));
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+ verify(mStatsLogger).log(eq(LAUNCHER_SYSTEM_SHORTCUT_DONT_SUGGEST_APP_TAP));
+
+ // Undo bar shown
+ Snackbar snackbar = AbstractFloatingView.getOpenView(mTestContext, TYPE_SNACKBAR);
+ assertNotNull(snackbar);
+ reset(mStatsLogger);
+ TestUtil.runOnExecutorSync(MAIN_EXECUTOR, snackbar.findViewById(
+ R.id.action)::performClick);
+ verify(mStatsLogger).log(eq(LAUNCHER_DISMISS_PREDICTION_UNDO));
}
@Test
diff --git a/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java b/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java
index b2e413d..b38dd4b 100644
--- a/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java
+++ b/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java
@@ -45,7 +45,6 @@
import com.android.launcher3.allapps.WorkProfileManager;
import com.android.launcher3.tapl.LauncherInstrumentation;
import com.android.launcher3.util.TestUtil;
-import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
import com.android.launcher3.util.rule.TestStabilityRule.Stability;
import org.junit.After;
@@ -147,7 +146,6 @@
// Staging; will be promoted to presubmit if stable
@Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT)
- @ScreenRecord
@Test
public void toggleWorks() {
assumeTrue(mWorkProfileSetupSuccessful);
@@ -195,7 +193,6 @@
}
- @ScreenRecord // b/322823478
@Test
public void testEdu() {
assumeTrue(mWorkProfileSetupSuccessful);
diff --git a/tests/src/com/android/launcher3/ui/workspace/TaplTwoPanelWorkspaceTest.java b/tests/src/com/android/launcher3/ui/workspace/TaplTwoPanelWorkspaceTest.java
index 638ae7c..2edd129 100644
--- a/tests/src/com/android/launcher3/ui/workspace/TaplTwoPanelWorkspaceTest.java
+++ b/tests/src/com/android/launcher3/ui/workspace/TaplTwoPanelWorkspaceTest.java
@@ -164,7 +164,6 @@
@Test
@PortraitLandscape
- @ScreenRecordRule.ScreenRecord // b/352130094
public void testDragIconToPage2() {
Workspace workspace = mLauncher.getWorkspace();
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index d3c423e..21e93c5 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -55,6 +55,7 @@
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.os.Trace;
import android.text.TextUtils;
import android.util.Log;
import android.view.InputDevice;
@@ -524,16 +525,19 @@
Closable addContextLayer(String piece) {
mDiagnosticContext.addLast(piece);
+ Trace.beginSection("Context: " + piece);
log("Entering context: " + piece);
return () -> {
+ Trace.endSection();
log("Leaving context: " + piece);
mDiagnosticContext.removeLast();
};
}
public void dumpViewHierarchy() {
- final ByteArrayOutputStream stream = new ByteArrayOutputStream();
try {
+ Trace.beginSection("dumpViewHierarchy");
+ final ByteArrayOutputStream stream = new ByteArrayOutputStream();
mDevice.dumpWindowHierarchy(stream);
stream.flush();
stream.close();
@@ -542,6 +546,8 @@
}
} catch (IOException e) {
Log.e(TAG, "error dumping XML to logcat", e);
+ } finally {
+ Trace.endSection();
}
}
@@ -621,15 +627,20 @@
*/
public void checkForAnomaly(
boolean ignoreNavmodeChangeStates, boolean ignoreOnlySystemUiViews) {
- if (mTestAnomalyChecker != null) mTestAnomalyChecker.run();
+ try {
+ Trace.beginSection("checkForAnomaly");
+ if (mTestAnomalyChecker != null) mTestAnomalyChecker.run();
- final String systemAnomalyMessage =
- getSystemAnomalyMessage(ignoreNavmodeChangeStates, ignoreOnlySystemUiViews);
- if (systemAnomalyMessage != null) {
- if (mOnFailure != null) mOnFailure.run();
- Assert.fail(formatSystemHealthMessage(formatErrorWithEvents(
- "http://go/tapl : Tests are broken by a non-Launcher system error: "
- + systemAnomalyMessage, false)));
+ final String systemAnomalyMessage =
+ getSystemAnomalyMessage(ignoreNavmodeChangeStates, ignoreOnlySystemUiViews);
+ if (systemAnomalyMessage != null) {
+ if (mOnFailure != null) mOnFailure.run();
+ Assert.fail(formatSystemHealthMessage(formatErrorWithEvents(
+ "http://go/tapl : Tests are broken by a non-Launcher system error: "
+ + systemAnomalyMessage, false)));
+ }
+ } finally {
+ Trace.endSection();
}
}
@@ -1005,16 +1016,20 @@
}
public void waitForLauncherInitialized() {
- for (int i = 0; i < 100; ++i) {
- if (getTestInfo(
- TestProtocol.REQUEST_IS_LAUNCHER_INITIALIZED).
- getBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD)) {
- return;
+ try {
+ Trace.beginSection("waitForLauncherInitialized");
+ for (int i = 0; i < 100; ++i) {
+ if (getTestInfo(TestProtocol.REQUEST_IS_LAUNCHER_INITIALIZED).getBoolean(
+ TestProtocol.TEST_INFO_RESPONSE_FIELD)) {
+ return;
+ }
+ SystemClock.sleep(100);
}
- SystemClock.sleep(100);
+ checkForAnomaly();
+ fail("Launcher didn't initialize");
+ } finally {
+ Trace.endSection();
}
- checkForAnomaly();
- fail("Launcher didn't initialize");
}
public boolean isLauncherActivityStarted() {
@@ -1259,8 +1274,13 @@
}
boolean isLauncherVisible() {
- mDevice.waitForIdle();
- return hasLauncherObject(getAnyObjectSelector());
+ try {
+ Trace.beginSection("isLauncherVisible");
+ mDevice.waitForIdle();
+ return hasLauncherObject(getAnyObjectSelector());
+ } finally {
+ Trace.endSection();
+ }
}
boolean isLauncherContainerVisible() {
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
index 5433fa7..9a8d952 100644
--- a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
@@ -282,7 +282,7 @@
* Returns whether the given String is contained in this Task's contentDescription. Also returns
* true if both Strings are null.
*
- * TODO(b/326565120): remove Nullable support once the bug causing it to be null is fixed.
+ * TODO(b/342627272): remove Nullable support once the bug causing it to be null is fixed.
*/
public boolean containsContentDescription(@Nullable String expected,
OverviewSplitTask overviewSplitTask) {