Scaffolding: reject installs based on device fingerprint

Add the scaffolding for teaching the package parser to reject a package
if its manifest specifies a set of prefixes, and the device fingerprint
does not start with one of the prefixes.

Bug: b/232475788
Test: m
Change-Id: I9f3f3d3ad96332d2d65fbf6f58c7ce35992bcd7e
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 7562b9a..a62f6ad 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -3602,4 +3602,19 @@
              false, the application cannot be profiled at all. Defaults to true. -->
         <attr name="enabled" format="boolean" />
     </declare-styleable>
+
+    <!-- <code>install-constraints</code> tag rejects installs unless one the constraints defined by
+         its child elements is true.
+         It is possible to have multiple <code>install-constraints</code> tags in a single manifest,
+         where each tag is evaluated independently.
+         @hide -->
+    <declare-styleable name="AndroidManifestInstallConstraints" parent="AndroidManifest" />
+
+    <!-- A constraint for <code>install-constraints</code>. Checks that the device fingerprint
+         starts with the given prefix.
+         @hide -->
+    <declare-styleable name="AndroidManifestInstallConstraintsFingerprintPrefix"
+                       parent="AndroidManifestInstallConstraints">
+        <attr name="value" />
+    </declare-styleable>
 </resources>
diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
index 9bfb40f..d8945ed 100644
--- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
+++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
@@ -169,9 +169,11 @@
 
     public static final String TAG_ADOPT_PERMISSIONS = "adopt-permissions";
     public static final String TAG_APPLICATION = "application";
+    public static final String TAG_ATTRIBUTION = "attribution";
     public static final String TAG_COMPATIBLE_SCREENS = "compatible-screens";
     public static final String TAG_EAT_COMMENT = "eat-comment";
     public static final String TAG_FEATURE_GROUP = "feature-group";
+    public static final String TAG_INSTALL_CONSTRAINTS = "install-constraints";
     public static final String TAG_INSTRUMENTATION = "instrumentation";
     public static final String TAG_KEY_SETS = "key-sets";
     public static final String TAG_MANIFEST = "manifest";
@@ -179,15 +181,16 @@
     public static final String TAG_OVERLAY = "overlay";
     public static final String TAG_PACKAGE = "package";
     public static final String TAG_PACKAGE_VERIFIER = "package-verifier";
-    public static final String TAG_ATTRIBUTION = "attribution";
     public static final String TAG_PERMISSION = "permission";
     public static final String TAG_PERMISSION_GROUP = "permission-group";
     public static final String TAG_PERMISSION_TREE = "permission-tree";
+    public static final String TAG_PROFILEABLE = "profileable";
     public static final String TAG_PROTECTED_BROADCAST = "protected-broadcast";
     public static final String TAG_QUERIES = "queries";
+    public static final String TAG_RECEIVER = "receiver";
     public static final String TAG_RESTRICT_UPDATE = "restrict-update";
-    public static final String TAG_SUPPORT_SCREENS = "supports-screens";
     public static final String TAG_SUPPORTS_INPUT = "supports-input";
+    public static final String TAG_SUPPORT_SCREENS = "supports-screens";
     public static final String TAG_USES_CONFIGURATION = "uses-configuration";
     public static final String TAG_USES_FEATURE = "uses-feature";
     public static final String TAG_USES_GL_TEXTURE = "uses-gl-texture";
@@ -196,8 +199,6 @@
     public static final String TAG_USES_PERMISSION_SDK_M = "uses-permission-sdk-m";
     public static final String TAG_USES_SDK = "uses-sdk";
     public static final String TAG_USES_SPLIT = "uses-split";
-    public static final String TAG_PROFILEABLE = "profileable";
-    public static final String TAG_RECEIVER = "receiver";
 
     public static final String METADATA_MAX_ASPECT_RATIO = "android.max_aspect";
     public static final String METADATA_SUPPORTS_SIZE_CHANGES = "android.supports_size_changes";
@@ -1040,6 +1041,8 @@
                 return input.success(pkg);
             case TAG_RESTRICT_UPDATE:
                 return parseRestrictUpdateHash(flags, input, pkg, res, parser);
+            case TAG_INSTALL_CONSTRAINTS:
+                return parseInstallConstraints(input, pkg, res, parser);
             case TAG_QUERIES:
                 return parseQueries(input, pkg, res, parser);
             default:
@@ -1729,6 +1732,19 @@
         return input.success(pkg);
     }
 
+    private static ParseResult<ParsingPackage> parseInstallConstraints(
+            ParseInput input, ParsingPackage pkg, Resources res, XmlResourceParser parser)
+            throws IOException, XmlPullParserException {
+        final int depth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG
+                || parser.getDepth() > depth)) {
+            // TODO(b/232475788): call input.skip if constraints check fails
+        }
+        return input.success(pkg);
+    }
+
     private static ParseResult<ParsingPackage> parseQueries(ParseInput input, ParsingPackage pkg,
             Resources res, XmlResourceParser parser) throws IOException, XmlPullParserException {
         final int depth = parser.getDepth();
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index d432341..948b11b 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -477,6 +477,7 @@
   manifest_action["compatible-screens"]["screen"];
   manifest_action["supports-gl-texture"];
   manifest_action["restrict-update"];
+  manifest_action["install-constraints"]["fingerprint-prefix"];
   manifest_action["package-verifier"];
   manifest_action["meta-data"] = meta_data_action;
   manifest_action["uses-split"].Action(RequiredNameIsJavaPackage);