Merge "Take snapshots of SettingBase subclasses" into sc-dev

This commit is contained in:
Lee Shombert
2021-07-13 21:38:50 +00:00
committed by Android (Google) Code Review
5 changed files with 101 additions and 9 deletions

View File

@@ -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 **/

View File

@@ -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();

View File

@@ -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.

View File

@@ -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;

View File

@@ -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();