13145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki/* 23145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki * Copyright (C) 2016 The Android Open Source Project 33145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki * 43145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki * Licensed under the Apache License, Version 2.0 (the "License"); 53145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki * you may not use this file except in compliance with the License. 63145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki * You may obtain a copy of the License at 73145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki * 83145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki * http://www.apache.org/licenses/LICENSE-2.0 93145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki * 103145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki * Unless required by applicable law or agreed to in writing, software 113145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki * distributed under the License is distributed on an "AS IS" BASIS, 123145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki * See the License for the specific language governing permissions and 143145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki * limitations under the License. 153145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki */ 163145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onukipackage com.android.server.pm; 173145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 183145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onukiimport android.annotation.NonNull; 192d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onukiimport android.annotation.Nullable; 203145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onukiimport android.annotation.UserIdInt; 21c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onukiimport android.content.pm.PackageInfo; 223145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onukiimport android.content.pm.ShortcutInfo; 233145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onukiimport android.util.ArrayMap; 243145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onukiimport android.util.ArraySet; 252e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onukiimport android.util.Slog; 262e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki 272e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onukiimport com.android.internal.annotations.VisibleForTesting; 282e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onukiimport com.android.server.pm.ShortcutUser.PackageWithUser; 293145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 3076269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onukiimport org.json.JSONException; 3176269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onukiimport org.json.JSONObject; 323145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onukiimport org.xmlpull.v1.XmlPullParser; 333145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onukiimport org.xmlpull.v1.XmlPullParserException; 343145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onukiimport org.xmlpull.v1.XmlSerializer; 353145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 363145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onukiimport java.io.IOException; 373145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onukiimport java.io.PrintWriter; 382e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onukiimport java.util.ArrayList; 393145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onukiimport java.util.List; 403145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 413145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki/** 423145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki * Launcher information used by {@link ShortcutService}. 4322fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki * 4422fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki * All methods should be guarded by {@code #mShortcutUser.mService.mLock}. 453145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki */ 469da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onukiclass ShortcutLauncher extends ShortcutPackageItem { 473145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki private static final String TAG = ShortcutService.TAG; 483145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 493145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki static final String TAG_ROOT = "launcher-pins"; 503145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 513145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki private static final String TAG_PACKAGE = "package"; 523145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki private static final String TAG_PIN = "pin"; 533145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 54d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki private static final String ATTR_LAUNCHER_USER_ID = "launcher-user"; 553145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki private static final String ATTR_VALUE = "value"; 563145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki private static final String ATTR_PACKAGE_NAME = "package-name"; 572e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki private static final String ATTR_PACKAGE_USER_ID = "package-user"; 583145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 599da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki private final int mOwnerUserId; 60d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki 613145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki /** 623145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki * Package name -> IDs. 633145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki */ 642e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki final private ArrayMap<PackageWithUser, ArraySet<String>> mPinnedShortcuts = new ArrayMap<>(); 653145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 664d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki private ShortcutLauncher(@NonNull ShortcutUser shortcutUser, 674d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki @UserIdInt int ownerUserId, @NonNull String packageName, 689da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki @UserIdInt int launcherUserId, ShortcutPackageInfo spi) { 694d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki super(shortcutUser, launcherUserId, packageName, 704d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki spi != null ? spi : ShortcutPackageInfo.newEmpty()); 719da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki mOwnerUserId = ownerUserId; 723145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki } 733145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 744d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki public ShortcutLauncher(@NonNull ShortcutUser shortcutUser, 754d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki @UserIdInt int ownerUserId, @NonNull String packageName, 769da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki @UserIdInt int launcherUserId) { 774d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki this(shortcutUser, ownerUserId, packageName, launcherUserId, null); 780acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki } 790acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki 809da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki @Override 819da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki public int getOwnerUserId() { 829da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki return mOwnerUserId; 83d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki } 84d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki 852e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki /** 862e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki * Called when the new package can't receive the backup, due to signature or version mismatch. 872e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki */ 882e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki @Override 89c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki protected void onRestoreBlocked() { 902e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki final ArrayList<PackageWithUser> pinnedPackages = 912e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki new ArrayList<>(mPinnedShortcuts.keySet()); 922e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki mPinnedShortcuts.clear(); 932e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki for (int i = pinnedPackages.size() - 1; i >= 0; i--) { 942e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki final PackageWithUser pu = pinnedPackages.get(i); 95c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki final ShortcutPackage p = mShortcutUser.getPackageShortcutsIfExists(pu.packageName); 96c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki if (p != null) { 97c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki p.refreshPinnedFlags(); 98c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki } 992e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki } 1002e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki } 1012e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki 1022e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki @Override 103c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki protected void onRestored() { 1042e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki // Nothing to do. 1052e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki } 1062e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki 1072d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki /** 1082d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki * Pin the given shortcuts, replacing the current pinned ones. 1092d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki */ 110c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki public void pinShortcuts(@UserIdInt int packageUserId, 1119da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki @NonNull String packageName, @NonNull List<String> ids) { 1129da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki final ShortcutPackage packageShortcuts = 113c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki mShortcutUser.getPackageShortcutsIfExists(packageName); 114c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki if (packageShortcuts == null) { 115c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki return; // No need to instantiate. 116c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki } 1170acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki 1182e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki final PackageWithUser pu = PackageWithUser.of(packageUserId, packageName); 1192e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki 1203145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki final int idSize = ids.size(); 1213145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki if (idSize == 0) { 1222e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki mPinnedShortcuts.remove(pu); 1233145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki } else { 1242e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki final ArraySet<String> prevSet = mPinnedShortcuts.get(pu); 1253145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 1263145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki // Pin shortcuts. Make sure only pin the ones that were visible to the caller. 1273145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki // i.e. a non-dynamic, pinned shortcut by *other launchers* shouldn't be pinned here. 1283145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 1293145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki final ArraySet<String> newSet = new ArraySet<>(); 1303145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 1313145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki for (int i = 0; i < idSize; i++) { 1323145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki final String id = ids.get(i); 1333145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki final ShortcutInfo si = packageShortcuts.findShortcutById(id); 1343145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki if (si == null) { 1353145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki continue; 1363145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki } 13722fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki if (si.isDynamic() || si.isManifestShortcut() 13822fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki || (prevSet != null && prevSet.contains(id))) { 1393145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki newSet.add(id); 1403145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki } 1413145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki } 1422e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki mPinnedShortcuts.put(pu, newSet); 1433145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki } 144c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki packageShortcuts.refreshPinnedFlags(); 1453145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki } 1463145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 1473145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki /** 1483145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki * Return the pinned shortcut IDs for the publisher package. 1493145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki */ 1502d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki @Nullable 1512e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki public ArraySet<String> getPinnedShortcutIds(@NonNull String packageName, 1522e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki @UserIdInt int packageUserId) { 1532e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki return mPinnedShortcuts.get(PackageWithUser.of(packageUserId, packageName)); 1543145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki } 1553145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 1562d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki /** 1572d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki * Return true if the given shortcut is pinned by this launcher. 1582d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki */ 1592d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki public boolean hasPinned(ShortcutInfo shortcut) { 1602d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki final ArraySet<String> pinned = 1612d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki getPinnedShortcutIds(shortcut.getPackage(), shortcut.getUserId()); 1622d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki return (pinned != null) && pinned.contains(shortcut.getId()); 1632d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki } 1642d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki 1652d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki /** 1662d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki * Additionally pin a shortcut. c.f. {@link #pinShortcuts(int, String, List)} 1672d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki */ 1682d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki public void addPinnedShortcut(@NonNull String packageName, @UserIdInt int packageUserId, 1692d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki String id) { 1702d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki final ArraySet<String> pinnedSet = getPinnedShortcutIds(packageName, packageUserId); 1712d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki final ArrayList<String> pinnedList; 1722d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki if (pinnedSet != null) { 1732d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki pinnedList = new ArrayList<>(pinnedSet.size() + 1); 1742d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki pinnedList.addAll(pinnedSet); 1752d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki } else { 1762d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki pinnedList = new ArrayList<>(1); 1772d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki } 1782d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki pinnedList.add(id); 1792d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki 1802d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki pinShortcuts(packageUserId, packageName, pinnedList); 1812d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki } 1822d895c3efd625e09e9f2cc4d0c7131b34f52f154Makoto Onuki 1832e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki boolean cleanUpPackage(String packageName, @UserIdInt int packageUserId) { 1842e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki return mPinnedShortcuts.remove(PackageWithUser.of(packageUserId, packageName)) != null; 1853145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki } 1863145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 187c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki public void ensureVersionInfo() { 188c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki final PackageInfo pi = mShortcutUser.mService.getPackageInfoWithSignatures( 189c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki getPackageName(), getPackageUserId()); 190c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki if (pi == null) { 191c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki Slog.w(TAG, "Package not found: " + getPackageName()); 192c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki return; 193c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki } 194c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki getPackageInfo().updateVersionInfo(pi); 195c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki } 196c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki 1973145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki /** 1983145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki * Persist. 1993145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki */ 2009da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki @Override 2019da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki public void saveToXml(XmlSerializer out, boolean forBackup) 2029da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki throws IOException { 2033145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki final int size = mPinnedShortcuts.size(); 2043145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki if (size == 0) { 2053145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki return; // Nothing to write. 2063145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki } 2073145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 2083145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki out.startTag(null, TAG_ROOT); 2099da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki ShortcutService.writeAttr(out, ATTR_PACKAGE_NAME, getPackageName()); 2109da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki ShortcutService.writeAttr(out, ATTR_LAUNCHER_USER_ID, getPackageUserId()); 2119da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki getPackageInfo().saveToXml(out); 2123145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 2133145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki for (int i = 0; i < size; i++) { 2142e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki final PackageWithUser pu = mPinnedShortcuts.keyAt(i); 2152e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki 2162e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki if (forBackup && (pu.userId != getOwnerUserId())) { 2172e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki continue; // Target package on a different user, skip. (i.e. work profile) 2182e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki } 2192e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki 2203145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki out.startTag(null, TAG_PACKAGE); 2212e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki ShortcutService.writeAttr(out, ATTR_PACKAGE_NAME, pu.packageName); 2222e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki ShortcutService.writeAttr(out, ATTR_PACKAGE_USER_ID, pu.userId); 2233145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 2243145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki final ArraySet<String> ids = mPinnedShortcuts.valueAt(i); 2253145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki final int idSize = ids.size(); 2263145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki for (int j = 0; j < idSize; j++) { 2273145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki ShortcutService.writeTagValue(out, TAG_PIN, ids.valueAt(j)); 2283145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki } 2293145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki out.endTag(null, TAG_PACKAGE); 2303145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki } 2313145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 2323145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki out.endTag(null, TAG_ROOT); 2333145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki } 2343145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 2353145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki /** 2363145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki * Load. 2373145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki */ 2384d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki public static ShortcutLauncher loadFromXml(XmlPullParser parser, ShortcutUser shortcutUser, 2394d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki int ownerUserId, boolean fromBackup) throws IOException, XmlPullParserException { 2403145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki final String launcherPackageName = ShortcutService.parseStringAttribute(parser, 2413145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki ATTR_PACKAGE_NAME); 2429da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki 2439da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki // If restoring, just use the real user ID. 2449da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki final int launcherUserId = 2459da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki fromBackup ? ownerUserId 2469da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki : ShortcutService.parseIntAttribute(parser, ATTR_LAUNCHER_USER_ID, ownerUserId); 2473145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 248c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki final ShortcutLauncher ret = new ShortcutLauncher(shortcutUser, ownerUserId, 2494d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki launcherPackageName, launcherUserId); 2503145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 2513145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki ArraySet<String> ids = null; 2523145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki final int outerDepth = parser.getDepth(); 2533145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki int type; 2543145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 2553145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 2563145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki if (type != XmlPullParser.START_TAG) { 2573145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki continue; 2583145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki } 2593145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki final int depth = parser.getDepth(); 2603145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki final String tag = parser.getName(); 2619da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki if (depth == outerDepth + 1) { 2629da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki switch (tag) { 2639da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki case ShortcutPackageInfo.TAG_ROOT: 2642e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki ret.getPackageInfo().loadFromXml(parser, fromBackup); 2659da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki continue; 2669da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki case TAG_PACKAGE: { 2679da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki final String packageName = ShortcutService.parseStringAttribute(parser, 2689da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki ATTR_PACKAGE_NAME); 2692e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki final int packageUserId = fromBackup ? ownerUserId 2702e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki : ShortcutService.parseIntAttribute(parser, 2712e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki ATTR_PACKAGE_USER_ID, ownerUserId); 2729da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki ids = new ArraySet<>(); 2732e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki ret.mPinnedShortcuts.put( 2742e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki PackageWithUser.of(packageUserId, packageName), ids); 2759da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki continue; 2769da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki } 2773145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki } 2789da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki } 2799da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki if (depth == outerDepth + 2) { 2809da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki switch (tag) { 2819da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki case TAG_PIN: { 2822e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki if (ids == null) { 2832e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki Slog.w(TAG, TAG_PIN + " in invalid place"); 2842e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki } else { 2852e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki ids.add(ShortcutService.parseStringAttribute(parser, ATTR_VALUE)); 2862e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki } 2879da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki continue; 2889da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki } 2893145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki } 2903145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki } 2919da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki ShortcutService.warnForInvalidTag(depth, tag); 2929da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki } 2933145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki return ret; 2943145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki } 2953145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 296c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki public void dump(@NonNull PrintWriter pw, @NonNull String prefix) { 2973145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki pw.println(); 2983145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 2993145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki pw.print(prefix); 3003145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki pw.print("Launcher: "); 3019da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki pw.print(getPackageName()); 3029da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki pw.print(" Package user: "); 3039da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki pw.print(getPackageUserId()); 3042e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki pw.print(" Owner user: "); 3052e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki pw.print(getOwnerUserId()); 3069da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki pw.println(); 3079da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki 308c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki getPackageInfo().dump(pw, prefix + " "); 3093145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki pw.println(); 3103145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 3113145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki final int size = mPinnedShortcuts.size(); 3123145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki for (int i = 0; i < size; i++) { 3133145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki pw.println(); 3143145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 3152e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki final PackageWithUser pu = mPinnedShortcuts.keyAt(i); 3162e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki 3173145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki pw.print(prefix); 3183145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki pw.print(" "); 3193145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki pw.print("Package: "); 3202e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki pw.print(pu.packageName); 3212e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki pw.print(" User: "); 3222e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki pw.println(pu.userId); 3233145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 3243145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki final ArraySet<String> ids = mPinnedShortcuts.valueAt(i); 3253145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki final int idSize = ids.size(); 3263145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki 3273145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki for (int j = 0; j < idSize; j++) { 3283145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki pw.print(prefix); 3290acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki pw.print(" Pinned: "); 3303145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki pw.print(ids.valueAt(j)); 3313145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki pw.println(); 3323145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki } 3333145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki } 3343145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki } 3352e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki 33676269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki @Override 33776269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki public JSONObject dumpCheckin(boolean clear) throws JSONException { 33876269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki final JSONObject result = super.dumpCheckin(clear); 33976269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki 34076269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki // Nothing really interesting to dump. 34176269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki 34276269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki return result; 34376269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki } 34476269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki 3452e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki @VisibleForTesting 3462e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki ArraySet<String> getAllPinnedShortcutsForTest(String packageName, int packageUserId) { 3472e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki return new ArraySet<>(mPinnedShortcuts.get(PackageWithUser.of(packageUserId, packageName))); 3482e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki } 3493145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki} 350