/*
 * Copyright (C) 2018 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.role;

import android.annotation.CheckResult;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.os.Environment;
import android.os.Handler;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.Slog;
import android.util.Xml;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.CollectionUtils;
import com.android.internal.util.dump.DualDumpOutputStream;
import com.android.internal.util.function.pooled.PooledLambda;

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.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * Stores the state of roles for a user.
 */
public class RoleUserState {

    private static final String LOG_TAG = RoleUserState.class.getSimpleName();

    public static final int VERSION_UNDEFINED = -1;

    private static final String ROLES_FILE_NAME = "roles.xml";

    private static final long WRITE_DELAY_MILLIS = 200;

    private static final String TAG_ROLES = "roles";
    private static final String TAG_ROLE = "role";
    private static final String TAG_HOLDER = "holder";
    private static final String ATTRIBUTE_VERSION = "version";
    private static final String ATTRIBUTE_NAME = "name";
    private static final String ATTRIBUTE_PACKAGES_HASH = "packagesHash";

    @UserIdInt
    private final int mUserId;

    @NonNull
    private final Callback mCallback;

    @NonNull
    private final Object mLock = new Object();

    @GuardedBy("mLock")
    private int mVersion = VERSION_UNDEFINED;

    @GuardedBy("mLock")
    @Nullable
    private String mPackagesHash;

    /**
     * Maps role names to its holders' package names. The values should never be null.
     */
    @GuardedBy("mLock")
    @NonNull
    private ArrayMap<String, ArraySet<String>> mRoles = new ArrayMap<>();

    @GuardedBy("mLock")
    private boolean mWriteScheduled;

    @GuardedBy("mLock")
    private boolean mDestroyed;

    @NonNull
    private final Handler mWriteHandler = new Handler(BackgroundThread.getHandler().getLooper());

    /**
     * Create a new user state, and read its state from disk if previously persisted.
     *
     * @param userId the user id for this user state
     * @param callback the callback for this user state
     */
    public RoleUserState(@UserIdInt int userId, @NonNull Callback callback) {
        mUserId = userId;
        mCallback = callback;

        readFile();
    }

    /**
     * Get the version of this user state.
     */
    public int getVersion() {
        synchronized (mLock) {
            throwIfDestroyedLocked();

            return mVersion;
        }
    }

    /**
     * Set the version of this user state.
     *
     * @param version the version to set
     */
    public void setVersion(int version) {
        synchronized (mLock) {
            throwIfDestroyedLocked();

            if (mVersion == version) {
                return;
            }
            mVersion = version;
            scheduleWriteFileLocked();
        }
    }

    /**
     * Get the hash representing the state of packages during the last time initial grants was run.
     *
     * @return the hash representing the state of packages
     */
    @Nullable
    public String getPackagesHash() {
        synchronized (mLock) {
            return mPackagesHash;
        }
    }

    /**
     * Set the hash representing the state of packages during the last time initial grants was run.
     *
     * @param packagesHash the hash representing the state of packages
     */
    public void setPackagesHash(@Nullable String packagesHash) {
        synchronized (mLock) {
            throwIfDestroyedLocked();

            if (Objects.equals(mPackagesHash, packagesHash)) {
                return;
            }
            mPackagesHash = packagesHash;
            scheduleWriteFileLocked();
        }
    }

    /**
     * Get whether the role is available.
     *
     * @param roleName the name of the role to get the holders for
     *
     * @return whether the role is available
     */
    public boolean isRoleAvailable(@NonNull String roleName) {
        synchronized (mLock) {
            throwIfDestroyedLocked();

            return mRoles.containsKey(roleName);
        }
    }

    /**
     * Get the holders of a role.
     *
     * @param roleName the name of the role to query for
     *
     * @return the set of role holders, or {@code null} if and only if the role is not found
     */
    @Nullable
    public ArraySet<String> getRoleHolders(@NonNull String roleName) {
        synchronized (mLock) {
            throwIfDestroyedLocked();

            ArraySet<String> packageNames = mRoles.get(roleName);
            if (packageNames == null) {
                return null;
            }
            return new ArraySet<>(packageNames);
        }
    }

