/*
 * 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.content.ComponentName;
import android.content.pm.ShortcutManager;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
import com.android.server.pm.ShortcutService.DumpFilter;
import com.android.server.pm.ShortcutService.InvalidFileFormatException;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Objects;
import java.util.function.Consumer;

/**
 * User information used by {@link ShortcutService}.
 *
 * All methods should be guarded by {@code #mService.mLock}.
 */
class ShortcutUser {
    private static final String TAG = ShortcutService.TAG;

    static final String TAG_ROOT = "user";
    private static final String TAG_LAUNCHER = "launcher";

    private static final String ATTR_VALUE = "value";
    private static final String ATTR_KNOWN_LOCALES = "locales";

    // Suffix "2" was added to force rescan all packages after the next OTA.
    private static final String ATTR_LAST_APP_SCAN_TIME = "last-app-scan-time2";
    private static final String ATTR_LAST_APP_SCAN_OS_FINGERPRINT = "last-app-scan-fp";
    private static final String ATTR_RESTORE_SOURCE_FINGERPRINT = "restore-from-fp";
    private static final String KEY_USER_ID = "userId";
    private static final String KEY_LAUNCHERS = "launchers";
    private static final String KEY_PACKAGES = "packages";

    static final class PackageWithUser {
        final int userId;
        final String packageName;

        private PackageWithUser(int userId, String packageName) {
            this.userId = userId;
            this.packageName = Preconditions.checkNotNull(packageName);
        }

        public static PackageWithUser of(int userId, String packageName) {
            return new PackageWithUser(userId, packageName);
        }

        public static PackageWithUser of(ShortcutPackageItem spi) {
            return new PackageWithUser(spi.getPackageUserId(), spi.getPackageName());
        }

        @Override
        public int hashCode() {
            return packageName.hashCode() ^ userId;
        }

        @Override
        public boolean equals(Object obj) {
            if (!(obj instanceof PackageWithUser)) {
                return false;
            }
            final PackageWithUser that = (PackageWithUser) obj;

            return userId == that.userId && packageName.equals(that.packageName);
        }

        @Override
        public String toString() {
            return String.format("[Package: %d, %s]", userId, packageName);
        }
    }

    final ShortcutService mService;

    @UserIdInt
    private final int mUserId;

    private final ArrayMap<String, ShortcutPackage> mPackages = new ArrayMap<>();

    private final ArrayMap<PackageWithUser, ShortcutLauncher> mLaunchers = new ArrayMap<>();

    /**
     * Last known launcher.  It's used when the default launcher isn't set in PM -- i.e.
     * when getHomeActivitiesAsUser() return null.  We need it so that in this situation the
     * previously default launcher can still access shortcuts.
     */
    private ComponentName mLastKnownLauncher;

    /** In-memory-cached default launcher. */
    private ComponentName mCachedLauncher;

    private String mKnownLocales;

    private long mLastAppScanTime;

    private String mLastAppScanOsFingerprint;
    private String mRestoreFromOsFingerprint;

    public ShortcutUser(ShortcutService service, int userId) {
        mService = service;
        mUserId = userId;
    }

    public int getUserId() {
        return mUserId;
    }

    public long getLastAppScanTime() {
        return mLastAppScanTime;
    }

    public void setLastAppScanTime(long lastAppScanTime) {
        mLastAppScanTime = lastAppScanTime;
    }

    public String getLastAppScanOsFingerprint() {
        return mLastAppScanOsFingerprint;
    }

    public void setLastAppScanOsFingerprint(String lastAppScanOsFingerprint) {
        mLastAppScanOsFingerprint = lastAppScanOsFingerprint;
    }

    // We don't expose this directly to non-test code because only ShortcutUser should add to/
    // remove from it.
    @VisibleForTesting
    ArrayMap<String, ShortcutPackage> getAllPackagesForTest() {
        return mPackages;
    }

    public boolean hasPackage(@NonNull String packageName) {
        return mPackages.containsKey(packageName);
    }

    private void addPackage(@NonNull ShortcutPackage p) {
        p.replaceUser(this);
        mPackages.put(p.getPackageName(), p);
    }

