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;
193145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onukiimport android.annotation.UserIdInt;
203145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onukiimport android.content.pm.ShortcutInfo;
213145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onukiimport android.util.ArrayMap;
223145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onukiimport android.util.ArraySet;
232e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onukiimport android.util.Slog;
242e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki
252e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onukiimport com.android.internal.annotations.VisibleForTesting;
262e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onukiimport com.android.server.pm.ShortcutUser.PackageWithUser;
273145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki
283145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onukiimport org.xmlpull.v1.XmlPullParser;
293145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onukiimport org.xmlpull.v1.XmlPullParserException;
303145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onukiimport org.xmlpull.v1.XmlSerializer;
313145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki
323145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onukiimport java.io.IOException;
333145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onukiimport java.io.PrintWriter;
342e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onukiimport java.util.ArrayList;
353145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onukiimport java.util.List;
363145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki
373145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki/**
383145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki * Launcher information used by {@link ShortcutService}.
393145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki */
409da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onukiclass ShortcutLauncher extends ShortcutPackageItem {
413145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki    private static final String TAG = ShortcutService.TAG;
423145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki
433145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki    static final String TAG_ROOT = "launcher-pins";
443145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki
453145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki    private static final String TAG_PACKAGE = "package";
463145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki    private static final String TAG_PIN = "pin";
473145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki
48d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki    private static final String ATTR_LAUNCHER_USER_ID = "launcher-user";
493145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki    private static final String ATTR_VALUE = "value";
503145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki    private static final String ATTR_PACKAGE_NAME = "package-name";
512e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki    private static final String ATTR_PACKAGE_USER_ID = "package-user";
523145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki
539da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki    private final int mOwnerUserId;
54d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki
553145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki    /**
563145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki     * Package name -> IDs.
573145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki     */
582e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki    final private ArrayMap<PackageWithUser, ArraySet<String>> mPinnedShortcuts = new ArrayMap<>();
593145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki
604d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki    private ShortcutLauncher(@NonNull ShortcutUser shortcutUser,
614d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki            @UserIdInt int ownerUserId, @NonNull String packageName,
629da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki            @UserIdInt int launcherUserId, ShortcutPackageInfo spi) {
634d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki        super(shortcutUser, launcherUserId, packageName,
644d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki                spi != null ? spi : ShortcutPackageInfo.newEmpty());
659da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki        mOwnerUserId = ownerUserId;
663145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki    }
673145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki
684d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki    public ShortcutLauncher(@NonNull ShortcutUser shortcutUser,
694d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki            @UserIdInt int ownerUserId, @NonNull String packageName,
709da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki            @UserIdInt int launcherUserId) {
714d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki        this(shortcutUser, ownerUserId, packageName, launcherUserId, null);
720acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki    }
730acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki
749da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki    @Override
759da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki    public int getOwnerUserId() {
769da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki        return mOwnerUserId;
77d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki    }
78d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki
792e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki    /**
802e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki     * Called when the new package can't receive the backup, due to signature or version mismatch.
812e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki     */
822e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki    @Override
832e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki    protected void onRestoreBlocked(ShortcutService s) {
842e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki        final ArrayList<PackageWithUser> pinnedPackages =
852e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki                new ArrayList<>(mPinnedShortcuts.keySet());
862e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki        mPinnedShortcuts.clear();
872e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki        for (int i = pinnedPackages.size() - 1; i >= 0; i--) {
882e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki            final PackageWithUser pu = pinnedPackages.get(i);
892e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki            s.getPackageShortcutsLocked(pu.packageName, pu.userId)
902e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki                    .refreshPinnedFlags(s);
912e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki        }
922e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki    }
932e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki
942e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki    @Override
952e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki    protected void onRestored(ShortcutService s) {
962e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki        // Nothing to do.
972e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki    }
982e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki
999da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki    public void pinShortcuts(@NonNull ShortcutService s, @UserIdInt int packageUserId,
1009da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki            @NonNull String packageName, @NonNull List<String> ids) {
1019da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki        final ShortcutPackage packageShortcuts =
1029da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki                s.getPackageShortcutsLocked(packageName, packageUserId);
1030acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki
1042e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki        final PackageWithUser pu = PackageWithUser.of(packageUserId, packageName);
1052e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki
1063145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki        final int idSize = ids.size();
1073145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki        if (idSize == 0) {
1082e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki            mPinnedShortcuts.remove(pu);
1093145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki        } else {
1102e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki            final ArraySet<String> prevSet = mPinnedShortcuts.get(pu);
1113145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki
1123145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki            // Pin shortcuts.  Make sure only pin the ones that were visible to the caller.
1133145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki            // i.e. a non-dynamic, pinned shortcut by *other launchers* shouldn't be pinned here.
1143145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki
1153145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki            final ArraySet<String> newSet = new ArraySet<>();
1163145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki
1173145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki            for (int i = 0; i < idSize; i++) {
1183145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki                final String id = ids.get(i);
1193145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki                final ShortcutInfo si = packageShortcuts.findShortcutById(id);
1203145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki                if (si == null) {
1213145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki                    continue;
1223145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki                }
1233145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki                if (si.isDynamic() || (prevSet != null && prevSet.contains(id))) {
1243145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki                    newSet.add(id);
1253145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki                }
1263145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki            }
1272e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki            mPinnedShortcuts.put(pu, newSet);
1283145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki        }
1299da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki        packageShortcuts.refreshPinnedFlags(s);
1303145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki    }
1313145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki
1323145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki    /**
1333145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki     * Return the pinned shortcut IDs for the publisher package.
1343145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki     */
1352e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki    public ArraySet<String> getPinnedShortcutIds(@NonNull String packageName,
1362e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki            @UserIdInt int packageUserId) {
1372e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki        return mPinnedShortcuts.get(PackageWithUser.of(packageUserId, packageName));
1383145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki    }
1393145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki
1402e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki    boolean cleanUpPackage(String packageName, @UserIdInt int packageUserId) {
1412e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki        return mPinnedShortcuts.remove(PackageWithUser.of(packageUserId, packageName)) != null;
1423145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki    }
1433145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki
1443145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki    /**
1453145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki     * Persist.
1463145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki     */
1479da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki    @Override
1489da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki    public void saveToXml(XmlSerializer out, boolean forBackup)
1499da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki            throws IOException {
1503145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki        final int size = mPinnedShortcuts.size();
1513145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki        if (size == 0) {
1523145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki            return; // Nothing to write.
1533145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki        }
1543145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki
1553145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki        out.startTag(null, TAG_ROOT);
1569da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki        ShortcutService.writeAttr(out, ATTR_PACKAGE_NAME, getPackageName());
1579da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki        ShortcutService.writeAttr(out, ATTR_LAUNCHER_USER_ID, getPackageUserId());
1589da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki        getPackageInfo().saveToXml(out);
1593145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki
1603145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki        for (int i = 0; i < size; i++) {
1612e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki            final PackageWithUser pu = mPinnedShortcuts.keyAt(i);
1622e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki
1632e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki            if (forBackup && (pu.userId != getOwnerUserId())) {
1642e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki                continue; // Target package on a different user, skip. (i.e. work profile)
1652e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki            }
1662e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki
1673145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki            out.startTag(null, TAG_PACKAGE);
1682e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki            ShortcutService.writeAttr(out, ATTR_PACKAGE_NAME, pu.packageName);
1692e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki            ShortcutService.writeAttr(out, ATTR_PACKAGE_USER_ID, pu.userId);
1703145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki
1713145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki            final ArraySet<String> ids = mPinnedShortcuts.valueAt(i);
1723145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki            final int idSize = ids.size();
1733145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki            for (int j = 0; j < idSize; j++) {
1743145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki                ShortcutService.writeTagValue(out, TAG_PIN, ids.valueAt(j));
1753145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki            }
1763145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki            out.endTag(null, TAG_PACKAGE);
1773145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki        }
1783145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki
1793145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki        out.endTag(null, TAG_ROOT);
1803145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki    }
1813145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki
1823145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki    /**
1833145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki     * Load.
1843145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki     */
1854d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki    public static ShortcutLauncher loadFromXml(XmlPullParser parser, ShortcutUser shortcutUser,
1864d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki            int ownerUserId, boolean fromBackup) throws IOException, XmlPullParserException {
1873145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki        final String launcherPackageName = ShortcutService.parseStringAttribute(parser,
1883145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki                ATTR_PACKAGE_NAME);
1899da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki
1909da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki        // If restoring, just use the real user ID.
1919da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki        final int launcherUserId =
1929da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki                fromBackup ? ownerUserId
1939da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki                : ShortcutService.parseIntAttribute(parser, ATTR_LAUNCHER_USER_ID, ownerUserId);
1943145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki
1954d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki        final ShortcutLauncher ret = new ShortcutLauncher(shortcutUser, launcherUserId,
1964d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki                launcherPackageName, launcherUserId);
1973145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki
1983145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki        ArraySet<String> ids = null;
1993145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki        final int outerDepth = parser.getDepth();
2003145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki        int type;
2013145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2023145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2033145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki            if (type != XmlPullParser.START_TAG) {
2043145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki                continue;
2053145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki            }
2063145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki            final int depth = parser.getDepth();
2073145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki            final String tag = parser.getName();
2089da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki            if (depth == outerDepth + 1) {
2099da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki                switch (tag) {
2109da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki                    case ShortcutPackageInfo.TAG_ROOT:
2112e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki                        ret.getPackageInfo().loadFromXml(parser, fromBackup);
2129da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki                        continue;
2139da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki                    case TAG_PACKAGE: {
2149da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki                        final String packageName = ShortcutService.parseStringAttribute(parser,
2159da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki                                ATTR_PACKAGE_NAME);
2162e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki                        final int packageUserId = fromBackup ? ownerUserId
2172e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki                                : ShortcutService.parseIntAttribute(parser,
2182e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki                                ATTR_PACKAGE_USER_ID, ownerUserId);
2199da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki                        ids = new ArraySet<>();
2202e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki                        ret.mPinnedShortcuts.put(
2212e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki                                PackageWithUser.of(packageUserId, packageName), ids);
2229da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki                        continue;
2239da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki                    }
2243145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki                }
2259da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki            }
2269da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki            if (depth == outerDepth + 2) {
2279da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki                switch (tag) {
2289da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki                    case TAG_PIN: {
2292e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki                        if (ids == null) {
2302e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki                            Slog.w(TAG, TAG_PIN + " in invalid place");
2312e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki                        } else {
2322e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki                            ids.add(ShortcutService.parseStringAttribute(parser, ATTR_VALUE));
2332e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki                        }
2349da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki                        continue;
2359da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki                    }
2363145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki                }
2373145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki            }
2389da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki            ShortcutService.warnForInvalidTag(depth, tag);
2399da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki        }
2403145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki        return ret;
2413145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki    }
2423145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki
2433145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki    public void dump(@NonNull ShortcutService s, @NonNull PrintWriter pw, @NonNull String prefix) {
2443145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki        pw.println();
2453145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki
2463145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki        pw.print(prefix);
2473145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki        pw.print("Launcher: ");
2489da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki        pw.print(getPackageName());
2499da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki        pw.print("  Package user: ");
2509da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki        pw.print(getPackageUserId());
2512e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki        pw.print("  Owner user: ");
2522e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki        pw.print(getOwnerUserId());
2539da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki        pw.println();
2549da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki
2559da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki        getPackageInfo().dump(s, pw, prefix + "  ");
2563145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki        pw.println();
2573145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki
2583145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki        final int size = mPinnedShortcuts.size();
2593145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki        for (int i = 0; i < size; i++) {
2603145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki            pw.println();
2613145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki
2622e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki            final PackageWithUser pu = mPinnedShortcuts.keyAt(i);
2632e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki
2643145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki            pw.print(prefix);
2653145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki            pw.print("  ");
2663145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki            pw.print("Package: ");
2672e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki            pw.print(pu.packageName);
2682e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki            pw.print("  User: ");
2692e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki            pw.println(pu.userId);
2703145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki
2713145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki            final ArraySet<String> ids = mPinnedShortcuts.valueAt(i);
2723145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki            final int idSize = ids.size();
2733145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki
2743145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki            for (int j = 0; j < idSize; j++) {
2753145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki                pw.print(prefix);
2760acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki                pw.print("    Pinned: ");
2773145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki                pw.print(ids.valueAt(j));
2783145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki                pw.println();
2793145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki            }
2803145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki        }
2813145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki    }
2822e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki
2832e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki    @VisibleForTesting
2842e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki    ArraySet<String> getAllPinnedShortcutsForTest(String packageName, int packageUserId) {
2852e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki        return new ArraySet<>(mPinnedShortcuts.get(PackageWithUser.of(packageUserId, packageName)));
2862e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki    }
2873145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki}
288