Revert "Shortcut integration with AppSearch (Part 5)"

Revert "Shortcut integration with AppSearch (CTS Test)"

Revert submission 13554951-shortcut-appsearch

Reason for revert: affecting multiuser and perf test
Reverted Changes:
I7ae7ec50a:Shortcut integration with AppSearch (Part 5)
I726e3777c:Shortcut integration with AppSearch (CTS Test)

Bug: 183982287, 183949746
Test: atest ShortcutManagerTest1 ShortcutManagerTest2
    ShortcutManagerTest3 ShortcutManagerTest4 ShortcutManagerTest5
    ShortcutManagerTest6 ShortcutManagerTest7 ShortcutManagerTest8
    ShortcutManagerTest9 ShortcutManagerTest10 ShortcutManagerTest11
Change-Id: I3e364d3532cd4c08c675e977f255b9aeb455eb8b
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index b02a21d..19c56f8 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -19,33 +19,18 @@
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.Person;
-import android.app.appsearch.AppSearchManager;
-import android.app.appsearch.AppSearchResult;
 import android.app.appsearch.AppSearchSession;
-import android.app.appsearch.GenericDocument;
-import android.app.appsearch.GetByUriRequest;
 import android.app.appsearch.PackageIdentifier;
-import android.app.appsearch.PutDocumentsRequest;
-import android.app.appsearch.RemoveByUriRequest;
-import android.app.appsearch.ReportUsageRequest;
-import android.app.appsearch.SearchResult;
-import android.app.appsearch.SearchResults;
-import android.app.appsearch.SearchSpec;
-import android.app.appsearch.SetSchemaRequest;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.LocusId;
-import android.content.pm.AppSearchPerson;
-import android.content.pm.AppSearchShortcutInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.ShortcutInfo;
 import android.content.pm.ShortcutManager;
 import android.content.res.Resources;
 import android.graphics.drawable.Icon;
-import android.os.Binder;
 import android.os.PersistableBundle;
-import android.os.StrictMode;
 import android.text.format.Formatter;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -58,10 +43,8 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.infra.AndroidFuture;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.CollectionUtils;
-import com.android.internal.util.ConcurrentUtils;
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.XmlUtils;
 import com.android.server.pm.ShortcutService.DumpFilter;
@@ -81,17 +64,13 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
-import java.util.concurrent.CompletableFuture;
 import java.util.function.Consumer;
-import java.util.function.Function;
 import java.util.function.Predicate;
 
 /**
@@ -158,9 +137,9 @@
     private static final String KEY_BITMAP_BYTES = "bitmapBytes";
 
     /**
-     * An temp in-memory copy of shortcuts for this package that was loaded from xml, keyed on IDs.
+     * All the shortcuts from the package, keyed on IDs.
      */
