/*
 * Copyright (C) 2011 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.content.pm.ApplicationInfo;
import android.content.pm.SigningDetails;
import android.service.pm.PackageServiceDumpProto;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.proto.ProtoOutputStream;

import com.android.internal.pm.pkg.component.ComponentMutateUtils;
import com.android.internal.pm.pkg.component.ParsedProcess;
import com.android.internal.pm.pkg.component.ParsedProcessImpl;
import com.android.internal.util.ArrayUtils;
import com.android.server.pm.permission.LegacyPermissionState;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.SharedUserApi;
import com.android.server.utils.SnapshotCache;
import com.android.server.utils.Watchable;
import com.android.server.utils.WatchedArraySet;
import com.android.server.utils.Watcher;

import libcore.util.EmptyArray;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * Settings data for a particular shared user ID we know about.
 */
public final class SharedUserSetting extends SettingBase implements SharedUserApi {
    final String name;

    int mAppId;

    /** @see SharedUserApi#getUidFlags() **/
    int uidFlags;
    int uidPrivateFlags;

    /** @see SharedUserApi#getSeInfoTargetSdkVersion() **/
    int seInfoTargetSdkVersion;

    private final WatchedArraySet<PackageSetting> mPackages;
    private final SnapshotCache<WatchedArraySet<PackageSetting>> mPackagesSnapshot;

    // It is possible for a system app to leave shared user ID by an update.
    // We need to keep track of the shadowed PackageSettings so that it is possible to uninstall
    // the update and revert the system app back into the original shared user ID.
    final WatchedArraySet<PackageSetting> mDisabledPackages;
    private final SnapshotCache<WatchedArraySet<PackageSetting>> mDisabledPackagesSnapshot;

    /**
     * The observer that watches for changes from array members
     */
    private final Watcher mObserver = new Watcher() {
        @Override
        public void onChange(@Nullable Watchable what) {
            SharedUserSetting.this.onChanged();
        }
    };

    final PackageSignatures signatures = new PackageSignatures();
    Boolean signaturesChanged;

    final ArrayMap<String, ParsedProcess> processes;

    /**
     * Snapshot support.
     */
    private final SnapshotCache<SharedUserSetting> mSnapshot;

    private SnapshotCache<SharedUserSetting> makeCache() {
        return new SnapshotCache<SharedUserSetting>(this, this) {
            @Override
            public SharedUserSetting createSnapshot() {
                return new SharedUserSetting(mSource);
            }};
    }

    SharedUserSetting(String _name, int _pkgFlags, int _pkgPrivateFlags) {
        super(_pkgFlags, _pkgPrivateFlags);
        uidFlags =  _pkgFlags;
        uidPrivateFlags = _pkgPrivateFlags;
        name = _name;
        seInfoTargetSdkVersion = android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
        mPackages = new WatchedArraySet<>();
        mPackagesSnapshot = new SnapshotCache.Auto<>(mPackages, mPackages,
                "SharedUserSetting.packages");
        mDisabledPackages = new WatchedArraySet<>();
        mDisabledPackagesSnapshot = new SnapshotCache.Auto<>(mDisabledPackages, mDisabledPackages,
                "SharedUserSetting.mDisabledPackages");
        processes = new ArrayMap<>();
        registerObservers();
        mSnapshot = makeCache();
    }

    // The copy constructor is used to create a snapshot
    private SharedUserSetting(SharedUserSetting orig) {
        super(orig);
        name = orig.name;
        mAppId = orig.mAppId;
        uidFlags = orig.uidFlags;
        uidPrivateFlags = orig.uidPrivateFlags;
        mPackages = orig.mPackagesSnapshot.snapshot();
        mPackagesSnapshot = new SnapshotCache.Sealed<>();
        mDisabledPackages = orig.mDisabledPackagesSnapshot.snapshot();
        mDisabledPackagesSnapshot = new SnapshotCache.Sealed<>();
        // A SigningDetails seems to consist solely of final attributes, so
        // it is safe to copy the reference.
        signatures.mSigningDetails = orig.signatures.mSigningDetails;
        signaturesChanged = orig.signaturesChanged;
        processes = new ArrayMap<>(orig.processes);
        mSnapshot = new SnapshotCache.Sealed<>();
    }

    private void registerObservers() {
        mPackages.registerObserver(mObserver);
        mDisabledPackages.registerObserver(mObserver);
    }

    /**
     * Return a read-only snapshot of this object.
     */
    public SharedUserSetting snapshot() {
        return mSnapshot.snapshot();
    }

