Merge "Adding feature flags for Launcher reboot and load improvements" into main
diff --git a/aconfig/launcher.aconfig b/aconfig/launcher.aconfig
index fc2be06..98dd4d6 100644
--- a/aconfig/launcher.aconfig
+++ b/aconfig/launcher.aconfig
@@ -85,6 +85,13 @@
}
flag {
+ name: "enable_shortcut_dont_suggest_app"
+ namespace: "launcher"
+ description: "Enables don't suggest app shortcut for suggested apps"
+ bug: "319250810"
+}
+
+flag {
name: "enable_support_for_archiving"
namespace: "launcher"
description: "Enables support for archived apps in Launcher3, such as empty progress bar etc."
diff --git a/quickstep/src/com/android/launcher3/model/AppEventProducer.java b/quickstep/src/com/android/launcher3/model/AppEventProducer.java
index 8dded8f..e17fc88 100644
--- a/quickstep/src/com/android/launcher3/model/AppEventProducer.java
+++ b/quickstep/src/com/android/launcher3/model/AppEventProducer.java
@@ -38,6 +38,7 @@
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ONRESUME;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_QUICKSWITCH_LEFT;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_QUICKSWITCH_RIGHT;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_DONT_SUGGEST_APP_TAP;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_SWIPE_DOWN;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP;
import static com.android.launcher3.model.PredictionHelper.isTrackedForHotseatPrediction;
@@ -137,7 +138,8 @@
|| event == LAUNCHER_QUICKSWITCH_LEFT
|| event == LAUNCHER_APP_LAUNCH_DRAGDROP) {
sendEvent(atomInfo, ACTION_LAUNCH, CONTAINER_PREDICTION);
- } else if (event == LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST) {
+ } else if (event == LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST
+ || event == LAUNCHER_SYSTEM_SHORTCUT_DONT_SUGGEST_APP_TAP) {
sendEvent(atomInfo, ACTION_DISMISS, CONTAINER_PREDICTION);
} else if (event == LAUNCHER_ITEM_DRAG_STARTED) {
mLastDragItem = atomInfo;
diff --git a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
index 382276a..fd0d655 100644
--- a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
@@ -22,6 +22,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
+import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.Outline;
@@ -39,6 +40,7 @@
import com.android.launcher3.util.Executors;
import com.android.launcher3.util.MultiPropertyFactory;
import com.android.launcher3.util.MultiValueAlpha;
+import com.android.quickstep.NavHandle;
import com.android.systemui.shared.navigationbar.RegionSamplingHelper;
import java.io.PrintWriter;
@@ -46,7 +48,8 @@
/**
* Handles properties/data collection, then passes the results to our stashed handle View to render.
*/
-public class StashedHandleViewController implements TaskbarControllers.LoggableTaskbarController {
+public class StashedHandleViewController implements TaskbarControllers.LoggableTaskbarController,
+ NavHandle {
public static final int ALPHA_INDEX_STASHED = 0;
public static final int ALPHA_INDEX_HOME_DISABLED = 1;
@@ -318,4 +321,24 @@
pw.println(prefix + "\tmStashedHandleHeight=" + mStashedHandleHeight);
mRegionSamplingHelper.dump(prefix, pw);
}
+
+ @Override
+ public void animateNavBarLongPress(boolean isTouchDown, boolean shrink, long durationMs) {
+ // TODO(b/308693847): Animate similarly to NavigationHandle.java (SysUI).
+ }
+
+ @Override
+ public boolean isNavHandleStashedTaskbar() {
+ return true;
+ }
+
+ @Override
+ public boolean canNavHandleBeLongPressed() {
+ return isStashedHandleVisible();
+ }
+
+ @Override
+ public int getNavHandleWidth(Context context) {
+ return mStashedHandleWidth;
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 7ad2c68..4b95d7b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -123,6 +123,7 @@
import com.android.launcher3.util.VibratorWrapper;
import com.android.launcher3.util.ViewCache;
import com.android.launcher3.views.ActivityContext;
+import com.android.quickstep.NavHandle;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.Task;
@@ -611,6 +612,11 @@
return mControllers.bubbleControllers.orElse(null);
}
+ @NonNull
+ public NavHandle getNavHandle() {
+ return mControllers.stashedHandleViewController;
+ }
+
@Override
public ViewCache getViewCache() {
return mViewCache;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 0d4a7f0..f0ab08c 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -39,6 +39,7 @@
import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
import static com.android.launcher3.popup.QuickstepSystemShortcut.getSplitSelectShortcutByPosition;
import static com.android.launcher3.popup.SystemShortcut.APP_INFO;
+import static com.android.launcher3.popup.SystemShortcut.DONT_SUGGEST_APP;
import static com.android.launcher3.popup.SystemShortcut.INSTALL;
import static com.android.launcher3.popup.SystemShortcut.PRIVATE_PROFILE_INSTALL;
import static com.android.launcher3.popup.SystemShortcut.WIDGETS;
@@ -417,10 +418,12 @@
shortcuts.addAll(getSplitShortcuts());
shortcuts.add(WIDGETS);
shortcuts.add(INSTALL);
-
if (Flags.enablePrivateSpaceInstallShortcut()) {
shortcuts.add(PRIVATE_PROFILE_INSTALL);
}
+ if (Flags.enableShortcutDontSuggestApp()) {
+ shortcuts.add(DONT_SUGGEST_APP);
+ }
return shortcuts.stream();
}
diff --git a/quickstep/src/com/android/quickstep/NavHandle.java b/quickstep/src/com/android/quickstep/NavHandle.java
new file mode 100644
index 0000000..da3311f
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/NavHandle.java
@@ -0,0 +1,54 @@
+/*
+ * 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;
+
+import android.content.Context;
+
+import com.android.launcher3.R;
+
+/**
+ * Control and get information about the gesture nav bar at the bottom of the screen, which has
+ * historically been drawn by SysUI, but is also emulated by the stashed Taskbar on large screens.
+ */
+public interface NavHandle {
+
+ /**
+ * Animate the nav bar being long-pressed.
+ *
+ * @param isTouchDown {@code true} if the button is starting to be pressed ({@code false} if
+ * released or canceled)
+ * @param shrink {@code true} if the handle should shrink, {@code false} if it should grow
+ * @param durationMs how long the animation should take (for the {@code isTouchDown} case, this
+ * should be the same as the amount of time to trigger a long-press)
+ */
+ void animateNavBarLongPress(boolean isTouchDown, boolean shrink, long durationMs);
+
+ /** @return {@code true} if this nav handle is actually the stashed taskbar */
+ default boolean isNavHandleStashedTaskbar() {
+ return false;
+ }
+
+ /** @return {@code true} if this nav handle can currently accept long presses */
+ default boolean canNavHandleBeLongPressed() {
+ return true;
+ }
+
+ /** @return the width of this nav handle, in pixels */
+ default int getNavHandleWidth(Context context) {
+ return context.getResources().getDimensionPixelSize(R.dimen.navigation_home_handle_width);
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index a8c6809..723af43 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -106,7 +106,7 @@
/**
* Holds the reference to SystemUI.
*/
-public class SystemUiProxy implements ISystemUiProxy {
+public class SystemUiProxy implements ISystemUiProxy, NavHandle {
private static final String TAG = SystemUiProxy.class.getSimpleName();
public static final MainThreadInitializedObject<SystemUiProxy> INSTANCE =
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 7982606..647ff90 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -1005,14 +1005,22 @@
base = new TaskbarUnstashInputConsumer(this, base, mInputMonitorCompat, tac,
mOverviewCommandHelper);
}
- } else if (canStartSystemGesture && !previousGestureState.isRecentsAnimationRunning()) {
+ }
+
+ NavHandle navHandle = tac != null ? tac.getNavHandle()
+ : SystemUiProxy.INSTANCE.get(this);
+ if (canStartSystemGesture && !previousGestureState.isRecentsAnimationRunning()
+ && navHandle.canNavHandleBeLongPressed()) {
reasonString.append(NEWLINE_PREFIX)
.append(reasonPrefix)
.append(SUBSTRING_PREFIX)
- .append("Not running recents animation, ")
- .append("using NavHandleLongPressInputConsumer");
+ .append("Not running recents animation, ");
+ if (tac != null && tac.getNavHandle().canNavHandleBeLongPressed()) {
+ reasonString.append("stashed handle is long-pressable, ");
+ }
+ reasonString.append("using NavHandleLongPressInputConsumer");
base = new NavHandleLongPressInputConsumer(this, base, mInputMonitorCompat,
- mDeviceState);
+ mDeviceState, navHandle);
}
if (mDeviceState.isBubblesExpanded()) {
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressHandler.java b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressHandler.java
index 4d47f07..1d00e53 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressHandler.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressHandler.java
@@ -22,6 +22,7 @@
import com.android.launcher3.R;
import com.android.launcher3.util.ResourceBasedOverride;
+import com.android.quickstep.NavHandle;
/**
* Class for extending nav handle long press behavior
@@ -42,19 +43,26 @@
* A Runnable is returned here to ensure the InputConsumer can call
* {@link android.view.InputMonitor#pilferPointers()} before invoking the long press behavior
* since pilfering can break the long press behavior.
+ *
+ * @param navHandle to handle this long press
*/
- public @Nullable Runnable getLongPressRunnable() {
+ public @Nullable Runnable getLongPressRunnable(NavHandle navHandle) {
return null;
}
/**
* Called when nav handle gesture starts.
+ *
+ * @param navHandle to handle the animation for this touch
*/
- public void onTouchStarted() {}
+ public void onTouchStarted(NavHandle navHandle) {}
/**
* Called when nav handle gesture is finished by the user lifting their finger or the system
* cancelling the touch for some other reason.
+ *
+ * @param navHandle to handle the animation for this touch
+ * @param reason why the touch ended
*/
- public void onTouchFinished(String reason) {}
+ public void onTouchFinished(NavHandle navHandle, String reason) {}
}
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java
index 0a558e2..4c0b550 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java
@@ -17,7 +17,9 @@
import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_TIMEOUT_MS;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_DEEP_PRESS_NAVBAR;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_DEEP_PRESS_STASHED_TASKBAR;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_LONG_PRESS_NAVBAR;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_LONG_PRESS_STASHED_TASKBAR;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.content.Context;
@@ -25,11 +27,11 @@
import android.view.ViewConfiguration;
import com.android.launcher3.LauncherPrefs;
-import com.android.launcher3.R;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.util.DisplayController;
import com.android.quickstep.InputConsumer;
+import com.android.quickstep.NavHandle;
import com.android.quickstep.RecentsAnimationDeviceState;
import com.android.quickstep.TopTaskTracker;
import com.android.systemui.shared.system.InputMonitorCompat;
@@ -47,6 +49,7 @@
private final float mTouchSlopSquared;
private final int mLongPressTimeout;
private final boolean mDeepPressEnabled;
+ private final NavHandle mNavHandle;
private final StatsLogManager mStatsLogManager;
private final TopTaskTracker mTopTaskTracker;
@@ -54,10 +57,9 @@
private boolean mDeepPressLogged; // Whether deep press has been logged for the current touch.
public NavHandleLongPressInputConsumer(Context context, InputConsumer delegate,
- InputMonitorCompat inputMonitor, RecentsAnimationDeviceState deviceState) {
+ InputMonitorCompat inputMonitor, RecentsAnimationDeviceState deviceState,
+ NavHandle navHandle) {
super(delegate, inputMonitor);
- mNavHandleWidth = context.getResources().getDimensionPixelSize(
- R.dimen.navigation_home_handle_width);
mScreenWidth = DisplayController.INSTANCE.get(context).getInfo().currentSize.x;
mDeepPressEnabled = FeatureFlags.ENABLE_LPNH_DEEP_PRESS.get();
if (FeatureFlags.CUSTOM_LPNH_THRESHOLDS.get()) {
@@ -66,6 +68,8 @@
mLongPressTimeout = ViewConfiguration.getLongPressTimeout();
}
mTouchSlopSquared = deviceState.getSquaredTouchSlop();
+ mNavHandle = navHandle;
+ mNavHandleWidth = navHandle.getNavHandleWidth(context);
mNavHandleLongPressHandler = NavHandleLongPressHandler.newInstance(context);
mStatsLogManager = StatsLogManager.newInstance(context);
mTopTaskTracker = TopTaskTracker.INSTANCE.get(context);
@@ -89,6 +93,11 @@
}
}
+ @Override
+ public void onHoverEvent(MotionEvent ev) {
+ mDelegate.onHoverEvent(ev);
+ }
+
private void handleMotionEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN -> {
@@ -98,9 +107,8 @@
mCurrentDownEvent = MotionEvent.obtain(ev);
mDeepPressLogged = false;
if (isInNavBarHorizontalArea(ev.getRawX())) {
- mNavHandleLongPressHandler.onTouchStarted();
- MAIN_EXECUTOR.getHandler().postDelayed(mTriggerLongPress,
- mLongPressTimeout);
+ mNavHandleLongPressHandler.onTouchStarted(mNavHandle);
+ MAIN_EXECUTOR.getHandler().postDelayed(mTriggerLongPress, mLongPressTimeout);
}
}
case MotionEvent.ACTION_MOVE -> {
@@ -127,8 +135,9 @@
// Log deep press even if feature is disabled.
String runningPackage = mTopTaskTracker.getCachedTopTask(
/* filterOnlyVisibleRecents */ true).getPackageName();
- mStatsLogManager.logger().withPackageName(runningPackage)
- .log(LAUNCHER_DEEP_PRESS_NAVBAR);
+ mStatsLogManager.logger().withPackageName(runningPackage).log(
+ mNavHandle.isNavHandleStashedTaskbar() ? LAUNCHER_DEEP_PRESS_STASHED_TASKBAR
+ : LAUNCHER_DEEP_PRESS_NAVBAR);
mDeepPressLogged = true;
// But only trigger if the feature is enabled.
@@ -142,9 +151,11 @@
private void triggerLongPress() {
String runningPackage = mTopTaskTracker.getCachedTopTask(
/* filterOnlyVisibleRecents */ true).getPackageName();
- mStatsLogManager.logger().withPackageName(runningPackage).log(LAUNCHER_LONG_PRESS_NAVBAR);
+ mStatsLogManager.logger().withPackageName(runningPackage).log(
+ mNavHandle.isNavHandleStashedTaskbar() ? LAUNCHER_LONG_PRESS_STASHED_TASKBAR
+ : LAUNCHER_LONG_PRESS_NAVBAR);
- Runnable longPressRunnable = mNavHandleLongPressHandler.getLongPressRunnable();
+ Runnable longPressRunnable = mNavHandleLongPressHandler.getLongPressRunnable(mNavHandle);
if (longPressRunnable == null) {
return;
}
@@ -161,7 +172,7 @@
private void cancelLongPress(String reason) {
MAIN_EXECUTOR.getHandler().removeCallbacks(mTriggerLongPress);
- mNavHandleLongPressHandler.onTouchFinished(reason);
+ mNavHandleLongPressHandler.onTouchFinished(mNavHandle, reason);
}
private boolean isInNavBarHorizontalArea(float x) {
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 34677f6..fb55c75 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -175,7 +175,7 @@
<string name="install_private_system_shortcut_label">Install in private</string>
<!-- Label for install drop target. [CHAR_LIMIT=20] -->
<string name="install_drop_target_label">Install</string>
- <!-- Label for install dismiss prediction. -->
+ <!-- Label for dismiss prediction. -->
<string name="dismiss_prediction_label">Don\'t suggest app</string>
<!-- Label for pinning predicted app. -->
<string name="pin_prediction">Pin Prediction</string>
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index a2f6bf9..826eeb2 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1512,7 +1512,6 @@
private void prepareAppWidget(AppWidgetHostView hostView, LauncherAppWidgetInfo item) {
hostView.setTag(item);
- item.onBindAppWidget(this, hostView);
hostView.setFocusable(true);
hostView.setOnFocusChangeListener(mFocusHandler);
}
diff --git a/src/com/android/launcher3/SecondaryDropTarget.java b/src/com/android/launcher3/SecondaryDropTarget.java
index 2dd610cb..0b92c28 100644
--- a/src/com/android/launcher3/SecondaryDropTarget.java
+++ b/src/com/android/launcher3/SecondaryDropTarget.java
@@ -155,6 +155,9 @@
}
return INVALID;
} else if (info.isPredictedItem()) {
+ if (Flags.enableShortcutDontSuggestApp()) {
+ return INVALID;
+ }
return DISMISS_PREDICTION;
}
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index 7cc33cf..45ff33b 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -211,6 +211,9 @@
@UiEvent(doc = "User tapped on pin system shortcut.")
LAUNCHER_SYSTEM_SHORTCUT_PIN_TAP(522),
+ @UiEvent(doc = "User tapped on don't suggest app system shortcut.")
+ LAUNCHER_SYSTEM_SHORTCUT_DONT_SUGGEST_APP_TAP(1603),
+
@UiEvent(doc = "User is shown All Apps education view.")
LAUNCHER_ALL_APPS_EDU_SHOWN(523),
@@ -284,6 +287,12 @@
@UiEvent(doc = "User long presses on the bottom bezel area.")
LAUNCHER_LONG_PRESS_NAVBAR(1544),
+ @UiEvent(doc = "User deep presses on the stashed taskbar")
+ LAUNCHER_DEEP_PRESS_STASHED_TASKBAR(1602),
+
+ @UiEvent(doc = "User long presses on the stashed taskbar")
+ LAUNCHER_LONG_PRESS_STASHED_TASKBAR(1592),
+
@UiEvent(doc = "User swipes or fling in UP direction from bottom bazel area.")
LAUNCHER_HOME_GESTURE(574),
diff --git a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
index 697fbc8..f98cab6 100644
--- a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
+++ b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
@@ -45,6 +45,7 @@
import com.android.launcher3.util.PackageUserKey
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo
import com.android.launcher3.widget.WidgetInflater
+import com.android.launcher3.widget.util.WidgetSizes
/**
* This items is used by LoaderTask to process items that have been loaded from the Launcher's DB.
@@ -423,44 +424,56 @@
}
val inflationResult = widgetInflater.inflateAppWidget(appWidgetInfo)
var shouldUpdate = inflationResult.isUpdate
- if (inflationResult.type == WidgetInflater.TYPE_DELETE) {
- c.markDeleted(inflationResult.reason, inflationResult.restoreErrorType)
- return
- }
-
val lapi = inflationResult.widgetInfo
- if (inflationResult.type == WidgetInflater.TYPE_PENDING) {
- tempPackageKey.update(component.packageName, c.user)
- val si = installingPkgs[tempPackageKey]
- if (
- !c.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_RESTORE_STARTED) &&
- !isSafeMode &&
- (si == null) &&
- (lapi == null)
- ) {
- // Restore never started
- c.markDeleted(
- "Unrestored widget removed: $component",
- RestoreError.APP_NOT_INSTALLED
- )
+ when (inflationResult.type) {
+ WidgetInflater.TYPE_DELETE -> {
+ c.markDeleted(inflationResult.reason, inflationResult.restoreErrorType)
return
- } else if (
- !c.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_RESTORE_STARTED) && si != null
- ) {
- shouldUpdate = true
- appWidgetInfo.restoreStatus =
- appWidgetInfo.restoreStatus or LauncherAppWidgetInfo.FLAG_RESTORE_STARTED
}
- appWidgetInfo.installProgress = if (si == null) 0 else (si.getProgress() * 100).toInt()
- appWidgetInfo.pendingItemInfo =
- WidgetsModel.newPendingItemInfo(
+ WidgetInflater.TYPE_PENDING -> {
+ tempPackageKey.update(component.packageName, c.user)
+ val si = installingPkgs[tempPackageKey]
+
+ if (
+ !c.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_RESTORE_STARTED) &&
+ !isSafeMode &&
+ (si == null) &&
+ (lapi == null)
+ ) {
+ // Restore never started
+ c.markDeleted(
+ "Unrestored widget removed: $component",
+ RestoreError.APP_NOT_INSTALLED
+ )
+ return
+ } else if (
+ !c.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_RESTORE_STARTED) && si != null
+ ) {
+ shouldUpdate = true
+ appWidgetInfo.restoreStatus =
+ appWidgetInfo.restoreStatus or LauncherAppWidgetInfo.FLAG_RESTORE_STARTED
+ }
+ appWidgetInfo.installProgress =
+ if (si == null) 0 else (si.getProgress() * 100).toInt()
+ appWidgetInfo.pendingItemInfo =
+ WidgetsModel.newPendingItemInfo(
+ app.context,
+ appWidgetInfo.providerName,
+ appWidgetInfo.user
+ )
+ iconCache.getTitleAndIconForApp(appWidgetInfo.pendingItemInfo, false)
+ }
+ WidgetInflater.TYPE_REAL ->
+ WidgetSizes.updateWidgetSizeRangesAsync(
+ appWidgetInfo.appWidgetId,
+ lapi,
app.context,
- appWidgetInfo.providerName,
- appWidgetInfo.user
+ appWidgetInfo.spanX,
+ appWidgetInfo.spanY
)
- iconCache.getTitleAndIconForApp(appWidgetInfo.pendingItemInfo, false)
}
+
if (shouldUpdate) {
c.updater()
.put(Favorites.APPWIDGET_PROVIDER, component.flattenToString())
diff --git a/src/com/android/launcher3/model/data/LauncherAppWidgetInfo.java b/src/com/android/launcher3/model/data/LauncherAppWidgetInfo.java
index 1fbe04f..6fa8c54 100644
--- a/src/com/android/launcher3/model/data/LauncherAppWidgetInfo.java
+++ b/src/com/android/launcher3/model/data/LauncherAppWidgetInfo.java
@@ -32,13 +32,11 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.util.ContentWriter;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
-import com.android.launcher3.widget.util.WidgetSizes;
/**
* Represents a widget (either instantiated or about to be) in the Launcher.
@@ -143,8 +141,6 @@
*/
private int widgetFeatures;
- private boolean mHasNotifiedInitialWidgetSizeChanged;
-
/**
* The container from which this widget was added (e.g. widgets tray, pin widget, search)
*/
@@ -202,17 +198,6 @@
.put(LauncherSettings.Favorites.APPWIDGET_SOURCE, sourceContainer);
}
- /**
- * When we bind the widget, we should notify the widget that the size has changed if we have not
- * done so already (only really for default workspace widgets).
- */
- public void onBindAppWidget(Launcher launcher, AppWidgetHostView hostView) {
- if (!mHasNotifiedInitialWidgetSizeChanged) {
- WidgetSizes.updateWidgetSizeRanges(hostView, launcher, spanX, spanY);
- mHasNotifiedInitialWidgetSizeChanged = true;
- }
- }
-
@Override
protected String dumpProperties() {
return super.dumpProperties()
diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java
index d4ab4ab..fa7700b 100644
--- a/src/com/android/launcher3/popup/SystemShortcut.java
+++ b/src/com/android/launcher3/popup/SystemShortcut.java
@@ -2,6 +2,7 @@
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_INSTALL_SYSTEM_SHORTCUT_TAP;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_APP_INFO_TAP;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_DONT_SUGGEST_APP_TAP;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_WIDGETS_TAP;
import android.app.ActivityOptions;
@@ -324,6 +325,34 @@
}
}
+ public static final Factory<Launcher> DONT_SUGGEST_APP = new Factory<Launcher>() {
+ @Nullable
+ @Override
+ public SystemShortcut<Launcher> getShortcut(Launcher activity, ItemInfo itemInfo,
+ View originalView) {
+ if (!itemInfo.isPredictedItem()) {
+ return null;
+ }
+ return new DontSuggestApp(activity, itemInfo, originalView);
+ }
+ };
+
+ private static class DontSuggestApp extends SystemShortcut<Launcher> {
+ DontSuggestApp(Launcher target, ItemInfo itemInfo,
+ View originalView) {
+ super(R.drawable.ic_block_no_shadow, R.string.dismiss_prediction_label, target,
+ itemInfo, originalView);
+ }
+
+ @Override
+ public void onClick(View view) {
+ dismissTaskMenuView(mTarget);
+ mTarget.getStatsLogManager().logger()
+ .withItemInfo(mItemInfo)
+ .log(LAUNCHER_SYSTEM_SHORTCUT_DONT_SUGGEST_APP_TAP);
+ }
+ }
+
public static <T extends Context & ActivityContext> void dismissTaskMenuView(T activity) {
AbstractFloatingView.closeOpenViews(activity, true,
AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE);
diff --git a/src/com/android/launcher3/widget/util/WidgetSizes.java b/src/com/android/launcher3/widget/util/WidgetSizes.java
index 7049509..4688359 100644
--- a/src/com/android/launcher3/widget/util/WidgetSizes.java
+++ b/src/com/android/launcher3/widget/util/WidgetSizes.java
@@ -15,8 +15,11 @@
*/
package com.android.launcher3.widget.util;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Point;
@@ -91,20 +94,33 @@
*/
public static void updateWidgetSizeRanges(AppWidgetHostView widgetView, Context context,
int spanX, int spanY) {
- AppWidgetManager widgetManager = AppWidgetManager.getInstance(context);
- int widgetId = widgetView.getAppWidgetId();
- if (widgetId <= 0) {
+ updateWidgetSizeRangesAsync(
+ widgetView.getAppWidgetId(), widgetView.getAppWidgetInfo(), context, spanX, spanY);
+ }
+
+ /**
+ * Updates a given {@code widgetId} with size, {@code spanX}, {@code spanY} asynchronously.
+ *
+ * <p>On Android S+, it also updates the given {@code widgetView} with a list of sizes derived
+ * from {@code spanX}, {@code spanY} in all supported device profiles.
+ */
+ public static void updateWidgetSizeRangesAsync(int widgetId,
+ AppWidgetProviderInfo info, Context context, int spanX, int spanY) {
+ if (widgetId <= 0 || info == null) {
return;
}
- Bundle sizeOptions = getWidgetSizeOptions(context, widgetView.getAppWidgetInfo().provider,
- spanX, spanY);
- if (sizeOptions.<SizeF>getParcelableArrayList(
- AppWidgetManager.OPTION_APPWIDGET_SIZES).equals(
- widgetManager.getAppWidgetOptions(widgetId).<SizeF>getParcelableArrayList(
- AppWidgetManager.OPTION_APPWIDGET_SIZES))) {
- return;
- }
- widgetManager.updateAppWidgetOptions(widgetId, sizeOptions);
+
+ UI_HELPER_EXECUTOR.execute(() -> {
+ AppWidgetManager widgetManager = AppWidgetManager.getInstance(context);
+ Bundle sizeOptions = getWidgetSizeOptions(context, info.provider, spanX, spanY);
+ if (sizeOptions.<SizeF>getParcelableArrayList(
+ AppWidgetManager.OPTION_APPWIDGET_SIZES).equals(
+ widgetManager.getAppWidgetOptions(widgetId).<SizeF>getParcelableArrayList(
+ AppWidgetManager.OPTION_APPWIDGET_SIZES))) {
+ return;
+ }
+ widgetManager.updateAppWidgetOptions(widgetId, sizeOptions);
+ });
}
/**