-    final ArraySet<ShortcutInfo> mShortcuts = new ArraySet<>();
+    private final ArrayMap<String, ShortcutInfo> mShortcuts = new ArrayMap<>();
 
     /**
      * All the share targets from the package
@@ -220,9 +199,7 @@
     }
 
     public int getShortcutCount() {
-        final int[] count = new int[1];
-        forEachShortcut(si -> count[0]++);
-        return count[0];
+        return mShortcuts.size();
     }
 
     @Override
@@ -236,20 +213,17 @@
         // - Unshadow all shortcuts.
         // - Set disabled reason.
         // - Disable if needed.
-        forEachShortcutMutateIf(si -> {
-            if (!si.hasFlags(ShortcutInfo.FLAG_SHADOW)
-                    && si.getDisabledReason() == restoreBlockReason
-                    && restoreBlockReason == ShortcutInfo.DISABLED_REASON_NOT_DISABLED) {
-                return false;
-            }
-            si.clearFlags(ShortcutInfo.FLAG_SHADOW);
+        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+            ShortcutInfo si = mShortcuts.valueAt(i);
+            mutateShortcut(si.getId(), si, shortcut -> {
+                shortcut.clearFlags(ShortcutInfo.FLAG_SHADOW);
 
-            si.setDisabledReason(restoreBlockReason);
-            if (restoreBlockReason != ShortcutInfo.DISABLED_REASON_NOT_DISABLED) {
-                si.addFlags(ShortcutInfo.FLAG_DISABLED);
-            }
-            return true;
-        });
+                shortcut.setDisabledReason(restoreBlockReason);
+                if (restoreBlockReason != ShortcutInfo.DISABLED_REASON_NOT_DISABLED) {
+                    shortcut.addFlags(ShortcutInfo.FLAG_DISABLED);
+                }
+            });
+        }
         // Because some launchers may not have been restored (e.g. allowBackup=false),
         // we need to re-calculate the pinned shortcuts.
         refreshPinnedFlags();
@@ -260,7 +234,7 @@
      */
     @Nullable
     public ShortcutInfo findShortcutById(String id) {
-        return getShortcutById(id);
+        return mShortcuts.get(id);
     }
 
     public boolean isShortcutExistsAndInvisibleToPublisher(String id) {
@@ -326,9 +300,8 @@
      * Delete a shortcut by ID. This will *always* remove it even if it's immutable or invisible.
      */
     private ShortcutInfo forceDeleteShortcutInner(@NonNull String id) {
-        final ShortcutInfo shortcut = getShortcutById(id);
+        final ShortcutInfo shortcut = mShortcuts.remove(id);
         if (shortcut != null) {
-            removeShortcut(id);
             mShortcutUser.mService.removeIconLocked(shortcut);
             shortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_PINNED
                     | ShortcutInfo.FLAG_MANIFEST | ShortcutInfo.FLAG_CACHED_ALL);
@@ -345,10 +318,10 @@
 
         forceDeleteShortcutInner(newShortcut.getId());
 
+        // Extract Icon and update the icon res ID and the bitmap path.
         s.saveIconAndFixUpShortcutLocked(newShortcut);
         s.fixUpShortcutResourceNamesAndValues(newShortcut);
-
-        saveShortcut(newShortcut);
+        mShortcuts.put(newShortcut.getId(), newShortcut);
     }
 
     /**
@@ -437,16 +410,6 @@
         }
 
         forceReplaceShortcutInner(newShortcut);
-        // TODO: Report usage can be filed async
-        runInAppSearch(session -> {
-            final AndroidFuture<Boolean> future = new AndroidFuture<>();
-            session.reportUsage(
-                    new ReportUsageRequest.Builder(getPackageName())
-                            .setUri(newShortcut.getId()).build(),
-                    mShortcutUser.mExecutor, result -> future.complete(result.isSuccess()));
-            return future;
-        });
-
         return deleted;
     }
 
@@ -456,12 +419,19 @@
      * @return List of removed shortcuts.
      */
     private List<ShortcutInfo> removeOrphans() {
-        final List<ShortcutInfo> removeList = new ArrayList<>(1);
-        forEachShortcut(si -> {
-            if (si.isAlive()) return;
+        List<ShortcutInfo> removeList = null;
+
+        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+            final ShortcutInfo si = mShortcuts.valueAt(i);
+
+            if (si.isAlive()) continue;
+
+            if (removeList == null) {
+                removeList = new ArrayList<>();
+            }
             removeList.add(si);
-        });
-        if (!removeList.isEmpty()) {
+        }
+        if (removeList != null) {
             for (int i = removeList.size() - 1; i >= 0; i--) {
                 forceDeleteShortcutInner(removeList.get(i).getId());
             }
@@ -478,19 +448,20 @@
     public List<ShortcutInfo> deleteAllDynamicShortcuts(boolean ignoreInvisible) {
         final long now = mShortcutUser.mService.injectCurrentTimeMillis();
 
-        final boolean[] changed = new boolean[1];
-        forEachShortcutMutateIf(si -> {
+        boolean changed = false;
+        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+            final ShortcutInfo si = mShortcuts.valueAt(i);
             if (si.isDynamic() && (!ignoreInvisible || si.isVisibleToPublisher())) {
-                changed[0] = true;
+                changed = true;
 
-                si.setTimestamp(now);
-                si.clearFlags(ShortcutInfo.FLAG_DYNAMIC);
-                si.setRank(0); // It may still be pinned, so clear the rank.
-                return true;
+                mutateShortcut(si.getId(), si, shortcut -> {
+                    shortcut.setTimestamp(now);
+                    shortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC);
+                    shortcut.setRank(0); // It may still be pinned, so clear the rank.
+                });
             }
-            return false;
-        });
-        if (changed[0]) {
+        }
+        if (changed) {
             return removeOrphans();
         }
         return null;
@@ -635,6 +606,11 @@
      * <p>Then remove all shortcuts that are not dynamic and no longer pinned either.
      */
     public void refreshPinnedFlags() {
+        final List<ShortcutInfo> shortcuts = new ArrayList<>(mShortcuts.values());
+        final Map<String, ShortcutInfo> shortcutMap = new ArrayMap<>(shortcuts.size());
+        for (ShortcutInfo si : shortcuts) {
+            shortcutMap.put(si.getId(), si);
+        }
         final Set<String> pinnedShortcuts = new ArraySet<>();
 
         // First, for the pinned set for each launcher, keep track of their id one by one.
@@ -644,20 +620,31 @@
             if (pinned == null || pinned.size() == 0) {
                 return;
             }
-            pinnedShortcuts.addAll(pinned);
+            for (int i = pinned.size() - 1; i >= 0; i--) {
+                final String id = pinned.valueAt(i);
+                final ShortcutInfo si = shortcutMap.get(id);
+                if (si == null) {
+                    // This happens if a launcher pinned shortcuts from this package, then backup&
+                    // restored, but this package doesn't allow backing up.
+                    // In that case the launcher ends up having a dangling pinned shortcuts.
+                    // That's fine, when the launcher is restored, we'll fix it.
+                    continue;
+                }
+                pinnedShortcuts.add(si.getId());
+            }
         });
         // Then, update the pinned state if necessary
-        forEachShortcutMutateIf(si -> {
+        for (int i = shortcuts.size() - 1; i >= 0; i--) {
+            final ShortcutInfo si = shortcuts.get(i);
             if (pinnedShortcuts.contains(si.getId()) && !si.isPinned()) {
-                si.addFlags(ShortcutInfo.FLAG_PINNED);
-                return true;
+                mutateShortcut(si.getId(), si,
+                        shortcut -> shortcut.addFlags(ShortcutInfo.FLAG_PINNED));
             }
             if (!pinnedShortcuts.contains(si.getId()) && si.isPinned()) {
-                si.clearFlags(ShortcutInfo.FLAG_PINNED);
-                return true;
+                mutateShortcut(si.getId(), si, shortcut ->
+                        shortcut.clearFlags(ShortcutInfo.FLAG_PINNED));
             }
-            return false;
-        });
+        }
 
         // Lastly, remove the ones that are no longer pinned, cached nor dynamic.
         removeOrphans();
@@ -772,7 +759,9 @@
         final ArraySet<String> pinnedByCallerSet = (callingLauncher == null) ? null
                 : s.getLauncherShortcutsLocked(callingLauncher, getPackageUserId(), launcherUserId)
                         .getPinnedShortcutIds(getPackageName(), getPackageUserId());
-        forEachShortcut(si -> {
+
+        for (int i = 0; i < mShortcuts.size(); i++) {
+            final ShortcutInfo si = mShortcuts.valueAt(i);
             // Need to adjust PINNED flag depending on the caller.
             // Basically if the caller is a launcher (callingLauncher != null) and the launcher
             // isn't pinning it, then we need to clear PINNED for this caller.
@@ -782,7 +771,7 @@
             if (!getPinnedByAnyLauncher) {
                 if (si.isFloating() && !si.isCached()) {
                     if (!isPinnedByCaller) {
-                        return;
+                        continue;
                     }
                 }
             }
@@ -802,7 +791,7 @@
                 }
                 result.add(clone);
             }
-        });
+        }
     }
 
     public void resetThrottling() {
@@ -872,7 +861,7 @@
      * the app's Xml resource.
      */
     int getSharingShortcutCount() {
-        if (getShortcutCount() == 0 || mShareTargets.isEmpty()) {
+        if (mShortcuts.isEmpty() || mShareTargets.isEmpty()) {
             return 0;
         }
 
@@ -910,12 +899,14 @@
      * Return the filenames (excluding path names) of icon bitmap files from this package.
      */
     public ArraySet<String> getUsedBitmapFiles() {
-        final ArraySet<String> usedFiles = new ArraySet<>(1);
-        forEachShortcut(si -> {
+        final ArraySet<String> usedFiles = new ArraySet<>(mShortcuts.size());
+
+        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+            final ShortcutInfo si = mShortcuts.valueAt(i);
             if (si.getBitmapPath() != null) {
                 usedFiles.add(getFileName(si.getBitmapPath()));
             }
-        });
+        }
         return usedFiles;
     }
 
@@ -932,29 +923,30 @@
      * @return false if any of the target activities are no longer enabled.
      */
     private boolean areAllActivitiesStillEnabled() {
+        if (mShortcuts.size() == 0) {
+            return true;
+        }
         final ShortcutService s = mShortcutUser.mService;
 
         // Normally the number of target activities is 1 or so, so no need to use a complex
         // structure like a set.
         final ArrayList<ComponentName> checked = new ArrayList<>(4);
-        final boolean[] reject = new boolean[1];
 
-        forEachShortcutStopWhen(si -> {
+        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+            final ShortcutInfo si = mShortcuts.valueAt(i);
             final ComponentName activity = si.getActivity();
 
             if (checked.contains(activity)) {
-                return false; // Already checked.
+                continue; // Already checked.
             }
             checked.add(activity);
 
             if ((activity != null)
                     && !s.injectIsActivityEnabledAndExported(activity, getOwnerUserId())) {
-                reject[0] = true;
-                return true; // Found at least 1 activity is disabled, so skip the rest.
+                return false;
             }
-            return false;
-        });
-        return !reject[0];
+        }
+        return true;
     }
 
     /**
@@ -1037,32 +1029,32 @@
 
         // See if there are any shortcuts that were prevented restoring because the app was of a
         // lower version, and re-enable them.
-        forEachShortcutMutateIf(si -> {
+        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+            final ShortcutInfo si = mShortcuts.valueAt(i);
             if (si.getDisabledReason() != ShortcutInfo.DISABLED_REASON_VERSION_LOWER) {
-                return false;
+                continue;
             }
             if (getPackageInfo().getBackupSourceVersionCode() > newVersionCode) {
                 if (ShortcutService.DEBUG) {
                     Slog.d(TAG, String.format("Shortcut %s require version %s, still not restored.",
                             si.getId(), getPackageInfo().getBackupSourceVersionCode()));
                 }
-                return false;
+                continue;
             }
             Slog.i(TAG, String.format("Restoring shortcut: %s", si.getId()));
-            if (si.hasFlags(ShortcutInfo.FLAG_DISABLED)
-                    || si.getDisabledReason() != ShortcutInfo.DISABLED_REASON_NOT_DISABLED) {
-                si.clearFlags(ShortcutInfo.FLAG_DISABLED);
-                si.setDisabledReason(ShortcutInfo.DISABLED_REASON_NOT_DISABLED);
-                return true;
-            }
-            return false;
-        });
+            mutateShortcut(si.getId(), si, shortcut -> {
+                shortcut.clearFlags(ShortcutInfo.FLAG_DISABLED);
+                shortcut.setDisabledReason(ShortcutInfo.DISABLED_REASON_NOT_DISABLED);
+            });
+        }
 
         // For existing shortcuts, update timestamps if they have any resources.
         // Also check if shortcuts' activities are still main activities.  Otherwise, disable them.
         if (!isNewApp) {
-            final Resources publisherRes = getPackageResources();
-            forEachShortcutMutateIf(si -> {
+            Resources publisherRes = null;
+
+            for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+                final ShortcutInfo si = mShortcuts.valueAt(i);
                 // Disable dynamic shortcuts whose target activity is gone.
                 if (si.isDynamic()) {
                     if (si.getActivity() == null) {
@@ -1075,26 +1067,33 @@
                                 getPackageName(), si.getId()));
                         if (disableDynamicWithId(si.getId(), /*ignoreInvisible*/ false,
                                 ShortcutInfo.DISABLED_REASON_APP_CHANGED) != null) {
-                            return false; // Actually removed.
+                            continue; // Actually removed.
                         }
                         // Still pinned, so fall-through and possibly update the resources.
                     }
                 }
 
