/*
 * Copyright (C) 2015 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.content.pm.PackageManager;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;

import android.util.SparseArray;
import android.util.SparseBooleanArray;
import com.android.internal.util.ArrayUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
 * This class encapsulates the permissions for a package or a shared user.
 * <p>
 * There are two types of permissions: install (granted at installation)
 * and runtime (granted at runtime). Install permissions are granted to
 * all device users while runtime permissions are granted explicitly to
 * specific users.
 * </p>
 * <p>
 * The permissions are kept on a per device user basis. For example, an
 * application may have some runtime permissions granted under the device
 * owner but not granted under the secondary user.
 * <p>
 * This class is also responsible for keeping track of the Linux gids per
 * user for a package or a shared user. The gids are computed as a set of
 * the gids for all granted permissions' gids on a per user basis.
 * </p>
 */
public final class PermissionsState {

    /** The permission operation failed. */
    public static final int PERMISSION_OPERATION_FAILURE = -1;

    /** The permission operation succeeded and no gids changed. */
    public static final int PERMISSION_OPERATION_SUCCESS = 0;

    /** The permission operation succeeded and gids changed. */
    public static final int PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED = 1;

    private static final int[] NO_GIDS = {};

    private ArrayMap<String, PermissionData> mPermissions;

    private int[] mGlobalGids = NO_GIDS;

    private SparseBooleanArray mPermissionReviewRequired;

    public PermissionsState() {
        /* do nothing */
    }

    public PermissionsState(PermissionsState prototype) {
        copyFrom(prototype);
    }

    /**
     * Sets the global gids, applicable to all users.
     *
     * @param globalGids The global gids.
     */
    public void setGlobalGids(int[] globalGids) {
        if (!ArrayUtils.isEmpty(globalGids)) {
            mGlobalGids = Arrays.copyOf(globalGids, globalGids.length);
        }
    }

    /**
     * Initialized this instance from another one.
     *
     * @param other The other instance.
     */
    public void copyFrom(PermissionsState other) {
        if (other == this) {
            return;
        }
        if (mPermissions != null) {
            if (other.mPermissions == null) {
                mPermissions = null;
            } else {
                mPermissions.clear();
            }
        }
        if (other.mPermissions != null) {
            if (mPermissions == null) {
                mPermissions = new ArrayMap<>();
            }
            final int permissionCount = other.mPermissions.size();
            for (int i = 0; i < permissionCount; i++) {
                String name = other.mPermissions.keyAt(i);
                PermissionData permissionData = other.mPermissions.valueAt(i);
                mPermissions.put(name, new PermissionData(permissionData));
            }
        }

        mGlobalGids = NO_GIDS;
        if (other.mGlobalGids != NO_GIDS) {
            mGlobalGids = Arrays.copyOf(other.mGlobalGids,
                    other.mGlobalGids.length);
        }

        if (mPermissionReviewRequired != null) {
            if (other.mPermissionReviewRequired == null) {
                mPermissionReviewRequired = null;
            } else {
                mPermissionReviewRequired.clear();
            }
        }
        if (other.mPermissionReviewRequired != null) {
            if (mPermissionReviewRequired == null) {
                mPermissionReviewRequired = new SparseBooleanArray();
            }
            final int userCount = other.mPermissionReviewRequired.size();
            for (int i = 0; i < userCount; i++) {
                final boolean reviewRequired = other.mPermissionReviewRequired.valueAt(i);
                mPermissionReviewRequired.put(i, reviewRequired);
            }
        }
    }

    public boolean isPermissionReviewRequired(int userId) {
        return mPermissionReviewRequired != null && mPermissionReviewRequired.get(userId);
    }

    /**
     * Grant an install permission.
     *
     * @param permission The permission to grant.
     * @return The operation result which is either {@link #PERMISSION_OPERATION_SUCCESS},
     *     or {@link #PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED}, or {@link
     *     #PERMISSION_OPERATION_FAILURE}.
     */
    public int grantInstallPermission(BasePermission permission) {
        return grantPermission(permission, UserHandle.USER_ALL);
    }