    @Override
    public String toString() {
        return "SharedUserSetting{" + Integer.toHexString(System.identityHashCode(this)) + " "
                + name + "/" + mAppId + "}";
    }

    public void dumpDebug(ProtoOutputStream proto, long fieldId) {
        long token = proto.start(fieldId);
        proto.write(PackageServiceDumpProto.SharedUserProto.UID, mAppId);
        proto.write(PackageServiceDumpProto.SharedUserProto.NAME, name);
        proto.end(token);
    }

    void addProcesses(Map<String, ParsedProcess> newProcs) {
        if (newProcs != null) {
            for (String key : newProcs.keySet()) {
                ParsedProcess newProc = newProcs.get(key);
                ParsedProcess proc = processes.get(newProc.getName());
                if (proc == null) {
                    proc = new ParsedProcessImpl(newProc);
                    processes.put(newProc.getName(), proc);
                } else {
                    ComponentMutateUtils.addStateFrom(proc, newProc);
                }
            }
            onChanged();
        }
    }

    boolean removePackage(PackageSetting packageSetting) {
        if (!mPackages.remove(packageSetting)) {
            return false;
        }
        // recalculate the pkgFlags for this shared user if needed
        if ((this.getFlags() & packageSetting.getFlags()) != 0) {
            int aggregatedFlags = uidFlags;
            for (int i = 0; i < mPackages.size(); i++) {
                PackageSetting ps = mPackages.valueAt(i);
                aggregatedFlags |= ps.getFlags();
            }
            setFlags(aggregatedFlags);
        }
        if ((this.getPrivateFlags() & packageSetting.getPrivateFlags()) != 0) {
            int aggregatedPrivateFlags = uidPrivateFlags;
            for (int i = 0; i < mPackages.size(); i++) {
                PackageSetting ps = mPackages.valueAt(i);
                aggregatedPrivateFlags |= ps.getPrivateFlags();
            }
            setPrivateFlags(aggregatedPrivateFlags);
        }
        // recalculate processes.
        updateProcesses();
        onChanged();
        return true;
    }

    void addPackage(PackageSetting packageSetting) {
        // If this is the first package added to this shared user, temporarily (until next boot) use
        // its targetSdkVersion when assigning seInfo for the shared user.
        if ((mPackages.size() == 0) && (packageSetting.getPkg() != null)) {
            seInfoTargetSdkVersion = packageSetting.getPkg().getTargetSdkVersion();
        }
        if (mPackages.add(packageSetting)) {
            setFlags(this.getFlags() | packageSetting.getFlags());
            setPrivateFlags(this.getPrivateFlags() | packageSetting.getPrivateFlags());
            onChanged();
        }
        if (packageSetting.getPkg() != null) {
            addProcesses(packageSetting.getPkg().getProcesses());
        }
    }

    @NonNull
    @Override
    public List<AndroidPackage> getPackages() {
        if (mPackages == null || mPackages.size() == 0) {
            return Collections.emptyList();
        }
        final ArrayList<AndroidPackage> pkgList = new ArrayList<>(mPackages.size());
        for (int i = 0; i < mPackages.size(); i++) {
            PackageSetting ps = mPackages.valueAt(i);
            if ((ps == null) || (ps.getPkg() == null)) {
                continue;
            }
            pkgList.add(ps.getPkg());
        }
        return pkgList;
    }

