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
|
* 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) {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user