OMS: Only allow trusted overlays to be registered.

Bug: 69383160
Test: cts-tradefed run cts -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.OverlayHostTest
Change-Id: I930c11716317cff1ec485a3943d1f22f07a423df
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index 0c893b0..5a91e94 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -16,10 +16,14 @@
 
 package android.content.pm;
 
+import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Overall information about the contents of a package.  This corresponds
  * to all of the information collected from AndroidManifest.xml.
@@ -330,8 +334,29 @@
     /** @hide */
     public int overlayPriority;
 
-    /** @hide */
-    public boolean isStaticOverlay;
+    /**
+     * Flag for use with {@link #mOverlayFlags}. Marks the overlay as static, meaning it cannot
+     * be enabled/disabled at runtime.
+     */
+    static final int FLAG_OVERLAY_STATIC = 1 << 1;
+
+    /**
+     * Flag for use with {@link #mOverlayFlags}. Marks the overlay as trusted (not 3rd party).
+     */
+    static final int FLAG_OVERLAY_TRUSTED = 1 << 2;
+
+    @IntDef(flag = true, prefix = "FLAG_OVERLAY_", value = {
+            FLAG_OVERLAY_STATIC,
+            FLAG_OVERLAY_TRUSTED
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    @interface OverlayFlags {}
+
+    /**
+     * Modifiers that affect the state of this overlay. See {@link #FLAG_OVERLAY_STATIC},
+     * {@link #FLAG_OVERLAY_TRUSTED}.
+     */
+    @OverlayFlags int mOverlayFlags;
 
     /**
      * The user-visible SDK version (ex. 26) of the framework against which the application claims
@@ -359,6 +384,23 @@
     public PackageInfo() {
     }
 
+    /**
+     * Returns true if the package is a valid Runtime Overlay package.
+     * @hide
+     */
+    public boolean isOverlayPackage() {
+        return overlayTarget != null && (mOverlayFlags & FLAG_OVERLAY_TRUSTED) != 0;
+    }
+
+    /**
+     * Returns true if the package is a valid static Runtime Overlay package. Static overlays
+     * are not updatable outside of a system update and are safe to load in the system process.
+     * @hide
+     */
+    public boolean isStaticOverlayPackage() {
+        return overlayTarget != null && (mOverlayFlags & FLAG_OVERLAY_STATIC) != 0;
+    }
+
     @Override
     public String toString() {
         return "PackageInfo{"
@@ -410,8 +452,8 @@
         dest.writeString(restrictedAccountType);
         dest.writeString(requiredAccountType);
         dest.writeString(overlayTarget);
-        dest.writeInt(isStaticOverlay ? 1 : 0);
         dest.writeInt(overlayPriority);
+        dest.writeInt(mOverlayFlags);
         dest.writeInt(compileSdkVersion);
         dest.writeString(compileSdkVersionCodename);
     }
@@ -465,8 +507,8 @@
         restrictedAccountType = source.readString();
         requiredAccountType = source.readString();
         overlayTarget = source.readString();
-        isStaticOverlay = source.readInt() != 0;
         overlayPriority = source.readInt();
+        mOverlayFlags = source.readInt();
         compileSdkVersion = source.readInt();
         compileSdkVersionCodename = source.readString();
 
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 153c944..fb1b885 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -689,7 +689,15 @@
         pi.requiredAccountType = p.mRequiredAccountType;
         pi.overlayTarget = p.mOverlayTarget;
         pi.overlayPriority = p.mOverlayPriority;
-        pi.isStaticOverlay = p.mIsStaticOverlay;
+
+        if (p.mIsStaticOverlay) {
+            pi.mOverlayFlags |= PackageInfo.FLAG_OVERLAY_STATIC;
+        }
+
+        if (p.mTrustedOverlay) {
+            pi.mOverlayFlags |= PackageInfo.FLAG_OVERLAY_TRUSTED;
+        }
+
         pi.compileSdkVersion = p.mCompileSdkVersion;
         pi.compileSdkVersionCodename = p.mCompileSdkVersionCodename;
         pi.firstInstallTime = firstInstallTime;
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index 2940a6e..2041de6 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -370,10 +370,10 @@
                             false);
                     if (pi != null) {
                         mPackageManager.cachePackageInfo(packageName, userId, pi);
-                        if (!isOverlayPackage(pi)) {
-                            mImpl.onTargetPackageAdded(packageName, userId);
-                        } else {
+                        if (pi.isOverlayPackage()) {
                             mImpl.onOverlayPackageAdded(packageName, userId);
+                        } else {
+                            mImpl.onTargetPackageAdded(packageName, userId);
                         }
                     }
                 }
@@ -388,10 +388,10 @@
                             false);
                     if (pi != null) {
                         mPackageManager.cachePackageInfo(packageName, userId, pi);
-                        if (!isOverlayPackage(pi)) {
-                            mImpl.onTargetPackageChanged(packageName, userId);
-                        } else {
+                        if (pi.isOverlayPackage()) {
                             mImpl.onOverlayPackageChanged(packageName, userId);
+                        } else {
+                            mImpl.onTargetPackageChanged(packageName, userId);
                         }
                     }
                 }
