Loading services/core/java/com/android/server/pm/ShortcutBitmapSaver.java +9 −6 Original line number Diff line number Diff line Loading @@ -280,7 +280,8 @@ public class ShortcutBitmapSaver { IoUtils.closeQuietly(out); } shortcut.setBitmapPath(file.getAbsolutePath()); final String path = file.getAbsolutePath(); mService.postValue(shortcut, si -> si.setBitmapPath(path)); } catch (IOException | RuntimeException e) { Slog.e(ShortcutService.TAG, "Unable to write bitmap to file", e); Loading @@ -295,12 +296,14 @@ public class ShortcutBitmapSaver { Slog.d(TAG, "Saved bitmap."); } if (shortcut != null) { if (shortcut.getBitmapPath() == null) { removeIcon(shortcut); mService.postValue(shortcut, si -> { if (si.getBitmapPath() == null) { removeIcon(si); } // Whatever happened, remove this flag. shortcut.clearFlags(ShortcutInfo.FLAG_ICON_FILE_PENDING_SAVE); si.clearFlags(ShortcutInfo.FLAG_ICON_FILE_PENDING_SAVE); }); } } return true; Loading services/core/java/com/android/server/pm/ShortcutPackage.java +120 −61 Original line number Diff line number Diff line Loading @@ -223,12 +223,14 @@ class ShortcutPackage extends ShortcutPackageItem { // - Disable if needed. for (int i = mShortcuts.size() - 1; i >= 0; i--) { ShortcutInfo si = mShortcuts.valueAt(i); si.clearFlags(ShortcutInfo.FLAG_SHADOW); mutateShortcut(si.getId(), si, shortcut -> { shortcut.clearFlags(ShortcutInfo.FLAG_SHADOW); si.setDisabledReason(restoreBlockReason); shortcut.setDisabledReason(restoreBlockReason); if (restoreBlockReason != ShortcutInfo.DISABLED_REASON_NOT_DISABLED) { si.addFlags(ShortcutInfo.FLAG_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. Loading Loading @@ -460,9 +462,11 @@ class ShortcutPackage extends ShortcutPackageItem { if (si.isDynamic() && (!ignoreInvisible || si.isVisibleToPublisher())) { changed = true; si.setTimestamp(now); si.clearFlags(ShortcutInfo.FLAG_DYNAMIC); si.setRank(0); // It may still be pinned, so clear the rank. 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. }); } } if (changed) { Loading Loading @@ -506,7 +510,7 @@ class ShortcutPackage extends ShortcutPackageItem { public ShortcutInfo deleteLongLivedWithId(@NonNull String shortcutId, boolean ignoreInvisible) { final ShortcutInfo shortcut = mShortcuts.get(shortcutId); if (shortcut != null) { shortcut.clearFlags(ShortcutInfo.FLAG_CACHED_ALL); mutateShortcut(shortcutId, null, si -> si.clearFlags(ShortcutInfo.FLAG_CACHED_ALL)); } return deleteOrDisableWithId( shortcutId, /* disable =*/ false, /* overrideImmutable=*/ false, ignoreInvisible, Loading @@ -527,7 +531,7 @@ class ShortcutPackage extends ShortcutPackageItem { overrideImmutable, ignoreInvisible, disabledReason); // If disabled id still exists, it is pinned and we need to update the disabled message. final ShortcutInfo disabled = mShortcuts.get(shortcutId); mutateShortcut(shortcutId, null, disabled -> { if (disabled != null) { if (disabledMessage != null) { disabled.setDisabledMessage(disabledMessage); Loading @@ -536,6 +540,7 @@ class ShortcutPackage extends ShortcutPackageItem { mShortcutUser.mService.fixUpShortcutResourceNamesAndValues(disabled); } } }); return deleted; } Loading @@ -557,21 +562,23 @@ class ShortcutPackage extends ShortcutPackageItem { } if (oldShortcut.isPinned() || oldShortcut.isCached()) { oldShortcut.setRank(0); oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_MANIFEST); mutateShortcut(oldShortcut.getId(), oldShortcut, si -> { si.setRank(0); si.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_MANIFEST); if (disable) { oldShortcut.addFlags(ShortcutInfo.FLAG_DISABLED); si.addFlags(ShortcutInfo.FLAG_DISABLED); // Do not overwrite the disabled reason if one is alreay set. if (oldShortcut.getDisabledReason() == ShortcutInfo.DISABLED_REASON_NOT_DISABLED) { oldShortcut.setDisabledReason(disabledReason); if (si.getDisabledReason() == ShortcutInfo.DISABLED_REASON_NOT_DISABLED) { si.setDisabledReason(disabledReason); } } oldShortcut.setTimestamp(mShortcutUser.mService.injectCurrentTimeMillis()); si.setTimestamp(mShortcutUser.mService.injectCurrentTimeMillis()); // See ShortcutRequestPinProcessor.directPinShortcut(). if (mShortcutUser.mService.isDummyMainActivity(oldShortcut.getActivity())) { oldShortcut.setActivity(null); if (mShortcutUser.mService.isDummyMainActivity(si.getActivity())) { si.setActivity(null); } }); return null; } else { Loading @@ -581,12 +588,11 @@ class ShortcutPackage extends ShortcutPackageItem { } public void enableWithId(@NonNull String shortcutId) { final ShortcutInfo shortcut = mShortcuts.get(shortcutId); if (shortcut != null) { ensureNotImmutable(shortcut, /*ignoreInvisible=*/ true); shortcut.clearFlags(ShortcutInfo.FLAG_DISABLED); shortcut.setDisabledReason(ShortcutInfo.DISABLED_REASON_NOT_DISABLED); } mutateShortcut(shortcutId, null, si -> { ensureNotImmutable(si, /*ignoreInvisible=*/ true); si.clearFlags(ShortcutInfo.FLAG_DISABLED); si.setDisabledReason(ShortcutInfo.DISABLED_REASON_NOT_DISABLED); }); } public void updateInvisibleShortcutForPinRequestWith(@NonNull ShortcutInfo shortcut) { Loading @@ -609,22 +615,25 @@ class ShortcutPackage extends ShortcutPackageItem { * <p>Then remove all shortcuts that are not dynamic and no longer pinned either. */ public void refreshPinnedFlags() { // First, un-pin all shortcuts for (int i = mShortcuts.size() - 1; i >= 0; i--) { mShortcuts.valueAt(i).clearFlags(ShortcutInfo.FLAG_PINNED); // TODO: rewrite this function with proper query (i.e. fetch only pinned shortcuts and // unpin if it's no longer pinned by any launcher and vice versa) 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<>(); // Then, for the pinned set for each launcher, set the pin flag one by one. // First, for the pinned set for each launcher, keep track of their id one by one. mShortcutUser.forAllLaunchers(launcherShortcuts -> { final ArraySet<String> pinned = launcherShortcuts.getPinnedShortcutIds( getPackageName(), getPackageUserId()); if (pinned == null || pinned.size() == 0) { return; } for (int i = pinned.size() - 1; i >= 0; i--) { final String id = pinned.valueAt(i); final ShortcutInfo si = mShortcuts.get(id); 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. Loading @@ -632,9 +641,21 @@ class ShortcutPackage extends ShortcutPackageItem { // That's fine, when the launcher is restored, we'll fix it. continue; } si.addFlags(ShortcutInfo.FLAG_PINNED); pinnedShortcuts.add(si.getId()); } }); // Then, update the pinned state if necessary for (int i = shortcuts.size() - 1; i >= 0; i--) { final ShortcutInfo si = shortcuts.get(i); if (pinnedShortcuts.contains(si.getId()) && !si.isPinned()) { mutateShortcut(si.getId(), si, shortcut -> shortcut.addFlags(ShortcutInfo.FLAG_PINNED)); } if (!pinnedShortcuts.contains(si.getId()) && si.isPinned()) { mutateShortcut(si.getId(), si, shortcut -> shortcut.clearFlags(ShortcutInfo.FLAG_PINNED)); } } // Lastly, remove the ones that are no longer pinned, cached nor dynamic. removeOrphans(); Loading Loading @@ -1034,8 +1055,10 @@ class ShortcutPackage extends ShortcutPackageItem { continue; } Slog.i(TAG, String.format("Restoring shortcut: %s", si.getId())); si.clearFlags(ShortcutInfo.FLAG_DISABLED); si.setDisabledReason(ShortcutInfo.DISABLED_REASON_NOT_DISABLED); 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. Loading Loading @@ -1065,7 +1088,6 @@ class ShortcutPackage extends ShortcutPackageItem { } if (si.hasAnyResources()) { if (!si.isOriginallyFromManifest()) { if (publisherRes == null) { publisherRes = getPackageResources(); if (publisherRes == null) { Loading @@ -1073,13 +1095,17 @@ class ShortcutPackage extends ShortcutPackageItem { } } // TODO: update resource strings in AppSearch 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.lookupAndFillInResourceIds(publisherRes); } si.setTimestamp(s.injectCurrentTimeMillis()); shortcut.setTimestamp(s.injectCurrentTimeMillis()); }); } } } Loading Loading @@ -1382,8 +1408,11 @@ class ShortcutPackage extends ShortcutPackageItem { } } si.resolveResourceStrings(publisherRes); si.setTimestamp(s.injectCurrentTimeMillis()); final Resources res = publisherRes; mutateShortcut(si.getId(), si, shortcut -> { shortcut.resolveResourceStrings(res); shortcut.setTimestamp(s.injectCurrentTimeMillis()); }); if (changedShortcuts == null) { changedShortcuts = new ArrayList<>(1); Loading @@ -1400,7 +1429,7 @@ class ShortcutPackage extends ShortcutPackageItem { public void clearAllImplicitRanks() { for (int i = mShortcuts.size() - 1; i >= 0; i--) { final ShortcutInfo si = mShortcuts.valueAt(i); si.clearImplicitRankAndRankChangedFlag(); mutateShortcut(si.getId(), si, ShortcutInfo::clearImplicitRankAndRankChangedFlag); } } Loading Loading @@ -1445,8 +1474,10 @@ class ShortcutPackage extends ShortcutPackageItem { final ShortcutInfo si = mShortcuts.valueAt(i); if (si.isFloating()) { if (si.getRank() != 0) { si.setTimestamp(now); si.setRank(0); mutateShortcut(si.getId(), si, shortcut -> { shortcut.setTimestamp(now); shortcut.setRank(0); }); } } } Loading Loading @@ -1479,8 +1510,10 @@ class ShortcutPackage extends ShortcutPackageItem { } final int thisRank = rank++; if (si.getRank() != thisRank) { si.setTimestamp(now); si.setRank(thisRank); mutateShortcut(si.getId(), si, shortcut -> { shortcut.setTimestamp(now); shortcut.setRank(thisRank); }); } } } Loading Loading @@ -2172,6 +2205,32 @@ class ShortcutPackage extends ShortcutPackageItem { resetAppSearch(null); } void mutateShortcut(@NonNull final String id, @Nullable final ShortcutInfo shortcut, @NonNull final Consumer<ShortcutInfo> transform) { Objects.requireNonNull(id); Objects.requireNonNull(transform); synchronized (mLock) { if (shortcut != null) { transform.accept(shortcut); } else { transform.accept(findShortcutById(id)); } // TODO: Load ShortcutInfo from AppSearch, apply transformation logic and save } } /** * Removes shortcuts from AppSearch. */ void removeShortcuts() { } /** * Merge/replace shortcuts parsed from xml file. */ void restoreParsedShortcuts(final boolean replace) { } private boolean verifyRanksSequential(List<ShortcutInfo> list) { boolean failed = false; Loading services/core/java/com/android/server/pm/ShortcutService.java +52 −45 Original line number Diff line number Diff line Loading @@ -1179,6 +1179,14 @@ public class ShortcutService extends IShortcutService.Stub { } } void postValue(@NonNull final ShortcutInfo shortcutInfo, @NonNull final Consumer<ShortcutInfo> cb) { final String pkg = shortcutInfo.getPackage(); final int userId = shortcutInfo.getUserId(); final String id = shortcutInfo.getId(); getPackageShortcutsLocked(pkg, userId).mutateShortcut(id, shortcutInfo, cb); } /** Return the last reset time. */ @GuardedBy("mLock") long getLastResetTimeLocked() { Loading Loading @@ -1566,7 +1574,6 @@ public class ShortcutService extends IShortcutService.Stub { * resource-based strings. */ void fixUpShortcutResourceNamesAndValues(ShortcutInfo si) { // TODO: update resource names in AppSearch final Resources publisherRes = injectGetResourcesForApplicationAsUser( si.getPackage(), si.getUserId()); if (publisherRes != null) { Loading Loading @@ -1947,7 +1954,7 @@ public class ShortcutService extends IShortcutService.Stub { final boolean unlimited = injectHasUnlimitedShortcutsApiCallsPermission( injectBinderCallingPid(), injectBinderCallingUid()); List<ShortcutInfo> changedShortcuts = null; final List<ShortcutInfo> changedShortcuts = new ArrayList<>(1); synchronized (mLock) { throwIfUserLockedL(userId); Loading Loading @@ -1975,11 +1982,10 @@ public class ShortcutService extends IShortcutService.Stub { final ShortcutInfo source = newShortcuts.get(i); fixUpIncomingShortcutInfo(source, /* forUpdate= */ true); final ShortcutInfo target = ps.findShortcutById(source.getId()); ps.mutateShortcut(source.getId(), null, target -> { // Invisible shortcuts can't be updated. if (target == null || !target.isVisibleToPublisher()) { continue; return; } if (target.isEnabled() != source.isEnabled()) { Loading Loading @@ -2018,16 +2024,15 @@ public class ShortcutService extends IShortcutService.Stub { fixUpShortcutResourceNamesAndValues(target); } if (changedShortcuts == null) { changedShortcuts = new ArrayList<>(1); } changedShortcuts.add(target); }); } // Lastly, adjust the ranks. ps.adjustRanks(); } packageShortcutsChanged(packageName, userId, changedShortcuts, null); packageShortcutsChanged(packageName, userId, changedShortcuts.isEmpty() ? null : changedShortcuts, null); verifyStates(); Loading Loading @@ -3114,7 +3119,8 @@ public class ShortcutService extends IShortcutService.Stub { if (doCache) { if (si.isLongLived()) { si.addFlags(cacheFlags); sp.mutateShortcut(si.getId(), si, shortcut -> shortcut.addFlags(cacheFlags)); if (changedShortcuts == null) { changedShortcuts = new ArrayList<>(1); } Loading @@ -3125,7 +3131,8 @@ public class ShortcutService extends IShortcutService.Stub { } } else { ShortcutInfo removed = null; si.clearFlags(cacheFlags); sp.mutateShortcut(si.getId(), si, shortcut -> shortcut.clearFlags(cacheFlags)); if (!si.isDynamic() && !si.isCached()) { removed = sp.deleteLongLivedWithId(id, /*ignoreInvisible=*/ true); } Loading services/core/java/com/android/server/pm/ShortcutUser.java +10 −1 Original line number Diff line number Diff line Loading @@ -185,6 +185,9 @@ class ShortcutUser { public ShortcutPackage removePackage(@NonNull String packageName) { final ShortcutPackage removed = mPackages.remove(packageName); if (removed != null) { removed.removeShortcuts(); } mService.cleanupBitmapsForPackage(mUserId, packageName); return removed; Loading Loading @@ -330,7 +333,10 @@ class ShortcutUser { if (!shortcutPackage.rescanPackageIfNeeded(isNewApp, forceRescan)) { if (isNewApp) { mPackages.remove(packageName); final ShortcutPackage sp = mPackages.remove(packageName); if (sp != null) { sp.removeShortcuts(); } } } } Loading Loading @@ -454,6 +460,7 @@ class ShortcutUser { case ShortcutPackage.TAG_ROOT: { final ShortcutPackage shortcuts = ShortcutPackage.loadFromXml( s, ret, parser, fromBackup); shortcuts.restoreParsedShortcuts(false); // Don't use addShortcut(), we don't need to save the icon. ret.mPackages.put(shortcuts.getPackageName(), shortcuts); Loading Loading @@ -488,6 +495,7 @@ class ShortcutUser { final ShortcutPackage sp = ShortcutPackage.loadFromFile(s, ret, f, fromBackup); if (sp != null) { ret.mPackages.put(sp.getPackageName(), sp); sp.restoreParsedShortcuts(false); } }); Loading Loading @@ -570,6 +578,7 @@ class ShortcutUser { Log.w(TAG, "Shortcuts for package " + sp.getPackageName() + " are being restored." + " Existing non-manifeset shortcuts will be overwritten."); } sp.restoreParsedShortcuts(true); addPackage(sp); restoredPackages[0]++; restoredShortcuts[0] += sp.getShortcutCount(); Loading Loading
services/core/java/com/android/server/pm/ShortcutBitmapSaver.java +9 −6 Original line number Diff line number Diff line Loading @@ -280,7 +280,8 @@ public class ShortcutBitmapSaver { IoUtils.closeQuietly(out); } shortcut.setBitmapPath(file.getAbsolutePath()); final String path = file.getAbsolutePath(); mService.postValue(shortcut, si -> si.setBitmapPath(path)); } catch (IOException | RuntimeException e) { Slog.e(ShortcutService.TAG, "Unable to write bitmap to file", e); Loading @@ -295,12 +296,14 @@ public class ShortcutBitmapSaver { Slog.d(TAG, "Saved bitmap."); } if (shortcut != null) { if (shortcut.getBitmapPath() == null) { removeIcon(shortcut); mService.postValue(shortcut, si -> { if (si.getBitmapPath() == null) { removeIcon(si); } // Whatever happened, remove this flag. shortcut.clearFlags(ShortcutInfo.FLAG_ICON_FILE_PENDING_SAVE); si.clearFlags(ShortcutInfo.FLAG_ICON_FILE_PENDING_SAVE); }); } } return true; Loading
services/core/java/com/android/server/pm/ShortcutPackage.java +120 −61 Original line number Diff line number Diff line Loading @@ -223,12 +223,14 @@ class ShortcutPackage extends ShortcutPackageItem { // - Disable if needed. for (int i = mShortcuts.size() - 1; i >= 0; i--) { ShortcutInfo si = mShortcuts.valueAt(i); si.clearFlags(ShortcutInfo.FLAG_SHADOW); mutateShortcut(si.getId(), si, shortcut -> { shortcut.clearFlags(ShortcutInfo.FLAG_SHADOW); si.setDisabledReason(restoreBlockReason); shortcut.setDisabledReason(restoreBlockReason); if (restoreBlockReason != ShortcutInfo.DISABLED_REASON_NOT_DISABLED) { si.addFlags(ShortcutInfo.FLAG_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. Loading Loading @@ -460,9 +462,11 @@ class ShortcutPackage extends ShortcutPackageItem { if (si.isDynamic() && (!ignoreInvisible || si.isVisibleToPublisher())) { changed = true; si.setTimestamp(now); si.clearFlags(ShortcutInfo.FLAG_DYNAMIC); si.setRank(0); // It may still be pinned, so clear the rank. 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. }); } } if (changed) { Loading Loading @@ -506,7 +510,7 @@ class ShortcutPackage extends ShortcutPackageItem { public ShortcutInfo deleteLongLivedWithId(@NonNull String shortcutId, boolean ignoreInvisible) { final ShortcutInfo shortcut = mShortcuts.get(shortcutId); if (shortcut != null) { shortcut.clearFlags(ShortcutInfo.FLAG_CACHED_ALL); mutateShortcut(shortcutId, null, si -> si.clearFlags(ShortcutInfo.FLAG_CACHED_ALL)); } return deleteOrDisableWithId( shortcutId, /* disable =*/ false, /* overrideImmutable=*/ false, ignoreInvisible, Loading @@ -527,7 +531,7 @@ class ShortcutPackage extends ShortcutPackageItem { overrideImmutable, ignoreInvisible, disabledReason); // If disabled id still exists, it is pinned and we need to update the disabled message. final ShortcutInfo disabled = mShortcuts.get(shortcutId); mutateShortcut(shortcutId, null, disabled -> { if (disabled != null) { if (disabledMessage != null) { disabled.setDisabledMessage(disabledMessage); Loading @@ -536,6 +540,7 @@ class ShortcutPackage extends ShortcutPackageItem { mShortcutUser.mService.fixUpShortcutResourceNamesAndValues(disabled); } } }); return deleted; } Loading @@ -557,21 +562,23 @@ class ShortcutPackage extends ShortcutPackageItem { } if (oldShortcut.isPinned() || oldShortcut.isCached()) { oldShortcut.setRank(0); oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_MANIFEST); mutateShortcut(oldShortcut.getId(), oldShortcut, si -> { si.setRank(0); si.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_MANIFEST); if (disable) { oldShortcut.addFlags(ShortcutInfo.FLAG_DISABLED); si.addFlags(ShortcutInfo.FLAG_DISABLED); // Do not overwrite the disabled reason if one is alreay set. if (oldShortcut.getDisabledReason() == ShortcutInfo.DISABLED_REASON_NOT_DISABLED) { oldShortcut.setDisabledReason(disabledReason); if (si.getDisabledReason() == ShortcutInfo.DISABLED_REASON_NOT_DISABLED) { si.setDisabledReason(disabledReason); } } oldShortcut.setTimestamp(mShortcutUser.mService.injectCurrentTimeMillis()); si.setTimestamp(mShortcutUser.mService.injectCurrentTimeMillis()); // See ShortcutRequestPinProcessor.directPinShortcut(). if (mShortcutUser.mService.isDummyMainActivity(oldShortcut.getActivity())) { oldShortcut.setActivity(null); if (mShortcutUser.mService.isDummyMainActivity(si.getActivity())) { si.setActivity(null); } }); return null; } else { Loading @@ -581,12 +588,11 @@ class ShortcutPackage extends ShortcutPackageItem { } public void enableWithId(@NonNull String shortcutId) { final ShortcutInfo shortcut = mShortcuts.get(shortcutId); if (shortcut != null) { ensureNotImmutable(shortcut, /*ignoreInvisible=*/ true); shortcut.clearFlags(ShortcutInfo.FLAG_DISABLED); shortcut.setDisabledReason(ShortcutInfo.DISABLED_REASON_NOT_DISABLED); } mutateShortcut(shortcutId, null, si -> { ensureNotImmutable(si, /*ignoreInvisible=*/ true); si.clearFlags(ShortcutInfo.FLAG_DISABLED); si.setDisabledReason(ShortcutInfo.DISABLED_REASON_NOT_DISABLED); }); } public void updateInvisibleShortcutForPinRequestWith(@NonNull ShortcutInfo shortcut) { Loading @@ -609,22 +615,25 @@ class ShortcutPackage extends ShortcutPackageItem { * <p>Then remove all shortcuts that are not dynamic and no longer pinned either. */ public void refreshPinnedFlags() { // First, un-pin all shortcuts for (int i = mShortcuts.size() - 1; i >= 0; i--) { mShortcuts.valueAt(i).clearFlags(ShortcutInfo.FLAG_PINNED); // TODO: rewrite this function with proper query (i.e. fetch only pinned shortcuts and // unpin if it's no longer pinned by any launcher and vice versa) 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<>(); // Then, for the pinned set for each launcher, set the pin flag one by one. // First, for the pinned set for each launcher, keep track of their id one by one. mShortcutUser.forAllLaunchers(launcherShortcuts -> { final ArraySet<String> pinned = launcherShortcuts.getPinnedShortcutIds( getPackageName(), getPackageUserId()); if (pinned == null || pinned.size() == 0) { return; } for (int i = pinned.size() - 1; i >= 0; i--) { final String id = pinned.valueAt(i); final ShortcutInfo si = mShortcuts.get(id); 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. Loading @@ -632,9 +641,21 @@ class ShortcutPackage extends ShortcutPackageItem { // That's fine, when the launcher is restored, we'll fix it. continue; } si.addFlags(ShortcutInfo.FLAG_PINNED); pinnedShortcuts.add(si.getId()); } }); // Then, update the pinned state if necessary for (int i = shortcuts.size() - 1; i >= 0; i--) { final ShortcutInfo si = shortcuts.get(i); if (pinnedShortcuts.contains(si.getId()) && !si.isPinned()) { mutateShortcut(si.getId(), si, shortcut -> shortcut.addFlags(ShortcutInfo.FLAG_PINNED)); } if (!pinnedShortcuts.contains(si.getId()) && si.isPinned()) { mutateShortcut(si.getId(), si, shortcut -> shortcut.clearFlags(ShortcutInfo.FLAG_PINNED)); } } // Lastly, remove the ones that are no longer pinned, cached nor dynamic. removeOrphans(); Loading Loading @@ -1034,8 +1055,10 @@ class ShortcutPackage extends ShortcutPackageItem { continue; } Slog.i(TAG, String.format("Restoring shortcut: %s", si.getId())); si.clearFlags(ShortcutInfo.FLAG_DISABLED); si.setDisabledReason(ShortcutInfo.DISABLED_REASON_NOT_DISABLED); 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. Loading Loading @@ -1065,7 +1088,6 @@ class ShortcutPackage extends ShortcutPackageItem { } if (si.hasAnyResources()) { if (!si.isOriginallyFromManifest()) { if (publisherRes == null) { publisherRes = getPackageResources(); if (publisherRes == null) { Loading @@ -1073,13 +1095,17 @@ class ShortcutPackage extends ShortcutPackageItem { } } // TODO: update resource strings in AppSearch 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.lookupAndFillInResourceIds(publisherRes); } si.setTimestamp(s.injectCurrentTimeMillis()); shortcut.setTimestamp(s.injectCurrentTimeMillis()); }); } } } Loading Loading @@ -1382,8 +1408,11 @@ class ShortcutPackage extends ShortcutPackageItem { } } si.resolveResourceStrings(publisherRes); si.setTimestamp(s.injectCurrentTimeMillis()); final Resources res = publisherRes; mutateShortcut(si.getId(), si, shortcut -> { shortcut.resolveResourceStrings(res); shortcut.setTimestamp(s.injectCurrentTimeMillis()); }); if (changedShortcuts == null) { changedShortcuts = new ArrayList<>(1); Loading @@ -1400,7 +1429,7 @@ class ShortcutPackage extends ShortcutPackageItem { public void clearAllImplicitRanks() { for (int i = mShortcuts.size() - 1; i >= 0; i--) { final ShortcutInfo si = mShortcuts.valueAt(i); si.clearImplicitRankAndRankChangedFlag(); mutateShortcut(si.getId(), si, ShortcutInfo::clearImplicitRankAndRankChangedFlag); } } Loading Loading @@ -1445,8 +1474,10 @@ class ShortcutPackage extends ShortcutPackageItem { final ShortcutInfo si = mShortcuts.valueAt(i); if (si.isFloating()) { if (si.getRank() != 0) { si.setTimestamp(now); si.setRank(0); mutateShortcut(si.getId(), si, shortcut -> { shortcut.setTimestamp(now); shortcut.setRank(0); }); } } } Loading Loading @@ -1479,8 +1510,10 @@ class ShortcutPackage extends ShortcutPackageItem { } final int thisRank = rank++; if (si.getRank() != thisRank) { si.setTimestamp(now); si.setRank(thisRank); mutateShortcut(si.getId(), si, shortcut -> { shortcut.setTimestamp(now); shortcut.setRank(thisRank); }); } } } Loading Loading @@ -2172,6 +2205,32 @@ class ShortcutPackage extends ShortcutPackageItem { resetAppSearch(null); } void mutateShortcut(@NonNull final String id, @Nullable final ShortcutInfo shortcut, @NonNull final Consumer<ShortcutInfo> transform) { Objects.requireNonNull(id); Objects.requireNonNull(transform); synchronized (mLock) { if (shortcut != null) { transform.accept(shortcut); } else { transform.accept(findShortcutById(id)); } // TODO: Load ShortcutInfo from AppSearch, apply transformation logic and save } } /** * Removes shortcuts from AppSearch. */ void removeShortcuts() { } /** * Merge/replace shortcuts parsed from xml file. */ void restoreParsedShortcuts(final boolean replace) { } private boolean verifyRanksSequential(List<ShortcutInfo> list) { boolean failed = false; Loading
services/core/java/com/android/server/pm/ShortcutService.java +52 −45 Original line number Diff line number Diff line Loading @@ -1179,6 +1179,14 @@ public class ShortcutService extends IShortcutService.Stub { } } void postValue(@NonNull final ShortcutInfo shortcutInfo, @NonNull final Consumer<ShortcutInfo> cb) { final String pkg = shortcutInfo.getPackage(); final int userId = shortcutInfo.getUserId(); final String id = shortcutInfo.getId(); getPackageShortcutsLocked(pkg, userId).mutateShortcut(id, shortcutInfo, cb); } /** Return the last reset time. */ @GuardedBy("mLock") long getLastResetTimeLocked() { Loading Loading @@ -1566,7 +1574,6 @@ public class ShortcutService extends IShortcutService.Stub { * resource-based strings. */ void fixUpShortcutResourceNamesAndValues(ShortcutInfo si) { // TODO: update resource names in AppSearch final Resources publisherRes = injectGetResourcesForApplicationAsUser( si.getPackage(), si.getUserId()); if (publisherRes != null) { Loading Loading @@ -1947,7 +1954,7 @@ public class ShortcutService extends IShortcutService.Stub { final boolean unlimited = injectHasUnlimitedShortcutsApiCallsPermission( injectBinderCallingPid(), injectBinderCallingUid()); List<ShortcutInfo> changedShortcuts = null; final List<ShortcutInfo> changedShortcuts = new ArrayList<>(1); synchronized (mLock) { throwIfUserLockedL(userId); Loading Loading @@ -1975,11 +1982,10 @@ public class ShortcutService extends IShortcutService.Stub { final ShortcutInfo source = newShortcuts.get(i); fixUpIncomingShortcutInfo(source, /* forUpdate= */ true); final ShortcutInfo target = ps.findShortcutById(source.getId()); ps.mutateShortcut(source.getId(), null, target -> { // Invisible shortcuts can't be updated. if (target == null || !target.isVisibleToPublisher()) { continue; return; } if (target.isEnabled() != source.isEnabled()) { Loading Loading @@ -2018,16 +2024,15 @@ public class ShortcutService extends IShortcutService.Stub { fixUpShortcutResourceNamesAndValues(target); } if (changedShortcuts == null) { changedShortcuts = new ArrayList<>(1); } changedShortcuts.add(target); }); } // Lastly, adjust the ranks. ps.adjustRanks(); } packageShortcutsChanged(packageName, userId, changedShortcuts, null); packageShortcutsChanged(packageName, userId, changedShortcuts.isEmpty() ? null : changedShortcuts, null); verifyStates(); Loading Loading @@ -3114,7 +3119,8 @@ public class ShortcutService extends IShortcutService.Stub { if (doCache) { if (si.isLongLived()) { si.addFlags(cacheFlags); sp.mutateShortcut(si.getId(), si, shortcut -> shortcut.addFlags(cacheFlags)); if (changedShortcuts == null) { changedShortcuts = new ArrayList<>(1); } Loading @@ -3125,7 +3131,8 @@ public class ShortcutService extends IShortcutService.Stub { } } else { ShortcutInfo removed = null; si.clearFlags(cacheFlags); sp.mutateShortcut(si.getId(), si, shortcut -> shortcut.clearFlags(cacheFlags)); if (!si.isDynamic() && !si.isCached()) { removed = sp.deleteLongLivedWithId(id, /*ignoreInvisible=*/ true); } Loading
services/core/java/com/android/server/pm/ShortcutUser.java +10 −1 Original line number Diff line number Diff line Loading @@ -185,6 +185,9 @@ class ShortcutUser { public ShortcutPackage removePackage(@NonNull String packageName) { final ShortcutPackage removed = mPackages.remove(packageName); if (removed != null) { removed.removeShortcuts(); } mService.cleanupBitmapsForPackage(mUserId, packageName); return removed; Loading Loading @@ -330,7 +333,10 @@ class ShortcutUser { if (!shortcutPackage.rescanPackageIfNeeded(isNewApp, forceRescan)) { if (isNewApp) { mPackages.remove(packageName); final ShortcutPackage sp = mPackages.remove(packageName); if (sp != null) { sp.removeShortcuts(); } } } } Loading Loading @@ -454,6 +460,7 @@ class ShortcutUser { case ShortcutPackage.TAG_ROOT: { final ShortcutPackage shortcuts = ShortcutPackage.loadFromXml( s, ret, parser, fromBackup); shortcuts.restoreParsedShortcuts(false); // Don't use addShortcut(), we don't need to save the icon. ret.mPackages.put(shortcuts.getPackageName(), shortcuts); Loading Loading @@ -488,6 +495,7 @@ class ShortcutUser { final ShortcutPackage sp = ShortcutPackage.loadFromFile(s, ret, f, fromBackup); if (sp != null) { ret.mPackages.put(sp.getPackageName(), sp); sp.restoreParsedShortcuts(false); } }); Loading Loading @@ -570,6 +578,7 @@ class ShortcutUser { Log.w(TAG, "Shortcuts for package " + sp.getPackageName() + " are being restored." + " Existing non-manifeset shortcuts will be overwritten."); } sp.restoreParsedShortcuts(true); addPackage(sp); restoredPackages[0]++; restoredShortcuts[0] += sp.getShortcutCount(); Loading