-                if (!si.hasAnyResources() || publisherRes == null) {
-                    return false;
-                }
+                if (si.hasAnyResources()) {
+                    if (publisherRes == null) {
+                        publisherRes = getPackageResources();
+                        if (publisherRes == null) {
+                            break; // Resources couldn't be loaded.
+                        }
+                    }
 
-                if (!si.isOriginallyFromManifest()) {
-                    si.lookupAndFillInResourceIds(publisherRes);
-                }
+                    final Resources res = publisherRes;
+                    mutateShortcut(si.getId(), si, shortcut -> {
+                        if (!shortcut.isOriginallyFromManifest()) {
+                            shortcut.lookupAndFillInResourceIds(res);
+                        }
 
-                // If this shortcut is not from a manifest, then update all resource IDs
-                // from resource names.  (We don't allow resource strings for
-                // non-manifest at the moment, but icons can still be resources.)
-                si.setTimestamp(s.injectCurrentTimeMillis());
-                return true;
-            });
+                        // If this shortcut is not from a manifest, then update all resource IDs
+                        // from resource names.  (We don't allow resource strings for
+                        // non-manifest at the moment, but icons can still be resources.)
+                        shortcut.setTimestamp(s.injectCurrentTimeMillis());
+                    });
+                }
+            }
         }
 
         // (Re-)publish manifest shortcut.
@@ -1120,12 +1119,17 @@
         boolean changed = false;
 
         // Keep the previous IDs.
