Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d6e8cc08 authored by Lee Shombert's avatar Lee Shombert Committed by Automerger Merge Worker
Browse files

Merge "Ensure PM watches all Watchables" into sc-dev am: df7b5b3a

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/13501298

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I424954e27c90bccbf24c2c9d3a7c8e448b56f1df
parents b565adde df7b5b3a
Loading
Loading
Loading
Loading
+17 −18
Original line number Diff line number Diff line
@@ -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) {
+7 −4
Original line number Diff line number Diff line
@@ -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);
+35 −21
Original line number Diff line number Diff line
@@ -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) {
    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);
    }
}