/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.server.pm;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.Context;
import android.content.Intent;
import android.content.pm.IShortcutService;
import android.content.pm.LauncherApps;
import android.content.pm.LauncherApps.ShortcutQuery;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ParceledListSlice;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutServiceInternal;
import android.content.pm.ShortcutServiceInternal.ShortcutChangeListener;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.RectF;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Binder;
import android.os.Environment;
import android.os.Handler;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.SELinux;
import android.os.ShellCommand;
import android.os.UserHandle;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.text.format.Time;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.KeyValueListParser;
import android.util.Slog;
import android.util.SparseArray;
import android.util.TypedValue;
import android.util.Xml;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.Preconditions;
import com.android.server.LocalServices;
import com.android.server.SystemService;

import libcore.io.IoUtils;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

/**
 * TODO:
 *
 * - Detect when already registered instances are passed to APIs again, which might break
 *   internal bitmap handling.
 *
 * - Listen to PACKAGE_*, remove orphan info, update timestamp for icon res
 *   -> Need to scan all packages when a user starts too.
 *   -> Clear data -> remove all dynamic?  but not the pinned?
 *
 * - Pinned per each launcher package (multiple launchers)
 *
 * - Make save async (should we?)
 *
 * - Scan and remove orphan bitmaps (just in case).
 *
 * - Backup & restore
 */
public class ShortcutService extends IShortcutService.Stub {
    static final String TAG = "ShortcutService";

    private static final boolean DEBUG = true; // STOPSHIP if true
    private static final boolean DEBUG_LOAD = true; // STOPSHIP if true

    @VisibleForTesting
    static final long DEFAULT_RESET_INTERVAL_SEC = 24 * 60 * 60; // 1 day

    @VisibleForTesting
    static final int DEFAULT_MAX_DAILY_UPDATES = 10;

    @VisibleForTesting
    static final int DEFAULT_MAX_SHORTCUTS_PER_APP = 5;

    @VisibleForTesting
    static final int DEFAULT_MAX_ICON_DIMENSION_DP = 96;

    @VisibleForTesting
    static final int DEFAULT_MAX_ICON_DIMENSION_LOWRAM_DP = 48;

    @VisibleForTesting
    static final String DEFAULT_ICON_PERSIST_FORMAT = CompressFormat.PNG.name();

    @VisibleForTesting
    static final int DEFAULT_ICON_PERSIST_QUALITY = 100;

    private static final int SAVE_DELAY_MS = 5000; // in milliseconds.

    @VisibleForTesting
    static final String FILENAME_BASE_STATE = "shortcut_service.xml";

    @VisibleForTesting
    static final String DIRECTORY_PER_USER = "shortcut_service";

    @VisibleForTesting
    static final String FILENAME_USER_PACKAGES = "shortcuts.xml";

    static final String DIRECTORY_BITMAPS = "bitmaps";

    private static final String TAG_ROOT = "root";
    private static final String TAG_PACKAGE = "package";
    private static final String TAG_LAST_RESET_TIME = "last_reset_time";
    private static final String TAG_INTENT_EXTRAS = "intent-extras";
    private static final String TAG_EXTRAS = "extras";
    private static final String TAG_SHORTCUT = "shortcut";

    private static final String ATTR_VALUE = "value";
    private static final String ATTR_NAME = "name";
    private static final String ATTR_DYNAMIC_COUNT = "dynamic-count";
    private static final String ATTR_CALL_COUNT = "call-count";
    private static final String ATTR_LAST_RESET = "last-reset";
    private static final String ATTR_ID = "id";
    private static final String ATTR_ACTIVITY = "activity";
    private static final String ATTR_TITLE = "title";
    private static final String ATTR_INTENT = "intent";
    private static final String ATTR_WEIGHT = "weight";
    private static final String ATTR_TIMESTAMP = "timestamp";
    private static final String ATTR_FLAGS = "flags";
    private static final String ATTR_ICON_RES = "icon-res";
    private static final String ATTR_BITMAP_PATH = "bitmap-path";

    @VisibleForTesting
    interface ConfigConstants {
        /**
         * Key name for the throttling reset interval, in seconds. (long)
         */
        String KEY_RESET_INTERVAL_SEC = "reset_interval_sec";

        /**
         * Key name for the max number of modifying API calls per app for every interval. (int)
         */
        String KEY_MAX_DAILY_UPDATES = "max_daily_updates";

        /**
         * Key name for the max icon dimensions in DP, for non-low-memory devices.
         */
        String KEY_MAX_ICON_DIMENSION_DP = "max_icon_dimension_dp";

        /**
         * Key name for the max icon dimensions in DP, for low-memory devices.
         */
        String KEY_MAX_ICON_DIMENSION_DP_LOWRAM = "max_icon_dimension_dp_lowram";

        /**
         * Key name for the max dynamic shortcuts per app. (int)
         */
        String KEY_MAX_SHORTCUTS = "max_shortcuts";

        /**
         * Key name for icom compression quality, 0-100.
         */
        String KEY_ICON_QUALITY = "icon_quality";

        /**
         * Key name for icon compression format: "PNG", "JPEG" or "WEBP"
         */
        String KEY_ICON_FORMAT = "icon_format";
    }

    private final Context mContext;

    private final Object mLock = new Object();

    private final Handler mHandler;

    @GuardedBy("mLock")
    private final ArrayList<ShortcutChangeListener> mListeners = new ArrayList<>(1);

    @GuardedBy("mLock")
    private long mRawLastResetTime;

    /**
     * All the information relevant to shortcuts from a single package (per-user).
     *
     * TODO Move the persisting code to this class.
     *
     * Only save/load/dump should look/touch inside this class.
     */
    private static class PackageShortcuts {
        @UserIdInt
        private final int mUserId;

        @NonNull
        private final String mPackageName;

        /**
         * All the shortcuts from the package, keyed on IDs.
         */
        final private ArrayMap<String, ShortcutInfo> mShortcuts = new ArrayMap<>();

        /**
         * # of dynamic shortcuts.
         */
        private int mDynamicShortcutCount = 0;

        /**
         * # of times the package has called rate-limited APIs.
         */
        private int mApiCallCount;

        /**
         * When {@link #mApiCallCount} was reset last time.
         */
        private long mLastResetTime;

        private PackageShortcuts(int userId, String packageName) {
            mUserId = userId;
            mPackageName = packageName;
        }

        @GuardedBy("mLock")
        @Nullable
        public ShortcutInfo findShortcutById(String id) {
            return mShortcuts.get(id);
        }

        private ShortcutInfo deleteShortcut(@NonNull ShortcutService s,
                @NonNull String id) {
            final ShortcutInfo shortcut = mShortcuts.remove(id);
            if (shortcut != null) {
                s.removeIcon(mUserId, shortcut);
                shortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_PINNED);
            }
            return shortcut;
        }

        void addShortcut(@NonNull ShortcutService s, @NonNull ShortcutInfo newShortcut) {
            deleteShortcut(s, newShortcut.getId());
            s.saveIconAndFixUpShortcut(mUserId, newShortcut);
            mShortcuts.put(newShortcut.getId(), newShortcut);
        }

        /**
         * Add a shortcut, or update one with the same ID, with taking over existing flags.
         *
         * It checks the max number of dynamic shortcuts.
         */
        @GuardedBy("mLock")
        public void updateShortcutWithCapping(@NonNull ShortcutService s,
                @NonNull ShortcutInfo newShortcut) {
            final ShortcutInfo oldShortcut = mShortcuts.get(newShortcut.getId());

            int oldFlags = 0;
            int newDynamicCount = mDynamicShortcutCount;

            if (oldShortcut != null) {
                oldFlags = oldShortcut.getFlags();
                if (oldShortcut.isDynamic()) {
                    newDynamicCount--;
                }
            }
            if (newShortcut.isDynamic()) {
                newDynamicCount++;
            }
            // Make sure there's still room.
            s.enforceMaxDynamicShortcuts(newDynamicCount);

            // Okay, make it dynamic and add.
            newShortcut.addFlags(oldFlags);

            addShortcut(s, newShortcut);
            mDynamicShortcutCount = newDynamicCount;
        }