-        final ArraySet<String> toDisableList = new ArraySet<>(1);
-        forEachShortcut(si -> {
+        ArraySet<String> toDisableList = null;
+        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+            final ShortcutInfo si = mShortcuts.valueAt(i);
+
             if (si.isManifestShortcut()) {
+                if (toDisableList == null) {
+                    toDisableList = new ArraySet<>();
+                }
                 toDisableList.add(si.getId());
             }
-        });
+        }
 
         // Publish new ones.
         if (newManifestShortcutList != null) {
@@ -1165,7 +1169,7 @@
                 // regardless.
                 forceReplaceShortcutInner(newShortcut); // This will clean up the old one too.
 
-                if (!newDisabled && !toDisableList.isEmpty()) {
+                if (!newDisabled && toDisableList != null) {
                     // Still alive, don't remove.
                     toDisableList.remove(id);
                 }
@@ -1173,7 +1177,7 @@
         }
 
         // Disable the previous manifest shortcuts that are no longer in the manifest.
-        if (!toDisableList.isEmpty()) {
+        if (toDisableList != null) {
             if (ShortcutService.DEBUG) {
                 Slog.d(TAG, String.format(
                         "Package %s: disabling %d stale shortcuts", getPackageName(),
@@ -1188,8 +1192,8 @@
                         /* overrideImmutable=*/ true, /*ignoreInvisible=*/ false,
                         ShortcutInfo.DISABLED_REASON_APP_CHANGED);
             }
+            removeOrphans();
         }
-        removeOrphans();
 
         adjustRanks();
         return changed;
@@ -1262,21 +1266,25 @@
     private ArrayMap<ComponentName, ArrayList<ShortcutInfo>> sortShortcutsToActivities() {
         final ArrayMap<ComponentName, ArrayList<ShortcutInfo>> activitiesToShortcuts
                 = new ArrayMap<>();
-        forEachShortcut(si -> {
+        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+            final ShortcutInfo si = mShortcuts.valueAt(i);
             if (si.isFloating()) {
-                return; // Ignore floating shortcuts, which are not tied to any activities.
+                continue; // Ignore floating shortcuts, which are not tied to any activities.
             }
 
             final ComponentName activity = si.getActivity();
             if (activity == null) {
                 mShortcutUser.mService.wtf("null activity detected.");
-                return;
+                continue;
             }
 
-            ArrayList<ShortcutInfo> list = activitiesToShortcuts.computeIfAbsent(activity,
-                    k -> new ArrayList<>());
+            ArrayList<ShortcutInfo> list = activitiesToShortcuts.get(activity);
+            if (list == null) {
+                list = new ArrayList<>();
+                activitiesToShortcuts.put(activity, list);
+            }
             list.add(si);
-        });
+        }
         return activitiesToShortcuts;
     }
 
@@ -1312,13 +1320,14 @@
         // (If it's for update, then don't count dynamic shortcuts, since they'll be replaced
         // anyway.)
         final ArrayMap<ComponentName, Integer> counts = new ArrayMap<>(4);
-        forEachShortcut(shortcut -> {
+        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+            final ShortcutInfo shortcut = mShortcuts.valueAt(i);
             if (shortcut.isManifestShortcut()) {
                 incrementCountForActivity(counts, shortcut.getActivity(), 1);
             } else if (shortcut.isDynamic() && (operation != ShortcutService.OPERATION_SET)) {
                 incrementCountForActivity(counts, shortcut.getActivity(), 1);
             }
-        });
+        }
 
         for (int i = newList.size() - 1; i >= 0; i--) {
             final ShortcutInfo newShortcut = newList.get(i);
@@ -1331,7 +1340,7 @@
                 continue; // Activity can be null for update.
             }
 
-            final ShortcutInfo original = findShortcutById(newShortcut.getId());
+            final ShortcutInfo original = mShortcuts.get(newShortcut.getId());
             if (original == null) {
                 if (operation == ShortcutService.OPERATION_UPDATE) {
                     continue; // When updating, ignore if there's no target.
@@ -1370,17 +1379,31 @@
     public void resolveResourceStrings() {
         final ShortcutService s = mShortcutUser.mService;
 
-        final Resources publisherRes = getPackageResources();
-        final List<ShortcutInfo> changedShortcuts = new ArrayList<>(1);
+        List<ShortcutInfo> changedShortcuts = null;
 
-        if (publisherRes != null) {
-            forEachShortcutMutateIf(si -> {
-                if (!si.hasStringResources()) return false;
-                si.resolveResourceStrings(publisherRes);
-                si.setTimestamp(s.injectCurrentTimeMillis());
+        Resources publisherRes = null;
+        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+            final ShortcutInfo si = mShortcuts.valueAt(i);
+
+            if (si.hasStringResources()) {
+                if (publisherRes == null) {
+                    publisherRes = getPackageResources();
+                    if (publisherRes == null) {
+                        break; // Resources couldn't be loaded.
+                    }
+                }
+
+                final Resources res = publisherRes;
+                mutateShortcut(si.getId(), si, shortcut -> {
+                    shortcut.resolveResourceStrings(res);
+                    shortcut.setTimestamp(s.injectCurrentTimeMillis());
+                });
+
+                if (changedShortcuts == null) {
+                    changedShortcuts = new ArrayList<>(1);
+                }
                 changedShortcuts.add(si);
-                return true;
-            });
+            }
         }
         if (!CollectionUtils.isEmpty(changedShortcuts)) {
             s.packageShortcutsChanged(getPackageName(), getPackageUserId(), changedShortcuts, null);
@@ -1389,7 +1412,10 @@
 
     /** Clears the implicit ranks for all shortcuts. */
     public void clearAllImplicitRanks() {
-        forEachShortcutMutate(ShortcutInfo::clearImplicitRankAndRankChangedFlag);
+        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+            final ShortcutInfo si = mShortcuts.valueAt(i);
+            mutateShortcut(si.getId(), si, ShortcutInfo::clearImplicitRankAndRankChangedFlag);
+        }
     }
 
     /**
@@ -1429,16 +1455,17 @@
         final long now = s.injectCurrentTimeMillis();
 
         // First, clear ranks for floating shortcuts.
-        forEachShortcutMutateIf(si -> {
+        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+            final ShortcutInfo si = mShortcuts.valueAt(i);
             if (si.isFloating()) {
                 if (si.getRank() != 0) {
-                    si.setTimestamp(now);
-                    si.setRank(0);
-                    return true;
+                    mutateShortcut(si.getId(), si, shortcut -> {
+                        shortcut.setTimestamp(now);
+                        shortcut.setRank(0);
+                    });
                 }
             }
-            return false;
-        });
+        }
 
         // Then adjust ranks.  Ranks are unique for each activity, so we first need to sort
         // shortcuts to each activity.
@@ -1463,7 +1490,7 @@
                 }
                 // At this point, it must be dynamic.
                 if (!si.isDynamic()) {
-                    s.wtf("Non-dynamic shortcut found.:  " + si.toInsecureString());
+                    s.wtf("Non-dynamic shortcut found.");
                     continue;
                 }
                 final int thisRank = rank++;
@@ -1480,14 +1507,13 @@
     /** @return true if there's any shortcuts that are not manifest shortcuts. */
     public boolean hasNonManifestShortcuts() {
         final boolean[] condition = new boolean[1];
-        forEachShortcutStopWhen(si -> {
+        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+            final ShortcutInfo si = mShortcuts.valueAt(i);
             if (!si.isDeclaredInManifest()) {
-                condition[0] = true;
                 return true;
             }
-            return false;
-        });
-        return condition[0];
+        }
+        return false;
     }
 
     public void dump(@NonNull PrintWriter pw, @NonNull String prefix, DumpFilter filter) {
@@ -1527,8 +1553,11 @@
 
         pw.print(prefix);
         pw.println("  Shortcuts:");
-        final long[] totalBitmapSize = new long[1];
-        forEachShortcut(si -> {
+        long totalBitmapSize = 0;
+        final ArrayMap<String, ShortcutInfo> shortcuts = mShortcuts;
+        final int size = shortcuts.size();
+        for (int i = 0; i < size; i++) {
+            final ShortcutInfo si = shortcuts.valueAt(i);
             pw.println(si.toDumpString(prefix + "    "));
             if (si.getBitmapPath() != null) {
                 final long len = new File(si.getBitmapPath()).length();
@@ -1537,15 +1566,15 @@
                 pw.print("bitmap size=");
                 pw.println(len);
 
-                totalBitmapSize[0] += len;
+                totalBitmapSize += len;
             }
-        });
+        }
         pw.print(prefix);
         pw.print("  ");
         pw.print("Total bitmap size: ");
-        pw.print(totalBitmapSize[0]);
+        pw.print(totalBitmapSize);
         pw.print(" (");
-        pw.print(Formatter.formatFileSize(mShortcutUser.mService.mContext, totalBitmapSize[0]));
+        pw.print(Formatter.formatFileSize(mShortcutUser.mService.mContext, totalBitmapSize));
         pw.println(")");
     }
 
@@ -1560,39 +1589,46 @@
                 | (matchManifest ? ShortcutInfo.FLAG_MANIFEST : 0)
                 | (matchCached ? ShortcutInfo.FLAG_CACHED_ALL : 0);
 
-        forEachShortcut(si -> {
+        final ArrayMap<String, ShortcutInfo> shortcuts = mShortcuts;
+        final int size = shortcuts.size();
+        for (int i = 0; i < size; i++) {
+            final ShortcutInfo si = shortcuts.valueAt(i);
             if ((si.getFlags() & shortcutFlags) != 0) {
                 pw.println(si.toDumpString(""));
             }
-        });
+        }
     }
 
     @Override
     public JSONObject dumpCheckin(boolean clear) throws JSONException {
         final JSONObject result = super.dumpCheckin(clear);
 
-        final int[] numDynamic = new int[1];
-        final int[] numPinned = new int[1];
-        final int[] numManifest = new int[1];
-        final int[] numBitmaps = new int[1];
-        final long[] totalBitmapSize = new long[1];
+        int numDynamic = 0;
+        int numPinned = 0;
+        int numManifest = 0;
+        int numBitmaps = 0;
+        long totalBitmapSize = 0;
 
-        forEachShortcut(si -> {
-            if (si.isDynamic()) numDynamic[0]++;
-            if (si.isDeclaredInManifest()) numManifest[0]++;
-            if (si.isPinned()) numPinned[0]++;
+        final ArrayMap<String, ShortcutInfo> shortcuts = mShortcuts;
+        final int size = shortcuts.size();
+        for (int i = 0; i < size; i++) {
+            final ShortcutInfo si = shortcuts.valueAt(i);
+
+            if (si.isDynamic()) numDynamic++;
+            if (si.isDeclaredInManifest()) numManifest++;
+            if (si.isPinned()) numPinned++;
 
             if (si.getBitmapPath() != null) {
-                numBitmaps[0]++;
-                totalBitmapSize[0] += new File(si.getBitmapPath()).length();
+                numBitmaps++;
+                totalBitmapSize += new File(si.getBitmapPath()).length();
             }
-        });
+        }
 
-        result.put(KEY_DYNAMIC, numDynamic[0]);
-        result.put(KEY_MANIFEST, numManifest[0]);
-        result.put(KEY_PINNED, numPinned[0]);
-        result.put(KEY_BITMAPS, numBitmaps[0]);
-        result.put(KEY_BITMAP_BYTES, totalBitmapSize[0]);
+        result.put(KEY_DYNAMIC, numDynamic);
+        result.put(KEY_MANIFEST, numManifest);
+        result.put(KEY_PINNED, numPinned);
+        result.put(KEY_BITMAPS, numBitmaps);
+        result.put(KEY_BITMAP_BYTES, totalBitmapSize);
 
         // TODO Log update frequency too.
 
@@ -1616,15 +1652,9 @@
         ShortcutService.writeAttr(out, ATTR_LAST_RESET, mLastResetTime);
         getPackageInfo().saveToXml(mShortcutUser.mService, out, forBackup);
 
-        if (forBackup) {
-            // Shortcuts are persisted in AppSearch, xml is only needed for backup.
-            forEachShortcut(si -> {
-                try {
-                    saveShortcut(out, si, forBackup, getPackageInfo().isBackupAllowed());
-                } catch (IOException | XmlPullParserException e) {
-                    throw new RuntimeException(e);
-                }
-            });
+        for (int j = 0; j < size; j++) {
+            saveShortcut(out, mShortcuts.valueAt(j), forBackup,
+                    getPackageInfo().isBackupAllowed());
         }
 
         if (!forBackup) {
@@ -1741,14 +1771,12 @@
             }
             final Intent[] intentsNoExtras = si.getIntentsNoExtras();
             final PersistableBundle[] intentsExtras = si.getIntentPersistableExtrases();
-            if (intentsNoExtras != null && intentsExtras != null) {
-                final int numIntents = intentsNoExtras.length;
-                for (int i = 0; i < numIntents; i++) {
-                    out.startTag(null, TAG_INTENT);
-                    ShortcutService.writeAttr(out, ATTR_INTENT_NO_EXTRA, intentsNoExtras[i]);
-                    ShortcutService.writeTagExtra(out, TAG_EXTRAS, intentsExtras[i]);
-                    out.endTag(null, TAG_INTENT);
-                }
+            final int numIntents = intentsNoExtras.length;
+            for (int i = 0; i < numIntents; i++) {
+                out.startTag(null, TAG_INTENT);
+                ShortcutService.writeAttr(out, ATTR_INTENT_NO_EXTRA, intentsNoExtras[i]);
+                ShortcutService.writeTagExtra(out, TAG_EXTRAS, intentsExtras[i]);
+                out.endTag(null, TAG_INTENT);
             }
 
             ShortcutService.writeTagExtra(out, TAG_EXTRAS, si.getExtras());
@@ -1836,7 +1864,7 @@
                         final ShortcutInfo si = parseShortcut(parser, packageName,
                                 shortcutUser.getUserId(), fromBackup);
                         // Don't use addShortcut(), we don't need to save the icon.
-                        ret.mShortcuts.add(si);
+                        ret.mShortcuts.put(si.getId(), si);
                         continue;
                     case TAG_SHARE_TARGET:
                         ret.mShareTargets.add(ShareTargetInfo.loadFromXml(parser));
@@ -2032,9 +2060,7 @@
 
     @VisibleForTesting
     List<ShortcutInfo> getAllShortcutsForTest() {
-        final List<ShortcutInfo> ret = new ArrayList<>(1);
-        forEachShortcut(ret::add);
-        return ret;
+        return new ArrayList<>(mShortcuts.values());
     }
 
     @VisibleForTesting
@@ -2046,7 +2072,7 @@
     public void verifyStates() {
         super.verifyStates();
 
-        final boolean[] failed = new boolean[1];
+        boolean failed = false;
 
         final ShortcutService s = mShortcutUser.mService;
 
@@ -2057,7 +2083,7 @@
         for (int outer = all.size() - 1; outer >= 0; outer--) {
             final ArrayList<ShortcutInfo> list = all.valueAt(outer);
             if (list.size() > mShortcutUser.mService.getMaxActivityShortcuts()) {
-                failed[0] = true;
+                failed = true;
                 Log.e(TAG_VERIFY, "Package " + getPackageName() + ": activity " + all.keyAt(outer)
                         + " has " + all.valueAt(outer).size() + " shortcuts.");
             }
@@ -2077,60 +2103,61 @@
         }
 
         // Verify each shortcut's status.
-        forEachShortcut(si -> {
+        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+            final ShortcutInfo si = mShortcuts.valueAt(i);
             if (!(si.isDeclaredInManifest() || si.isDynamic() || si.isPinned() || si.isCached())) {
-                failed[0] = true;
+                failed = true;
                 Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
                         + " is not manifest, dynamic or pinned.");
             }
             if (si.isDeclaredInManifest() && si.isDynamic()) {
-                failed[0] = true;
+                failed = true;
                 Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
                         + " is both dynamic and manifest at the same time.");
             }
             if (si.getActivity() == null && !si.isFloating()) {
-                failed[0] = true;
+                failed = true;
                 Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
                         + " has null activity, but not floating.");
             }
             if ((si.isDynamic() || si.isManifestShortcut()) && !si.isEnabled()) {
-                failed[0] = true;
+                failed = true;
                 Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
                         + " is not floating, but is disabled.");
             }
             if (si.isFloating() && si.getRank() != 0) {
-                failed[0] = true;
+                failed = true;
                 Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
                         + " is floating, but has rank=" + si.getRank());
             }
             if (si.getIcon() != null) {
-                failed[0] = true;
+                failed = true;
                 Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
                         + " still has an icon");
             }
             if (si.hasAdaptiveBitmap() && !(si.hasIconFile() || si.hasIconUri())) {
-                failed[0] = true;
+                failed = true;
                 Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
                         + " has adaptive bitmap but was not saved to a file nor has icon uri.");
             }
             if (si.hasIconFile() && si.hasIconResource()) {
-                failed[0] = true;
+                failed = true;
                 Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
                         + " has both resource and bitmap icons");
             }
             if (si.hasIconFile() && si.hasIconUri()) {
-                failed[0] = true;
+                failed = true;
                 Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
                         + " has both url and bitmap icons");
             }
             if (si.hasIconUri() && si.hasIconResource()) {
-                failed[0] = true;
+                failed = true;
                 Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
                         + " has both url and resource icons");
             }
             if (si.isEnabled()
                     != (si.getDisabledReason() == ShortcutInfo.DISABLED_REASON_NOT_DISABLED)) {
-                failed[0] = true;
+                failed = true;
                 Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
                         + " isEnabled() and getDisabledReason() disagree: "
                         + si.isEnabled() + " vs " + si.getDisabledReason());