    /**
     * Adds the given role, effectively marking it as {@link #isRoleAvailable available}
     *
     * @param roleName the name of the role
     *
     * @return whether any changes were made
     */
    public boolean addRoleName(@NonNull String roleName) {
        synchronized (mLock) {
            throwIfDestroyedLocked();

            if (!mRoles.containsKey(roleName)) {
                mRoles.put(roleName, new ArraySet<>());
                Slog.i(LOG_TAG, "Added new role: " + roleName);
                scheduleWriteFileLocked();
                return true;
            } else {
                return false;
            }
        }
    }

    /**
     * Set the names of all available roles.
     *
     * @param roleNames the names of all the available roles
     */
    public void setRoleNames(@NonNull List<String> roleNames) {
        synchronized (mLock) {
            throwIfDestroyedLocked();

            boolean changed = false;

            for (int i = mRoles.size() - 1; i >= 0; i--) {
                String roleName = mRoles.keyAt(i);

                if (!roleNames.contains(roleName)) {
                    ArraySet<String> packageNames = mRoles.valueAt(i);
                    if (!packageNames.isEmpty()) {
                        Slog.e(LOG_TAG, "Holders of a removed role should have been cleaned up,"
                                + " role: " + roleName + ", holders: " + packageNames);
                    }
                    mRoles.removeAt(i);
                    changed = true;
                }
            }

            int roleNamesSize = roleNames.size();
            for (int i = 0; i < roleNamesSize; i++) {
                changed |= addRoleName(roleNames.get(i));
            }

            if (changed) {
                scheduleWriteFileLocked();
            }
        }
    }

    /**
     * Add a holder to a role.
     *
     * @param roleName the name of the role to add the holder to
     * @param packageName the package name of the new holder
     *
     * @return {@code false} if and only if the role is not found
     */
    @CheckResult
    public boolean addRoleHolder(@NonNull String roleName, @NonNull String packageName) {
        boolean changed;

        synchronized (mLock) {
            throwIfDestroyedLocked();

            ArraySet<String> roleHolders = mRoles.get(roleName);
            if (roleHolders == null) {
                Slog.e(LOG_TAG, "Cannot add role holder for unknown role, role: " + roleName
                        + ", package: " + packageName);
                return false;
            }
            changed = roleHolders.add(packageName);
            if (changed) {
                scheduleWriteFileLocked();
            }
        }

        if (changed) {
            mCallback.onRoleHoldersChanged(roleName, mUserId);
        }
        return true;
    }

    /**
     * Remove a holder from a role.
     *
     * @param roleName the name of the role to remove the holder from
     * @param packageName the package name of the holder to remove
     *
     * @return {@code false} if and only if the role is not found
     */
    @CheckResult
    public boolean removeRoleHolder(@NonNull String roleName, @NonNull String packageName) {
        boolean changed;

        synchronized (mLock) {
            throwIfDestroyedLocked();

            ArraySet<String> roleHolders = mRoles.get(roleName);
            if (roleHolders == null) {
                Slog.e(LOG_TAG, "Cannot remove role holder for unknown role, role: " + roleName
                        + ", package: " + packageName);
                return false;
            }

            changed = roleHolders.remove(packageName);
            if (changed) {
                scheduleWriteFileLocked();
            }
        }

        if (changed) {
            mCallback.onRoleHoldersChanged(roleName, mUserId);
        }
        return true;
    }

    /**
     * @see android.app.role.RoleManager#getHeldRolesFromController
     */
    @NonNull
    public List<String> getHeldRoles(@NonNull String packageName) {
        ArrayList<String> result = new ArrayList<>();
        int size = mRoles.size();
        for (int i = 0; i < size; i++) {
            if (mRoles.valueAt(i).contains(packageName)) {
                result.add(mRoles.keyAt(i));
            }
        }
        return result;
    }

    /**
     * Schedule writing the state to file.
     */
    @GuardedBy("mLock")
    private void scheduleWriteFileLocked() {
        throwIfDestroyedLocked();

        if (!mWriteScheduled) {
            mWriteHandler.sendMessageDelayed(PooledLambda.obtainMessage(RoleUserState::writeFile,
                    this), WRITE_DELAY_MILLIS);
            mWriteScheduled = true;
        }
    }

