Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fcde8146 authored by Lee Shombert's avatar Lee Shombert
Browse files

Take snapshots of SettingBase subclasses

Bug: 192478088

Snapshot SharedUserSetting and PackageSetting.

Test: atest
 * CtsContentTestCases:IntentFilterTest
 * CtsDynamicMimeHostTestCases
 * CtsRoleTestCases
 * FrameworksServicesTests:UserSystemPackageInstallerTest
 * FrameworksServicesTests:PackageManagerSettingsTests
 * FrameworksServicesTests:PackageManagerServiceTest
 * FrameworksServicesTests:AppsFilterTest
 * FrameworksServicesTests:PackageInstallerSessionTest
 * FrameworksServicesTests:ScanTests
 * UserLifecycleTests#startUser
 * UserLifecycleTests#stopUser
 * UserLifecycleTests#switchUser
 * FrameworksServicesTests:WatcherTest
 * android.appsecurity.cts.EphemeralTest
 * android.appsecurity.cts.InstantAppUserTest

Change-Id: I5ccd77bd8a07aa833219c6bab797cdc153c1136f
parent 16d25c70
Loading
Loading
Loading
Loading
+44 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.permission.LegacyPermissionDataProvider;
import com.android.server.pm.permission.LegacyPermissionState;
import com.android.server.pm.pkg.PackageStateUnserialized;
import com.android.server.utils.SnapshotCache;