@@ -2138,18 +2165,18 @@
             if ((si.getDisabledReason() == ShortcutInfo.DISABLED_REASON_VERSION_LOWER)
                     && (getPackageInfo().getBackupSourceVersionCode()
                     == ShortcutInfo.VERSION_CODE_UNKNOWN)) {
-                failed[0] = true;
+                failed = true;
                 Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
                         + " RESTORED_VERSION_LOWER with no backup source version code.");
             }
             if (s.isDummyMainActivity(si.getActivity())) {
-                failed[0] = true;
+                failed = true;
                 Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
                         + " has a dummy target activity");
             }
-        });
+        }
 
-        if (failed[0]) {
+        if (failed) {
             throw new IllegalStateException("See logcat for errors");
         }
     }
@@ -2160,7 +2187,6 @@
         } else {
             mPackageIdentifiers.remove(packageName);
         }
-        resetAppSearch(session -> AndroidFuture.completedFuture(true));
     }
 
     void mutateShortcut(@NonNull final String id, @Nullable final ShortcutInfo shortcut,
@@ -2170,302 +2196,23 @@
         synchronized (mLock) {
             if (shortcut != null) {
                 transform.accept(shortcut);
+            } else {
+                transform.accept(findShortcutById(id));
             }
-            final ShortcutInfo si = getShortcutById(id);
-            if (si == null) {
-                return;
-            }
-            transform.accept(si);
-            saveShortcut(si);
+            // TODO: Load ShortcutInfo from AppSearch, apply transformation logic and save
         }
     }
 
