Merge changes I8dc57930,Ia993613f,I111cc425 into sc-dev
* changes: Enable PackageManagerService snapshots Improve snapshot performance Correct snapshot races
This commit is contained in:
committed by
Android (Google) Code Review
commit
209a1ee0b1
@@ -58,6 +58,7 @@ public final class DumpState {
|
||||
private boolean mTitlePrinted;
|
||||
private boolean mFullPreferred;
|
||||
private boolean mCheckIn;
|
||||
private boolean mBrief;
|
||||
|
||||
private String mTargetPackageName;
|
||||
|
||||
@@ -128,4 +129,12 @@ public final class DumpState {
|
||||
public void setCheckIn(boolean checkIn) {
|
||||
mCheckIn = checkIn;
|
||||
}
|
||||
|
||||
public boolean isBrief() {
|
||||
return mBrief;
|
||||
}
|
||||
|
||||
public void setBrief(boolean brief) {
|
||||
mBrief = brief;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import android.util.TypedXmlPullParser;
|
||||
import android.util.TypedXmlSerializer;
|
||||
|
||||
import com.android.server.pm.parsing.pkg.AndroidPackage;
|
||||
import com.android.server.utils.WatchedArrayMap;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
@@ -65,7 +66,7 @@ public class KeySetManagerService {
|
||||
|
||||
protected final LongSparseArray<ArraySet<Long>> mKeySetMapping;
|
||||
|
||||
private final ArrayMap<String, PackageSetting> mPackages;
|
||||
private final WatchedArrayMap<String, PackageSetting> mPackages;
|
||||
|
||||
private long lastIssuedKeySetId = 0;
|
||||
|
||||
@@ -114,7 +115,7 @@ public class KeySetManagerService {
|
||||
}
|
||||
}
|
||||
|
||||
public KeySetManagerService(ArrayMap<String, PackageSetting> packages) {
|
||||
public KeySetManagerService(WatchedArrayMap<String, PackageSetting> packages) {
|
||||
mKeySets = new LongSparseArray<KeySetHandle>();
|
||||
mPublicKeys = new LongSparseArray<PublicKeyHandle>();
|
||||
mKeySetMapping = new LongSparseArray<ArraySet<Long>>();
|
||||
|
||||
@@ -404,6 +404,7 @@ import com.android.server.pm.verify.domain.proxy.DomainVerificationProxyV2;
|
||||
import com.android.server.rollback.RollbackManagerInternal;
|
||||
import com.android.server.storage.DeviceStorageMonitorInternal;
|
||||
import com.android.server.uri.UriGrantsManagerInternal;
|
||||
import com.android.server.utils.SnapshotCache;
|
||||
import com.android.server.utils.TimingsTraceAndSlog;
|
||||
import com.android.server.utils.Watchable;
|
||||
import com.android.server.utils.Watched;
|
||||
@@ -871,12 +872,17 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
@Watched
|
||||
@GuardedBy("mLock")
|
||||
final WatchedArrayMap<String, AndroidPackage> mPackages = new WatchedArrayMap<>();
|
||||
private final SnapshotCache<WatchedArrayMap<String, AndroidPackage>> mPackagesSnapshot =
|
||||
new SnapshotCache.Auto(mPackages, mPackages, "PackageManagerService.mPackages");
|
||||
|
||||
// Keys are isolated uids and values are the uid of the application
|
||||
// that created the isolated process.
|
||||
@Watched
|
||||
@GuardedBy("mLock")
|
||||
final WatchedSparseIntArray mIsolatedOwners = new WatchedSparseIntArray();
|
||||
private final SnapshotCache<WatchedSparseIntArray> mIsolatedOwnersSnapshot =
|
||||
new SnapshotCache.Auto(mIsolatedOwners, mIsolatedOwners,
|
||||
"PackageManagerService.mIsolatedOwners");
|
||||
|
||||
/**
|
||||
* Tracks new system packages [received in an OTA] that we expect to
|
||||
@@ -1309,14 +1315,17 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
// Avoid invalidation-thrashing by preventing cache invalidations from causing property
|
||||
// writes if the cache isn't enabled yet. We re-enable writes later when we're
|
||||
// done initializing.
|
||||
sSnapshotCorked = true;
|
||||
sSnapshotCorked.incrementAndGet();
|
||||
PackageManager.corkPackageInfoCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enablePackageCaches() {
|
||||
// Uncork cache invalidations and allow clients to cache package information.
|
||||
sSnapshotCorked = false;
|
||||
int corking = sSnapshotCorked.decrementAndGet();
|
||||
if (TRACE_SNAPSHOTS && corking == 0) {
|
||||
Log.i(TAG, "snapshot: corking returns to 0");
|
||||
}
|
||||
PackageManager.uncorkPackageInfoCache();
|
||||
}
|
||||
}
|
||||
@@ -1395,14 +1404,27 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
@Watched
|
||||
final WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>>
|
||||
mSharedLibraries = new WatchedArrayMap<>();
|
||||
private final SnapshotCache<WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>>>
|
||||
mSharedLibrariesSnapshot =
|
||||
new SnapshotCache.Auto<>(mSharedLibraries, mSharedLibraries,
|
||||
"PackageManagerService.mSharedLibraries");
|
||||
@Watched
|
||||
final WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>>
|
||||
mStaticLibsByDeclaringPackage = new WatchedArrayMap<>();
|
||||
private final SnapshotCache<WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>>>
|
||||
mStaticLibsByDeclaringPackageSnapshot =
|
||||
new SnapshotCache.Auto<>(mSharedLibraries, mSharedLibraries,
|
||||
"PackageManagerService.mSharedLibraries");
|
||||
|
||||
// Mapping from instrumentation class names to info about them.
|
||||
@Watched
|
||||
final WatchedArrayMap<ComponentName, ParsedInstrumentation> mInstrumentation =
|
||||
new WatchedArrayMap<>();
|
||||
private final SnapshotCache<WatchedArrayMap<ComponentName, ParsedInstrumentation>>
|
||||
mInstrumentationSnapshot =
|
||||
new SnapshotCache.Auto<>(mInstrumentation, mInstrumentation,
|
||||
"PackageManagerService.mInstrumentation");
|
||||
|
||||
|
||||
// Packages whose data we have transfered into another package, thus
|
||||
// should no longer exist.
|
||||
@@ -1588,6 +1610,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
static final int INTEGRITY_VERIFICATION_COMPLETE = 25;
|
||||
static final int CHECK_PENDING_INTEGRITY_VERIFICATION = 26;
|
||||
static final int DOMAIN_VERIFICATION = 27;
|
||||
static final int SNAPSHOT_UNCORK = 28;
|
||||
|
||||
static final int DEFERRED_NO_KILL_POST_DELETE_DELAY_MS = 3 * 1000;
|
||||
static final int DEFERRED_NO_KILL_INSTALL_OBSERVER_DELAY_MS = 500;
|
||||
@@ -1834,11 +1857,11 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
Snapshot(int type) {
|
||||
if (type == Snapshot.SNAPPED) {
|
||||
settings = mSettings.snapshot();
|
||||
isolatedOwners = mIsolatedOwners.snapshot();
|
||||
packages = mPackages.snapshot();
|
||||
sharedLibs = mSharedLibraries.snapshot();
|
||||
staticLibs = mStaticLibsByDeclaringPackage.snapshot();
|
||||
instrumentation = mInstrumentation.snapshot();
|
||||
isolatedOwners = mIsolatedOwnersSnapshot.snapshot();
|
||||
packages = mPackagesSnapshot.snapshot();
|
||||
sharedLibs = mSharedLibrariesSnapshot.snapshot();
|
||||
staticLibs = mStaticLibsByDeclaringPackageSnapshot.snapshot();
|
||||
instrumentation = mInstrumentationSnapshot.snapshot();
|
||||
resolveComponentName = mResolveComponentName.clone();
|
||||
resolveActivity = new ActivityInfo(mResolveActivity);
|
||||
instantAppInstallerActivity =
|
||||
@@ -4874,12 +4897,16 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
// A lock-free cache for frequently called functions.
|
||||
private volatile Computer mSnapshotComputer;
|
||||
// If true, the snapshot is invalid (stale). The attribute is static since it may be
|
||||
// set from outside classes.
|
||||
private static volatile boolean sSnapshotInvalid = true;
|
||||
// set from outside classes. The attribute may be set to true anywhere, although it
|
||||
// should only be set true while holding mLock. However, the attribute id guaranteed
|
||||
// to be set false only while mLock and mSnapshotLock are both held.
|
||||
private static AtomicBoolean sSnapshotInvalid = new AtomicBoolean(true);
|
||||
// The package manager that is using snapshots.
|
||||
private static PackageManagerService sSnapshotConsumer = null;
|
||||
// If true, the snapshot is corked. Do not create a new snapshot but use the live
|
||||
// computer. This throttles snapshot creation during periods of churn in Package
|
||||
// Manager.
|
||||
private static volatile boolean sSnapshotCorked = false;
|
||||
private static AtomicInteger sSnapshotCorked = new AtomicInteger(0);
|
||||
|
||||
/**
|
||||
* This lock is used to make reads from {@link #sSnapshotInvalid} and
|
||||
@@ -4897,7 +4924,10 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
|
||||
// The snapshot disable/enable switch. An image with the flag set true uses snapshots
|
||||
// and an image with the flag set false does not use snapshots.
|
||||
private static final boolean SNAPSHOT_ENABLED = false;
|
||||
private static final boolean SNAPSHOT_ENABLED = true;
|
||||
|
||||
// The default auto-cork delay for snapshots. This is 1s.
|
||||
private static final long SNAPSHOT_AUTOCORK_DELAY_MS = TimeUnit.SECONDS.toMillis(1);
|
||||
|
||||
// The per-instance snapshot disable/enable flag. This is generally set to false in
|
||||
// test instances and set to SNAPSHOT_ENABLED in operational instances.
|
||||
@@ -4922,15 +4952,16 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
// If the current thread holds mLock then it may have modified state but not
|
||||
// yet invalidated the snapshot. Always give the thread the live computer.
|
||||
return mLiveComputer;
|
||||
} else if (sSnapshotCorked.get() > 0) {
|
||||
// Snapshots are corked, which means new ones should not be built right now.
|
||||
mSnapshotStatistics.corked();
|
||||
return mLiveComputer;
|
||||
}
|
||||
synchronized (mSnapshotLock) {
|
||||
// This synchronization block serializes access to the snapshot computer and
|
||||
// to the code that samples mSnapshotInvalid.
|
||||
Computer c = mSnapshotComputer;
|
||||
if (sSnapshotCorked && (c != null)) {
|
||||
// Snapshots are corked, which means new ones should not be built right now.
|
||||
c.use();
|
||||
return c;
|
||||
}
|
||||
if (sSnapshotInvalid || (c == null)) {
|
||||
if (sSnapshotInvalid.getAndSet(false) || (c == null)) {
|
||||
// The snapshot is invalid if it is marked as invalid or if it is null. If it
|
||||
// is null, then it is currently being rebuilt by rebuildSnapshot().
|
||||
synchronized (mLock) {
|
||||
@@ -4938,9 +4969,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
// invalidated as it is rebuilt. However, the snapshot is still
|
||||
// self-consistent (the lock is being held) and is current as of the time
|
||||
// this function is entered.
|
||||
if (sSnapshotInvalid) {
|
||||
rebuildSnapshot();
|
||||
}
|
||||
rebuildSnapshot();
|
||||
|
||||
// Guaranteed to be non-null. mSnapshotComputer is only be set to null
|
||||
// temporarily in rebuildSnapshot(), which is guarded by mLock(). Since
|
||||
@@ -4958,12 +4987,11 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
* Rebuild the cached computer. mSnapshotComputer is temporarily set to null to block other
|
||||
* threads from using the invalid computer until it is rebuilt.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
@GuardedBy({ "mLock", "mSnapshotLock"})
|
||||
private void rebuildSnapshot() {
|
||||
final long now = SystemClock.currentTimeMicro();
|
||||
final int hits = mSnapshotComputer == null ? -1 : mSnapshotComputer.getUsed();
|
||||
mSnapshotComputer = null;
|
||||
sSnapshotInvalid = false;
|
||||
final Snapshot args = new Snapshot(Snapshot.SNAPPED);
|
||||
mSnapshotComputer = new ComputerEngine(args);
|
||||
final long done = SystemClock.currentTimeMicro();
|
||||
@@ -4971,6 +4999,30 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
mSnapshotStatistics.rebuild(now, done, hits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new snapshot. Used for testing only. This does collect statistics or
|
||||
* update the snapshot used by other actors. It does not alter the invalidation
|
||||
* flag. This method takes the mLock internally.
|
||||
*/
|
||||
private Computer createNewSnapshot() {
|
||||
synchronized (mLock) {
|
||||
final Snapshot args = new Snapshot(Snapshot.SNAPPED);
|
||||
return new ComputerEngine(args);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cork snapshots. This times out after the programmed delay.
|
||||
*/
|
||||
private void corkSnapshots(int multiplier) {
|
||||
int corking = sSnapshotCorked.getAndIncrement();
|
||||
if (TRACE_SNAPSHOTS && corking == 0) {
|
||||
Log.i(TAG, "snapshot: corking goes positive");
|
||||
}
|
||||
Message message = mHandler.obtainMessage(SNAPSHOT_UNCORK);
|
||||
mHandler.sendMessageDelayed(message, SNAPSHOT_AUTOCORK_DELAY_MS * multiplier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a live computer
|
||||
*/
|
||||
@@ -4986,9 +5038,9 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
*/
|
||||
public static void onChange(@Nullable Watchable what) {
|
||||
if (TRACE_SNAPSHOTS) {
|
||||
Log.e(TAG, "snapshot: onChange(" + what + ")");
|
||||
Log.i(TAG, "snapshot: onChange(" + what + ")");
|
||||
}
|
||||
sSnapshotInvalid = true;
|
||||
sSnapshotInvalid.set(true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -5367,6 +5419,13 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
mDomainVerificationManager.runMessage(messageCode, object);
|
||||
break;
|
||||
}
|
||||
case SNAPSHOT_UNCORK: {
|
||||
int corking = sSnapshotCorked.decrementAndGet();
|
||||
if (TRACE_SNAPSHOTS && corking == 0) {
|
||||
Log.e(TAG, "snapshot: corking goes to zero in message handler");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6383,12 +6442,13 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
// constructor, at which time the invalidation method updates it. The cache is
|
||||
// corked initially to ensure a cached computer is not built until the end of the
|
||||
// constructor.
|
||||
mSnapshotEnabled = SNAPSHOT_ENABLED;
|
||||
sSnapshotCorked = true;
|
||||
sSnapshotInvalid = true;
|
||||
mSnapshotStatistics = new SnapshotStatistics();
|
||||
sSnapshotConsumer = this;
|
||||
sSnapshotCorked.set(1);
|
||||
sSnapshotInvalid.set(true);
|
||||
mLiveComputer = createLiveComputer();
|
||||
mSnapshotComputer = null;
|
||||
mSnapshotEnabled = SNAPSHOT_ENABLED;
|
||||
registerObserver();
|
||||
}
|
||||
|
||||
@@ -18521,7 +18581,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy({"mInstallLock", "mLock"})
|
||||
@GuardedBy("mInstallLock")
|
||||
private void installPackagesTracedLI(List<InstallRequest> requests) {
|
||||
try {
|
||||
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackages");
|
||||
@@ -24018,6 +24078,15 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
dumpState.setDump(DumpState.DUMP_PER_UID_READ_TIMEOUTS);
|
||||
} else if ("snapshot".equals(cmd)) {
|
||||
dumpState.setDump(DumpState.DUMP_SNAPSHOT_STATISTICS);
|
||||
if (opti < args.length) {
|
||||
if ("--full".equals(args[opti])) {
|
||||
dumpState.setBrief(false);
|
||||
opti++;
|
||||
} else if ("--brief".equals(args[opti])) {
|
||||
dumpState.setBrief(true);
|
||||
opti++;
|
||||
}
|
||||
}
|
||||
} else if ("write".equals(cmd)) {
|
||||
synchronized (mLock) {
|
||||
writeSettingsLPrTEMP();
|
||||
@@ -24353,13 +24422,14 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
pw.println(" Snapshots disabled");
|
||||
} else {
|
||||
int hits = 0;
|
||||
int level = sSnapshotCorked.get();
|
||||
synchronized (mSnapshotLock) {
|
||||
if (mSnapshotComputer != null) {
|
||||
hits = mSnapshotComputer.getUsed();
|
||||
}
|
||||
}
|
||||
final long now = SystemClock.currentTimeMicro();
|
||||
mSnapshotStatistics.dump(pw, " ", now, hits, true);
|
||||
mSnapshotStatistics.dump(pw, " ", now, hits, level, dumpState.isBrief());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,6 +351,7 @@ public final class Settings implements Watchable, Snappable {
|
||||
|
||||
private final PackageManagerTracedLock mLock;
|
||||
|
||||
@Watched(manual = true)
|
||||
private final RuntimePermissionPersistence mRuntimePermissionsPersistence;
|
||||
|
||||
private final File mSettingsFilename;
|
||||
@@ -364,19 +365,21 @@ public final class Settings implements Watchable, Snappable {
|
||||
/** Map from package name to settings */
|
||||
@Watched
|
||||
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
|
||||
final WatchedArrayMap<String, PackageSetting> mPackages = new WatchedArrayMap<>();
|
||||
final WatchedArrayMap<String, PackageSetting> mPackages;
|
||||
private final SnapshotCache<WatchedArrayMap<String, PackageSetting>> mPackagesSnapshot;
|
||||
|
||||
/**
|
||||
* List of packages that were involved in installing other packages, i.e. are listed
|
||||
* in at least one app's InstallSource.
|
||||
*/
|
||||
@Watched
|
||||
private final WatchedArraySet<String> mInstallerPackages = new WatchedArraySet<>();
|
||||
private final WatchedArraySet<String> mInstallerPackages;
|
||||
private final SnapshotCache<WatchedArraySet<String>> mInstallerPackagesSnapshot;
|
||||
|
||||
/** Map from package name to appId and excluded userids */
|
||||
@Watched
|
||||
private final WatchedArrayMap<String, KernelPackageState> mKernelMapping =
|
||||
new WatchedArrayMap<>();
|
||||
private final WatchedArrayMap<String, KernelPackageState> mKernelMapping;
|
||||
private final SnapshotCache<WatchedArrayMap<String, KernelPackageState>> mKernelMappingSnapshot;
|
||||
|
||||
// List of replaced system applications
|
||||
@Watched
|
||||
@@ -397,7 +400,7 @@ public final class Settings implements Watchable, Snappable {
|
||||
|
||||
/** Map from volume UUID to {@link VersionInfo} */
|
||||
@Watched
|
||||
private WatchedArrayMap<String, VersionInfo> mVersion = new WatchedArrayMap<>();
|
||||
private final WatchedArrayMap<String, VersionInfo> mVersion = new WatchedArrayMap<>();
|
||||
|
||||
/**
|
||||
* Version details for a storage volume that may hold apps.
|
||||
@@ -435,6 +438,7 @@ public final class Settings implements Watchable, Snappable {
|
||||
}
|
||||
|
||||
/** Device identity for the purpose of package verification. */
|
||||
@Watched(manual = true)
|
||||
private VerifierDeviceIdentity mVerifierDeviceIdentity;
|
||||
|
||||
// The user's preferred activities associated with particular intent
|
||||
@@ -462,10 +466,12 @@ public final class Settings implements Watchable, Snappable {
|
||||
private final WatchedSparseArray<SettingBase> mOtherAppIds;
|
||||
|
||||
// For reading/writing settings file.
|
||||
private final ArrayList<Signature> mPastSignatures =
|
||||
new ArrayList<Signature>();
|
||||
private final ArrayMap<Long, Integer> mKeySetRefs =
|
||||
new ArrayMap<Long, Integer>();
|
||||
@Watched
|
||||
private final WatchedArrayList<Signature> mPastSignatures =
|
||||
new WatchedArrayList<Signature>();
|
||||
@Watched
|
||||
private final WatchedArrayMap<Long, Integer> mKeySetRefs =
|
||||
new WatchedArrayMap<Long, Integer>();
|
||||
|
||||
// Packages that have been renamed since they were first installed.
|
||||
// Keys are the new names of the packages, values are the original
|
||||
@@ -495,18 +501,21 @@ public final class Settings implements Watchable, Snappable {
|
||||
* TODO: make this just a local variable that is passed in during package
|
||||
* scanning to make it less confusing.
|
||||
*/
|
||||
private final ArrayList<PackageSetting> mPendingPackages = new ArrayList<>();
|
||||
@Watched
|
||||
private final WatchedArrayList<PackageSetting> mPendingPackages = new WatchedArrayList<>();
|
||||
|
||||
private final File mSystemDir;
|
||||
|
||||
public final KeySetManagerService mKeySetManagerService =
|
||||
new KeySetManagerService(mPackages.untrackedStorage());
|
||||
private final KeySetManagerService mKeySetManagerService;
|
||||
|
||||
/** Settings and other information about permissions */
|
||||
@Watched(manual = true)
|
||||
final LegacyPermissionSettings mPermissions;
|
||||
|
||||
@Watched(manual = true)
|
||||
private final LegacyPermissionDataProvider mPermissionDataProvider;
|
||||
|
||||
@Watched(manual = true)
|
||||
private final DomainVerificationManagerInternal mDomainVerificationManager;
|
||||
|
||||
/**
|
||||
@@ -532,23 +541,7 @@ public final class Settings implements Watchable, Snappable {
|
||||
}};
|
||||
}
|
||||
|
||||
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
|
||||
public Settings(Map<String, PackageSetting> pkgSettings) {
|
||||
mLock = new PackageManagerTracedLock();
|
||||
mPackages.putAll(pkgSettings);
|
||||
mAppIds = new WatchedArrayList<>();
|
||||
mOtherAppIds = new WatchedSparseArray<>();
|
||||
mSystemDir = null;
|
||||
mPermissions = null;
|
||||
mRuntimePermissionsPersistence = null;
|
||||
mPermissionDataProvider = null;
|
||||
mSettingsFilename = null;
|
||||
mBackupSettingsFilename = null;
|
||||
mPackageListFilename = null;
|
||||
mStoppedPackagesFilename = null;
|
||||
mBackupStoppedPackagesFilename = null;
|
||||
mKernelMappingFilename = null;
|
||||
mDomainVerificationManager = null;
|
||||
private void registerObservers() {
|
||||
mPackages.registerObserver(mObserver);
|
||||
mInstallerPackages.registerObserver(mObserver);
|
||||
mKernelMapping.registerObserver(mObserver);
|
||||
@@ -564,7 +557,43 @@ public final class Settings implements Watchable, Snappable {
|
||||
mRenamedPackages.registerObserver(mObserver);
|
||||
mNextAppLinkGeneration.registerObserver(mObserver);
|
||||
mDefaultBrowserApp.registerObserver(mObserver);
|
||||
mPendingPackages.registerObserver(mObserver);
|
||||
mPastSignatures.registerObserver(mObserver);
|
||||
mKeySetRefs.registerObserver(mObserver);
|
||||
}
|
||||
|
||||
// CONSTRUCTOR
|
||||
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
|
||||
public Settings(Map<String, PackageSetting> pkgSettings) {
|
||||
mPackages = new WatchedArrayMap<>();
|
||||
mPackagesSnapshot =
|
||||
new SnapshotCache.Auto<>(mPackages, mPackages, "Settings.mPackages");
|
||||
mKernelMapping = new WatchedArrayMap<>();
|
||||
mKernelMappingSnapshot =
|
||||
new SnapshotCache.Auto<>(mKernelMapping, mKernelMapping, "Settings.mKernelMapping");
|
||||
mInstallerPackages = new WatchedArraySet<>();
|
||||
mInstallerPackagesSnapshot =
|
||||
new SnapshotCache.Auto<>(mInstallerPackages, mInstallerPackages,
|
||||
"Settings.mInstallerPackages");
|
||||
mKeySetManagerService = new KeySetManagerService(mPackages);
|
||||
|
||||
mLock = new PackageManagerTracedLock();
|
||||
mPackages.putAll(pkgSettings);
|
||||
mAppIds = new WatchedArrayList<>();
|
||||
mOtherAppIds = new WatchedSparseArray<>();
|
||||
mSystemDir = null;
|
||||
mPermissions = null;
|
||||
mRuntimePermissionsPersistence = null;
|
||||
mPermissionDataProvider = null;
|
||||
mSettingsFilename = null;
|
||||
mBackupSettingsFilename = null;
|
||||
mPackageListFilename = null;
|
||||
mStoppedPackagesFilename = null;
|
||||
mBackupStoppedPackagesFilename = null;
|
||||
mKernelMappingFilename = null;
|
||||
mDomainVerificationManager = null;
|
||||
|
||||
registerObservers();
|
||||
Watchable.verifyWatchedAttributes(this, mObserver);
|
||||
|
||||
mSnapshot = makeCache();
|
||||
@@ -574,6 +603,18 @@ public final class Settings implements Watchable, Snappable {
|
||||
LegacyPermissionDataProvider permissionDataProvider,
|
||||
@NonNull DomainVerificationManagerInternal domainVerificationManager,
|
||||
@NonNull PackageManagerTracedLock lock) {
|
||||
mPackages = new WatchedArrayMap<>();
|
||||
mPackagesSnapshot =
|
||||
new SnapshotCache.Auto<>(mPackages, mPackages, "Settings.mPackages");
|
||||
mKernelMapping = new WatchedArrayMap<>();
|
||||
mKernelMappingSnapshot =
|
||||
new SnapshotCache.Auto<>(mKernelMapping, mKernelMapping, "Settings.mKernelMapping");
|
||||
mInstallerPackages = new WatchedArraySet<>();
|
||||
mInstallerPackagesSnapshot =
|
||||
new SnapshotCache.Auto<>(mInstallerPackages, mInstallerPackages,
|
||||
"Settings.mInstallerPackages");
|
||||
mKeySetManagerService = new KeySetManagerService(mPackages);
|
||||
|
||||
mLock = lock;
|
||||
mAppIds = new WatchedArrayList<>();
|
||||
mOtherAppIds = new WatchedSparseArray<>();
|
||||
@@ -602,22 +643,7 @@ public final class Settings implements Watchable, Snappable {
|
||||
|
||||
mDomainVerificationManager = domainVerificationManager;
|
||||
|
||||
mPackages.registerObserver(mObserver);
|
||||
mInstallerPackages.registerObserver(mObserver);
|
||||
mKernelMapping.registerObserver(mObserver);
|
||||
mDisabledSysPackages.registerObserver(mObserver);
|
||||
mBlockUninstallPackages.registerObserver(mObserver);
|
||||
mVersion.registerObserver(mObserver);
|
||||
mPreferredActivities.registerObserver(mObserver);
|
||||
mPersistentPreferredActivities.registerObserver(mObserver);
|
||||
mCrossProfileIntentResolvers.registerObserver(mObserver);
|
||||
mSharedUsers.registerObserver(mObserver);
|
||||
mAppIds.registerObserver(mObserver);
|
||||
mOtherAppIds.registerObserver(mObserver);
|
||||
mRenamedPackages.registerObserver(mObserver);
|
||||
mNextAppLinkGeneration.registerObserver(mObserver);
|
||||
mDefaultBrowserApp.registerObserver(mObserver);
|
||||
|
||||
registerObservers();
|
||||
Watchable.verifyWatchedAttributes(this, mObserver);
|
||||
|
||||
mSnapshot = makeCache();
|
||||
@@ -629,8 +655,13 @@ public final class Settings implements Watchable, Snappable {
|
||||
* are changed by PackageManagerService APIs are deep-copied
|
||||
*/
|
||||
private Settings(Settings r) {
|
||||
final int mPackagesSize = r.mPackages.size();
|
||||
mPackages.putAll(r.mPackages);
|
||||
mPackages = r.mPackagesSnapshot.snapshot();
|
||||
mPackagesSnapshot = new SnapshotCache.Sealed<>();
|
||||
mKernelMapping = r.mKernelMappingSnapshot.snapshot();
|
||||
mKernelMappingSnapshot = new SnapshotCache.Sealed<>();
|
||||
mInstallerPackages = r.mInstallerPackagesSnapshot.snapshot();
|
||||
mInstallerPackagesSnapshot = new SnapshotCache.Sealed<>();
|
||||
mKeySetManagerService = new KeySetManagerService(mPackages);
|
||||
|
||||
// The following assignments satisfy Java requirements but are not
|
||||
// needed by the read-only methods. Note especially that the lock
|
||||
@@ -647,9 +678,7 @@ public final class Settings implements Watchable, Snappable {
|
||||
|
||||
mDomainVerificationManager = r.mDomainVerificationManager;
|
||||
|
||||
mInstallerPackages.addAll(r.mInstallerPackages);
|
||||
mKernelMapping.putAll(r.mKernelMapping);
|
||||
mDisabledSysPackages.putAll(r.mDisabledSysPackages);
|
||||
mDisabledSysPackages.snapshot(r.mDisabledSysPackages);
|
||||
mBlockUninstallPackages.snapshot(r.mBlockUninstallPackages);
|
||||
mVersion.putAll(r.mVersion);
|
||||
mVerifierDeviceIdentity = r.mVerifierDeviceIdentity;
|
||||
@@ -659,23 +688,26 @@ public final class Settings implements Watchable, Snappable {
|
||||
mPersistentPreferredActivities, r.mPersistentPreferredActivities);
|
||||
WatchedSparseArray.snapshot(
|
||||
mCrossProfileIntentResolvers, r.mCrossProfileIntentResolvers);
|
||||
mSharedUsers.putAll(r.mSharedUsers);
|
||||
mSharedUsers.snapshot(r.mSharedUsers);
|
||||
mAppIds = r.mAppIds.snapshot();
|
||||
mOtherAppIds = r.mOtherAppIds.snapshot();
|
||||
mPastSignatures.addAll(r.mPastSignatures);
|
||||
mKeySetRefs.putAll(r.mKeySetRefs);
|
||||
WatchedArrayList.snapshot(
|
||||
mPastSignatures, r.mPastSignatures);
|
||||
WatchedArrayMap.snapshot(
|
||||
mKeySetRefs, r.mKeySetRefs);
|
||||
mRenamedPackages.snapshot(r.mRenamedPackages);
|
||||
mNextAppLinkGeneration.snapshot(r.mNextAppLinkGeneration);
|
||||
mDefaultBrowserApp.snapshot(r.mDefaultBrowserApp);
|
||||
// mReadMessages
|
||||
mPendingPackages.addAll(r.mPendingPackages);
|
||||
WatchedArrayList.snapshot(
|
||||
mPendingPackages, r.mPendingPackages);
|
||||
mSystemDir = null;
|
||||
// mKeySetManagerService;
|
||||
mPermissions = r.mPermissions;
|
||||
mPermissionDataProvider = r.mPermissionDataProvider;
|
||||
|
||||
// Do not register any Watchables and do not create a snapshot cache.
|
||||
mSnapshot = null;
|
||||
mSnapshot = new SnapshotCache.Sealed();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2326,7 +2358,7 @@ public final class Settings implements Watchable, Snappable {
|
||||
serializer.startTag(null, "shared-user");
|
||||
serializer.attribute(null, ATTR_NAME, usr.name);
|
||||
serializer.attributeInt(null, "userId", usr.userId);
|
||||
usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
|
||||
usr.signatures.writeXml(serializer, "sigs", mPastSignatures.untrackedStorage());
|
||||
serializer.endTag(null, "shared-user");
|
||||
}
|
||||
|
||||
@@ -2736,11 +2768,11 @@ public final class Settings implements Watchable, Snappable {
|
||||
|
||||
writeUsesStaticLibLPw(serializer, pkg.usesStaticLibraries, pkg.usesStaticLibrariesVersions);
|
||||
|
||||
pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
|
||||
pkg.signatures.writeXml(serializer, "sigs", mPastSignatures.untrackedStorage());
|
||||
|
||||
if (installSource.initiatingPackageSignatures != null) {
|
||||
installSource.initiatingPackageSignatures.writeXml(
|
||||
serializer, "install-initiator-sigs", mPastSignatures);
|
||||
serializer, "install-initiator-sigs", mPastSignatures.untrackedStorage());
|
||||
}
|
||||
|
||||
writeSigningKeySetLPr(serializer, pkg.keySetData);
|
||||
@@ -2909,7 +2941,7 @@ public final class Settings implements Watchable, Snappable {
|
||||
} else if (TAG_READ_EXTERNAL_STORAGE.equals(tagName)) {
|
||||
// No longer used.
|
||||
} else if (tagName.equals("keyset-settings")) {
|
||||
mKeySetManagerService.readKeySetsLPw(parser, mKeySetRefs);
|
||||
mKeySetManagerService.readKeySetsLPw(parser, mKeySetRefs.untrackedStorage());
|
||||
} else if (TAG_VERSION.equals(tagName)) {
|
||||
final String volumeUuid = XmlUtils.readStringAttribute(parser,
|
||||
ATTR_VOLUME_UUID);
|
||||
@@ -3697,7 +3729,7 @@ public final class Settings implements Watchable, Snappable {
|
||||
} else if (tagName.equals(TAG_ENABLED_COMPONENTS)) {
|
||||
readEnabledComponentsLPw(packageSetting, parser, 0);
|
||||
} else if (tagName.equals("sigs")) {
|
||||
packageSetting.signatures.readXml(parser, mPastSignatures);
|
||||
packageSetting.signatures.readXml(parser, mPastSignatures.untrackedStorage());
|
||||
} else if (tagName.equals(TAG_PERMISSIONS)) {
|
||||
readInstallPermissionsLPr(parser,
|
||||
packageSetting.getLegacyPermissionState(), users);
|
||||
@@ -3728,7 +3760,7 @@ public final class Settings implements Watchable, Snappable {
|
||||
packageSetting.keySetData.addDefinedKeySet(id, alias);
|
||||
} else if (tagName.equals("install-initiator-sigs")) {
|
||||
final PackageSignatures signatures = new PackageSignatures();
|
||||
signatures.readXml(parser, mPastSignatures);
|
||||
signatures.readXml(parser, mPastSignatures.untrackedStorage());
|
||||
packageSetting.installSource =
|
||||
packageSetting.installSource.setInitiatingPackageSignatures(signatures);
|
||||
} else if (tagName.equals(TAG_DOMAIN_VERIFICATION)) {
|
||||
@@ -3923,7 +3955,7 @@ public final class Settings implements Watchable, Snappable {
|
||||
|
||||
String tagName = parser.getName();
|
||||
if (tagName.equals("sigs")) {
|
||||
su.signatures.readXml(parser, mPastSignatures);
|
||||
su.signatures.readXml(parser, mPastSignatures.untrackedStorage());
|
||||
} else if (tagName.equals("perms")) {
|
||||
readInstallPermissionsLPr(parser, su.getLegacyPermissionState(), users);
|
||||
} else {
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.os.Message;
|
||||
import android.os.SystemClock;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.server.EventLogTags;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
@@ -238,6 +239,11 @@ public class SnapshotStatistics {
|
||||
*/
|
||||
public int mTotalUsed = 0;
|
||||
|
||||
/**
|
||||
* The total number of times a snapshot was bypassed because corking was in effect.
|
||||
*/
|
||||
public int mTotalCorked = 0;
|
||||
|
||||
/**
|
||||
* The total number of builds that count as big, which means they took longer than
|
||||
* SNAPSHOT_BIG_BUILD_TIME_NS.
|
||||
@@ -291,6 +297,13 @@ public class SnapshotStatistics {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Record a cork.
|
||||
*/
|
||||
private void corked() {
|
||||
mTotalCorked++;
|
||||
}
|
||||
|
||||
private Stats(long now) {
|
||||
mStartTimeUs = now;
|
||||
mTimes = new int[mTimeBins.count()];
|
||||
@@ -308,6 +321,7 @@ public class SnapshotStatistics {
|
||||
mUsed = Arrays.copyOf(orig.mUsed, orig.mUsed.length);
|
||||
mTotalBuilds = orig.mTotalBuilds;
|
||||
mTotalUsed = orig.mTotalUsed;
|
||||
mTotalCorked = orig.mTotalCorked;
|
||||
mBigBuilds = orig.mBigBuilds;
|
||||
mShortLived = orig.mShortLived;
|
||||
mTotalTimeUs = orig.mTotalTimeUs;
|
||||
@@ -365,6 +379,7 @@ public class SnapshotStatistics {
|
||||
* Dump the summary statistics record. Choose the header or the data.
|
||||
* number of builds
|
||||
* number of uses
|
||||
* number of corks
|
||||
* number of big builds
|
||||
* number of short lifetimes
|
||||
* cumulative build time, in seconds
|
||||
@@ -373,13 +388,13 @@ public class SnapshotStatistics {
|
||||
private void dumpStats(PrintWriter pw, String indent, long now, boolean header) {
|
||||
dumpPrefix(pw, indent, now, header, "Summary stats");
|
||||
if (header) {
|
||||
pw.format(Locale.US, " %10s %10s %10s %10s %10s %10s",
|
||||
"TotBlds", "TotUsed", "BigBlds", "ShortLvd",
|
||||
pw.format(Locale.US, " %10s %10s %10s %10s %10s %10s %10s",
|
||||
"TotBlds", "TotUsed", "TotCork", "BigBlds", "ShortLvd",
|
||||
"TotTime", "MaxTime");
|
||||
} else {
|
||||
pw.format(Locale.US,
|
||||
" %10d %10d %10d %10d %10d %10d",
|
||||
mTotalBuilds, mTotalUsed, mBigBuilds, mShortLived,
|
||||
" %10d %10d %10d %10d %10d %10d %10d",
|
||||
mTotalBuilds, mTotalUsed, mTotalCorked, mBigBuilds, mShortLived,
|
||||
mTotalTimeUs / 1000, mMaxBuildTimeUs / 1000);
|
||||
}
|
||||
pw.println();
|
||||
@@ -516,7 +531,7 @@ public class SnapshotStatistics {
|
||||
* @param done The time at which the snapshot rebuild completed, in ns.
|
||||
* @param hits The number of times the previous snapshot was used.
|
||||
*/
|
||||
public void rebuild(long now, long done, int hits) {
|
||||
public final void rebuild(long now, long done, int hits) {
|
||||
// The duration has a span of about 2000s
|
||||
final int duration = (int) (done - now);
|
||||
boolean reportEvent = false;
|
||||
@@ -543,10 +558,21 @@ public class SnapshotStatistics {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Record a corked snapshot request.
|
||||
*/
|
||||
public final void corked() {
|
||||
synchronized (mLock) {
|
||||
mShort[0].corked();
|
||||
mLong[0].corked();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Roll a stats array. Shift the elements up an index and create a new element at
|
||||
* index zero. The old element zero is completed with the specified time.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
private void shift(Stats[] s, long now) {
|
||||
s[0].complete(now);
|
||||
for (int i = s.length - 1; i > 0; i--) {
|
||||
@@ -598,7 +624,8 @@ public class SnapshotStatistics {
|
||||
* Dump the statistics. The format is compatible with the PackageManager dumpsys
|
||||
* output.
|
||||
*/
|
||||
public void dump(PrintWriter pw, String indent, long now, int unrecorded, boolean full) {
|
||||
public void dump(PrintWriter pw, String indent, long now, int unrecorded,
|
||||
int corkLevel, boolean full) {
|
||||
// Grab the raw statistics under lock, but print them outside of the lock.
|
||||
Stats[] l;
|
||||
Stats[] s;
|
||||
@@ -608,7 +635,8 @@ public class SnapshotStatistics {
|
||||
s = Arrays.copyOf(mShort, mShort.length);
|
||||
s[0] = new Stats(s[0]);
|
||||
}
|
||||
pw.format(Locale.US, "%s Unrecorded hits %d", indent, unrecorded);
|
||||
pw.format(Locale.US, "%s Unrecorded-hits: %d Cork-level: %d", indent,
|
||||
unrecorded, corkLevel);
|
||||
pw.println();
|
||||
dump(pw, indent, now, l, s, "stats");
|
||||
if (!full) {
|
||||
|
||||
@@ -19,6 +19,9 @@ package com.android.server.utils;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* A class that caches snapshots. Instances are instantiated on a {@link Watchable}; when the
|
||||
* {@link Watchable} reports a change, the cache is cleared. The snapshot() method fetches the
|
||||
@@ -35,25 +38,65 @@ public abstract class SnapshotCache<T> extends Watcher{
|
||||
*/
|
||||
private static final boolean ENABLED = true;
|
||||
|
||||
/**
|
||||
* The statistics for a single cache. The object records the number of times a
|
||||
* snapshot was reused and the number of times a snapshot was rebuilt.
|
||||
*/
|
||||
private static class Statistics {
|
||||
final String mName;
|
||||
private final AtomicInteger mReused = new AtomicInteger(0);
|
||||
private final AtomicInteger mRebuilt = new AtomicInteger(0);
|
||||
Statistics(@NonNull String n) {
|
||||
mName = n;
|
||||
}
|
||||
}
|
||||
|
||||
// The source object from which snapshots are created. This may be null if createSnapshot()
|
||||
// does not require it.
|
||||
protected final T mSource;
|
||||
|
||||
// The cached snapshot
|
||||
private T mSnapshot = null;
|
||||
private volatile T mSnapshot = null;
|
||||
|
||||
// True if the snapshot is sealed and may not be modified.
|
||||
private boolean mSealed = false;
|
||||
private volatile boolean mSealed = false;
|
||||
|
||||
// The statistics for this cache. This may be null.
|
||||
private final Statistics mStatistics;
|
||||
|
||||
/**
|
||||
* The global list of caches.
|
||||
*/
|
||||
private static final WeakHashMap<SnapshotCache, Void> sCaches = new WeakHashMap<>();
|
||||
|
||||
/**
|
||||
* Create a cache with a source object for rebuilding snapshots and a
|
||||
* {@link Watchable} that notifies when the cache is invalid.
|
||||
* {@link Watchable} that notifies when the cache is invalid. If the name is null
|
||||
* then statistics are not collected for this cache.
|
||||
* @param source Source data for rebuilding snapshots.
|
||||
* @param watchable The object that notifies when the cache is invalid.
|
||||
* @param name The name of the cache, for statistics reporting.
|
||||
*/
|
||||
public SnapshotCache(@Nullable T source, @NonNull Watchable watchable, @Nullable String name) {
|
||||
mSource = source;
|
||||
watchable.registerObserver(this);
|
||||
if (name != null) {
|
||||
mStatistics = new Statistics(name);
|
||||
sCaches.put(this, null);
|
||||
} else {
|
||||
mStatistics = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a cache with a source object for rebuilding snapshots and a
|
||||
* {@link Watchable} that notifies when the cache is invalid. The name is null in
|
||||
* this API.
|
||||
* @param source Source data for rebuilding snapshots.
|
||||
* @param watchable The object that notifies when the cache is invalid.
|
||||
*/
|
||||
public SnapshotCache(@Nullable T source, @NonNull Watchable watchable) {
|
||||
mSource = source;
|
||||
watchable.registerObserver(this);
|
||||
this(source, watchable, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,13 +106,14 @@ public abstract class SnapshotCache<T> extends Watcher{
|
||||
public SnapshotCache() {
|
||||
mSource = null;
|
||||
mSealed = true;
|
||||
mStatistics = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify the object that the source object has changed. If the local object is sealed then
|
||||
* IllegalStateException is thrown. Otherwise, the cache is cleared.
|
||||
*/
|
||||
public void onChange(@Nullable Watchable what) {
|
||||
public final void onChange(@Nullable Watchable what) {
|
||||
if (mSealed) {
|
||||
throw new IllegalStateException("attempt to change a sealed object");
|
||||
}
|
||||
@@ -79,7 +123,7 @@ public abstract class SnapshotCache<T> extends Watcher{
|
||||
/**
|
||||
* Seal the cache. Attempts to modify the cache will generate an exception.
|
||||
*/
|
||||
public void seal() {
|
||||
public final void seal() {
|
||||
mSealed = true;
|
||||
}
|
||||
|
||||
@@ -88,11 +132,14 @@ public abstract class SnapshotCache<T> extends Watcher{
|
||||
* new snapshot and saves it in the cache.
|
||||
* @return A snapshot as returned by createSnapshot() and possibly cached.
|
||||
*/
|
||||
public T snapshot() {
|
||||
public final T snapshot() {
|
||||
T s = mSnapshot;
|
||||
if (s == null || !ENABLED) {
|
||||
s = createSnapshot();
|
||||
mSnapshot = s;
|
||||
if (mStatistics != null) mStatistics.mRebuilt.incrementAndGet();
|
||||
} else {
|
||||
if (mStatistics != null) mStatistics.mReused.incrementAndGet();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@@ -123,4 +170,25 @@ public abstract class SnapshotCache<T> extends Watcher{
|
||||
throw new UnsupportedOperationException("cannot snapshot a sealed snaphot");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A snapshot cache suitable for Snappable types. The key is that Snappable types
|
||||
* have a known implementation of createSnapshot() so that this class is concrete.
|
||||
* @param <T> The class whose snapshot is being cached.
|
||||
*/
|
||||
public static class Auto<T extends Snappable<T>> extends SnapshotCache<T> {
|
||||
public Auto(@NonNull T source, @NonNull Watchable watchable, @Nullable String name) {
|
||||
super(source, watchable, name);
|
||||
}
|
||||
public Auto(@NonNull T source, @NonNull Watchable watchable) {
|
||||
this(source, watchable, null);
|
||||
}
|
||||
/**
|
||||
* Concrete createSnapshot() using the snapshot() method of <T>.
|
||||
*/
|
||||
public T createSnapshot() {
|
||||
return mSource.snapshot();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.util.ArraySet;
|
||||
import android.util.LongSparseArray;
|
||||
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.server.utils.WatchedArrayMap;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -33,7 +34,7 @@ import java.security.cert.CertificateException;
|
||||
|
||||
public class KeySetManagerServiceTest extends AndroidTestCase {
|
||||
|
||||
private ArrayMap<String, PackageSetting> mPackagesMap;
|
||||
private WatchedArrayMap<String, PackageSetting> mPackagesMap;
|
||||
private KeySetManagerService mKsms;
|
||||
|
||||
public PackageSetting generateFakePackageSetting(String name) {
|
||||
@@ -46,7 +47,7 @@ public class KeySetManagerServiceTest extends AndroidTestCase {
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
mPackagesMap = new ArrayMap<String, PackageSetting>();
|
||||
mPackagesMap = new WatchedArrayMap<String, PackageSetting>();
|
||||
mKsms = new KeySetManagerService(mPackagesMap);
|
||||
}
|
||||
|
||||
@@ -94,7 +95,8 @@ public class KeySetManagerServiceTest extends AndroidTestCase {
|
||||
}
|
||||
|
||||
public void testEncodePublicKey() throws IOException {
|
||||
ArrayMap<String, PackageSetting> packagesMap = new ArrayMap<String, PackageSetting>();
|
||||
WatchedArrayMap<String, PackageSetting> packagesMap =
|
||||
new WatchedArrayMap<String, PackageSetting>();
|
||||
KeySetManagerService ksms = new KeySetManagerService(packagesMap);
|
||||
|
||||
PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA);
|
||||
|
||||
@@ -47,7 +47,6 @@ import android.os.BaseBundle;
|
||||
import android.os.PersistableBundle;
|
||||
import android.os.Process;
|
||||
import android.os.UserHandle;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.AtomicFile;
|
||||
import android.util.Log;
|
||||
@@ -64,6 +63,7 @@ import com.android.server.pm.parsing.pkg.ParsedPackage;
|
||||
import com.android.server.pm.permission.LegacyPermissionDataProvider;
|
||||
import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
|
||||
import com.android.server.utils.WatchableTester;
|
||||
import com.android.server.utils.WatchedArrayMap;
|
||||
|
||||
import com.google.common.truth.Truth;
|
||||
|
||||
@@ -1202,9 +1202,8 @@ public class PackageManagerSettingsTests {
|
||||
|
||||
private void verifyKeySetMetaData(Settings settings)
|
||||
throws ReflectiveOperationException, IllegalAccessException {
|
||||
ArrayMap<String, PackageSetting> packages =
|
||||
settings.mPackages.untrackedStorage();
|
||||
KeySetManagerService ksms = settings.mKeySetManagerService;
|
||||
WatchedArrayMap<String, PackageSetting> packages = settings.mPackages;
|
||||
KeySetManagerService ksms = settings.getKeySetManagerService();
|
||||
|
||||
/* verify keyset and public key ref counts */
|
||||
assertThat(KeySetUtils.getKeySetRefCount(ksms, 1), is(2));
|
||||
|
||||
Reference in New Issue
Block a user