Define targetSandboxVersion

The new attribute allows both ephemeral and non-ephemeral apps to
opt into a new, tighter security model.

Test: Manual; built app w/ targetSandboxVersion and verified the security domain
Change-Id: I8fcaf84e25f0519b438ba51302f79790e680e025
diff --git a/api/current.txt b/api/current.txt
index 1228db8..1edf0ef 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1268,6 +1268,7 @@
     field public static final int targetId = 16843740; // 0x10103dc
     field public static final int targetName = 16843853; // 0x101044d
     field public static final int targetPackage = 16842785; // 0x1010021
+    field public static final int targetSandboxVersion = 16844110; // 0x101054e
     field public static final int targetSdkVersion = 16843376; // 0x1010270
     field public static final int taskAffinity = 16842770; // 0x1010012
     field public static final int taskCloseEnterAnimation = 16842942; // 0x10100be
diff --git a/api/system-current.txt b/api/system-current.txt
index 4698a68..1a6d0c0 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1383,6 +1383,7 @@
     field public static final int targetId = 16843740; // 0x10103dc
     field public static final int targetName = 16843853; // 0x101044d
     field public static final int targetPackage = 16842785; // 0x1010021
+    field public static final int targetSandboxVersion = 16844110; // 0x101054e
     field public static final int targetSdkVersion = 16843376; // 0x1010270
     field public static final int taskAffinity = 16842770; // 0x1010012
     field public static final int taskCloseEnterAnimation = 16842942; // 0x10100be
diff --git a/api/test-current.txt b/api/test-current.txt
index 15844cd..512de48 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1268,6 +1268,7 @@
     field public static final int targetId = 16843740; // 0x10103dc
     field public static final int targetName = 16843853; // 0x101044d
     field public static final int targetPackage = 16842785; // 0x1010021
+    field public static final int targetSandboxVersion = 16844110; // 0x101054e
     field public static final int targetSdkVersion = 16843376; // 0x1010270
     field public static final int taskAffinity = 16842770; // 0x1010012
     field public static final int taskCloseEnterAnimation = 16842942; // 0x10100be
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 3d9ba96..ef59444 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -827,6 +827,12 @@
     public int networkSecurityConfigRes;
 
     /**
+     * Version of the sandbox the application wants to run in.
+     * @hide
+     */
+    public int targetSandboxVersion;
+
+    /**
      * The category of this app. Categories are used to cluster multiple apps
      * together into meaningful groups, such as when summarizing battery,
      * network, or disk usage. Apps should only define this value when they fit
@@ -1007,7 +1013,8 @@
         pw.println(prefix + "enabled=" + enabled
                 + " minSdkVersion=" + minSdkVersion
                 + " targetSdkVersion=" + targetSdkVersion
-                + " versionCode=" + versionCode);
+                + " versionCode=" + versionCode
+                + " targetSandboxVersion=" + targetSandboxVersion);
         if ((flags&DUMP_FLAG_DETAILS) != 0) {
             if (manageSpaceActivityName != null) {
                 pw.println(prefix + "manageSpaceActivityName=" + manageSpaceActivityName);
@@ -1122,6 +1129,7 @@
         fullBackupContent = orig.fullBackupContent;
         networkSecurityConfigRes = orig.networkSecurityConfigRes;
         category = orig.category;
+        targetSandboxVersion = orig.targetSandboxVersion;
     }
 
     public String toString() {
@@ -1182,6 +1190,7 @@
         dest.writeInt(fullBackupContent);
         dest.writeInt(networkSecurityConfigRes);
         dest.writeInt(category);
+        dest.writeInt(targetSandboxVersion);
     }
 
     public static final Parcelable.Creator<ApplicationInfo> CREATOR
@@ -1242,6 +1251,7 @@
         fullBackupContent = source.readInt();
         networkSecurityConfigRes = source.readInt();
         category = source.readInt();
+        targetSandboxVersion = source.readInt();
     }
 
     /**
@@ -1310,6 +1320,7 @@
         } else {
             dataDir = credentialProtectedDataDir;
         }
+        // TODO: modify per-user ephemerality
     }
 
     /**
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 8223726..401bf40 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -296,6 +296,7 @@
     private static boolean sCompatibilityModeEnabled = true;
     private static final int PARSE_DEFAULT_INSTALL_LOCATION =
             PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
+    private static final int PARSE_DEFAULT_TARGET_SANDBOX = 1;
 
     static class ParsePackageItemArgs {
         final Package owner;
@@ -1996,6 +1997,10 @@
                 PARSE_DEFAULT_INSTALL_LOCATION);
         pkg.applicationInfo.installLocation = pkg.installLocation;
 
+        final int targetSandboxVersion = sa.getInteger(
+                com.android.internal.R.styleable.AndroidManifest_targetSandboxVersion,
+                PARSE_DEFAULT_TARGET_SANDBOX);
+        pkg.applicationInfo.targetSandboxVersion = targetSandboxVersion;
 
         /* Set the global "forward lock" flag */
         if ((flags & PARSE_FORWARD_LOCK) != 0) {
diff --git a/core/java/android/security/net/config/ManifestConfigSource.java b/core/java/android/security/net/config/ManifestConfigSource.java
index 0f2994d..8fcd5ab 100644
--- a/core/java/android/security/net/config/ManifestConfigSource.java
+++ b/core/java/android/security/net/config/ManifestConfigSource.java
@@ -32,7 +32,7 @@
     private final int mApplicationInfoFlags;
     private final int mTargetSdkVersion;
     private final int mConfigResourceId;
-    private final boolean mEphemeralApp;
+    private final int mTargetSandboxVesrsion;
 
     private ConfigSource mConfigSource;
 
@@ -43,7 +43,7 @@
         mApplicationInfoFlags = info.flags;
         mTargetSdkVersion = info.targetSdkVersion;
         mConfigResourceId = info.networkSecurityConfigRes;
-        mEphemeralApp = info.isEphemeralApp();
+        mTargetSandboxVesrsion = info.targetSandboxVersion;
     }
 
     @Override