-    private void saveShortcut(@NonNull final ShortcutInfo... shortcuts) {
-        Objects.requireNonNull(shortcuts);
-        saveShortcut(Arrays.asList(shortcuts));
-    }
-
-    private void saveShortcut(@NonNull final Collection<ShortcutInfo> shortcuts) {
-        Objects.requireNonNull(shortcuts);
-        if (shortcuts.isEmpty()) {
-            // No need to invoke AppSearch when there's nothing to save.
-            return;
-        }
-        ConcurrentUtils.waitForFutureNoInterrupt(
-                runInAppSearch(session -> {
-                    final AndroidFuture<Boolean> future = new AndroidFuture<>();
-                    session.put(new PutDocumentsRequest.Builder()
-                                    .addGenericDocuments(
-                                            AppSearchShortcutInfo.toGenericDocuments(shortcuts))
-                                    .build(),
-                            mShortcutUser.mExecutor,
-                            result -> {
-                                if (!result.isSuccess()) {
-                                    for (AppSearchResult<Void> k : result.getFailures().values()) {
-                                        Slog.e(TAG, k.getErrorMessage());
-                                    }
-                                    future.completeExceptionally(new RuntimeException(
-                                            "failed to save shortcuts"));
-                                    return;
-                                }
-                                future.complete(true);
-                            });
-                    return future;
-                }),
-                "saving shortcut");
-    }
-
     /**
      * Removes shortcuts from AppSearch.
      */
     void removeShortcuts() {
-        awaitInAppSearch("removing shortcuts", session -> {
-            final AndroidFuture<Boolean> future = new AndroidFuture<>();
-            session.remove("",
-                    new SearchSpec.Builder()
-                            .addFilterSchemas(AppSearchShortcutInfo.SCHEMA_TYPE)
-                            .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
-                            .build(),
-                    mShortcutUser.mExecutor, result -> {
-                        if (!result.isSuccess()) {
-                            future.completeExceptionally(new RuntimeException(
-                                    "Failed to cleanup shortcuts " + result.getErrorMessage()));
-                            return;
-                        }
-                        future.complete(true);
-                    });
-            return future;
-        });
-    }
-
-    private void removeShortcut(@NonNull final String id) {
-        Objects.requireNonNull(id);
-        awaitInAppSearch("removing shortcut with id=" + id, session -> {
-            final AndroidFuture<Boolean> future = new AndroidFuture<>();
-            session.remove(new RemoveByUriRequest.Builder(getPackageName()).addUris(id).build(),
-                    mShortcutUser.mExecutor, result -> {
-                        if (!result.isSuccess()) {
-                            final Map<String, AppSearchResult<Void>> failures =
-                                    result.getFailures();
-                            for (String key : failures.keySet()) {
-                                Slog.e(TAG, "Failed deleting " + key + ", error message:"
-                                        + failures.get(key).getErrorMessage());
-                            }
-                            future.completeExceptionally(new RuntimeException(
-                                    "Failed to delete shortcut: " + id));
-                            return;
-                        }
-                        future.complete(true);
-                    });
-            return future;
-        });
-    }
-
-    private ShortcutInfo getShortcutById(String id) {
-        return awaitInAppSearch("getting shortcut with id=" + id, session -> {
-            final AndroidFuture<ShortcutInfo> future = new AndroidFuture<>();
-            session.getByUri(
-                    new GetByUriRequest.Builder(getPackageName()).addUris(id).build(),
-                    mShortcutUser.mExecutor,
-                    results -> {
-                        if (results.isSuccess()) {
-                            Map<String, GenericDocument> documents = results.getSuccesses();
-                            for (GenericDocument doc : documents.values()) {
-                                final ShortcutInfo info = new AppSearchShortcutInfo(doc)
-                                        .toShortcutInfo(mShortcutUser.getUserId());
-                                future.complete(info);
-                                return;
-                            }
-                        }
-                        future.complete(null);
-                    });
-            return future;
-        });
-    }
-
-    private void forEachShortcut(
-            @NonNull final Consumer<ShortcutInfo> cb) {
-        forEachShortcutStopWhen(si -> {
-            cb.accept(si);
-            return false;
-        });
-    }
-
-    private void forEachShortcutMutate(@NonNull final Consumer<ShortcutInfo> cb) {
-        forEachShortcutMutateIf(si -> {
-            cb.accept(si);
-            return true;
-        });
-    }
-
-    private void forEachShortcutMutateIf(@NonNull final Function<ShortcutInfo, Boolean> cb) {
-        final SearchResults res = awaitInAppSearch("mutating shortcuts", session ->
-                AndroidFuture.completedFuture(session.search("", new SearchSpec.Builder()
-                        .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY).build())));
-        if (res == null) return;
-        List<ShortcutInfo> shortcuts = getNextPage(res);
-        while (!shortcuts.isEmpty()) {
-            final List<ShortcutInfo> changed = new ArrayList<>(1);
-            for (ShortcutInfo si : shortcuts) {
-                if (cb.apply(si)) changed.add(si);
-            }
-            saveShortcut(changed);
-            shortcuts = getNextPage(res);
-        }
-    }
-
-    private void forEachShortcutStopWhen(
-            @NonNull final Function<ShortcutInfo, Boolean> cb) {
-        forEachShortcutStopWhen("", cb);
-    }
-
-    private void forEachShortcutStopWhen(
-            @NonNull final String query, @NonNull final Function<ShortcutInfo, Boolean> cb) {
-        final SearchResults res = awaitInAppSearch("iterating shortcuts", session ->
-                AndroidFuture.completedFuture(session.search(query, new SearchSpec.Builder()
-                        .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY).build())));
-        if (res == null) return;
-        List<ShortcutInfo> shortcuts = getNextPage(res);
-        while (!shortcuts.isEmpty()) {
-            for (ShortcutInfo si : shortcuts) {
-                if (cb.apply(si)) return;
-            }
-            shortcuts = getNextPage(res);
-        }
-    }
-
-    private List<ShortcutInfo> getNextPage(@NonNull final SearchResults res) {
-        final AndroidFuture<List<ShortcutInfo>> future = new AndroidFuture<>();
-        final List<ShortcutInfo> ret = new ArrayList<>();
-        final long callingIdentity = Binder.clearCallingIdentity();
-        try {
-            res.getNextPage(mShortcutUser.mExecutor, nextPage -> {
-                if (!nextPage.isSuccess()) {
-                    future.complete(ret);
-                    return;
-                }
-                final List<SearchResult> results = nextPage.getResultValue();
-                if (results.isEmpty()) {
-                    future.complete(ret);
-                    return;
-                }
-                final List<ShortcutInfo> page = new ArrayList<>(results.size());
-                for (SearchResult result : results) {
-                    final ShortcutInfo si = new AppSearchShortcutInfo(result.getGenericDocument())
-                            .toShortcutInfo(mShortcutUser.getUserId());
-                    page.add(si);
-                }
-                ret.addAll(page);
-                future.complete(ret);
-            });
-            return ConcurrentUtils.waitForFutureNoInterrupt(future,
-                    "getting next batch of shortcuts");
-        } finally {
-            Binder.restoreCallingIdentity(callingIdentity);
-        }
-    }
-
-    @Nullable
-    private <T> T awaitInAppSearch(
-            @NonNull final String description,
-            @NonNull final Function<AppSearchSession, CompletableFuture<T>> cb) {
-        return ConcurrentUtils.waitForFutureNoInterrupt(runInAppSearch(cb), description);
-    }
-
-    @Nullable
-    private <T> CompletableFuture<T> runInAppSearch(
-            @NonNull final Function<AppSearchSession, CompletableFuture<T>> cb) {
-        synchronized (mLock) {
-            final StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
-            try {
-                StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
-                        .detectAll()
-                        .penaltyLog() // TODO: change this to penaltyDeath to fix the call-site
-                        .build());
-                if (mAppSearchSession != null) {
-                    final long callingIdentity = Binder.clearCallingIdentity();
-                    try {
-                        return AndroidFuture.supply(() -> mAppSearchSession).thenCompose(cb);
-                    } finally {
-                        Binder.restoreCallingIdentity(callingIdentity);
-                    }
-                } else {
-                    return resetAppSearch(cb);
-                }
-            } finally {
-                StrictMode.setThreadPolicy(oldPolicy);
-            }
-        }
-    }
-
-    private <T> CompletableFuture<T> resetAppSearch(
-            @NonNull final Function<AppSearchSession, CompletableFuture<T>> cb) {
-        final long callingIdentity = Binder.clearCallingIdentity();
-        final AppSearchManager.SearchContext searchContext =
-                new AppSearchManager.SearchContext.Builder(getPackageName()).build();
-        final AppSearchSession session;
-        try {
-            session = ConcurrentUtils.waitForFutureNoInterrupt(
-                    mShortcutUser.getAppSearch(searchContext), "resetting app search");
-            ConcurrentUtils.waitForFutureNoInterrupt(setupSchema(session), "setting up schema");
-            mAppSearchSession = session;
-            return cb.apply(mAppSearchSession);
-        } catch (Exception e) {
-            Slog.e(TAG, "Failed to initiate app search for shortcut package "
-                    + getPackageName() + " user " + mShortcutUser.getUserId(), e);
-            return AndroidFuture.completedFuture(null);
-        } finally {
-            Binder.restoreCallingIdentity(callingIdentity);
-        }
-    }
-
-    void closeAppSearchSession() {
-        synchronized (mLock) {
-            if (mAppSearchSession != null) {
-                final long callingIdentity = Binder.clearCallingIdentity();
-                try {
-                    mAppSearchSession.close();
-                } finally {
-                    Binder.restoreCallingIdentity(callingIdentity);
-                }
-            }
-            mAppSearchSession = null;
-        }
-    }
-
-    @NonNull
-    private AndroidFuture<AppSearchSession> setupSchema(
-            @NonNull final AppSearchSession session) {
-        SetSchemaRequest.Builder schemaBuilder = new SetSchemaRequest.Builder()
-                .addSchemas(AppSearchPerson.SCHEMA, AppSearchShortcutInfo.SCHEMA);
-        for (PackageIdentifier pi : mPackageIdentifiers.values()) {
-            schemaBuilder = schemaBuilder
-                    .setSchemaTypeVisibilityForPackage(
-                            AppSearchPerson.SCHEMA_TYPE, true, pi)
-                    .setSchemaTypeVisibilityForPackage(
-                            AppSearchShortcutInfo.SCHEMA_TYPE, true, pi);
-        }
-        final AndroidFuture<AppSearchSession> future = new AndroidFuture<>();
-        session.setSchema(
-                schemaBuilder.build(), mShortcutUser.mExecutor, mShortcutUser.mExecutor, result -> {
-            if (!result.isSuccess()) {
-                future.completeExceptionally(
-                        new IllegalArgumentException(result.getErrorMessage()));
-                return;
-            }
-            future.complete(session);
-        });
-        return future;
     }
 
     /**
      * Merge/replace shortcuts parsed from xml file.
      */
     void restoreParsedShortcuts(final boolean replace) {
-        if (replace) {
-            removeShortcuts();
-        }
-        saveShortcut(mShortcuts);
     }
 
     private boolean verifyRanksSequential(List<ShortcutInfo> list) {
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 4cfa353..8e999de 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -1051,8 +1051,6 @@
         }
 
         final ShortcutUser user = getUserShortcutsLocked(userId);