    @Override
    public boolean isPrivileged() {
        return (this.getPrivateFlags() & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
    }

    /**
     * A shared user is considered "single user" if there is exactly one single package
     * currently using it. In the case when that package is also a system app, the APK on
     * the system partition has to also leave shared UID.
     */
    public boolean isSingleUser() {
        if (mPackages.size() != 1) {
            return false;
        }
        if (mDisabledPackages.size() > 1) {
            return false;
        }
        if (mDisabledPackages.size() == 1) {
            final AndroidPackage pkg = mDisabledPackages.valueAt(0).getPkg();
            return pkg != null && pkg.isLeavingSharedUser();
        }
        return true;
    }

    /**
     * Determine the targetSdkVersion for a sharedUser and update pkg.applicationInfo.seInfo
     * to ensure that all apps within the sharedUser share an SELinux domain. Use the lowest
     * targetSdkVersion of all apps within the shared user, which corresponds to the least
     * restrictive selinux domain.
     */
    public void fixSeInfoLocked() {
        if (mPackages == null || mPackages.size() == 0) {
            return;
        }
        for (int i = 0; i < mPackages.size(); i++) {
            PackageSetting ps = mPackages.valueAt(i);
            if ((ps == null) || (ps.getPkg() == null)) {
                continue;
            }
            if (ps.getPkg().getTargetSdkVersion() < seInfoTargetSdkVersion) {
                seInfoTargetSdkVersion = ps.getPkg().getTargetSdkVersion();
                onChanged();
            }
        }

        for (int i = 0; i < mPackages.size(); i++) {
            PackageSetting ps = mPackages.valueAt(i);
            if ((ps == null) || (ps.getPkg() == null)) {
                continue;
            }
            final boolean isPrivileged = isPrivileged() | ps.isPrivileged();
            ps.getPkgState().setOverrideSeInfo(SELinuxMMAC.getSeInfo(ps, ps.getPkg(), isPrivileged,
                    seInfoTargetSdkVersion));
            onChanged();
        }
    }

    /**
     * Update tracked data about processes based on all known packages in the shared user ID.
     */
    public void updateProcesses() {
        processes.clear();
        for (int i = mPackages.size() - 1; i >= 0; i--) {
            final AndroidPackage pkg = mPackages.valueAt(i).getPkg();
            if (pkg != null) {
                addProcesses(pkg.getProcesses());
            }
        }
    }

    /** Returns userIds which doesn't have any packages with this sharedUserId */
    public int[] getNotInstalledUserIds() {
        int[] excludedUserIds = null;
        for (int i = 0; i < mPackages.size(); i++) {
            PackageSetting ps = mPackages.valueAt(i);
            final int[] userIds = ps.getNotInstalledUserIds();
            if (excludedUserIds == null) {
                excludedUserIds = userIds;
            } else {
                for (int userId : excludedUserIds) {
                    if (!ArrayUtils.contains(userIds, userId)) {
                        excludedUserIds = ArrayUtils.removeInt(excludedUserIds, userId);
                    }
                }
            }
        }
        return excludedUserIds == null ? EmptyArray.INT : excludedUserIds;
    }

    /** Updates all fields in this shared user setting from another. */
    public SharedUserSetting updateFrom(SharedUserSetting sharedUser) {
        super.copySettingBase(sharedUser);
        this.mAppId = sharedUser.mAppId;
        this.uidFlags = sharedUser.uidFlags;
        this.uidPrivateFlags = sharedUser.uidPrivateFlags;
        this.seInfoTargetSdkVersion = sharedUser.seInfoTargetSdkVersion;
        this.mPackages.clear();
        this.mPackages.addAll(sharedUser.mPackages);
        this.signaturesChanged = sharedUser.signaturesChanged;
        if (sharedUser.processes != null) {
            final int numProcs = sharedUser.processes.size();
            this.processes.clear();
            this.processes.ensureCapacity(numProcs);
            for (int i = 0; i < numProcs; i++) {
                ParsedProcess proc = new ParsedProcessImpl(sharedUser.processes.valueAt(i));
                this.processes.put(proc.getName(), proc);
            }
        } else {
            this.processes.clear();
        }
        onChanged();
        return this;
    }

    @NonNull
    @Override
    public String getName() {
        return name;
    }

    @Override
    public int getAppId() {
        return mAppId;
    }

    @Override
    public int getUidFlags() {
        return uidFlags;
    }

    @Override
    public int getPrivateUidFlags() {
        return uidPrivateFlags;
    }

    @Override
    public int getSeInfoTargetSdkVersion() {
        return seInfoTargetSdkVersion;
    }

    public WatchedArraySet<PackageSetting> getPackageSettings() {
        return mPackages;
    }

    public WatchedArraySet<PackageSetting> getDisabledPackageSettings() {
        return mDisabledPackages;
    }

    @NonNull
    @Override
    public ArraySet<? extends PackageStateInternal> getPackageStates() {
        return mPackages.untrackedStorage();
    }

    @NonNull
    @Override
    public ArraySet<? extends PackageStateInternal> getDisabledPackageStates() {
        return mDisabledPackages.untrackedStorage();
    }

    @NonNull
    @Override
    public SigningDetails getSigningDetails() {
        return signatures.mSigningDetails;
    }

    @NonNull
    @Override
    public ArrayMap<String, ParsedProcess> getProcesses() {
        return processes;
    }

    @NonNull
    @Override
    public LegacyPermissionState getSharedUserLegacyPermissionState() {
        return super.getLegacyPermissionState();
    }
}
