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 * A extremely minimal constructor designed to start up a PackageManagerService instance for
* testing. * testing.
@@ -6023,15 +6038,7 @@ public class PackageManagerService extends IPackageManager.Stub
sSnapshotCorked = true; sSnapshotCorked = true;
mLiveComputer = createLiveComputer(); mLiveComputer = createLiveComputer();
mSnapshotComputer = mLiveComputer; mSnapshotComputer = mLiveComputer;
registerObserver();
// 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);
mPackages.putAll(testParams.packages); mPackages.putAll(testParams.packages);
mEnableFreeCacheV2 = testParams.enableFreeCacheV2; mEnableFreeCacheV2 = testParams.enableFreeCacheV2;
@@ -6185,15 +6192,6 @@ public class PackageManagerService extends IPackageManager.Stub
mDomainVerificationManager = injector.getDomainVerificationManagerInternal(); mDomainVerificationManager = injector.getDomainVerificationManagerInternal();
mDomainVerificationManager.setConnection(mDomainVerificationConnection); 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 // 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 // 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 // constructor, at which time the invalidation method updates it. The cache is
@@ -6202,6 +6200,7 @@ public class PackageManagerService extends IPackageManager.Stub
sSnapshotCorked = true; sSnapshotCorked = true;
mLiveComputer = createLiveComputer(); mLiveComputer = createLiveComputer();
mSnapshotComputer = mLiveComputer; mSnapshotComputer = mLiveComputer;
registerObserver();
// CHECKSTYLE:OFF IndentationCheck // CHECKSTYLE:OFF IndentationCheck
synchronized (mInstallLock) { synchronized (mInstallLock) {

View File

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

View File

@@ -19,8 +19,8 @@ package com.android.server.utils;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.os.Build; import android.os.Build;
import android.util.Log;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field; import java.lang.reflect.Field;
/** /**
@@ -60,41 +60,55 @@ public interface Watchable {
*/ */
public void dispatchChange(@Nullable Watchable what); 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 * Verify that all @Watched {@link Watchable} attributes are being watched by this
* class. This requires reflection and only runs in engineering or user debug * class. This requires reflection and only runs in engineering or user debug
* builds. * 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) { static void verifyWatchedAttributes(Object base, Watcher observer, boolean logOnly) {
if (Build.IS_ENG || Build.IS_USERDEBUG) { if (!(Build.IS_ENG || Build.IS_USERDEBUG)) {
return;
}
for (Field f : base.getClass().getDeclaredFields()) { for (Field f : base.getClass().getDeclaredFields()) {
if (f.getAnnotation(Watched.class) != null) {
final String fn = base.getClass().getName() + "." + f.getName();
try { try {
final boolean flagged = isWatched(f); f.setAccessible(true);
final Object o = f.get(base); final Object o = f.get(base);
final boolean watchable = o instanceof Watchable; if (o instanceof Watchable) {
if (flagged && watchable) { Watchable attr = (Watchable) (o);
Watchable attr = (Watchable) f.get(base);
if (attr != null && !attr.isRegisteredObserver(observer)) { 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) { } catch (IllegalAccessException e) {
// The field is protected; ignore it. Other exceptions that may be thrown by // The field is protected; ignore it. Other exceptions that may be thrown by
// Field.get() are allowed to roll up. // 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);
}
} }