-        // Close AppSearchSession to flush pending changes.
-        user.forAllPackages(ShortcutPackage::closeAppSearchSession);
         user.logSharingShortcutStats(mMetricsLogger);
     }
 
@@ -5083,17 +5081,6 @@
     }
 
     @VisibleForTesting
-    void updatePackageShortcutForTest(String packageName, String shortcutId, int userId,
-            Consumer<ShortcutInfo> cb) {
-        synchronized (mLock) {
-            final ShortcutPackage pkg = getPackageShortcutForTest(packageName, userId);
-            if (pkg == null) return;
-
-            pkg.mutateShortcut(shortcutId, null, cb);
-        }
-    }
-
-    @VisibleForTesting
     ShortcutLauncher getLauncherShortcutForTest(String packageName, int userId) {
         synchronized (mLock) {
             final ShortcutUser user = mUsers.get(userId);
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 88b0651..589b3b4 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -2041,11 +2041,6 @@
         return mService.getPackageShortcutForTest(packageName, shortcutId, userId);
     }
 
-    protected void updatePackageShortcut(String packageName, String shortcutId, int userId,
-            Consumer<ShortcutInfo> cb) {
-        mService.updatePackageShortcutForTest(packageName, shortcutId, userId, cb);
-    }
-
     protected void assertShortcutExists(String packageName, String shortcutId, int userId) {
         assertTrue(getPackageShortcut(packageName, shortcutId, userId) != null);
     }
@@ -2241,10 +2236,6 @@
         return getPackageShortcut(getCallingPackage(), shortcutId, getCallingUserId());
     }
 