@@ -71,7 +71,7 @@
                             + " debugBuild: " + debugBuild);
                 }
                 source = new XmlConfigSource(mContext, mConfigResourceId, debugBuild,
-                        mTargetSdkVersion, mEphemeralApp);
+                        mTargetSdkVersion, mTargetSandboxVesrsion);
             } else {
                 if (DBG) {
                     Log.d(LOG_TAG, "No Network Security Config specified, using platform default");
@@ -80,9 +80,9 @@
                 // should use the network security config.
                 boolean usesCleartextTraffic =
                         (mApplicationInfoFlags & ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC) != 0
-                        && !mEphemeralApp;
+                        && mTargetSandboxVesrsion < 2;
                 source = new DefaultConfigSource(usesCleartextTraffic, mTargetSdkVersion,
-                        mEphemeralApp);
+                        mTargetSandboxVesrsion);
             }
             mConfigSource = source;
             return mConfigSource;
@@ -94,9 +94,9 @@
         private final NetworkSecurityConfig mDefaultConfig;
 
         public DefaultConfigSource(boolean usesCleartextTraffic, int targetSdkVersion,
-                boolean ephemeralApp) {
+                int targetSandboxVesrsion) {
             mDefaultConfig = NetworkSecurityConfig.getDefaultBuilder(targetSdkVersion,
-                    ephemeralApp)
+                    targetSandboxVesrsion)
                     .setCleartextTrafficPermitted(usesCleartextTraffic)
                     .build();
         }
diff --git a/core/java/android/security/net/config/NetworkSecurityConfig.java b/core/java/android/security/net/config/NetworkSecurityConfig.java
index 7923702..789fc27 100644
--- a/core/java/android/security/net/config/NetworkSecurityConfig.java
+++ b/core/java/android/security/net/config/NetworkSecurityConfig.java
@@ -175,13 +175,14 @@
      *
      * @hide
      */