    public ShortcutPackage removePackage(@NonNull String packageName) {
        final ShortcutPackage removed = mPackages.remove(packageName);

        mService.cleanupBitmapsForPackage(mUserId, packageName);

        return removed;
    }

    // We don't expose this directly to non-test code because only ShortcutUser should add to/
    // remove from it.
    @VisibleForTesting
    ArrayMap<PackageWithUser, ShortcutLauncher> getAllLaunchersForTest() {
        return mLaunchers;
    }

    private void addLauncher(ShortcutLauncher launcher) {
        launcher.replaceUser(this);
        mLaunchers.put(PackageWithUser.of(launcher.getPackageUserId(),
                launcher.getPackageName()), launcher);
    }

    @Nullable
    public ShortcutLauncher removeLauncher(
            @UserIdInt int packageUserId, @NonNull String packageName) {
        return mLaunchers.remove(PackageWithUser.of(packageUserId, packageName));
    }

    @Nullable
    public ShortcutPackage getPackageShortcutsIfExists(@NonNull String packageName) {
        final ShortcutPackage ret = mPackages.get(packageName);
        if (ret != null) {
            ret.attemptToRestoreIfNeededAndSave();
        }
        return ret;
    }

    @NonNull
    public ShortcutPackage getPackageShortcuts(@NonNull String packageName) {
        ShortcutPackage ret = getPackageShortcutsIfExists(packageName);
        if (ret == null) {
            ret = new ShortcutPackage(this, mUserId, packageName);
            mPackages.put(packageName, ret);
        }
        return ret;
    }

    @NonNull
    public ShortcutLauncher getLauncherShortcuts(@NonNull String packageName,
            @UserIdInt int launcherUserId) {
        final PackageWithUser key = PackageWithUser.of(launcherUserId, packageName);
        ShortcutLauncher ret = mLaunchers.get(key);
        if (ret == null) {
            ret = new ShortcutLauncher(this, mUserId, packageName, launcherUserId);
            mLaunchers.put(key, ret);
        } else {
            ret.attemptToRestoreIfNeededAndSave();
        }
        return ret;
    }

    public void forAllPackages(Consumer<? super ShortcutPackage> callback) {
        final int size = mPackages.size();
        for (int i = 0; i < size; i++) {
            callback.accept(mPackages.valueAt(i));
        }
    }

    public void forAllLaunchers(Consumer<? super ShortcutLauncher> callback) {
        final int size = mLaunchers.size();
        for (int i = 0; i < size; i++) {
            callback.accept(mLaunchers.valueAt(i));
        }
    }

    public void forAllPackageItems(Consumer<? super ShortcutPackageItem> callback) {
        forAllLaunchers(callback);
        forAllPackages(callback);
    }

    public void forPackageItem(@NonNull String packageName, @UserIdInt int packageUserId,
            Consumer<ShortcutPackageItem> callback) {
        forAllPackageItems(spi -> {
            if ((spi.getPackageUserId() == packageUserId)
                    && spi.getPackageName().equals(packageName)) {
                callback.accept(spi);
            }
        });
    }

    /**
     * Must be called at any entry points on {@link ShortcutManager} APIs to make sure the
     * information on the package is up-to-date.
     *
     * We use broadcasts to handle locale changes and package changes, but because broadcasts
     * are asynchronous, there's a chance a publisher calls getXxxShortcuts() after a certain event
     * (e.g. system locale change) but shortcut manager hasn't finished processing the broadcast.
     *
     * So we call this method at all entry points from publishers to make sure we update all
     * relevant information.
     *
     * Similar inconsistencies can happen when the launcher fetches shortcut information, but
     * that's a less of an issue because for the launcher we report shortcut changes with
     * callbacks.
     */
    public void onCalledByPublisher(@NonNull String packageName) {
        detectLocaleChange();
        rescanPackageIfNeeded(packageName, /*forceRescan=*/ false);
    }

    private String getKnownLocales() {
        if (TextUtils.isEmpty(mKnownLocales)) {
            mKnownLocales = mService.injectGetLocaleTagsForUser(mUserId);
            mService.scheduleSaveUser(mUserId);
        }
        return mKnownLocales;
    }