    /**
     * Revoke an install permission.
     *
     * @param permission The permission to revoke.
     * @return The operation result which is either {@link #PERMISSION_OPERATION_SUCCESS},
     *     or {@link #PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED}, or {@link
     *     #PERMISSION_OPERATION_FAILURE}.
     */
    public int revokeInstallPermission(BasePermission permission) {
        return revokePermission(permission, UserHandle.USER_ALL);
    }

    /**
     * Grant a runtime permission for a given device user.
     *
     * @param permission The permission to grant.
     * @param userId The device user id.
     * @return The operation result which is either {@link #PERMISSION_OPERATION_SUCCESS},
     *     or {@link #PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED}, or {@link
     *     #PERMISSION_OPERATION_FAILURE}.
     */
    public int grantRuntimePermission(BasePermission permission, int userId) {
        enforceValidUserId(userId);
        if (userId == UserHandle.USER_ALL) {
            return PERMISSION_OPERATION_FAILURE;
        }
        return grantPermission(permission, userId);
    }

    /**
     *  Revoke a runtime permission for a given device user.
     *
     * @param permission The permission to revoke.
     * @param userId The device user id.
     * @return The operation result which is either {@link #PERMISSION_OPERATION_SUCCESS},
     *     or {@link #PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED}, or {@link
     *     #PERMISSION_OPERATION_FAILURE}.
     */
    public int revokeRuntimePermission(BasePermission permission, int userId) {
        enforceValidUserId(userId);
        if (userId == UserHandle.USER_ALL) {
            return PERMISSION_OPERATION_FAILURE;
        }
        return revokePermission(permission, userId);
    }

    /**
     * Gets whether this state has a given runtime permission for a
     * given device user id.
     *
     * @param name The permission name.
     * @param userId The device user id.
     * @return Whether this state has the permission.
     */
    public boolean hasRuntimePermission(String name, int userId) {
        enforceValidUserId(userId);
        return !hasInstallPermission(name) && hasPermission(name, userId);
    }

    /**
     * Gets whether this state has a given install permission.
     *
     * @param name The permission name.
     * @return Whether this state has the permission.
     */
    public boolean hasInstallPermission(String name) {
        return hasPermission(name, UserHandle.USER_ALL);
    }

    /**
     * Gets whether the state has a given permission for the specified
     * user, regardless if this is an install or a runtime permission.
     *
     * @param name The permission name.
     * @param userId The device user id.
     * @return Whether the user has the permission.
     */
    public boolean hasPermission(String name, int userId) {
        enforceValidUserId(userId);

        if (mPermissions == null) {
            return false;
        }

        PermissionData permissionData = mPermissions.get(name);
        return permissionData != null && permissionData.isGranted(userId);
    }

    /**
     * Returns whether the state has any known request for the given permission name,
     * whether or not it has been granted.
     */
    public boolean hasRequestedPermission(ArraySet<String> names) {
        if (mPermissions == null) {
            return false;
        }
        for (int i=names.size()-1; i>=0; i--) {
            if (mPermissions.get(names.valueAt(i)) != null) {
                return true;
            }
        }
        return false;
    }

    /**
     * Gets all permissions for a given device user id regardless if they
     * are install time or runtime permissions.
     *
     * @param userId The device user id.
     * @return The permissions or an empty set.
     */
    public Set<String> getPermissions(int userId) {
        enforceValidUserId(userId);

        if (mPermissions == null) {
            return Collections.emptySet();
        }

        Set<String> permissions = new ArraySet<>();

        final int permissionCount = mPermissions.size();
        for (int i = 0; i < permissionCount; i++) {
            String permission = mPermissions.keyAt(i);

            if (hasInstallPermission(permission)) {
                permissions.add(permission);
            }

            if (userId != UserHandle.USER_ALL) {
                if (hasRuntimePermission(permission, userId)) {
                    permissions.add(permission);
                }
            }
        }

        return permissions;
    }

    /**
     * Gets the state for an install permission or null if no such.
     *
     * @param name The permission name.
     * @return The permission state.
     */
    public PermissionState getInstallPermissionState(String name) {
        return getPermissionState(name, UserHandle.USER_ALL);
    }