-    public static final Builder getDefaultBuilder(int targetSdkVersion, boolean ephemeralApp) {
+    public static final Builder getDefaultBuilder(int targetSdkVersion, int targetSandboxVesrsion) {
         Builder builder = new Builder()
-                .setCleartextTrafficPermitted(!ephemeralApp)
                 .setHstsEnforced(DEFAULT_HSTS_ENFORCED)
                 // System certificate store, does not bypass static pins.
                 .addCertificatesEntryRef(
                         new CertificatesEntryRef(SystemCertificateSource.getInstance(), false));
+        final boolean cleartextTrafficPermitted = targetSandboxVesrsion < 2;
+        builder.setCleartextTrafficPermitted(cleartextTrafficPermitted);
         // Applications targeting N and above must opt in into trusting the user added certificate
         // store.
         if (targetSdkVersion <= Build.VERSION_CODES.M) {
diff --git a/core/java/android/security/net/config/XmlConfigSource.java b/core/java/android/security/net/config/XmlConfigSource.java
index 38fe6b8..a111fbce 100644
--- a/core/java/android/security/net/config/XmlConfigSource.java
+++ b/core/java/android/security/net/config/XmlConfigSource.java
@@ -37,7 +37,7 @@
     private final int mResourceId;
     private final boolean mDebugBuild;
     private final int mTargetSdkVersion;
-    private final boolean mEphemeralApp;
+    private final int mTargetSandboxVesrsion;
 
     private boolean mInitialized;
     private NetworkSecurityConfig mDefaultConfig;
@@ -57,16 +57,16 @@
     @VisibleForTesting
     public XmlConfigSource(Context context, int resourceId, boolean debugBuild,
             int targetSdkVersion) {
-        this(context, resourceId, debugBuild, targetSdkVersion, false);
+        this(context, resourceId, debugBuild, targetSdkVersion, 1 /*targetSandboxVersion*/);
     }
 
     public XmlConfigSource(Context context, int resourceId, boolean debugBuild,
-            int targetSdkVersion, boolean ephemeralApp) {
+            int targetSdkVersion, int targetSandboxVesrsion) {
         mResourceId = resourceId;
         mContext = context;
         mDebugBuild = debugBuild;
         mTargetSdkVersion = targetSdkVersion;
-        mEphemeralApp = ephemeralApp;
+        mTargetSandboxVesrsion = targetSandboxVesrsion;
     }
 
     public Set<Pair<Domain, NetworkSecurityConfig>> getPerDomainConfigs() {
@@ -365,7 +365,7 @@
         // Use the platform default as the parent of the base config for any values not provided
         // there. If there is no base config use the platform default.
         NetworkSecurityConfig.Builder platformDefaultBuilder =
-                NetworkSecurityConfig.getDefaultBuilder(mTargetSdkVersion, mEphemeralApp);
+                NetworkSecurityConfig.getDefaultBuilder(mTargetSdkVersion, mTargetSandboxVesrsion);
         addDebugAnchorsIfNeeded(debugConfigBuilder, platformDefaultBuilder);
         if (baseConfigBuilder != null) {
             baseConfigBuilder.setParent(platformDefaultBuilder);
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 0dde91b..53d7a82 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1247,6 +1247,12 @@
          split that contains the defined component. -->
     <attr name="splitName" format="string" />
 
+    <!-- Specifies the target sandbox this app wants to use. Higher sanbox versions
+         will have increasing levels of security.
+
+         <p>The default value of this attribute is <code>1</code>. -->
+    <attr name="targetSandboxVersion" format="integer" />
+
     <!-- The <code>manifest</code> tag is the root of an
          <code>AndroidManifest.xml</code> file,
          describing the contents of an Android package (.apk) file.  One
@@ -1274,6 +1280,7 @@
         <attr name="sharedUserLabel" />
         <attr name="installLocation" />
         <attr name="isolatedSplits" />
+        <attr name="targetSandboxVersion" />
     </declare-styleable>
 
     <!-- The <code>application</code> tag describes application-level components
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 1146871..4883078 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2790,6 +2790,7 @@
         <public name="splitName" />
         <public name="colorMode" />
         <public name="isolatedSplits" />
+        <public name="targetSandboxVersion" />
     </public-group>
 
     <public-group type="style" first-id="0x010302e0">
diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java
index 9222917..b9bf1db 100644
--- a/services/core/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java
@@ -66,6 +66,9 @@
     // Append privapp to existing seinfo label
     private static final String PRIVILEGED_APP_STR = ":privapp";
 
+    // Append v2 to existing seinfo label
+    private static final String SANDBOX_V2_STR = ":v2";
+
     // Append ephemeral to existing seinfo label
     private static final String EPHEMERAL_APP_STR = ":ephemeralapp";
 
@@ -287,6 +290,9 @@
         if (pkg.applicationInfo.isEphemeralApp())
             pkg.applicationInfo.seinfo += EPHEMERAL_APP_STR;
 
+        if (pkg.applicationInfo.targetSandboxVersion == 2)
+            pkg.applicationInfo.seinfo += SANDBOX_V2_STR;
+
         if (pkg.applicationInfo.isPrivilegedApp())
             pkg.applicationInfo.seinfo += PRIVILEGED_APP_STR;
 
diff --git a/tests/NetworkSecurityConfigTest/src/android/security/net/config/NetworkSecurityConfigTests.java b/tests/NetworkSecurityConfigTest/src/android/security/net/config/NetworkSecurityConfigTests.java
index dc3b337..25bfa53 100644
--- a/tests/NetworkSecurityConfigTest/src/android/security/net/config/NetworkSecurityConfigTests.java
+++ b/tests/NetworkSecurityConfigTest/src/android/security/net/config/NetworkSecurityConfigTests.java
@@ -227,7 +227,7 @@
     public void testConfigBuilderUsesParents() throws Exception {
         // Check that a builder with a parent uses the parent's values when non is set.
         NetworkSecurityConfig config = new NetworkSecurityConfig.Builder()
-                .setParent(NetworkSecurityConfig.getDefaultBuilder(Build.VERSION_CODES.N, false))
+                .setParent(NetworkSecurityConfig.getDefaultBuilder(Build.VERSION_CODES.N, 1))
                 .build();
         assert(!config.getTrustAnchors().isEmpty());
     }
@@ -268,9 +268,9 @@
             // Install the test CA.
             store.installCertificate(TEST_CA_CERT);
             NetworkSecurityConfig preNConfig =
-                    NetworkSecurityConfig.getDefaultBuilder(Build.VERSION_CODES.M, false).build();
+                    NetworkSecurityConfig.getDefaultBuilder(Build.VERSION_CODES.M, 1).build();
             NetworkSecurityConfig nConfig =
-                    NetworkSecurityConfig.getDefaultBuilder(Build.VERSION_CODES.N, false).build();
+                    NetworkSecurityConfig.getDefaultBuilder(Build.VERSION_CODES.N, 1).build();
             Set<TrustAnchor> preNAnchors = preNConfig.getTrustAnchors();
             Set<TrustAnchor> nAnchors = nConfig.getTrustAnchors();
             Set<X509Certificate> preNCerts = new HashSet<X509Certificate>();