    @WorkerThread
    private void writeFile() {
        int version;
        String packagesHash;
        ArrayMap<String, ArraySet<String>> roles;
        synchronized (mLock) {
            if (mDestroyed) {
                return;
            }

            mWriteScheduled = false;

            version = mVersion;
            packagesHash = mPackagesHash;
            roles = snapshotRolesLocked();
        }

        AtomicFile atomicFile = new AtomicFile(getFile(mUserId), "roles-" + mUserId);
        FileOutputStream out = null;
        try {
            out = atomicFile.startWrite();

            XmlSerializer serializer = Xml.newSerializer();
            serializer.setOutput(out, StandardCharsets.UTF_8.name());
            serializer.setFeature(
                    "http://xmlpull.org/v1/doc/features.html#indent-output", true);
            serializer.startDocument(null, true);

            serializeRoles(serializer, version, packagesHash, roles);

            serializer.endDocument();
            atomicFile.finishWrite(out);
            Slog.i(LOG_TAG, "Wrote roles.xml successfully");
        } catch (IllegalArgumentException | IllegalStateException | IOException e) {
            Slog.wtf(LOG_TAG, "Failed to write roles.xml, restoring backup", e);
            if (out != null) {
                atomicFile.failWrite(out);
            }
        } finally {
            IoUtils.closeQuietly(out);
        }
    }

    @WorkerThread
    private void serializeRoles(@NonNull XmlSerializer serializer, int version,
            @Nullable String packagesHash, @NonNull ArrayMap<String, ArraySet<String>> roles)
            throws IOException {
        serializer.startTag(null, TAG_ROLES);

        serializer.attribute(null, ATTRIBUTE_VERSION, Integer.toString(version));

        if (packagesHash != null) {
            serializer.attribute(null, ATTRIBUTE_PACKAGES_HASH, packagesHash);
        }

        for (int i = 0, size = roles.size(); i < size; ++i) {
            String roleName = roles.keyAt(i);
            ArraySet<String> roleHolders = roles.valueAt(i);

            serializer.startTag(null, TAG_ROLE);
            serializer.attribute(null, ATTRIBUTE_NAME, roleName);
            serializeRoleHolders(serializer, roleHolders);
            serializer.endTag(null, TAG_ROLE);
        }

        serializer.endTag(null, TAG_ROLES);
    }

    @WorkerThread
    private void serializeRoleHolders(@NonNull XmlSerializer serializer,
            @NonNull ArraySet<String> roleHolders) throws IOException {
        for (int i = 0, size = roleHolders.size(); i < size; ++i) {
            String roleHolder = roleHolders.valueAt(i);

            serializer.startTag(null, TAG_HOLDER);
            serializer.attribute(null, ATTRIBUTE_NAME, roleHolder);
            serializer.endTag(null, TAG_HOLDER);
        }
    }

    /**
     * Read the state from file.
     */
    private void readFile() {
        synchronized (mLock) {
            File file = getFile(mUserId);
            try (FileInputStream in = new AtomicFile(file).openRead()) {
                XmlPullParser parser = Xml.newPullParser();
                parser.setInput(in, null);
                parseXmlLocked(parser);
                Slog.i(LOG_TAG, "Read roles.xml successfully");
            } catch (FileNotFoundException e) {
                Slog.i(LOG_TAG, "roles.xml not found");
            } catch (XmlPullParserException | IOException e) {
                throw new IllegalStateException("Failed to parse roles.xml: " + file, e);
            }
        }
    }