        /**
         * Remove all shortcuts that aren't pinned nor dynamic.
         */
        private void removeOrphans(@NonNull ShortcutService s) {
            ArrayList<String> removeList = null; // Lazily initialize.

            for (int i = mShortcuts.size() - 1; i >= 0; i--) {
                final ShortcutInfo si = mShortcuts.valueAt(i);

                if (si.isPinned() || si.isDynamic()) continue;

                if (removeList == null) {
                    removeList = new ArrayList<>();
                }
                removeList.add(si.getId());
            }
            if (removeList != null) {
                for (int i = removeList.size() - 1 ; i >= 0; i--) {
                    deleteShortcut(s, removeList.get(i));
                }
            }
        }

        @GuardedBy("mLock")
        public void deleteAllDynamicShortcuts(@NonNull ShortcutService s) {
            for (int i = mShortcuts.size() - 1; i >= 0; i--) {
                mShortcuts.valueAt(i).clearFlags(ShortcutInfo.FLAG_DYNAMIC);
            }
            removeOrphans(s);
            mDynamicShortcutCount = 0;
        }

        @GuardedBy("mLock")
        public void deleteDynamicWithId(@NonNull ShortcutService s, @NonNull String shortcutId) {
            final ShortcutInfo oldShortcut = mShortcuts.get(shortcutId);

            if (oldShortcut == null) {
                return;
            }
            if (oldShortcut.isDynamic()) {
                mDynamicShortcutCount--;
            }
            if (oldShortcut.isPinned()) {
                oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC);
            } else {
                deleteShortcut(s, shortcutId);
            }
        }

        @GuardedBy("mLock")
        public void replacePinned(@NonNull ShortcutService s, String launcherPackage,
                List<String> shortcutIds) {

            // TODO Should be per launcherPackage.

            // First, un-pin all shortcuts
            for (int i = mShortcuts.size() - 1; i >= 0; i--) {
                mShortcuts.valueAt(i).clearFlags(ShortcutInfo.FLAG_PINNED);
            }

            // Then pin ALL
            for (int i = shortcutIds.size() - 1; i >= 0; i--) {
                final ShortcutInfo shortcut = mShortcuts.get(shortcutIds.get(i));
                if (shortcut != null) {
                    shortcut.addFlags(ShortcutInfo.FLAG_PINNED);
                }
            }

            removeOrphans(s);
        }

        /**
         * Number of calls that the caller has made, since the last reset.
         */
        @GuardedBy("mLock")
        public int getApiCallCount(@NonNull ShortcutService s) {
            final long last = s.getLastResetTimeLocked();

            final long now = s.injectCurrentTimeMillis();
            if (mLastResetTime > now) {
                // Clock rewound. // TODO Test it
                mLastResetTime = now;
            }

            // If not reset yet, then reset.
            if (mLastResetTime < last) {
                mApiCallCount = 0;
                mLastResetTime = last;
            }
            return mApiCallCount;
        }

        /**
         * If the caller app hasn't been throttled yet, increment {@link #mApiCallCount}
         * and return true.  Otherwise just return false.
         */
        @GuardedBy("mLock")
        public boolean tryApiCall(@NonNull ShortcutService s) {
            if (getApiCallCount(s) >= s.mMaxDailyUpdates) {
                return false;
            }
            mApiCallCount++;
            return true;
        }

        @GuardedBy("mLock")
        public void resetRateLimitingForCommandLine() {
            mApiCallCount = 0;
            mLastResetTime = 0;
        }

        /**
         * Find all shortcuts that match {@code query}.
         */
        @GuardedBy("mLock")
        public void findAll(@NonNull List<ShortcutInfo> result,
                @Nullable Predicate<ShortcutInfo> query, int cloneFlag) {
            for (int i = 0; i < mShortcuts.size(); i++) {
                final ShortcutInfo si = mShortcuts.valueAt(i);
                if (query == null || query.test(si)) {
                    result.add(si.clone(cloneFlag));
                }
            }
        }
    }

    /**
     * User ID -> package name -> list of ShortcutInfos.
     */
    @GuardedBy("mLock")
    private final SparseArray<ArrayMap<String, PackageShortcuts>> mShortcuts =
            new SparseArray<>();

    /**
     * Max number of dynamic shortcuts that each application can have at a time.
     */
    private int mMaxDynamicShortcuts;

    /**
     * Max number of updating API calls that each application can make a day.
     */
    private int mMaxDailyUpdates;

    /**
     * Actual throttling-reset interval.  By default it's a day.
     */
    private long mResetInterval;

    /**
     * Icon max width/height in pixels.
     */
    private int mMaxIconDimension;

    private CompressFormat mIconPersistFormat;
    private int mIconPersistQuality;

    public ShortcutService(Context context) {
        mContext = Preconditions.checkNotNull(context);
        LocalServices.addService(ShortcutServiceInternal.class, new LocalService());
        mHandler = new Handler(BackgroundThread.get().getLooper());
    }

    /**
     * System service lifecycle.
     */
    public static final class Lifecycle extends SystemService {
        final ShortcutService mService;

        public Lifecycle(Context context) {
            super(context);
            mService = new ShortcutService(context);
        }

        @Override
        public void onStart() {
            publishBinderService(Context.SHORTCUT_SERVICE, mService);
        }

        @Override
        public void onBootPhase(int phase) {
            mService.onBootPhase(phase);
        }

        @Override
        public void onCleanupUser(int userHandle) {
            synchronized (mService.mLock) {
                mService.onCleanupUserInner(userHandle);
            }
        }

        @Override
        public void onStartUser(int userId) {
            synchronized (mService.mLock) {
                mService.onStartUserLocked(userId);
            }
        }
    }

    /** lifecycle event */
    void onBootPhase(int phase) {
        if (DEBUG) {
            Slog.d(TAG, "onBootPhase: " + phase);
        }
        switch (phase) {
            case SystemService.PHASE_LOCK_SETTINGS_READY:
                initialize();
                break;
        }
    }

    /** lifecycle event */
    void onStartUserLocked(int userId) {
        // Preload
        getUserShortcutsLocked(userId);
    }

    /** lifecycle event */
    void onCleanupUserInner(int userId) {
        // Unload
        mShortcuts.delete(userId);
    }

    /** Return the base state file name */
    private AtomicFile getBaseStateFile() {
        final File path = new File(injectSystemDataPath(), FILENAME_BASE_STATE);
        path.mkdirs();
        return new AtomicFile(path);
    }

    /**
     * Init the instance. (load the state file, etc)
     */
    private void initialize() {
        synchronized (mLock) {
            loadConfigurationLocked();
            loadBaseStateLocked();
        }
    }

    /**
     * Load the configuration from Settings.
     */
    private void loadConfigurationLocked() {
        updateConfigurationLocked(injectShortcutManagerConstants());
    }

    /**
     * Load the configuration from Settings.
     */
    @VisibleForTesting
    boolean updateConfigurationLocked(String config) {
        boolean result = true;

        final KeyValueListParser parser = new KeyValueListParser(',');
        try {
            parser.setString(config);
        } catch (IllegalArgumentException e) {
            // Failed to parse the settings string, log this and move on
            // with defaults.
            Slog.e(TAG, "Bad shortcut manager settings", e);
            result = false;
        }

        mResetInterval = parser.getLong(
                ConfigConstants.KEY_RESET_INTERVAL_SEC, DEFAULT_RESET_INTERVAL_SEC)
                * 1000L;

        mMaxDailyUpdates = (int) parser.getLong(
                ConfigConstants.KEY_MAX_DAILY_UPDATES, DEFAULT_MAX_DAILY_UPDATES);

        mMaxDynamicShortcuts = (int) parser.getLong(
                ConfigConstants.KEY_MAX_SHORTCUTS, DEFAULT_MAX_SHORTCUTS_PER_APP);

        final int iconDimensionDp = injectIsLowRamDevice()
                ? (int) parser.getLong(
                    ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM,
                    DEFAULT_MAX_ICON_DIMENSION_LOWRAM_DP)
                : (int) parser.getLong(
                    ConfigConstants.KEY_MAX_ICON_DIMENSION_DP,
                    DEFAULT_MAX_ICON_DIMENSION_DP);

        mMaxIconDimension = injectDipToPixel(iconDimensionDp);

        mIconPersistFormat = CompressFormat.valueOf(
                parser.getString(ConfigConstants.KEY_ICON_FORMAT, DEFAULT_ICON_PERSIST_FORMAT));

        mIconPersistQuality = (int) parser.getLong(
                ConfigConstants.KEY_ICON_QUALITY,
                DEFAULT_ICON_PERSIST_QUALITY);

        return result;
    }

    @VisibleForTesting
    String injectShortcutManagerConstants() {
        return android.provider.Settings.Global.getString(
                mContext.getContentResolver(),
                android.provider.Settings.Global.SHORTCUT_MANAGER_CONSTANTS);
    }

    @VisibleForTesting
    int injectDipToPixel(int dip) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip,
                mContext.getResources().getDisplayMetrics());
    }

    // === Persisting ===

    @Nullable
    private String parseStringAttribute(XmlPullParser parser, String attribute) {
        return parser.getAttributeValue(null, attribute);
    }

    private long parseLongAttribute(XmlPullParser parser, String attribute) {
        final String value = parseStringAttribute(parser, attribute);
        if (TextUtils.isEmpty(value)) {
            return 0;
        }
        try {
            return Long.parseLong(value);
        } catch (NumberFormatException e) {
            Slog.e(TAG, "Error parsing long " + value);
            return 0;
        }
    }

    @Nullable
    private ComponentName parseComponentNameAttribute(XmlPullParser parser, String attribute) {
        final String value = parseStringAttribute(parser, attribute);
        if (TextUtils.isEmpty(value)) {
            return null;
        }
        return ComponentName.unflattenFromString(value);
    }

    @Nullable
    private Intent parseIntentAttribute(XmlPullParser parser, String attribute) {
        final String value = parseStringAttribute(parser, attribute);
        if (TextUtils.isEmpty(value)) {
            return null;
        }
        try {
            return Intent.parseUri(value, /* flags =*/ 0);
        } catch (URISyntaxException e) {
            Slog.e(TAG, "Error parsing intent", e);
            return null;
        }
    }

    private void writeTagValue(XmlSerializer out, String tag, String value) throws IOException {
        if (TextUtils.isEmpty(value)) return;

        out.startTag(null, tag);
        out.attribute(null, ATTR_VALUE, value);
        out.endTag(null, tag);
    }

    private void writeTagValue(XmlSerializer out, String tag, long value) throws IOException {
        writeTagValue(out, tag, Long.toString(value));
    }

    private void writeTagExtra(XmlSerializer out, String tag, PersistableBundle bundle)
            throws IOException, XmlPullParserException {
        if (bundle == null) return;

        out.startTag(null, tag);
        bundle.saveToXml(out);
        out.endTag(null, tag);
    }

    private void writeAttr(XmlSerializer out, String name, String value) throws IOException {
        if (TextUtils.isEmpty(value)) return;

        out.attribute(null, name, value);
    }

    private void writeAttr(XmlSerializer out, String name, long value) throws IOException {
        writeAttr(out, name, String.valueOf(value));
    }

    private void writeAttr(XmlSerializer out, String name, ComponentName comp) throws IOException {
        if (comp == null) return;
        writeAttr(out, name, comp.flattenToString());
    }

    private void writeAttr(XmlSerializer out, String name, Intent intent) throws IOException {
        if (intent == null) return;

        writeAttr(out, name, intent.toUri(/* flags =*/ 0));
    }

    @VisibleForTesting
    void saveBaseStateLocked() {
        final AtomicFile file = getBaseStateFile();
        if (DEBUG) {
            Slog.i(TAG, "Saving to " + file.getBaseFile());
        }

        FileOutputStream outs = null;
        try {
            outs = file.startWrite();

            // Write to XML
            XmlSerializer out = new FastXmlSerializer();
            out.setOutput(outs, StandardCharsets.UTF_8.name());
            out.startDocument(null, true);
            out.startTag(null, TAG_ROOT);

            // Body.
            writeTagValue(out, TAG_LAST_RESET_TIME, mRawLastResetTime);

            // Epilogue.
            out.endTag(null, TAG_ROOT);
            out.endDocument();

            // Close.
            file.finishWrite(outs);
        } catch (IOException e) {
            Slog.e(TAG, "Failed to write to file " + file.getBaseFile(), e);
            file.failWrite(outs);
        }
    }

    private void loadBaseStateLocked() {
        mRawLastResetTime = 0;

        final AtomicFile file = getBaseStateFile();
        if (DEBUG) {
            Slog.i(TAG, "Loading from " + file.getBaseFile());
        }
        try (FileInputStream in = file.openRead()) {
            XmlPullParser parser = Xml.newPullParser();
            parser.setInput(in, StandardCharsets.UTF_8.name());

            int type;
            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
                if (type != XmlPullParser.START_TAG) {
                    continue;
                }
                final int depth = parser.getDepth();
                // Check the root tag
                final String tag = parser.getName();
                if (depth == 1) {
                    if (!TAG_ROOT.equals(tag)) {
                        Slog.e(TAG, "Invalid root tag: " + tag);
                        return;
                    }
                    continue;
                }
                // Assume depth == 2
                switch (tag) {
                    case TAG_LAST_RESET_TIME:
                        mRawLastResetTime = parseLongAttribute(parser, ATTR_VALUE);
                        break;
                    default:
                        Slog.e(TAG, "Invalid tag: " + tag);
                        break;
                }
            }
        } catch (FileNotFoundException e) {
            // Use the default
        } catch (IOException|XmlPullParserException e) {
            Slog.e(TAG, "Failed to read file " + file.getBaseFile(), e);

            mRawLastResetTime = 0;
        }
        // Adjust the last reset time.
        getLastResetTimeLocked();
    }

    private void saveUserLocked(@UserIdInt int userId) {
        final File path = new File(injectUserDataPath(userId), FILENAME_USER_PACKAGES);
        if (DEBUG) {
            Slog.i(TAG, "Saving to " + path);
        }
        path.mkdirs();
        final AtomicFile file = new AtomicFile(path);
        FileOutputStream outs = null;
        try {
            outs = file.startWrite();

            // Write to XML
            XmlSerializer out = new FastXmlSerializer();
            out.setOutput(outs, StandardCharsets.UTF_8.name());
            out.startDocument(null, true);
            out.startTag(null, TAG_ROOT);

            final ArrayMap<String, PackageShortcuts> packages = getUserShortcutsLocked(userId);

            // Body.
            for (int i = 0; i < packages.size(); i++) {
                final String packageName = packages.keyAt(i);
                final PackageShortcuts packageShortcuts = packages.valueAt(i);

                // TODO Move this to PackageShortcuts.

                out.startTag(null, TAG_PACKAGE);

                writeAttr(out, ATTR_NAME, packageName);
                writeAttr(out, ATTR_DYNAMIC_COUNT, packageShortcuts.mDynamicShortcutCount);
                writeAttr(out, ATTR_CALL_COUNT, packageShortcuts.mApiCallCount);
                writeAttr(out, ATTR_LAST_RESET, packageShortcuts.mLastResetTime);

                final ArrayMap<String, ShortcutInfo> shortcuts = packageShortcuts.mShortcuts;
                final int size = shortcuts.size();
                for (int j = 0; j < size; j++) {
                    saveShortcut(out, shortcuts.valueAt(j));
                }

                out.endTag(null, TAG_PACKAGE);
            }

            // Epilogue.
            out.endTag(null, TAG_ROOT);
            out.endDocument();

            // Close.
            file.finishWrite(outs);
        } catch (IOException|XmlPullParserException e) {
            Slog.e(TAG, "Failed to write to file " + file.getBaseFile(), e);
            file.failWrite(outs);
        }
    }

    private void saveShortcut(XmlSerializer out, ShortcutInfo si)
            throws IOException, XmlPullParserException {
        out.startTag(null, TAG_SHORTCUT);
        writeAttr(out, ATTR_ID, si.getId());
        // writeAttr(out, "package", si.getPackageName()); // not needed
        writeAttr(out, ATTR_ACTIVITY, si.getActivityComponent());
        // writeAttr(out, "icon", si.getIcon());  // We don't save it.
        writeAttr(out, ATTR_TITLE, si.getTitle());
        writeAttr(out, ATTR_INTENT, si.getIntentNoExtras());
        writeAttr(out, ATTR_WEIGHT, si.getWeight());
        writeAttr(out, ATTR_TIMESTAMP, si.getLastChangedTimestamp());
        writeAttr(out, ATTR_FLAGS, si.getFlags());
        writeAttr(out, ATTR_ICON_RES, si.getIconResourceId());
        writeAttr(out, ATTR_BITMAP_PATH, si.getBitmapPath());

        writeTagExtra(out, TAG_INTENT_EXTRAS, si.getIntentPersistableExtras());
        writeTagExtra(out, TAG_EXTRAS, si.getExtras());

        out.endTag(null, TAG_SHORTCUT);
    }

    private static IOException throwForInvalidTag(int depth, String tag) throws IOException {
        throw new IOException(String.format("Invalid tag '%s' found at depth %d", tag, depth));
    }

    @Nullable
    private ArrayMap<String, PackageShortcuts> loadUserLocked(@UserIdInt int userId) {
        final File path = new File(injectUserDataPath(userId), FILENAME_USER_PACKAGES);
        if (DEBUG) {
            Slog.i(TAG, "Loading from " + path);
        }
        path.mkdirs();
        final AtomicFile file = new AtomicFile(path);

        final FileInputStream in;
        try {
            in = file.openRead();
        } catch (FileNotFoundException e) {
            if (DEBUG) {
                Slog.i(TAG, "Not found " + path);
            }
            return null;
        }
        final ArrayMap<String, PackageShortcuts> ret = new ArrayMap<String, PackageShortcuts>();
        try {
            XmlPullParser parser = Xml.newPullParser();
            parser.setInput(in, StandardCharsets.UTF_8.name());

            String packageName = null;
            PackageShortcuts shortcuts = null;

            int type;
            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
                if (type != XmlPullParser.START_TAG) {
                    continue;
                }
                final int depth = parser.getDepth();

                // TODO Move some of this to PackageShortcuts.

                final String tag = parser.getName();
                if (DEBUG_LOAD) {
                    Slog.d(TAG, String.format("depth=%d type=%d name=%s",
                            depth, type, tag));
                }
                switch (depth) {
                    case 1: {
                        if (TAG_ROOT.equals(tag)) {
                            continue;
                        }
                        break;
                    }
                    case 2: {
                        switch (tag) {
                            case TAG_PACKAGE:
                                packageName = parseStringAttribute(parser, ATTR_NAME);
                                shortcuts = new PackageShortcuts(userId, packageName);
                                ret.put(packageName, shortcuts);

                                shortcuts.mDynamicShortcutCount =
                                        (int) parseLongAttribute(parser, ATTR_DYNAMIC_COUNT);
                                shortcuts.mApiCallCount =
                                        (int) parseLongAttribute(parser, ATTR_CALL_COUNT);
                                shortcuts.mLastResetTime = parseLongAttribute(parser,
                                        ATTR_LAST_RESET);
                                continue;
                        }
                        break;
                    }
                    case 3: {
                        switch (tag) {
                            case TAG_SHORTCUT:
                                final ShortcutInfo si = parseShortcut(parser, packageName);

                                // Don't use addShortcut(), we don't need to save the icon.
                                shortcuts.mShortcuts.put(si.getId(), si);
                                continue;
                        }
                        break;
                    }
                }
                throwForInvalidTag(depth, tag);
            }
            return ret;
        } catch (IOException|XmlPullParserException e) {
            Slog.e(TAG, "Failed to read file " + file.getBaseFile(), e);
            return null;
        } finally {
            IoUtils.closeQuietly(in);
        }
    }

    private ShortcutInfo parseShortcut(XmlPullParser parser, String packgeName)
            throws IOException, XmlPullParserException {
        String id;
        ComponentName activityComponent;
        Icon icon;
        String title;
        Intent intent;
        PersistableBundle intentPersistableExtras = null;
        int weight;
        PersistableBundle extras = null;
        long lastChangedTimestamp;
        int flags;
        int iconRes;
        String bitmapPath;

        id = parseStringAttribute(parser, ATTR_ID);
        activityComponent = parseComponentNameAttribute(parser, ATTR_ACTIVITY);
        title = parseStringAttribute(parser, ATTR_TITLE);
        intent = parseIntentAttribute(parser, ATTR_INTENT);
        weight = (int) parseLongAttribute(parser, ATTR_WEIGHT);
        lastChangedTimestamp = (int) parseLongAttribute(parser, ATTR_TIMESTAMP);
        flags = (int) parseLongAttribute(parser, ATTR_FLAGS);
        iconRes = (int) parseLongAttribute(parser, ATTR_ICON_RES);
        bitmapPath = parseStringAttribute(parser, ATTR_BITMAP_PATH);

        final int outerDepth = parser.getDepth();
        int type;
        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
            if (type != XmlPullParser.START_TAG) {
                continue;
            }
            final int depth = parser.getDepth();
            final String tag = parser.getName();
            if (DEBUG_LOAD) {
                Slog.d(TAG, String.format("  depth=%d type=%d name=%s",
                        depth, type, tag));
            }
            switch (tag) {
                case TAG_INTENT_EXTRAS:
                    intentPersistableExtras = PersistableBundle.restoreFromXml(parser);
                    continue;
                case TAG_EXTRAS:
                    extras = PersistableBundle.restoreFromXml(parser);
                    continue;
            }
            throw throwForInvalidTag(depth, tag);
        }
        return new ShortcutInfo(
                id, packgeName, activityComponent, /* icon =*/ null, title, intent,
                intentPersistableExtras, weight, extras, lastChangedTimestamp, flags,
                iconRes, bitmapPath);
    }

    // TODO Actually make it async.
    private void scheduleSaveBaseState() {
        synchronized (mLock) {
            saveBaseStateLocked();
        }
    }

    // TODO Actually make it async.
    private void scheduleSaveUser(@UserIdInt int userId) {
        synchronized (mLock) {
            saveUserLocked(userId);
        }
    }

    /** Return the last reset time. */
    long getLastResetTimeLocked() {
        updateTimes();
        return mRawLastResetTime;
    }

    /** Return the next reset time. */
    long getNextResetTimeLocked() {
        updateTimes();
        return mRawLastResetTime + mResetInterval;
    }

    /**
     * Update the last reset time.
     */
    private void updateTimes() {

        final long now = injectCurrentTimeMillis();

        final long prevLastResetTime = mRawLastResetTime;

        if (mRawLastResetTime == 0) { // first launch.
            // TODO Randomize??
            mRawLastResetTime = now;
        } else if (now < mRawLastResetTime) {
            // Clock rewound.
            // TODO Randomize??
            mRawLastResetTime = now;
        } else {
            // TODO Do it properly.
            while ((mRawLastResetTime + mResetInterval) <= now) {
                mRawLastResetTime += mResetInterval;
            }
        }
        if (prevLastResetTime != mRawLastResetTime) {
            scheduleSaveBaseState();
        }
    }

    /** Return the per-user state. */
    @GuardedBy("mLock")
    @NonNull
    private ArrayMap<String, PackageShortcuts> getUserShortcutsLocked(@UserIdInt int userId) {
        ArrayMap<String, PackageShortcuts> userPackages = mShortcuts.get(userId);
        if (userPackages == null) {
            userPackages = loadUserLocked(userId);
            if (userPackages == null) {
                userPackages = new ArrayMap<>();
            }
            mShortcuts.put(userId, userPackages);
        }
        return userPackages;
    }

    /** Return the per-user per-package state. */
    @GuardedBy("mLock")
    @NonNull
    private PackageShortcuts getPackageShortcutsLocked(
            @NonNull String packageName, @UserIdInt int userId) {
        final ArrayMap<String, PackageShortcuts> userPackages = getUserShortcutsLocked(userId);
        PackageShortcuts shortcuts = userPackages.get(packageName);
        if (shortcuts == null) {
            shortcuts = new PackageShortcuts(userId, packageName);
            userPackages.put(packageName, shortcuts);
        }
        return shortcuts;
    }

    // === Caller validation ===

    void removeIcon(@UserIdInt int userId, ShortcutInfo shortcut) {
        if (shortcut.getBitmapPath() != null) {
            if (DEBUG) {
                Slog.d(TAG, "Removing " + shortcut.getBitmapPath());
            }
            new File(shortcut.getBitmapPath()).delete();

            shortcut.setBitmapPath(null);
            shortcut.setIconResourceId(0);
            shortcut.clearFlags(ShortcutInfo.FLAG_HAS_ICON_FILE | ShortcutInfo.FLAG_HAS_ICON_RES);
        }
    }

    @VisibleForTesting
    static class FileOutputStreamWithPath extends FileOutputStream {
        private final File mFile;

        public FileOutputStreamWithPath(File file) throws FileNotFoundException {
            super(file);
            mFile = file;
        }

        public File getFile() {
            return mFile;
        }
    }

    /**
     * Build the cached bitmap filename for a shortcut icon.
     *
     * The filename will be based on the ID, except certain characters will be escaped.
     */
    @VisibleForTesting
    FileOutputStreamWithPath openIconFileForWrite(@UserIdInt int userId, ShortcutInfo shortcut)
            throws IOException {
        final File packagePath = new File(getUserBitmapFilePath(userId),
                shortcut.getPackageName());
        if (!packagePath.isDirectory()) {
            packagePath.mkdirs();
            if (!packagePath.isDirectory()) {
                throw new IOException("Unable to create directory " + packagePath);
            }
            SELinux.restorecon(packagePath);
        }

        final String baseName = String.valueOf(injectCurrentTimeMillis());
        for (int suffix = 0;; suffix++) {
            final String filename = (suffix == 0 ? baseName : baseName + "_" + suffix) + ".png";
            final File file = new File(packagePath, filename);
            if (!file.exists()) {
                if (DEBUG) {
                    Slog.d(TAG, "Saving icon to " + file.getAbsolutePath());
                }
                return new FileOutputStreamWithPath(file);
            }
        }
    }

    void saveIconAndFixUpShortcut(@UserIdInt int userId, ShortcutInfo shortcut) {
        if (shortcut.hasIconFile() || shortcut.hasIconResource()) {
            return;
        }

        final long token = Binder.clearCallingIdentity();
        try {
            // Clear icon info on the shortcut.
            shortcut.setIconResourceId(0);
            shortcut.setBitmapPath(null);

            final Icon icon = shortcut.getIcon();
            if (icon == null) {
                return; // has no icon
            }

            Bitmap bitmap = null;
            try {
                switch (icon.getType()) {
                    case Icon.TYPE_RESOURCE: {
                        injectValidateIconResPackage(shortcut, icon);

                        shortcut.setIconResourceId(icon.getResId());
                        shortcut.addFlags(ShortcutInfo.FLAG_HAS_ICON_RES);
                        return;
                    }
                    case Icon.TYPE_BITMAP: {
                        bitmap = icon.getBitmap();
                        break;
                    }
                    case Icon.TYPE_URI: {
                        final Uri uri = ContentProvider.maybeAddUserId(icon.getUri(), userId);

                        try (InputStream is = mContext.getContentResolver().openInputStream(uri)) {

                            bitmap = BitmapFactory.decodeStream(is);

                        } catch (IOException e) {
                            Slog.e(TAG, "Unable to load icon from " + uri);
                            return;
                        }
                        break;
                    }
                    default:
                        // This shouldn't happen because we've already validated the icon, but
                        // just in case.
                        throw ShortcutInfo.getInvalidIconException();
                }
                if (bitmap == null) {
                    Slog.e(TAG, "Null bitmap detected");
                    return;
                }
                // Shrink and write to the file.
                File path = null;
                try {
                    final FileOutputStreamWithPath out = openIconFileForWrite(userId, shortcut);
                    try {
                        path = out.getFile();

                        shrinkBitmap(bitmap, mMaxIconDimension)
                                .compress(mIconPersistFormat, mIconPersistQuality, out);

                        shortcut.setBitmapPath(out.getFile().getAbsolutePath());
                        shortcut.addFlags(ShortcutInfo.FLAG_HAS_ICON_FILE);
                    } finally {
                        IoUtils.closeQuietly(out);
                    }
                } catch (IOException|RuntimeException e) {
                    // STOPSHIP Change wtf to e
                    Slog.wtf(ShortcutService.TAG, "Unable to write bitmap to file", e);
                    if (path != null && path.exists()) {
                        path.delete();
                    }
                }
            } finally {
                if (bitmap != null) {
                    bitmap.recycle();
                }
                // Once saved, we won't use the original icon information, so null it out.
                shortcut.clearIcon();
            }
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    // Unfortunately we can't do this check in unit tests because we fake creator package names,
    // so override in unit tests.
    // TODO CTS this case.
    void injectValidateIconResPackage(ShortcutInfo shortcut, Icon icon) {
        if (!shortcut.getPackageName().equals(icon.getResPackage())) {
            throw new IllegalArgumentException(
                    "Icon resource must reside in shortcut owner package");
        }
    }

    @VisibleForTesting
    static Bitmap shrinkBitmap(Bitmap in, int maxSize) {
        // Original width/height.
        final int ow = in.getWidth();
        final int oh = in.getHeight();
        if ((ow <= maxSize) && (oh <= maxSize)) {
            if (DEBUG) {
                Slog.d(TAG, String.format("Icon size %dx%d, no need to shrink", ow, oh));
            }
            return in;
        }
        final int longerDimension = Math.max(ow, oh);

        // New width and height.
        final int nw = ow * maxSize / longerDimension;
        final int nh = oh * maxSize / longerDimension;
        if (DEBUG) {
            Slog.d(TAG, String.format("Icon size %dx%d, shrinking to %dx%d",
                    ow, oh, nw, nh));
        }

        final Bitmap scaledBitmap = Bitmap.createBitmap(nw, nh, Bitmap.Config.ARGB_8888);
        final Canvas c = new Canvas(scaledBitmap);

        final RectF dst = new RectF(0, 0, nw, nh);

        c.drawBitmap(in, /*src=*/ null, dst, /* paint =*/ null);

        in.recycle();

        return scaledBitmap;
    }

    // === Caller validation ===

    private boolean isCallerSystem() {
        final int callingUid = injectBinderCallingUid();
         return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID);
    }

    private boolean isCallerShell() {
        final int callingUid = injectBinderCallingUid();
        return callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID;
    }

    private void enforceSystemOrShell() {
        Preconditions.checkState(isCallerSystem() || isCallerShell(),
                "Caller must be system or shell");
    }

    private void enforceShell() {
        Preconditions.checkState(isCallerShell(), "Caller must be shell");
    }

    private void verifyCaller(@NonNull String packageName, @UserIdInt int userId) {
        Preconditions.checkStringNotEmpty(packageName, "packageName");

        if (isCallerSystem()) {
            return; // no check
        }

        final int callingUid = injectBinderCallingUid();

        // Otherwise, make sure the arguments are valid.
        if (UserHandle.getUserId(callingUid) != userId) {
            throw new SecurityException("Invalid user-ID");
        }
        if (injectGetPackageUid(packageName, userId) == injectBinderCallingUid()) {
            return; // Caller is valid.
        }
        throw new SecurityException("Caller UID= doesn't own " + packageName);
    }

    // Test overrides it.
    int injectGetPackageUid(@NonNull String packageName, @UserIdInt int userId) {
        try {

            // TODO Is MATCH_UNINSTALLED_PACKAGES correct to get SD card app info?

            return mContext.getPackageManager().getPackageUidAsUser(packageName,
                    PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE
                            | PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
        } catch (NameNotFoundException e) {
            return -1;
        }
    }

    /**
     * Throw if {@code numShortcuts} is bigger than {@link #mMaxDynamicShortcuts}.
     */
    void enforceMaxDynamicShortcuts(int numShortcuts) {
        if (numShortcuts > mMaxDynamicShortcuts) {
            throw new IllegalArgumentException("Max number of dynamic shortcuts exceeded");
        }
    }

    /**
     * - Sends a notification to LauncherApps
     * - Write to file
     */
    private void userPackageChanged(@NonNull String packageName, @UserIdInt int userId) {
        notifyListeners(packageName, userId);
        scheduleSaveUser(userId);
    }

    private void notifyListeners(@NonNull String packageName, @UserIdInt int userId) {
        final ArrayList<ShortcutChangeListener> copy;
        final List<ShortcutInfo> shortcuts = new ArrayList<>();
        synchronized (mLock) {
            copy = new ArrayList<>(mListeners);

            getPackageShortcutsLocked(packageName, userId)
                    .findAll(shortcuts, /* query =*/ null, ShortcutInfo.CLONE_REMOVE_NON_KEY_INFO);
        }
        for (int i = copy.size() - 1; i >= 0; i--) {
            copy.get(i).onShortcutChanged(packageName, shortcuts, userId);
        }
    }

    /**
     * Clean up / validate an incoming shortcut.
     * - Make sure all mandatory fields are set.
     * - Make sure the intent's extras are persistable, and them to set
     *  {@link ShortcutInfo#mIntentPersistableExtras}.  Also clear its extras.
     * - Clear flags.
     *
     * TODO Detailed unit tests
     */
    private void fixUpIncomingShortcutInfo(@NonNull ShortcutInfo shortcut, boolean forUpdate) {
        Preconditions.checkNotNull(shortcut, "Null shortcut detected");
        if (shortcut.getActivityComponent() != null) {
            Preconditions.checkState(
                    shortcut.getPackageName().equals(
                            shortcut.getActivityComponent().getPackageName()),
                    "Activity package name mismatch");
        }

        if (!forUpdate) {
            shortcut.enforceMandatoryFields();
        }
        if (shortcut.getIcon() != null) {
            ShortcutInfo.validateIcon(shortcut.getIcon());
        }

        validateForXml(shortcut.getId());
        validateForXml(shortcut.getTitle());
        validatePersistableBundleForXml(shortcut.getIntentPersistableExtras());
        validatePersistableBundleForXml(shortcut.getExtras());

        shortcut.setFlags(0);
    }

    // KXmlSerializer is strict and doesn't allow certain characters, so we disallow those
    // characters.

    private static void validatePersistableBundleForXml(PersistableBundle b) {
        if (b == null || b.size() == 0) {
            return;
        }
        for (String key : b.keySet()) {
            validateForXml(key);
            final Object value = b.get(key);
            if (value == null) {
                continue;
            } else if (value instanceof String) {
                validateForXml((String) value);
            } else if (value instanceof String[]) {
                for (String v : (String[]) value) {
                    validateForXml(v);
                }
            } else if (value instanceof PersistableBundle) {
                validatePersistableBundleForXml((PersistableBundle) value);
            }
        }
    }

    private static void validateForXml(String s) {
        if (TextUtils.isEmpty(s)) {
            return;
        }
        for (int i = s.length() - 1; i >= 0; i--) {
            if (!isAllowedInXml(s.charAt(i))) {
                throw new IllegalArgumentException("Unsupported character detected in: " + s);
            }
        }
    }

    private static boolean isAllowedInXml(char c) {
        return (c >= 0x20 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xfffd);
    }

    // === APIs ===

    @Override
    public boolean setDynamicShortcuts(String packageName, ParceledListSlice shortcutInfoList,
            @UserIdInt int userId) {
        verifyCaller(packageName, userId);

        final List<ShortcutInfo> newShortcuts = (List<ShortcutInfo>) shortcutInfoList.getList();
        final int size = newShortcuts.size();

        synchronized (mLock) {
            final PackageShortcuts ps = getPackageShortcutsLocked(packageName, userId);

            // Throttling.
            if (!ps.tryApiCall(this)) {
                return false;
            }
            enforceMaxDynamicShortcuts(size);

            // Validate the shortcuts.
            for (int i = 0; i < size; i++) {
                fixUpIncomingShortcutInfo(newShortcuts.get(i), /* forUpdate= */ false);
            }

            // First, remove all un-pinned; dynamic shortcuts
            ps.deleteAllDynamicShortcuts(this);

            // Then, add/update all.  We need to make sure to take over "pinned" flag.
            for (int i = 0; i < size; i++) {
                final ShortcutInfo newShortcut = newShortcuts.get(i);
                newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
                ps.updateShortcutWithCapping(this, newShortcut);
            }
        }
        userPackageChanged(packageName, userId);
        return true;
    }

    @Override
    public boolean updateShortcuts(String packageName, ParceledListSlice shortcutInfoList,
            @UserIdInt int userId) {
        verifyCaller(packageName, userId);

        final List<ShortcutInfo> newShortcuts = (List<ShortcutInfo>) shortcutInfoList.getList();
        final int size = newShortcuts.size();

        synchronized (mLock) {
            final PackageShortcuts ps = getPackageShortcutsLocked(packageName, userId);

            // Throttling.
            if (!ps.tryApiCall(this)) {
                return false;
            }

            for (int i = 0; i < size; i++) {
                final ShortcutInfo source = newShortcuts.get(i);
                fixUpIncomingShortcutInfo(source, /* forUpdate= */ true);

                final ShortcutInfo target = ps.findShortcutById(source.getId());
                if (target != null) {
                    final boolean replacingIcon = (source.getIcon() != null);
                    if (replacingIcon) {
                        removeIcon(userId, target);
                    }

                    target.copyNonNullFieldsFrom(source);

                    if (replacingIcon) {
                        saveIconAndFixUpShortcut(userId, target);
                    }
                }
            }
        }
        userPackageChanged(packageName, userId);

        return true;
    }

    @Override
    public boolean addDynamicShortcut(String packageName, ShortcutInfo newShortcut,
            @UserIdInt int userId) {
        verifyCaller(packageName, userId);

        synchronized (mLock) {
            final PackageShortcuts ps = getPackageShortcutsLocked(packageName, userId);

            // Throttling.
            if (!ps.tryApiCall(this)) {
                return false;
            }

            // Validate the shortcut.
            fixUpIncomingShortcutInfo(newShortcut, /* forUpdate= */ false);

            // Add it.
            newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
            ps.updateShortcutWithCapping(this, newShortcut);
        }
        userPackageChanged(packageName, userId);

        return true;
    }

    @Override
    public void deleteDynamicShortcut(String packageName, String shortcutId,
            @UserIdInt int userId) {
        verifyCaller(packageName, userId);
        Preconditions.checkStringNotEmpty(shortcutId, "shortcutId must be provided");

        synchronized (mLock) {
            getPackageShortcutsLocked(packageName, userId).deleteDynamicWithId(this, shortcutId);
        }
        userPackageChanged(packageName, userId);
    }

    @Override
    public void deleteAllDynamicShortcuts(String packageName, @UserIdInt int userId) {
        verifyCaller(packageName, userId);

        synchronized (mLock) {
            getPackageShortcutsLocked(packageName, userId).deleteAllDynamicShortcuts(this);
        }
        userPackageChanged(packageName, userId);
    }

    @Override
    public ParceledListSlice<ShortcutInfo> getDynamicShortcuts(String packageName,
            @UserIdInt int userId) {
        verifyCaller(packageName, userId);
        synchronized (mLock) {
            return getShortcutsWithQueryLocked(
                    packageName, userId, ShortcutInfo.CLONE_REMOVE_FOR_CREATOR,
                    ShortcutInfo::isDynamic);
        }
    }

    @Override
    public ParceledListSlice<ShortcutInfo> getPinnedShortcuts(String packageName,
            @UserIdInt int userId) {
        verifyCaller(packageName, userId);
        synchronized (mLock) {
            return getShortcutsWithQueryLocked(
                    packageName, userId, ShortcutInfo.CLONE_REMOVE_FOR_CREATOR,
                    ShortcutInfo::isPinned);
        }
    }

    private ParceledListSlice<ShortcutInfo> getShortcutsWithQueryLocked(@NonNull String packageName,
            @UserIdInt int userId, int cloneFlags, @NonNull Predicate<ShortcutInfo> query) {

        final ArrayList<ShortcutInfo> ret = new ArrayList<>();

        getPackageShortcutsLocked(packageName, userId).findAll(ret, query, cloneFlags);

        return new ParceledListSlice<>(ret);
    }

    @Override
    public int getMaxDynamicShortcutCount(String packageName, @UserIdInt int userId)
            throws RemoteException {
        verifyCaller(packageName, userId);

        return mMaxDynamicShortcuts;
    }

    @Override
    public int getRemainingCallCount(String packageName, @UserIdInt int userId) {
        verifyCaller(packageName, userId);

        synchronized (mLock) {
            return mMaxDailyUpdates
                    - getPackageShortcutsLocked(packageName, userId).getApiCallCount(this);
        }
    }

    @Override
    public long getRateLimitResetTime(String packageName, @UserIdInt int userId) {
        verifyCaller(packageName, userId);

        synchronized (mLock) {
            return getNextResetTimeLocked();
        }
    }

    @Override
    public int getIconMaxDimensions(String packageName, int userId) throws RemoteException {
        synchronized (mLock) {
            return mMaxIconDimension;
        }
    }

    /**
     * Reset all throttling, for developer options and command line.  Only system/shell can call it.
     */
    @Override
    public void resetThrottling() {
        enforceSystemOrShell();

        resetThrottlingInner();
    }

    @VisibleForTesting
    void resetThrottlingInner() {
        synchronized (mLock) {
            mRawLastResetTime = injectCurrentTimeMillis();
        }
        scheduleSaveBaseState();
        Slog.i(TAG, "ShortcutManager: throttling counter reset");
    }

    /**
     * Entry point from {@link LauncherApps}.
     */
    private class LocalService extends ShortcutServiceInternal {
        @Override
        public List<ShortcutInfo> getShortcuts(
                @NonNull String callingPackage, long changedSince,
                @Nullable String packageName, @Nullable ComponentName componentName,
                int queryFlags, int userId) {
            final ArrayList<ShortcutInfo> ret = new ArrayList<>();
            final int cloneFlag =
                    ((queryFlags & ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY) == 0)
                            ? ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER
                            : ShortcutInfo.CLONE_REMOVE_NON_KEY_INFO;

            synchronized (mLock) {
                if (packageName != null) {
                    getShortcutsInnerLocked(packageName, changedSince, componentName, queryFlags,
                            userId, ret, cloneFlag);
                } else {
                    final ArrayMap<String, PackageShortcuts> packages =
                            getUserShortcutsLocked(userId);
                    for (int i = packages.size() - 1; i >= 0; i--) {
                        getShortcutsInnerLocked(
                                packages.keyAt(i),
                                changedSince, componentName, queryFlags, userId, ret, cloneFlag);
                    }
                }
            }
            return ret;
        }

        private void getShortcutsInnerLocked(@Nullable String packageName,long changedSince,
                @Nullable ComponentName componentName, int queryFlags,
                int userId, ArrayList<ShortcutInfo> ret, int cloneFlag) {
            getPackageShortcutsLocked(packageName, userId).findAll(ret,
                    (ShortcutInfo si) -> {
                        if (si.getLastChangedTimestamp() < changedSince) {
                            return false;
                        }
                        if (componentName != null
                                && !componentName.equals(si.getActivityComponent())) {
                            return false;
                        }
                        final boolean matchDynamic =
                                ((queryFlags & ShortcutQuery.FLAG_GET_DYNAMIC) != 0)
                                && si.isDynamic();
                        final boolean matchPinned =
                                ((queryFlags & ShortcutQuery.FLAG_GET_PINNED) != 0)
                                        && si.isPinned();
                        return matchDynamic || matchPinned;
                    }, cloneFlag);
        }

        @Override
        public List<ShortcutInfo> getShortcutInfo(
                @NonNull String callingPackage,
                @NonNull String packageName, @Nullable List<String> ids, int userId) {
            // Calling permission must be checked by LauncherAppsImpl.
            Preconditions.checkStringNotEmpty(packageName, "packageName");

            final ArrayList<ShortcutInfo> ret = new ArrayList<>(ids.size());
            final ArraySet<String> idSet = new ArraySet<>(ids);
            synchronized (mLock) {
                getPackageShortcutsLocked(packageName, userId).findAll(ret,
                        (ShortcutInfo si) -> idSet.contains(si.getId()),
                        ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER);
            }
            return ret;
        }

        @Override
        public void pinShortcuts(@NonNull String callingPackage, @NonNull String packageName,
                @NonNull List<String> shortcutIds, int userId) {
            // Calling permission must be checked by LauncherAppsImpl.
            Preconditions.checkStringNotEmpty(packageName, "packageName");
            Preconditions.checkNotNull(shortcutIds, "shortcutIds");

            synchronized (mLock) {
                getPackageShortcutsLocked(packageName, userId).replacePinned(
                        ShortcutService.this, callingPackage, shortcutIds);
            }
            userPackageChanged(packageName, userId);
        }

        @Override
        public Intent createShortcutIntent(@NonNull String callingPackage,
                @NonNull String packageName, @NonNull String shortcutId, int userId) {
            // Calling permission must be checked by LauncherAppsImpl.
            Preconditions.checkStringNotEmpty(packageName, "packageName can't be empty");
            Preconditions.checkStringNotEmpty(shortcutId, "shortcutId can't be empty");

            synchronized (mLock) {
                final ShortcutInfo fullShortcut =
                        getPackageShortcutsLocked(packageName, userId)
                        .findShortcutById(shortcutId);
                return fullShortcut == null ? null : fullShortcut.getIntent();
            }
        }

        @Override
        public void addListener(@NonNull ShortcutChangeListener listener) {
            synchronized (mLock) {
                mListeners.add(Preconditions.checkNotNull(listener));
            }
        }

        @Override
        public int getShortcutIconResId(@NonNull String callingPackage,
                @NonNull ShortcutInfo shortcut, int userId) {
            Preconditions.checkNotNull(shortcut, "shortcut");

            synchronized (mLock) {
                final ShortcutInfo shortcutInfo = getPackageShortcutsLocked(
                        shortcut.getPackageName(), userId).findShortcutById(shortcut.getId());
                return (shortcutInfo != null && shortcutInfo.hasIconResource())
                        ? shortcutInfo.getIconResourceId() : 0;
            }
        }

        @Override
        public ParcelFileDescriptor getShortcutIconFd(@NonNull String callingPackage,
                @NonNull ShortcutInfo shortcut, int userId) {
            Preconditions.checkNotNull(shortcut, "shortcut");

            synchronized (mLock) {
                final ShortcutInfo shortcutInfo = getPackageShortcutsLocked(
                        shortcut.getPackageName(), userId).findShortcutById(shortcut.getId());
                if (shortcutInfo == null || !shortcutInfo.hasIconFile()) {
                    return null;
                }
                try {
                    return ParcelFileDescriptor.open(
                            new File(shortcutInfo.getBitmapPath()),
                            ParcelFileDescriptor.MODE_READ_ONLY);
                } catch (FileNotFoundException e) {
                    Slog.e(TAG, "Icon file not found: " + shortcutInfo.getBitmapPath());
                    return null;
                }
            }
        }
    }

    // === Dump ===

    @Override
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
                != PackageManager.PERMISSION_GRANTED) {
            pw.println("Permission Denial: can't dump UserManager from from pid="
                    + Binder.getCallingPid()
                    + ", uid=" + Binder.getCallingUid()
                    + " without permission "
                    + android.Manifest.permission.DUMP);
            return;
        }
        dumpInner(pw);
    }

    @VisibleForTesting
    void dumpInner(PrintWriter pw) {
        synchronized (mLock) {
            final long now = injectCurrentTimeMillis();
            pw.print("Now: [");
            pw.print(now);
            pw.print("] ");
            pw.print(formatTime(now));

            pw.print("  Raw last reset: [");
            pw.print(mRawLastResetTime);
            pw.print("] ");
            pw.print(formatTime(mRawLastResetTime));

            final long last = getLastResetTimeLocked();
            pw.print("  Last reset: [");
            pw.print(last);
            pw.print("] ");
            pw.print(formatTime(last));

            final long next = getNextResetTimeLocked();
            pw.print("  Next reset: [");
            pw.print(next);
            pw.print("] ");
            pw.print(formatTime(next));
            pw.println();

            pw.print("  Max icon dim: ");
            pw.print(mMaxIconDimension);
            pw.print("  Icon format: ");
            pw.print(mIconPersistFormat);
            pw.print("  Icon quality: ");
            pw.print(mIconPersistQuality);
            pw.println();

            pw.println();

            for (int i = 0; i < mShortcuts.size(); i++) {
                dumpUserLocked(pw, mShortcuts.keyAt(i));
            }
        }
    }

    private void dumpUserLocked(PrintWriter pw, int userId) {
        pw.print("  User: ");
        pw.print(userId);
        pw.println();

        final ArrayMap<String, PackageShortcuts> packages = mShortcuts.get(userId);
        if (packages == null) {
            return;
        }
        for (int j = 0; j < packages.size(); j++) {
            dumpPackageLocked(pw, userId, packages.keyAt(j));
        }
        pw.println();
    }

    private void dumpPackageLocked(PrintWriter pw, int userId, String packageName) {
        final PackageShortcuts packageShortcuts = mShortcuts.get(userId).get(packageName);
        if (packageShortcuts == null) {
            return;
        }

        pw.print("    Package: ");
        pw.print(packageName);
        pw.println();

        pw.print("      Calls: ");
        pw.print(packageShortcuts.getApiCallCount(this));
        pw.println();

        // This should be after getApiCallCount(), which may update it.
        pw.print("      Last reset: [");
        pw.print(packageShortcuts.mLastResetTime);
        pw.print("] ");
        pw.print(formatTime(packageShortcuts.mLastResetTime));
        pw.println();

        pw.println("      Shortcuts:");
        long totalBitmapSize = 0;
        final ArrayMap<String, ShortcutInfo> shortcuts = packageShortcuts.mShortcuts;
        final int size = shortcuts.size();
        for (int i = 0; i < size; i++) {
            final ShortcutInfo si = shortcuts.valueAt(i);
            pw.print("        ");
            pw.println(si.toInsecureString());
            if (si.hasIconFile()) {
                final long len = new File(si.getBitmapPath()).length();
                pw.print("          ");
                pw.print("bitmap size=");
                pw.println(len);

                totalBitmapSize += len;
            }
        }
        pw.print("      Total bitmap size: ");
        pw.print(totalBitmapSize);
        pw.print(" (");
        pw.print(Formatter.formatFileSize(mContext, totalBitmapSize));
        pw.println(")");
    }

    private static String formatTime(long time) {
        Time tobj = new Time();
        tobj.set(time);
        return tobj.format("%Y-%m-%d %H:%M:%S");
    }

    // === Shell support ===

    @Override
    public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
            String[] args, ResultReceiver resultReceiver) throws RemoteException {

        enforceShell();

        (new MyShellCommand()).exec(this, in, out, err, args, resultReceiver);
    }

    /**
     * Handle "adb shell cmd".
     */
    private class MyShellCommand extends ShellCommand {
        @Override
        public int onCommand(String cmd) {
            if (cmd == null) {
                return handleDefaultCommands(cmd);
            }
            final PrintWriter pw = getOutPrintWriter();
            int ret = 1;
            switch (cmd) {
                case "reset-package-throttling":
                    ret = handleResetPackageThrottling();
                    break;
                case "reset-throttling":
                    ret = handleResetThrottling();
                    break;
                case "override-config":
                    ret = handleOverrideConfig();
                    break;
                case "reset-config":
                    ret = handleResetConfig();
                    break;
                default:
                    return handleDefaultCommands(cmd);
            }
            if (ret == 0) {
                pw.println("Success");
            }
            return ret;
        }

        @Override
        public void onHelp() {
            final PrintWriter pw = getOutPrintWriter();
            pw.println("Usage: cmd shortcut COMMAND [options ...]");
            pw.println();
            pw.println("cmd shortcut reset-package-throttling [--user USER_ID] PACKAGE");
            pw.println("    Reset throttling for a package");
            pw.println();
            pw.println("cmd shortcut reset-throttling");
            pw.println("    Reset throttling for all packages and users");
            pw.println();
            pw.println("cmd shortcut override-config CONFIG");
            pw.println("    Override the configuration for testing (will last until reboot)");
            pw.println();
            pw.println("cmd shortcut reset-config");
            pw.println("    Reset the configuration set with \"update-config\"");
            pw.println();
        }

        private int handleResetThrottling() {
            resetThrottling();
            return 0;
        }

        private int handleResetPackageThrottling() {
            final PrintWriter pw = getOutPrintWriter();

            int userId = UserHandle.USER_SYSTEM;
            String opt;
            while ((opt = getNextOption()) != null) {
                switch (opt) {
                    case "--user":
                        userId = UserHandle.parseUserArg(getNextArgRequired());
                        break;
                    default:
                        pw.println("Error: Unknown option: " + opt);
                        return 1;
                }
            }
            final String packageName = getNextArgRequired();

            synchronized (mLock) {
                getPackageShortcutsLocked(packageName, userId).resetRateLimitingForCommandLine();
                saveUserLocked(userId);
            }

            return 0;
        }

        private int handleOverrideConfig() {
            final PrintWriter pw = getOutPrintWriter();
            final String config = getNextArgRequired();

            synchronized (mLock) {
                if (!updateConfigurationLocked(config)) {
                    pw.println("override-config failed.  See logcat for details.");
                    return 1;
                }
            }
            return 0;
        }

        private int handleResetConfig() {
            synchronized (mLock) {
                loadConfigurationLocked();
            }
            return 0;
        }
    }

    // === Unit test support ===

    // Injection point.
    long injectCurrentTimeMillis() {
        return System.currentTimeMillis();
    }

    // Injection point.
    int injectBinderCallingUid() {
        return getCallingUid();
    }

    File injectSystemDataPath() {
        return Environment.getDataSystemDirectory();
    }

    File injectUserDataPath(@UserIdInt int userId) {
        return new File(Environment.getDataSystemCeDirectory(userId), DIRECTORY_PER_USER);
    }

    @VisibleForTesting
    boolean injectIsLowRamDevice() {
        return ActivityManager.isLowRamDeviceStatic();
    }

    File getUserBitmapFilePath(@UserIdInt int userId) {
        return new File(injectUserDataPath(userId), DIRECTORY_BITMAPS);
    }

    @VisibleForTesting
    SparseArray<ArrayMap<String, PackageShortcuts>> getShortcutsForTest() {
        return mShortcuts;
    }

    @VisibleForTesting
    int getMaxDynamicShortcutsForTest() {
        return mMaxDynamicShortcuts;
    }

    @VisibleForTesting
    int getMaxDailyUpdatesForTest() {
        return mMaxDailyUpdates;
    }

    @VisibleForTesting
    long getResetIntervalForTest() {
        return mResetInterval;
    }

    @VisibleForTesting
    int getMaxIconDimensionForTest() {
        return mMaxIconDimension;
    }

    @VisibleForTesting
    CompressFormat getIconPersistFormatForTest() {
        return mIconPersistFormat;
    }

    @VisibleForTesting
    int getIconPersistQualityForTest() {
        return mIconPersistQuality;
    }
}