    /**
     * Gets the state for a runtime permission or null if no such.
     *
     * @param name The permission name.
     * @param userId The device user id.
     * @return The permission state.
     */
    public PermissionState getRuntimePermissionState(String name, int userId) {
        enforceValidUserId(userId);
        return getPermissionState(name, userId);
    }

    /**
     * Gets all install permission states.
     *
     * @return The permission states or an empty set.
     */
    public List<PermissionState> getInstallPermissionStates() {
        return getPermissionStatesInternal(UserHandle.USER_ALL);
    }

    /**
     * Gets all runtime permission states.
     *
     * @return The permission states or an empty set.
     */
    public List<PermissionState> getRuntimePermissionStates(int userId) {
        enforceValidUserId(userId);
        return getPermissionStatesInternal(userId);
    }

    /**
     * Gets the flags for a permission regardless if it is install or
     * runtime permission.
     *
     * @param name The permission name.
     * @return The permission state or null if no such.
     */
    public int getPermissionFlags(String name, int userId) {
        PermissionState installPermState = getInstallPermissionState(name);
        if (installPermState != null) {
            return installPermState.getFlags();
        }
        PermissionState runtimePermState = getRuntimePermissionState(name, userId);
        if (runtimePermState != null) {
            return runtimePermState.getFlags();
        }
        return 0;
    }