    private void parseXmlLocked(@NonNull XmlPullParser parser) throws IOException,
            XmlPullParserException {
        int type;
        int depth;
        int innerDepth = parser.getDepth() + 1;
        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
            if (depth > innerDepth || type != XmlPullParser.START_TAG) {
                continue;
            }

            if (parser.getName().equals(TAG_ROLES)) {
                parseRolesLocked(parser);
                return;
            }
        }
        Slog.w(LOG_TAG, "Missing <" + TAG_ROLES + "> in roles.xml");
    }

    private void parseRolesLocked(@NonNull XmlPullParser parser) throws IOException,
            XmlPullParserException {
        mVersion = Integer.parseInt(parser.getAttributeValue(null, ATTRIBUTE_VERSION));
        mPackagesHash = parser.getAttributeValue(null, ATTRIBUTE_PACKAGES_HASH);
        mRoles.clear();

        int type;
        int depth;
        int innerDepth = parser.getDepth() + 1;
        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
            if (depth > innerDepth || type != XmlPullParser.START_TAG) {
                continue;
            }

            if (parser.getName().equals(TAG_ROLE)) {
                String roleName = parser.getAttributeValue(null, ATTRIBUTE_NAME);
                ArraySet<String> roleHolders = parseRoleHoldersLocked(parser);
                mRoles.put(roleName, roleHolders);
            }
        }
    }

    @NonNull
    private ArraySet<String> parseRoleHoldersLocked(@NonNull XmlPullParser parser)
            throws IOException, XmlPullParserException {
        ArraySet<String> roleHolders = new ArraySet<>();

        int type;
        int depth;
        int innerDepth = parser.getDepth() + 1;
        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
            if (depth > innerDepth || type != XmlPullParser.START_TAG) {
                continue;
            }

            if (parser.getName().equals(TAG_HOLDER)) {
                String roleHolder = parser.getAttributeValue(null, ATTRIBUTE_NAME);
                roleHolders.add(roleHolder);
            }
        }

        return roleHolders;
    }

    /**
     * Dump this user state.
     *
     * @param dumpOutputStream the output stream to dump to
     */
    public void dump(@NonNull DualDumpOutputStream dumpOutputStream, @NonNull String fieldName,
            long fieldId) {
        int version;
        String packagesHash;
        ArrayMap<String, ArraySet<String>> roles;
        synchronized (mLock) {
            throwIfDestroyedLocked();

            version = mVersion;
            packagesHash = mPackagesHash;
            roles = snapshotRolesLocked();
        }

        long fieldToken = dumpOutputStream.start(fieldName, fieldId);
        dumpOutputStream.write("user_id", RoleUserStateProto.USER_ID, mUserId);
        dumpOutputStream.write("version", RoleUserStateProto.VERSION, version);
        dumpOutputStream.write("packages_hash", RoleUserStateProto.PACKAGES_HASH, packagesHash);

        int rolesSize = roles.size();
        for (int rolesIndex = 0; rolesIndex < rolesSize; rolesIndex++) {
            String roleName = roles.keyAt(rolesIndex);
            ArraySet<String> roleHolders = roles.valueAt(rolesIndex);

            long rolesToken = dumpOutputStream.start("roles", RoleUserStateProto.ROLES);
            dumpOutputStream.write("name", RoleProto.NAME, roleName);

            int roleHoldersSize = roleHolders.size();
            for (int roleHoldersIndex = 0; roleHoldersIndex < roleHoldersSize; roleHoldersIndex++) {
                String roleHolder = roleHolders.valueAt(roleHoldersIndex);

                dumpOutputStream.write("holders", RoleProto.HOLDERS, roleHolder);
            }

            dumpOutputStream.end(rolesToken);
        }

        dumpOutputStream.end(fieldToken);
    }

    @GuardedBy("mLock")
    private ArrayMap<String, ArraySet<String>> snapshotRolesLocked() {
        ArrayMap<String, ArraySet<String>> roles = new ArrayMap<>();
        for (int i = 0, size = CollectionUtils.size(mRoles); i < size; ++i) {
            String roleName = mRoles.keyAt(i);
            ArraySet<String> roleHolders = mRoles.valueAt(i);

            roleHolders = new ArraySet<>(roleHolders);
            roles.put(roleName, roleHolders);
        }
        return roles;
    }

    /**
     * Destroy this user state and delete the corresponding file. Any pending writes to the file
     * will be cancelled, and any future interaction with this state will throw an exception.
     */
    public void destroy() {
        synchronized (mLock) {
            throwIfDestroyedLocked();
            mWriteHandler.removeCallbacksAndMessages(null);
            getFile(mUserId).delete();
            mDestroyed = true;
        }
    }

    @GuardedBy("mLock")
    private void throwIfDestroyedLocked() {
        if (mDestroyed) {
            throw new IllegalStateException("This RoleUserState has already been destroyed");
        }
    }

    private static @NonNull File getFile(@UserIdInt int userId) {
        return new File(Environment.getUserSystemDirectory(userId), ROLES_FILE_NAME);
    }

    /**
     * Callback for a user state.
     */
    public interface Callback {

        /**
         * Called when the holders of roles are changed.
         *
         * @param roleName the name of the role whose holders are changed
         * @param userId the user id for this role holder change
         */
        void onRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId);
    }
}