@@ -404,10 +404,10 @@
                 synchronized (mLock) {
                     mPackageManager.forgetPackageInfo(packageName, userId);
                     final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId);
-                    if (oi == null) {
-                        mImpl.onTargetPackageUpgrading(packageName, userId);
-                    } else {
+                    if (oi != null) {
                         mImpl.onOverlayPackageUpgrading(packageName, userId);
+                    } else {
+                        mImpl.onTargetPackageUpgrading(packageName, userId);
                     }
                 }
             }
@@ -421,10 +421,10 @@
                             false);
                     if (pi != null) {
                         mPackageManager.cachePackageInfo(packageName, userId, pi);
-                        if (!isOverlayPackage(pi)) {
-                            mImpl.onTargetPackageUpgraded(packageName, userId);
-                        } else {
+                        if (pi.isOverlayPackage()) {
                             mImpl.onOverlayPackageUpgraded(packageName, userId);
+                        } else {
+                            mImpl.onTargetPackageUpgraded(packageName, userId);
                         }
                     }
                 }
@@ -437,10 +437,10 @@
                 synchronized (mLock) {
                     mPackageManager.forgetPackageInfo(packageName, userId);
                     final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId);
-                    if (oi == null) {
-                        mImpl.onTargetPackageRemoved(packageName, userId);
-                    } else {
+                    if (oi != null) {
                         mImpl.onOverlayPackageRemoved(packageName, userId);
+                    } else {
+                        mImpl.onTargetPackageRemoved(packageName, userId);
                     }
                 }
             }
@@ -668,10 +668,6 @@
         }
     };
 
-    private boolean isOverlayPackage(@NonNull final PackageInfo pi) {
-        return pi != null && pi.overlayTarget != null;
-    }
-
     private final class OverlayChangeListener
             implements OverlayManagerServiceImpl.OverlayChangeListener {
         @Override
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index db6e974..253d4f5 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -102,11 +102,11 @@
                 mSettings.init(overlayPackage.packageName, newUserId,
                         overlayPackage.overlayTarget,
                         overlayPackage.applicationInfo.getBaseCodePath(),
-                        overlayPackage.isStaticOverlay, overlayPackage.overlayPriority);
+                        overlayPackage.isStaticOverlayPackage(), overlayPackage.overlayPriority);
 
                 if (oi == null) {
                     // This overlay does not exist in our settings.
-                    if (overlayPackage.isStaticOverlay ||
+                    if (overlayPackage.isStaticOverlayPackage() ||
                             mDefaultOverlays.contains(overlayPackage.packageName)) {
                         // Enable this overlay by default.
                         if (DEBUG) {
@@ -255,8 +255,8 @@
                 mPackageManager.getPackageInfo(overlayPackage.overlayTarget, userId);
 
         mSettings.init(packageName, userId, overlayPackage.overlayTarget,
-                overlayPackage.applicationInfo.getBaseCodePath(), overlayPackage.isStaticOverlay,
-                overlayPackage.overlayPriority);
+                overlayPackage.applicationInfo.getBaseCodePath(),
+                overlayPackage.isStaticOverlayPackage(), overlayPackage.overlayPriority);
         try {
             if (updateState(targetPackage, overlayPackage, userId)) {
                 mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId);
@@ -313,7 +313,7 @@
         }
 
         // Ignore static overlays.
-        if (overlayPackage.isStaticOverlay) {
+        if (overlayPackage.isStaticOverlayPackage()) {
             return false;
         }
 
@@ -363,7 +363,7 @@
                     continue;
                 }
 
-                if (disabledOverlayPackageInfo.isStaticOverlay) {
+                if (disabledOverlayPackageInfo.isStaticOverlayPackage()) {
                     // Don't touch static overlays.
                     continue;
                 }
@@ -388,7 +388,7 @@
 
     private boolean isPackageUpdatableOverlay(@NonNull final String packageName, final int userId) {
         final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
-        if (overlayPackage == null || overlayPackage.isStaticOverlay) {
+        if (overlayPackage == null || overlayPackage.isStaticOverlayPackage()) {
             return false;
         }
         return true;
@@ -483,7 +483,8 @@
             throws OverlayManagerSettings.BadKeyException {
         // Static RROs targeting to "android", ie framework-res.apk, are handled by native layers.
         if (targetPackage != null &&
-                !("android".equals(targetPackage.packageName) && overlayPackage.isStaticOverlay)) {
+                !("android".equals(targetPackage.packageName)
+                        && overlayPackage.isStaticOverlayPackage())) {
             mIdmapManager.createIdmap(targetPackage, overlayPackage, userId);
         }