    /**
     * Update the flags associated with a given permission.
     * @param permission The permission whose flags to update.
     * @param userId The user for which to update.
     * @param flagMask Mask for which flags to change.
     * @param flagValues New values for the mask flags.
     * @return Whether the permission flags changed.
     */
    public boolean updatePermissionFlags(BasePermission permission, int userId,
            int flagMask, int flagValues) {
        enforceValidUserId(userId);

        final boolean mayChangeFlags = flagValues != 0 || flagMask != 0;

        if (mPermissions == null) {
            if (!mayChangeFlags) {
                return false;
            }
            ensurePermissionData(permission);
        }

        PermissionData permissionData = mPermissions.get(permission.name);
        if (permissionData == null) {
            if (!mayChangeFlags) {
                return false;
            }
            permissionData = ensurePermissionData(permission);
        }

        final int oldFlags = permissionData.getFlags(userId);

        final boolean updated = permissionData.updateFlags(userId, flagMask, flagValues);
        if (updated) {
            final int newFlags = permissionData.getFlags(userId);
            if ((oldFlags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) == 0
                    && (newFlags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
                if (mPermissionReviewRequired == null) {
                    mPermissionReviewRequired = new SparseBooleanArray();
                }
                mPermissionReviewRequired.put(userId, true);
            } else if ((oldFlags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0
                    && (newFlags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) == 0) {
                if (mPermissionReviewRequired != null) {
                    mPermissionReviewRequired.delete(userId);
                    if (mPermissionReviewRequired.size() <= 0) {
                        mPermissionReviewRequired = null;
                    }
                }
            }
        }
        return updated;
    }

    public boolean updatePermissionFlagsForAllPermissions(
            int userId, int flagMask, int flagValues) {
        enforceValidUserId(userId);

        if (mPermissions == null) {
            return false;
        }
        boolean changed = false;
        final int permissionCount = mPermissions.size();
        for (int i = 0; i < permissionCount; i++) {
            PermissionData permissionData = mPermissions.valueAt(i);
            changed |= permissionData.updateFlags(userId, flagMask, flagValues);
        }
        return changed;
    }

    /**
     * Compute the Linux gids for a given device user from the permissions
     * granted to this user. Note that these are computed to avoid additional
     * state as they are rarely accessed.
     *
     * @param userId The device user id.
     * @return The gids for the device user.
     */
    public int[] computeGids(int userId) {
        enforceValidUserId(userId);

        int[] gids = mGlobalGids;

        if (mPermissions != null) {
            final int permissionCount = mPermissions.size();
            for (int i = 0; i < permissionCount; i++) {
                String permission = mPermissions.keyAt(i);
                if (!hasPermission(permission, userId)) {
                    continue;
                }
                PermissionData permissionData = mPermissions.valueAt(i);
                final int[] permGids = permissionData.computeGids(userId);
                if (permGids != NO_GIDS) {
                    gids = appendInts(gids, permGids);
                }
            }
        }

        return gids;
    }

    /**
     * Compute the Linux gids for all device users from the permissions
     * granted to these users.
     *
     * @return The gids for all device users.
     */
    public int[] computeGids(int[] userIds) {
        int[] gids = mGlobalGids;

        for (int userId : userIds) {
            final int[] userGids = computeGids(userId);
            gids = appendInts(gids, userGids);
        }

        return gids;
    }

    /**
     * Resets the internal state of this object.
     */
    public void reset() {
        mGlobalGids = NO_GIDS;
        mPermissions = null;
        mPermissionReviewRequired = null;
    }

    private PermissionState getPermissionState(String name, int userId) {
        if (mPermissions == null) {
            return null;
        }
        PermissionData permissionData = mPermissions.get(name);
        if (permissionData == null) {
            return null;
        }
        return permissionData.getPermissionState(userId);
    }

    private List<PermissionState> getPermissionStatesInternal(int userId) {
        enforceValidUserId(userId);

        if (mPermissions == null) {
            return Collections.emptyList();
        }

        List<PermissionState> permissionStates = new ArrayList<>();

        final int permissionCount = mPermissions.size();
        for (int i = 0; i < permissionCount; i++) {
            PermissionData permissionData = mPermissions.valueAt(i);

            PermissionState permissionState = permissionData.getPermissionState(userId);
            if (permissionState != null) {
                permissionStates.add(permissionState);
            }
        }

        return permissionStates;
    }

    private int grantPermission(BasePermission permission, int userId) {
        if (hasPermission(permission.name, userId)) {
            return PERMISSION_OPERATION_FAILURE;
        }

        final boolean hasGids = !ArrayUtils.isEmpty(permission.computeGids(userId));
        final int[] oldGids = hasGids ? computeGids(userId) : NO_GIDS;

        PermissionData permissionData = ensurePermissionData(permission);

        if (!permissionData.grant(userId)) {
            return PERMISSION_OPERATION_FAILURE;
        }

        if (hasGids) {
            final int[] newGids = computeGids(userId);
            if (oldGids.length != newGids.length) {
                return PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED;
            }
        }

        return PERMISSION_OPERATION_SUCCESS;
    }

    private int revokePermission(BasePermission permission, int userId) {
        if (!hasPermission(permission.name, userId)) {
            return PERMISSION_OPERATION_FAILURE;
        }

        final boolean hasGids = !ArrayUtils.isEmpty(permission.computeGids(userId));
        final int[] oldGids = hasGids ? computeGids(userId) : NO_GIDS;

        PermissionData permissionData = mPermissions.get(permission.name);

        if (!permissionData.revoke(userId)) {
            return PERMISSION_OPERATION_FAILURE;
        }

        if (permissionData.isDefault()) {
            ensureNoPermissionData(permission.name);
        }

        if (hasGids) {
            final int[] newGids = computeGids(userId);
            if (oldGids.length != newGids.length) {
                return PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED;
            }
        }

        return PERMISSION_OPERATION_SUCCESS;
    }

    private static int[] appendInts(int[] current, int[] added) {
        if (current != null && added != null) {
            for (int guid : added) {
                current = ArrayUtils.appendInt(current, guid);
            }
        }
        return current;
    }

    private static void enforceValidUserId(int userId) {
        if (userId != UserHandle.USER_ALL && userId < 0) {
            throw new IllegalArgumentException("Invalid userId:" + userId);
        }
    }

    private PermissionData ensurePermissionData(BasePermission permission) {
        if (mPermissions == null) {
            mPermissions = new ArrayMap<>();
        }
        PermissionData permissionData = mPermissions.get(permission.name);
        if (permissionData == null) {
            permissionData = new PermissionData(permission);
            mPermissions.put(permission.name, permissionData);
        }
        return permissionData;
    }

    private void ensureNoPermissionData(String name) {
        if (mPermissions == null) {
            return;
        }
        mPermissions.remove(name);
        if (mPermissions.isEmpty()) {
            mPermissions = null;
        }
    }

    private static final class PermissionData {
        private final BasePermission mPerm;
        private SparseArray<PermissionState> mUserStates = new SparseArray<>();

        public PermissionData(BasePermission perm) {
            mPerm = perm;
        }

        public PermissionData(PermissionData other) {
            this(other.mPerm);
            final int otherStateCount = other.mUserStates.size();
            for (int i = 0; i < otherStateCount; i++) {
                final int otherUserId = other.mUserStates.keyAt(i);
                PermissionState otherState = other.mUserStates.valueAt(i);
                mUserStates.put(otherUserId, new PermissionState(otherState));
            }
        }

        public int[] computeGids(int userId) {
            return mPerm.computeGids(userId);
        }

        public boolean isGranted(int userId) {
            if (isInstallPermission()) {
                userId = UserHandle.USER_ALL;
            }

            PermissionState userState = mUserStates.get(userId);
            if (userState == null) {
                return false;
            }

            return userState.mGranted;
        }

        public boolean grant(int userId) {
            if (!isCompatibleUserId(userId)) {
                return false;
            }

            if (isGranted(userId)) {
                return false;
            }

            PermissionState userState = mUserStates.get(userId);
            if (userState == null) {
                userState = new PermissionState(mPerm.name);
                mUserStates.put(userId, userState);
            }

            userState.mGranted = true;

            return true;
        }

        public boolean revoke(int userId) {
            if (!isCompatibleUserId(userId)) {
                return false;
            }

            if (!isGranted(userId)) {
                return false;
            }

            PermissionState userState = mUserStates.get(userId);
            userState.mGranted = false;

            if (userState.isDefault()) {
                mUserStates.remove(userId);
            }

            return true;
        }

        public PermissionState getPermissionState(int userId) {
            return mUserStates.get(userId);
        }

        public int getFlags(int userId) {
            PermissionState userState = mUserStates.get(userId);
            if (userState != null) {
                return userState.mFlags;
            }
            return 0;
        }

        public boolean isDefault() {
            return mUserStates.size() <= 0;
        }

        public static boolean isInstallPermissionKey(int userId) {
            return userId == UserHandle.USER_ALL;
        }

        public boolean updateFlags(int userId, int flagMask, int flagValues) {
            if (isInstallPermission()) {
                userId = UserHandle.USER_ALL;
            }

            if (!isCompatibleUserId(userId)) {
                return false;
            }

            final int newFlags = flagValues & flagMask;

            PermissionState userState = mUserStates.get(userId);
            if (userState != null) {
                final int oldFlags = userState.mFlags;
                userState.mFlags = (userState.mFlags & ~flagMask) | newFlags;
                if (userState.isDefault()) {
                    mUserStates.remove(userId);
                }
                return userState.mFlags != oldFlags;
            } else if (newFlags != 0) {
                userState = new PermissionState(mPerm.name);
                userState.mFlags = newFlags;
                mUserStates.put(userId, userState);
                return true;
            }

            return false;
        }

        private boolean isCompatibleUserId(int userId) {
            return isDefault() || !(isInstallPermission() ^ isInstallPermissionKey(userId));
        }

        private boolean isInstallPermission() {
            return mUserStates.size() == 1
                    && mUserStates.get(UserHandle.USER_ALL) != null;
        }
    }

    public static final class PermissionState {
        private final String mName;
        private boolean mGranted;
        private int mFlags;

        public PermissionState(String name) {
            mName = name;
        }

        public PermissionState(PermissionState other) {
            mName = other.mName;
            mGranted = other.mGranted;
            mFlags = other.mFlags;
        }

        public boolean isDefault() {
            return !mGranted && mFlags == 0;
        }

        public String getName() {
            return mName;
        }

        public boolean isGranted() {
            return mGranted;
        }

        public int getFlags() {
            return mFlags;
        }
    }
}