    /**
     * Check to see if the system locale has changed, and if so, reset throttling
     * and update resource strings.
     */
    public void detectLocaleChange() {
        final String currentLocales = mService.injectGetLocaleTagsForUser(mUserId);
        if (!TextUtils.isEmpty(mKnownLocales) && mKnownLocales.equals(currentLocales)) {
            return;
        }
        if (ShortcutService.DEBUG) {
            Slog.d(TAG, "Locale changed from " + mKnownLocales + " to " + currentLocales
                    + " for user " + mUserId);
        }

        mKnownLocales = currentLocales;

        forAllPackages(pkg -> {
            pkg.resetRateLimiting();
            pkg.resolveResourceStrings();
        });

        mService.scheduleSaveUser(mUserId);
    }

    public void rescanPackageIfNeeded(@NonNull String packageName, boolean forceRescan) {
        final boolean isNewApp = !mPackages.containsKey(packageName);

        final ShortcutPackage shortcutPackage = getPackageShortcuts(packageName);

        if (!shortcutPackage.rescanPackageIfNeeded(isNewApp, forceRescan)) {
            if (isNewApp) {
                mPackages.remove(packageName);
            }
        }
    }

    public void attemptToRestoreIfNeededAndSave(ShortcutService s, @NonNull String packageName,
            @UserIdInt int packageUserId) {
        forPackageItem(packageName, packageUserId, spi -> {
            spi.attemptToRestoreIfNeededAndSave();
        });
    }

    public void saveToXml(XmlSerializer out, boolean forBackup)
            throws IOException, XmlPullParserException {
        out.startTag(null, TAG_ROOT);

        if (!forBackup) {
            // Don't have to back them up.
            ShortcutService.writeAttr(out, ATTR_KNOWN_LOCALES, mKnownLocales);
            ShortcutService.writeAttr(out, ATTR_LAST_APP_SCAN_TIME,
                    mLastAppScanTime);
            ShortcutService.writeAttr(out, ATTR_LAST_APP_SCAN_OS_FINGERPRINT,
                    mLastAppScanOsFingerprint);
            ShortcutService.writeAttr(out, ATTR_RESTORE_SOURCE_FINGERPRINT,
                    mRestoreFromOsFingerprint);

            ShortcutService.writeTagValue(out, TAG_LAUNCHER, mLastKnownLauncher);
        } else {
            ShortcutService.writeAttr(out, ATTR_RESTORE_SOURCE_FINGERPRINT,
                    mService.injectBuildFingerprint());
        }

        // Can't use forEachPackageItem due to the checked exceptions.
        {
            final int size = mLaunchers.size();
            for (int i = 0; i < size; i++) {
                saveShortcutPackageItem(out, mLaunchers.valueAt(i), forBackup);
            }
        }
        {
            final int size = mPackages.size();
            for (int i = 0; i < size; i++) {
                saveShortcutPackageItem(out, mPackages.valueAt(i), forBackup);
            }
        }

        out.endTag(null, TAG_ROOT);
    }

    private void saveShortcutPackageItem(XmlSerializer out,
            ShortcutPackageItem spi, boolean forBackup) throws IOException, XmlPullParserException {
        if (forBackup) {
            if (spi.getPackageUserId() != spi.getOwnerUserId()) {
                return; // Don't save cross-user information.
            }
        }
        spi.saveToXml(out, forBackup);
    }

