Merge "Ensure PM watches all Watchables" into sc-dev
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user