Adding support for new APIs in O related to configurable shortcuts
> Config activities can now return PinItemRequest which can be used to pin
deep shortcuts
Bug: 33584624
Change-Id: Ic0df436bd79e069615b9d60d24eb7594b824b2da
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 13534b9..9245f18 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -86,6 +86,7 @@
import com.android.launcher3.anim.AnimationLayerSet;
import com.android.launcher3.compat.AppWidgetManagerCompat;
import com.android.launcher3.compat.LauncherAppsCompat;
+import com.android.launcher3.compat.PinItemRequestCompat;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.config.ProviderConfig;
@@ -96,6 +97,7 @@
import com.android.launcher3.dynamicui.ExtractedColors;
import com.android.launcher3.folder.Folder;
import com.android.launcher3.folder.FolderIcon;
+import com.android.launcher3.graphics.LauncherIcons;
import com.android.launcher3.keyboard.CustomActionsPopup;
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
import com.android.launcher3.logging.FileLog;
@@ -105,6 +107,7 @@
import com.android.launcher3.pageindicators.PageIndicator;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.shortcuts.DeepShortcutsContainer;
+import com.android.launcher3.shortcuts.ShortcutInfoCompat;
import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
@@ -118,6 +121,7 @@
import com.android.launcher3.util.TestingUtils;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.util.ViewOnDrawExecutor;
+import com.android.launcher3.widget.PendingAddShortcutInfo;
import com.android.launcher3.widget.PendingAddWidgetInfo;
import com.android.launcher3.widget.WidgetHostViewLoader;
import com.android.launcher3.widget.WidgetsContainerView;
@@ -1430,19 +1434,42 @@
int[] cellXY = mTmpAddItemCellCoordinates;
CellLayout layout = getCellLayout(container, screenId);
- ShortcutInfo info = InstallShortcutReceiver.fromShortcutIntent(this, data);
- if (info == null || args.getRequestCode() != REQUEST_CREATE_SHORTCUT ||
+ if (args.getRequestCode() != REQUEST_CREATE_SHORTCUT ||
args.getPendingIntent().getComponent() == null) {
return;
}
- if (!PackageManagerHelper.hasPermissionForActivity(
- this, info.intent, args.getPendingIntent().getComponent().getPackageName())) {
- // The app is trying to add a shortcut without sufficient permissions
- Log.e(TAG, "Ignoring malicious intent " + info.intent.toUri(0));
- return;
- }
- final View view = createShortcut(info);
+ ShortcutInfo info = null;
+ if (Utilities.isAtLeastO()) {
+ PinItemRequestCompat request = PinItemRequestCompat.getPinItemRequest(data);
+ // request.accept will initiate a shortcutChanged callback. To ensure that the model is
+ // consistent, that callback must be processed by the model, after the ShortcutInfo is
+ // added to the model. This is guaranteed here the callback comes on the UI thread, and
+ // we will add the shortcut on the UI thread as well.
+ if (request != null &&
+ request.getRequestType() == PinItemRequestCompat.REQUEST_TYPE_SHORTCUT &&
+ request.isValid() && request.accept()) {
+ ShortcutInfoCompat compat = new ShortcutInfoCompat(request.getShortcutInfo());
+ info = new ShortcutInfo(compat, this);
+ // Apply the unbadged icon and fetch the actual icon asynchronously.
+ info.iconBitmap = LauncherIcons
+ .createShortcutIcon(compat, this, false /* badged */);
+ getModel().updateAndBindShortcutInfo(info, compat);
+ }
+ }
+
+ if (info == null) {
+ info = InstallShortcutReceiver.fromShortcutIntent(this, data);
+
+ if (info == null || !PackageManagerHelper.hasPermissionForActivity(
+ this, info.intent, args.getPendingIntent().getComponent().getPackageName())) {
+ // The app is trying to add a shortcut without sufficient permissions
+ Log.e(TAG, "Ignoring malicious intent " + info.intent.toUri(0));
+ return;
+ }
+ }
+
+ final View view = createShortcut(info);
boolean foundCellSpan = false;
// First we check if we already know the exact location where we want to add this item.
if (cellX >= 0 && cellY >= 0) {
@@ -2025,7 +2052,7 @@
addAppWidgetFromDrop((PendingAddWidgetInfo) info);
break;
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
- processShortcutFromDrop(info);
+ processShortcutFromDrop((PendingAddShortcutInfo) info);
break;
default:
throw new IllegalStateException("Unknown item type: " + info.itemType);
@@ -2035,10 +2062,12 @@
/**
* Process a shortcut drop.
*/
- private void processShortcutFromDrop(PendingAddItemInfo info) {
+ private void processShortcutFromDrop(PendingAddShortcutInfo info) {
Intent intent = new Intent(Intent.ACTION_CREATE_SHORTCUT).setComponent(info.componentName);
setWaitingForResult(PendingRequestArgs.forIntent(REQUEST_CREATE_SHORTCUT, intent, info));
- Utilities.startActivityForResultSafely(this, intent, REQUEST_CREATE_SHORTCUT);
+ if (!info.activityInfo.startConfigActivity(this, REQUEST_CREATE_SHORTCUT)) {
+ handleActivityResult(REQUEST_CREATE_SHORTCUT, RESULT_CANCELED, null);
+ }
}
/**