Loading services/core/java/com/android/server/pm/ShortcutLauncher.java +69 −38 Original line number Diff line number Diff line Loading @@ -26,7 +26,7 @@ import android.util.ArraySet; import android.util.Slog; import android.util.Xml; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.GuardedBy; import com.android.modules.utils.TypedXmlPullParser; import com.android.modules.utils.TypedXmlSerializer; import com.android.server.pm.ShortcutService.DumpFilter; Loading Loading @@ -66,6 +66,7 @@ class ShortcutLauncher extends ShortcutPackageItem { /** * Package name -> IDs. */ @GuardedBy("mLock") private final ArrayMap<UserPackage, ArraySet<String>> mPinnedShortcuts = new ArrayMap<>(); private ShortcutLauncher(@NonNull ShortcutUser shortcutUser, Loading Loading @@ -97,9 +98,11 @@ class ShortcutLauncher extends ShortcutPackageItem { * Called when the new package can't receive the backup, due to signature or version mismatch. */ private void onRestoreBlocked() { final ArrayList<UserPackage> pinnedPackages = new ArrayList<>(mPinnedShortcuts.keySet()); final ArrayList<UserPackage> pinnedPackages; synchronized (mLock) { pinnedPackages = new ArrayList<>(mPinnedShortcuts.keySet()); mPinnedShortcuts.clear(); } for (int i = pinnedPackages.size() - 1; i >= 0; i--) { final UserPackage up = pinnedPackages.get(i); final ShortcutPackage p = mShortcutUser.getPackageShortcutsIfExists(up.packageName); Loading Loading @@ -135,17 +138,17 @@ class ShortcutLauncher extends ShortcutPackageItem { final int idSize = ids.size(); if (idSize == 0) { synchronized (mLock) { mPinnedShortcuts.remove(up); } } else { final ArraySet<String> prevSet = mPinnedShortcuts.get(up); // Actually pin shortcuts. // This logic here is to make sure a launcher cannot pin a shortcut that is not dynamic // nor long-lived nor manifest but is pinned. // In this case, technically the shortcut doesn't exist to this launcher, so it can't // pin it. // This logic here is to make sure a launcher cannot pin a shortcut that is not // dynamic nor long-lived nor manifest but is pinned. // In this case, technically the shortcut doesn't exist to this launcher, so it // can't pin it. // (Maybe unnecessarily strict...) final ArraySet<String> floatingSet = new ArraySet<>(); final ArraySet<String> newSet = new ArraySet<>(); for (int i = 0; i < idSize; i++) { Loading @@ -156,13 +159,25 @@ class ShortcutLauncher extends ShortcutPackageItem { } if (si.isDynamic() || si.isLongLived() || si.isManifestShortcut() || (prevSet != null && prevSet.contains(id)) || forPinRequest) { newSet.add(id); } else { floatingSet.add(id); } } synchronized (mLock) { final ArraySet<String> prevSet = mPinnedShortcuts.get(up); if (prevSet != null) { for (String id : floatingSet) { if (prevSet.contains(id)) { newSet.add(id); } } } mPinnedShortcuts.put(up, newSet); } } packageShortcuts.refreshPinnedFlags(); } Loading @@ -172,39 +187,50 @@ class ShortcutLauncher extends ShortcutPackageItem { @Nullable public ArraySet<String> getPinnedShortcutIds(@NonNull String packageName, @UserIdInt int packageUserId) { return mPinnedShortcuts.get(UserPackage.of(packageUserId, packageName)); synchronized (mLock) { final ArraySet<String> pinnedShortcuts = mPinnedShortcuts.get( UserPackage.of(packageUserId, packageName)); return pinnedShortcuts == null ? null : new ArraySet<>(pinnedShortcuts); } } /** * Return true if the given shortcut is pinned by this launcher.<code></code> */ public boolean hasPinned(ShortcutInfo shortcut) { final ArraySet<String> pinned = getPinnedShortcutIds(shortcut.getPackage(), shortcut.getUserId()); synchronized (mLock) { final ArraySet<String> pinned = mPinnedShortcuts.get( UserPackage.of(shortcut.getUserId(), shortcut.getPackage())); return (pinned != null) && pinned.contains(shortcut.getId()); } } /** * Additionally pin a shortcut. c.f. {@link #pinShortcuts(int, String, List, boolean)} */ public void addPinnedShortcut(@NonNull String packageName, @UserIdInt int packageUserId, String id, boolean forPinRequest) { final ArraySet<String> pinnedSet = getPinnedShortcutIds(packageName, packageUserId); final ArrayList<String> pinnedList; synchronized (mLock) { final ArraySet<String> pinnedSet = mPinnedShortcuts.get( UserPackage.of(packageUserId, packageName)); if (pinnedSet != null) { pinnedList = new ArrayList<>(pinnedSet.size() + 1); pinnedList.addAll(pinnedSet); } else { pinnedList = new ArrayList<>(1); } } pinnedList.add(id); pinShortcuts(packageUserId, packageName, pinnedList, forPinRequest); } boolean cleanUpPackage(String packageName, @UserIdInt int packageUserId) { synchronized (mLock) { return mPinnedShortcuts.remove(UserPackage.of(packageUserId, packageName)) != null; } } public void ensurePackageInfo() { final PackageInfo pi = mShortcutUser.mService.getPackageInfoWithSignatures( Loading @@ -226,7 +252,11 @@ class ShortcutLauncher extends ShortcutPackageItem { // If an launcher app doesn't support backup&restore, then nothing to do. return; } final int size = mPinnedShortcuts.size(); final ArrayMap<UserPackage, ArraySet<String>> pinnedShortcuts; synchronized (mLock) { pinnedShortcuts = new ArrayMap<>(mPinnedShortcuts); } final int size = pinnedShortcuts.size(); if (size == 0) { return; // Nothing to write. } Loading @@ -237,7 +267,7 @@ class ShortcutLauncher extends ShortcutPackageItem { getPackageInfo().saveToXml(mShortcutUser.mService, out, forBackup); for (int i = 0; i < size; i++) { final UserPackage up = mPinnedShortcuts.keyAt(i); final UserPackage up = pinnedShortcuts.keyAt(i); if (forBackup && (up.userId != getOwnerUserId())) { continue; // Target package on a different user, skip. (i.e. work profile) Loading @@ -247,7 +277,7 @@ class ShortcutLauncher extends ShortcutPackageItem { ShortcutService.writeAttr(out, ATTR_PACKAGE_NAME, up.packageName); ShortcutService.writeAttr(out, ATTR_PACKAGE_USER_ID, up.userId); final ArraySet<String> ids = mPinnedShortcuts.valueAt(i); final ArraySet<String> ids = pinnedShortcuts.valueAt(i); final int idSize = ids.size(); for (int j = 0; j < idSize; j++) { ShortcutService.writeTagValue(out, TAG_PIN, ids.valueAt(j)); Loading Loading @@ -336,8 +366,10 @@ class ShortcutLauncher extends ShortcutPackageItem { : ShortcutService.parseIntAttribute(parser, ATTR_PACKAGE_USER_ID, ownerUserId); ids = new ArraySet<>(); synchronized (ret.mLock) { ret.mPinnedShortcuts.put( UserPackage.of(packageUserId, packageName), ids); } continue; } } Loading Loading @@ -374,11 +406,15 @@ class ShortcutLauncher extends ShortcutPackageItem { getPackageInfo().dump(pw, prefix + " "); pw.println(); final int size = mPinnedShortcuts.size(); final ArrayMap<UserPackage, ArraySet<String>> pinnedShortcuts; synchronized (mLock) { pinnedShortcuts = new ArrayMap<>(mPinnedShortcuts); } final int size = pinnedShortcuts.size(); for (int i = 0; i < size; i++) { pw.println(); final UserPackage up = mPinnedShortcuts.keyAt(i); final UserPackage up = pinnedShortcuts.keyAt(i); pw.print(prefix); pw.print(" "); Loading @@ -387,7 +423,7 @@ class ShortcutLauncher extends ShortcutPackageItem { pw.print(" User: "); pw.println(up.userId); final ArraySet<String> ids = mPinnedShortcuts.valueAt(i); final ArraySet<String> ids = pinnedShortcuts.valueAt(i); final int idSize = ids.size(); for (int j = 0; j < idSize; j++) { Loading @@ -408,11 +444,6 @@ class ShortcutLauncher extends ShortcutPackageItem { return result; } @VisibleForTesting ArraySet<String> getAllPinnedShortcutsForTest(String packageName, int packageUserId) { return new ArraySet<>(mPinnedShortcuts.get(UserPackage.of(packageUserId, packageName))); } @Override protected File getShortcutPackageItemFile() { final File path = new File(mShortcutUser.mService.injectUserDataPath( Loading Loading
services/core/java/com/android/server/pm/ShortcutLauncher.java +69 −38 Original line number Diff line number Diff line Loading @@ -26,7 +26,7 @@ import android.util.ArraySet; import android.util.Slog; import android.util.Xml; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.GuardedBy; import com.android.modules.utils.TypedXmlPullParser; import com.android.modules.utils.TypedXmlSerializer; import com.android.server.pm.ShortcutService.DumpFilter; Loading Loading @@ -66,6 +66,7 @@ class ShortcutLauncher extends ShortcutPackageItem { /** * Package name -> IDs. */ @GuardedBy("mLock") private final ArrayMap<UserPackage, ArraySet<String>> mPinnedShortcuts = new ArrayMap<>(); private ShortcutLauncher(@NonNull ShortcutUser shortcutUser, Loading Loading @@ -97,9 +98,11 @@ class ShortcutLauncher extends ShortcutPackageItem { * Called when the new package can't receive the backup, due to signature or version mismatch. */ private void onRestoreBlocked() { final ArrayList<UserPackage> pinnedPackages = new ArrayList<>(mPinnedShortcuts.keySet()); final ArrayList<UserPackage> pinnedPackages; synchronized (mLock) { pinnedPackages = new ArrayList<>(mPinnedShortcuts.keySet()); mPinnedShortcuts.clear(); } for (int i = pinnedPackages.size() - 1; i >= 0; i--) { final UserPackage up = pinnedPackages.get(i); final ShortcutPackage p = mShortcutUser.getPackageShortcutsIfExists(up.packageName); Loading Loading @@ -135,17 +138,17 @@ class ShortcutLauncher extends ShortcutPackageItem { final int idSize = ids.size(); if (idSize == 0) { synchronized (mLock) { mPinnedShortcuts.remove(up); } } else { final ArraySet<String> prevSet = mPinnedShortcuts.get(up); // Actually pin shortcuts. // This logic here is to make sure a launcher cannot pin a shortcut that is not dynamic // nor long-lived nor manifest but is pinned. // In this case, technically the shortcut doesn't exist to this launcher, so it can't // pin it. // This logic here is to make sure a launcher cannot pin a shortcut that is not // dynamic nor long-lived nor manifest but is pinned. // In this case, technically the shortcut doesn't exist to this launcher, so it // can't pin it. // (Maybe unnecessarily strict...) final ArraySet<String> floatingSet = new ArraySet<>(); final ArraySet<String> newSet = new ArraySet<>(); for (int i = 0; i < idSize; i++) { Loading @@ -156,13 +159,25 @@ class ShortcutLauncher extends ShortcutPackageItem { } if (si.isDynamic() || si.isLongLived() || si.isManifestShortcut() || (prevSet != null && prevSet.contains(id)) || forPinRequest) { newSet.add(id); } else { floatingSet.add(id); } } synchronized (mLock) { final ArraySet<String> prevSet = mPinnedShortcuts.get(up); if (prevSet != null) { for (String id : floatingSet) { if (prevSet.contains(id)) { newSet.add(id); } } } mPinnedShortcuts.put(up, newSet); } } packageShortcuts.refreshPinnedFlags(); } Loading @@ -172,39 +187,50 @@ class ShortcutLauncher extends ShortcutPackageItem { @Nullable public ArraySet<String> getPinnedShortcutIds(@NonNull String packageName, @UserIdInt int packageUserId) { return mPinnedShortcuts.get(UserPackage.of(packageUserId, packageName)); synchronized (mLock) { final ArraySet<String> pinnedShortcuts = mPinnedShortcuts.get( UserPackage.of(packageUserId, packageName)); return pinnedShortcuts == null ? null : new ArraySet<>(pinnedShortcuts); } } /** * Return true if the given shortcut is pinned by this launcher.<code></code> */ public boolean hasPinned(ShortcutInfo shortcut) { final ArraySet<String> pinned = getPinnedShortcutIds(shortcut.getPackage(), shortcut.getUserId()); synchronized (mLock) { final ArraySet<String> pinned = mPinnedShortcuts.get( UserPackage.of(shortcut.getUserId(), shortcut.getPackage())); return (pinned != null) && pinned.contains(shortcut.getId()); } } /** * Additionally pin a shortcut. c.f. {@link #pinShortcuts(int, String, List, boolean)} */ public void addPinnedShortcut(@NonNull String packageName, @UserIdInt int packageUserId, String id, boolean forPinRequest) { final ArraySet<String> pinnedSet = getPinnedShortcutIds(packageName, packageUserId); final ArrayList<String> pinnedList; synchronized (mLock) { final ArraySet<String> pinnedSet = mPinnedShortcuts.get( UserPackage.of(packageUserId, packageName)); if (pinnedSet != null) { pinnedList = new ArrayList<>(pinnedSet.size() + 1); pinnedList.addAll(pinnedSet); } else { pinnedList = new ArrayList<>(1); } } pinnedList.add(id); pinShortcuts(packageUserId, packageName, pinnedList, forPinRequest); } boolean cleanUpPackage(String packageName, @UserIdInt int packageUserId) { synchronized (mLock) { return mPinnedShortcuts.remove(UserPackage.of(packageUserId, packageName)) != null; } } public void ensurePackageInfo() { final PackageInfo pi = mShortcutUser.mService.getPackageInfoWithSignatures( Loading @@ -226,7 +252,11 @@ class ShortcutLauncher extends ShortcutPackageItem { // If an launcher app doesn't support backup&restore, then nothing to do. return; } final int size = mPinnedShortcuts.size(); final ArrayMap<UserPackage, ArraySet<String>> pinnedShortcuts; synchronized (mLock) { pinnedShortcuts = new ArrayMap<>(mPinnedShortcuts); } final int size = pinnedShortcuts.size(); if (size == 0) { return; // Nothing to write. } Loading @@ -237,7 +267,7 @@ class ShortcutLauncher extends ShortcutPackageItem { getPackageInfo().saveToXml(mShortcutUser.mService, out, forBackup); for (int i = 0; i < size; i++) { final UserPackage up = mPinnedShortcuts.keyAt(i); final UserPackage up = pinnedShortcuts.keyAt(i); if (forBackup && (up.userId != getOwnerUserId())) { continue; // Target package on a different user, skip. (i.e. work profile) Loading @@ -247,7 +277,7 @@ class ShortcutLauncher extends ShortcutPackageItem { ShortcutService.writeAttr(out, ATTR_PACKAGE_NAME, up.packageName); ShortcutService.writeAttr(out, ATTR_PACKAGE_USER_ID, up.userId); final ArraySet<String> ids = mPinnedShortcuts.valueAt(i); final ArraySet<String> ids = pinnedShortcuts.valueAt(i); final int idSize = ids.size(); for (int j = 0; j < idSize; j++) { ShortcutService.writeTagValue(out, TAG_PIN, ids.valueAt(j)); Loading Loading @@ -336,8 +366,10 @@ class ShortcutLauncher extends ShortcutPackageItem { : ShortcutService.parseIntAttribute(parser, ATTR_PACKAGE_USER_ID, ownerUserId); ids = new ArraySet<>(); synchronized (ret.mLock) { ret.mPinnedShortcuts.put( UserPackage.of(packageUserId, packageName), ids); } continue; } } Loading Loading @@ -374,11 +406,15 @@ class ShortcutLauncher extends ShortcutPackageItem { getPackageInfo().dump(pw, prefix + " "); pw.println(); final int size = mPinnedShortcuts.size(); final ArrayMap<UserPackage, ArraySet<String>> pinnedShortcuts; synchronized (mLock) { pinnedShortcuts = new ArrayMap<>(mPinnedShortcuts); } final int size = pinnedShortcuts.size(); for (int i = 0; i < size; i++) { pw.println(); final UserPackage up = mPinnedShortcuts.keyAt(i); final UserPackage up = pinnedShortcuts.keyAt(i); pw.print(prefix); pw.print(" "); Loading @@ -387,7 +423,7 @@ class ShortcutLauncher extends ShortcutPackageItem { pw.print(" User: "); pw.println(up.userId); final ArraySet<String> ids = mPinnedShortcuts.valueAt(i); final ArraySet<String> ids = pinnedShortcuts.valueAt(i); final int idSize = ids.size(); for (int j = 0; j < idSize; j++) { Loading @@ -408,11 +444,6 @@ class ShortcutLauncher extends ShortcutPackageItem { return result; } @VisibleForTesting ArraySet<String> getAllPinnedShortcutsForTest(String packageName, int packageUserId) { return new ArraySet<>(mPinnedShortcuts.get(UserPackage.of(packageUserId, packageName))); } @Override protected File getShortcutPackageItemFile() { final File path = new File(mShortcutUser.mService.injectUserDataPath( Loading