Merge "Ensure PM watches all Watchables" into sc-dev

This commit is contained in:
Lee Shombert
2021-02-09 17:34:47 +00:00
committed by Android (Google) Code Review
3 changed files with 59 additions and 43 deletions

View File

@@ -5940,6 +5940,21 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
// Link watchables to the class
private void registerObserver() {
mPackages.registerObserver(mWatcher);
mSharedLibraries.registerObserver(mWatcher);
mStaticLibsByDeclaringPackage.registerObserver(mWatcher);
mInstrumentation.registerObserver(mWatcher);
mWebInstantAppsDisabled.registerObserver(mWatcher);
mAppsFilter.registerObserver(mWatcher);
mInstantAppRegistry.registerObserver(mWatcher);
mSettings.registerObserver(mWatcher);
// If neither "build" attribute is true then this may be a mockito test, and verification
// can fail as a false positive.
Watchable.verifyWatchedAttributes(this, mWatcher, !(mIsEngBuild || mIsUserDebugBuild));
}
/**
* A extremely minimal constructor designed to start up a PackageManagerService instance for
* testing.
@@ -6023,15 +6038,7 @@ public class PackageManagerService extends IPackageManager.Stub
sSnapshotCorked = true;
mLiveComputer = createLiveComputer();
mSnapshotComputer = mLiveComputer;
// Link up the watchers
mPackages.registerObserver(mWatcher);
mSharedLibraries.registerObserver(mWatcher);
mStaticLibsByDeclaringPackage.registerObserver(mWatcher);
mInstrumentation.registerObserver(mWatcher);
mWebInstantAppsDisabled.registerObserver(mWatcher);
mAppsFilter.registerObserver(mWatcher);
Watchable.verifyWatchedAttributes(this, mWatcher);
registerObserver();
mPackages.putAll(testParams.packages);
mEnableFreeCacheV2 = testParams.enableFreeCacheV2;
@@ -6185,15 +6192,6 @@ public class PackageManagerService extends IPackageManager.Stub
mDomainVerificationManager = injector.getDomainVerificationManagerInternal();
mDomainVerificationManager.setConnection(mDomainVerificationConnection);
// Link up the watchers
mPackages.registerObserver(mWatcher);
mSharedLibraries.registerObserver(mWatcher);
mStaticLibsByDeclaringPackage.registerObserver(mWatcher);
mInstrumentation.registerObserver(mWatcher);
mWebInstantAppsDisabled.registerObserver(mWatcher);
mAppsFilter.registerObserver(mWatcher);
Watchable.verifyWatchedAttributes(this, mWatcher);
// Create the computer as soon as the state objects have been installed. The
// cached computer is the same as the live computer until the end of the
// constructor, at which time the invalidation method updates it. The cache is
@@ -6202,6 +6200,7 @@ public class PackageManagerService extends IPackageManager.Stub
sSnapshotCorked = true;
mLiveComputer = createLiveComputer();
mSnapshotComputer = mLiveComputer;
registerObserver();
// CHECKSTYLE:OFF IndentationCheck
synchronized (mInstallLock) {

View File

@@ -107,9 +107,6 @@ import com.android.permission.persistence.RuntimePermissionsState;
import com.android.server.LocalServices;
import com.android.server.backup.PreferredActivityBackupHelper;
import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.verify.domain.DomainVerificationLegacySettings;
import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
import com.android.server.pm.verify.domain.DomainVerificationPersistence;
import com.android.server.pm.parsing.PackageInfoUtils;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
@@ -117,6 +114,9 @@ import com.android.server.pm.permission.LegacyPermissionDataProvider;
import com.android.server.pm.permission.LegacyPermissionSettings;
import com.android.server.pm.permission.LegacyPermissionState;
import com.android.server.pm.permission.LegacyPermissionState.PermissionState;
import com.android.server.pm.verify.domain.DomainVerificationLegacySettings;
import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
import com.android.server.pm.verify.domain.DomainVerificationPersistence;
import com.android.server.utils.Snappable;
import com.android.server.utils.TimingsTraceAndSlog;
import com.android.server.utils.Watchable;
@@ -489,7 +489,7 @@ public final class Settings implements Watchable, Snappable {
// App-link priority tracking, per-user
@NonNull
@Watched
final WatchedSparseIntArray mNextAppLinkGeneration = new WatchedSparseIntArray();
private final WatchedSparseIntArray mNextAppLinkGeneration = new WatchedSparseIntArray();
final StringBuilder mReadMessages = new StringBuilder();
@@ -554,6 +554,7 @@ public final class Settings implements Watchable, Snappable {
mAppIds.registerObserver(mObserver);
mOtherAppIds.registerObserver(mObserver);
mRenamedPackages.registerObserver(mObserver);
mNextAppLinkGeneration.registerObserver(mObserver);
mDefaultBrowserApp.registerObserver(mObserver);
Watchable.verifyWatchedAttributes(this, mObserver);
@@ -604,6 +605,7 @@ public final class Settings implements Watchable, Snappable {
mAppIds.registerObserver(mObserver);
mOtherAppIds.registerObserver(mObserver);
mRenamedPackages.registerObserver(mObserver);
mNextAppLinkGeneration.registerObserver(mObserver);
mDefaultBrowserApp.registerObserver(mObserver);
Watchable.verifyWatchedAttributes(this, mObserver);
@@ -651,6 +653,7 @@ public final class Settings implements Watchable, Snappable {
mPastSignatures.addAll(r.mPastSignatures);
mKeySetRefs.putAll(r.mKeySetRefs);
mRenamedPackages.snapshot(r.mRenamedPackages);
mNextAppLinkGeneration.snapshot(r.mNextAppLinkGeneration);
mDefaultBrowserApp.snapshot(r.mDefaultBrowserApp);
// mReadMessages
mPendingPackages.addAll(r.mPendingPackages);

View File

@@ -19,8 +19,8 @@ package com.android.server.utils;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Build;
import android.util.Log;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
/**
@@ -60,41 +60,55 @@ public interface Watchable {
*/
public void dispatchChange(@Nullable Watchable what);
/**
* Return true if the field is tagged with @Watched
*/
private static boolean isWatched(Field f) {
for (Annotation a : f.getDeclaredAnnotations()) {
if (a.annotationType().equals(Watched.class)) {
return true;
}
}
return false;
}
/**
* Verify that all @Watched {@link Watchable} attributes are being watched by this
* class. This requires reflection and only runs in engineering or user debug
* builds.
* @param base The object that contains watched attributes.
* @param observer The {@link Watcher} that should be watching these attributes.
* @param logOnly If true then log errors; if false then throw an RuntimeExecption on error.
*/
static void verifyWatchedAttributes(Object base, Watcher observer) {
if (Build.IS_ENG || Build.IS_USERDEBUG) {
for (Field f : base.getClass().getDeclaredFields()) {
static void verifyWatchedAttributes(Object base, Watcher observer, boolean logOnly) {
if (!(Build.IS_ENG || Build.IS_USERDEBUG)) {
return;
}
for (Field f : base.getClass().getDeclaredFields()) {
if (f.getAnnotation(Watched.class) != null) {
final String fn = base.getClass().getName() + "." + f.getName();
try {
final boolean flagged = isWatched(f);
f.setAccessible(true);
final Object o = f.get(base);
final boolean watchable = o instanceof Watchable;
if (flagged && watchable) {
Watchable attr = (Watchable) f.get(base);
if (o instanceof Watchable) {
Watchable attr = (Watchable) (o);
if (attr != null && !attr.isRegisteredObserver(observer)) {
throw new RuntimeException(f.getName() + " missing an observer");
if (logOnly) {
Log.e("Watchable", fn + " missing an observer");
} else {
throw new RuntimeException("Watchable " + fn
+ " missing an observer");
}
}
}
} catch (IllegalAccessException e) {
// The field is protected; ignore it. Other exceptions that may be thrown by
// Field.get() are allowed to roll up.
if (logOnly) {
Log.e("Watchable", fn + " not visible");
} else {
throw new RuntimeException("Watchable " + fn + " not visible");
}
}
}
}
}
/**
* Verify that all @Watched {@link Watchable} attributes are being watched by this
* class. This calls verifyWatchedAttributes() with logOnly set to false.
* @param base The object that contains watched attributes.
* @param observer The {@link Watcher} that should be watching these attributes.
*/
static void verifyWatchedAttributes(Object base, Watcher observer) {
verifyWatchedAttributes(base, observer, false);
}
}