-    protected void updateCallerShortcut(String shortcutId, Consumer<ShortcutInfo> cb) {
-        updatePackageShortcut(getCallingPackage(), shortcutId, getCallingUserId(), cb);
-    }
-
     protected List<ShortcutInfo> getLauncherShortcuts(String launcher, int userId, int queryFlags) {
         final List<ShortcutInfo>[] ret = new List[1];
         runWithCaller(launcher, userId, () -> {
@@ -2404,8 +2395,6 @@
 
         deleteAllSavedFiles();
 
-        mMockAppSearchManager.removeShortcuts();
-
         initService();
         mService.applyRestore(payload, USER_0);
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 3f680e6..4d0beef 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -1385,7 +1385,6 @@
             mService.waitForBitmapSavesForTest();
             assertWith(getCallerShortcuts())
                     .forShortcutWithId("s1", si -> {
-                        Log.d("ShortcutManagerTest1", si.toString());
                         assertTrue(si.hasIconFile());
                     });
 
@@ -1703,8 +1702,8 @@
 
         // Because setDynamicShortcuts will update the timestamps when ranks are changing,
         // we explicitly set timestamps here.
-        updateCallerShortcut("s1", si -> si.setTimestamp(5000));
-        updateCallerShortcut("s2", si -> si.setTimestamp(1000));
+        getCallerShortcut("s1").setTimestamp(5000);
+        getCallerShortcut("s2").setTimestamp(1000);
 
         setCaller(CALLING_PACKAGE_2);
         final ShortcutInfo s2_2 = makeShortcut("s2");
@@ -1714,9 +1713,9 @@
                 makeComponent(ShortcutActivity.class));
         assertTrue(mManager.setDynamicShortcuts(list(s2_2, s2_3, s2_4)));
 
-        updateCallerShortcut("s2", si -> si.setTimestamp(1500));
-        updateCallerShortcut("s3", si -> si.setTimestamp(3000));
-        updateCallerShortcut("s4", si -> si.setTimestamp(500));
+        getCallerShortcut("s2").setTimestamp(1500);
+        getCallerShortcut("s3").setTimestamp(3000);
+        getCallerShortcut("s4").setTimestamp(500);
 
         setCaller(CALLING_PACKAGE_3);
         final ShortcutInfo s3_2 = makeShortcutWithLocusId("s3", makeLocusId("l2"));
@@ -1724,7 +1723,7 @@
 
         assertTrue(mManager.setDynamicShortcuts(list(s3_2)));
 
-        updateCallerShortcut("s3", si -> si.setTimestamp(START_TIME + 5000));
+        getCallerShortcut("s3").setTimestamp(START_TIME + 5000);
 
         setCaller(LAUNCHER_1);
 
@@ -7687,7 +7686,7 @@
                         assertEquals("http://www/", si.getIntent().getData().toString());
                         assertEquals("foo/bar", si.getIntent().getType());
                         assertEquals(
-                                new ComponentName("abc", "abc.xyz"), si.getIntent().getComponent());
+                                new ComponentName("abc", ".xyz"), si.getIntent().getComponent());
 
                         assertEquals(set("cat1", "cat2"), si.getIntent().getCategories());
                         assertEquals("value1", si.getIntent().getStringExtra("key1"));