    public static ShortcutUser loadFromXml(ShortcutService s, XmlPullParser parser, int userId,
            boolean fromBackup) throws IOException, XmlPullParserException, InvalidFileFormatException {
        final ShortcutUser ret = new ShortcutUser(s, userId);

        try {
            ret.mKnownLocales = ShortcutService.parseStringAttribute(parser,
                    ATTR_KNOWN_LOCALES);

            // If lastAppScanTime is in the future, that means the clock went backwards.
            // Just scan all apps again.
            final long lastAppScanTime = ShortcutService.parseLongAttribute(parser,
                    ATTR_LAST_APP_SCAN_TIME);
            final long currentTime = s.injectCurrentTimeMillis();
            ret.mLastAppScanTime = lastAppScanTime < currentTime ? lastAppScanTime : 0;
            ret.mLastAppScanOsFingerprint = ShortcutService.parseStringAttribute(parser,
                    ATTR_LAST_APP_SCAN_OS_FINGERPRINT);
            ret.mRestoreFromOsFingerprint = ShortcutService.parseStringAttribute(parser,
                    ATTR_RESTORE_SOURCE_FINGERPRINT);
            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 (depth == outerDepth + 1) {
                    switch (tag) {
                        case TAG_LAUNCHER: {
                            ret.mLastKnownLauncher = ShortcutService.parseComponentNameAttribute(
                                    parser, ATTR_VALUE);
                            continue;
                        }
                        case ShortcutPackage.TAG_ROOT: {
                            final ShortcutPackage shortcuts = ShortcutPackage.loadFromXml(
                                    s, ret, parser, fromBackup);

                            // Don't use addShortcut(), we don't need to save the icon.
                            ret.mPackages.put(shortcuts.getPackageName(), shortcuts);
                            continue;
                        }

                        case ShortcutLauncher.TAG_ROOT: {
                            ret.addLauncher(
                                    ShortcutLauncher.loadFromXml(parser, ret, userId, fromBackup));
                            continue;
                        }
                    }
                }
                ShortcutService.warnForInvalidTag(depth, tag);
            }
        } catch (RuntimeException e) {
            throw new ShortcutService.InvalidFileFormatException(
                    "Unable to parse file", e);
        }
        return ret;
    }

    public ComponentName getLastKnownLauncher() {
        return mLastKnownLauncher;
    }

    public void setLauncher(ComponentName launcherComponent) {
        setLauncher(launcherComponent, /* allowPurgeLastKnown */ false);
    }

    /** Clears the launcher information without clearing the last known one */
    public void clearLauncher() {
        setLauncher(null);
    }

    /**
     * Clears the launcher information *with(* clearing the last known one; we do this witl
     * "cmd shortcut clear-default-launcher".
     */
    public void forceClearLauncher() {
        setLauncher(null, /* allowPurgeLastKnown */ true);
    }

    private void setLauncher(ComponentName launcherComponent, boolean allowPurgeLastKnown) {
        mCachedLauncher = launcherComponent; // Always update the in-memory cache.

        if (Objects.equals(mLastKnownLauncher, launcherComponent)) {
            return;
        }
        if (!allowPurgeLastKnown && launcherComponent == null) {
            return;
        }
        mLastKnownLauncher = launcherComponent;
        mService.scheduleSaveUser(mUserId);
    }

    public ComponentName getCachedLauncher() {
        return mCachedLauncher;
    }

    public void resetThrottling() {
        for (int i = mPackages.size() - 1; i >= 0; i--) {
            mPackages.valueAt(i).resetThrottling();
        }
    }

    public void mergeRestoredFile(ShortcutUser restored) {
        final ShortcutService s = mService;
        // Note, a restore happens only at the end of setup wizard.  At this point, no apps are
        // installed from Play Store yet, but it's still possible that system apps have already
        // published dynamic shortcuts, since some apps do so on BOOT_COMPLETED.
        // When such a system app has allowbackup=true, then we go ahead and replace all existing
        // shortcuts with the restored shortcuts.  (Then we'll re-publish manifest shortcuts later
        // in the call site.)
        // When such a system app has allowbackup=false, then we'll keep the shortcuts that have
        // already been published.  So we selectively add restored ShortcutPackages here.
        //
        // The same logic applies to launchers, but since launchers shouldn't pin shortcuts
        // without users interaction it's really not a big deal, so we just clear existing
        // ShortcutLauncher instances in mLaunchers and add all the restored ones here.

        int[] restoredLaunchers = new int[1];
        int[] restoredPackages = new int[1];
        int[] restoredShortcuts = new int[1];

        mLaunchers.clear();
        restored.forAllLaunchers(sl -> {
            // If the app is already installed and allowbackup = false, then ignore the restored
            // data.
            if (s.isPackageInstalled(sl.getPackageName(), getUserId())
                    && !s.shouldBackupApp(sl.getPackageName(), getUserId())) {
                return;
            }
            addLauncher(sl);
            restoredLaunchers[0]++;
        });
        restored.forAllPackages(sp -> {
            // If the app is already installed and allowbackup = false, then ignore the restored
            // data.
            if (s.isPackageInstalled(sp.getPackageName(), getUserId())
                    && !s.shouldBackupApp(sp.getPackageName(), getUserId())) {
                return;
            }

            final ShortcutPackage previous = getPackageShortcutsIfExists(sp.getPackageName());
            if (previous != null && previous.hasNonManifestShortcuts()) {
                Log.w(TAG, "Shortcuts for package " + sp.getPackageName() + " are being restored."
                        + " Existing non-manifeset shortcuts will be overwritten.");
            }
            addPackage(sp);
            restoredPackages[0]++;
            restoredShortcuts[0] += sp.getShortcutCount();
        });
        // Empty the launchers and packages in restored to avoid accidentally using them.
        restored.mLaunchers.clear();
        restored.mPackages.clear();

        mRestoreFromOsFingerprint = restored.mRestoreFromOsFingerprint;

        Slog.i(TAG, "Restored: L=" + restoredLaunchers[0]
                + " P=" + restoredPackages[0]
                + " S=" + restoredShortcuts[0]);
    }

    public void dump(@NonNull PrintWriter pw, @NonNull String prefix, DumpFilter filter) {
        if (filter.shouldDumpDetails()) {
            pw.print(prefix);
            pw.print("User: ");
            pw.print(mUserId);
            pw.print("  Known locales: ");
            pw.print(mKnownLocales);
            pw.print("  Last app scan: [");
            pw.print(mLastAppScanTime);
            pw.print("] ");
            pw.println(ShortcutService.formatTime(mLastAppScanTime));

            prefix += prefix + "  ";

            pw.print(prefix);
            pw.print("Last app scan FP: ");
            pw.println(mLastAppScanOsFingerprint);

            pw.print(prefix);
            pw.print("Restore from FP: ");
            pw.print(mRestoreFromOsFingerprint);
            pw.println();


            pw.print(prefix);
            pw.print("Cached launcher: ");
            pw.print(mCachedLauncher);
            pw.println();

            pw.print(prefix);
            pw.print("Last known launcher: ");
            pw.print(mLastKnownLauncher);
            pw.println();
        }

        for (int i = 0; i < mLaunchers.size(); i++) {
            ShortcutLauncher launcher = mLaunchers.valueAt(i);
            if (filter.isPackageMatch(launcher.getPackageName())) {
                launcher.dump(pw, prefix, filter);
            }
        }

        for (int i = 0; i < mPackages.size(); i++) {
            ShortcutPackage pkg = mPackages.valueAt(i);
            if (filter.isPackageMatch(pkg.getPackageName())) {
                pkg.dump(pw, prefix, filter);
            }
        }

        if (filter.shouldDumpDetails()) {
            pw.println();
            pw.print(prefix);
            pw.println("Bitmap directories: ");
            dumpDirectorySize(pw, prefix + "  ", mService.getUserBitmapFilePath(mUserId));
        }
    }

    private void dumpDirectorySize(@NonNull PrintWriter pw,
            @NonNull String prefix, File path) {
        int numFiles = 0;
        long size = 0;
        final File[] children = path.listFiles();
        if (children != null) {
            for (File child : path.listFiles()) {
                if (child.isFile()) {
                    numFiles++;
                    size += child.length();
                } else if (child.isDirectory()) {
                    dumpDirectorySize(pw, prefix + "  ", child);
                }
            }
        }
        pw.print(prefix);
        pw.print("Path: ");
        pw.print(path.getName());
        pw.print("/ has ");
        pw.print(numFiles);
        pw.print(" files, size=");
        pw.print(size);
        pw.print(" (");
        pw.print(Formatter.formatFileSize(mService.mContext, size));
        pw.println(")");
    }

    public JSONObject dumpCheckin(boolean clear) throws JSONException {
        final JSONObject result = new JSONObject();

        result.put(KEY_USER_ID, mUserId);

        {
            final JSONArray launchers = new JSONArray();
            for (int i = 0; i < mLaunchers.size(); i++) {
                launchers.put(mLaunchers.valueAt(i).dumpCheckin(clear));
            }
            result.put(KEY_LAUNCHERS, launchers);
        }

        {
            final JSONArray packages = new JSONArray();
            for (int i = 0; i < mPackages.size(); i++) {
                packages.put(mPackages.valueAt(i).dumpCheckin(clear));
            }
            result.put(KEY_PACKAGES, packages);
        }

        return result;
    }
}