import java.io.File;
import java.util.ArrayList;
@@ -81,6 +82,7 @@ public class PackageSetting extends PackageSettingBase {
     * object equality to check whether shared user settings are the same.
     */
    SharedUserSetting sharedUser;

    /**
     * Temporary holding space for the shared user ID. While parsing package settings, the
     * shared users tag may come after the packages. In this case, we must delay linking the
@@ -103,6 +105,19 @@ public class PackageSetting extends PackageSettingBase {
    @NonNull
    private UUID mDomainSetId;

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

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

    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public PackageSetting(String name, String realName, @NonNull File codePath,
            String legacyNativeLibraryPathString, String primaryCpuAbiString,
@@ -118,6 +133,7 @@ public class PackageSetting extends PackageSettingBase {
        this.sharedUserId = sharedUserId;
        mDomainSetId = domainSetId;
        copyMimeGroups(mimeGroups);
        mSnapshot = makeCache();
    }

    /**
@@ -127,6 +143,7 @@ public class PackageSetting extends PackageSettingBase {
    PackageSetting(PackageSetting orig) {
        super(orig, orig.realName);
        doCopy(orig);
        mSnapshot = makeCache();
    }

    /**
@@ -137,6 +154,33 @@ public class PackageSetting extends PackageSettingBase {
    PackageSetting(PackageSetting orig, String realPkgName) {
        super(orig, realPkgName);
        doCopy(orig);
        mSnapshot = makeCache();
    }

    /**
     * Create a snapshot.  The copy constructor is already in use and cannot be modified
     * for this purpose.
     */
    PackageSetting(PackageSetting orig, boolean snapshot) {
        super(orig, snapshot);
        // The existing doCopy() method cannot be used in here because sharedUser must be
        // a snapshot, and not a reference.  Also, the pkgState must be copied.  However,
        // this code should otherwise be kept in sync with doCopy().
        appId = orig.appId;
        pkg = orig.pkg;
        sharedUser = orig.sharedUser == null ? null : orig.sharedUser.snapshot();
        sharedUserId = orig.sharedUserId;
        copyMimeGroups(orig.mimeGroups);
        pkgState = orig.pkgState;
        mDomainSetId = orig.getDomainSetId();
        mSnapshot = new SnapshotCache.Sealed();
    }

    /**
     * Return the package snapshot.
     */
    public PackageSetting snapshot() {
        return mSnapshot.snapshot();
    }

    /** @see #pkg **/
+9 −0
Original line number Diff line number Diff line
@@ -169,6 +169,15 @@ public abstract class PackageSettingBase extends SettingBase {
        doCopy(base);
    }

    // A copy constructor used to create snapshots.  The boolean is present only to
    // match up with the constructor in PackageSetting.
    PackageSettingBase(PackageSettingBase orig, boolean snapshot) {
        super(orig);
        name = orig.name;
        realName = orig.realName;
        doCopy(orig);
    }

    public void setInstallerPackageName(String packageName) {
        installSource = installSource.setInstallerPackage(packageName);
        onChanged();
+2 −1
Original line number Diff line number Diff line
@@ -22,12 +22,13 @@ import android.content.pm.ApplicationInfo;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.pm.permission.LegacyPermissionState;
import com.android.server.utils.Snappable;
import com.android.server.utils.Watchable;
import com.android.server.utils.WatchableImpl;
import com.android.server.utils.Watcher;

@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public abstract class SettingBase implements Watchable {
public abstract class SettingBase implements Watchable, Snappable {
    // TODO: make this variable protected, or even private with a getter and setter.
    // Simply making it protected or private requires that the name be changed to conformm
    // to the Android naming convention, and that touches quite a few files.
+45 −8
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.util.proto.ProtoOutputStream;

import com.android.internal.util.ArrayUtils;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.utils.SnapshotCache;

import libcore.util.EmptyArray;

@@ -49,12 +50,25 @@ public final class SharedUserSetting extends SettingBase {
    // that all apps within the sharedUser run in the same selinux context.
    int seInfoTargetSdkVersion;

    final ArraySet<PackageSetting> packages = new ArraySet<>();
    final ArraySet<PackageSetting> packages;

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

    ArrayMap<String, ParsedProcess> processes;
    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);
@@ -62,6 +76,31 @@ public final class SharedUserSetting extends SettingBase {
        uidPrivateFlags = _pkgPrivateFlags;
        name = _name;
        seInfoTargetSdkVersion = android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
        packages = new ArraySet<>();
        processes = new ArrayMap<>();
        mSnapshot = makeCache();
    }

    // The copy constructor is used to create a snapshot
    private SharedUserSetting(SharedUserSetting orig) {
        super(orig);
        name = orig.name;
        uidFlags = orig.uidFlags;
        uidPrivateFlags = orig.uidPrivateFlags;
        packages = new ArraySet(orig.packages);
        // A PackageParser.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();
    }

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

    @Override
@@ -80,9 +119,6 @@ public final class SharedUserSetting extends SettingBase {
    void addProcesses(Map<String, ParsedProcess> newProcs) {
        if (newProcs != null) {
            final int numProcs = newProcs.size();
            if (processes == null) {
                processes = new ArrayMap<>(numProcs);
            }
            for (String key : newProcs.keySet()) {
                ParsedProcess newProc = newProcs.get(key);
                ParsedProcess proc = processes.get(newProc.getName());
@@ -191,7 +227,7 @@ public final class SharedUserSetting extends SettingBase {
     * Update tracked data about processes based on all known packages in the shared user ID.
     */
    public void updateProcesses() {
        processes = null;
        processes.clear();
        for (int i = packages.size() - 1; i >= 0; i--) {
            final AndroidPackage pkg = packages.valueAt(i).pkg;
            if (pkg != null) {
@@ -230,14 +266,15 @@ public final class SharedUserSetting extends SettingBase {
        this.signaturesChanged = sharedUser.signaturesChanged;
        if (sharedUser.processes != null) {
            final int numProcs = sharedUser.processes.size();
            this.processes = new ArrayMap<>(numProcs);
            this.processes.clear();
            this.processes.ensureCapacity(numProcs);
            for (int i = 0; i < numProcs; i++) {
                ParsedProcess proc =
                        new ParsedProcess(sharedUser.processes.valueAt(i));
                this.processes.put(proc.getName(), proc);
            }
        } else {
            this.processes = null;
            this.processes.clear();
        }
        onChanged();
        return this;
+1 −0
Original line number Diff line number Diff line
@@ -198,6 +198,7 @@ public class PackageManagerSettingsTests {
                new WatchableTester(settingsUnderTest, "noSuspendingPackage");
        watcher.register();
        settingsUnderTest.mPackages.put(PACKAGE_NAME_1, createPackageSetting(PACKAGE_NAME_1));
        settingsUnderTest.readPackageRestrictionsLPr(0);
        watcher.verifyChangeReported("put package 1");
        // Collect a snapshot at the midway point (package 2 has not been added)
        final Settings snapshot = settingsUnderTest.snapshot();