Add virtual preload bit to ApplicationInfo

Change-Id: I2735b3823a8709b2ffb65cc8085ffcd952d3e1f2
Fixes: 64205417
Test: Manual
Test: Create a sample app and install it as a normal app
Test: See that it returns 'false' for "isVirtualPreload"
Test: Create a sample app and install it as a virtual preload ["--preload"]
Test: See that it returns 'true' for "isVirtualPreload"
Test: Run sample apps after reboot and see they return the correct value
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 0bfe567..72075a5 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -572,7 +572,7 @@
     public static final int PRIVATE_FLAG_STATIC_SHARED_LIBRARY = 1 << 14;
 
     /**
-     * Value for {@linl #privateFlags}: When set, the application will only have its splits loaded
+     * Value for {@link #privateFlags}: When set, the application will only have its splits loaded
      * if they are required to load a component. Splits can be loaded on demand using the
      * {@link Context#createContextForSplit(String)} API.
      * @hide
@@ -580,10 +580,40 @@
     public static final int PRIVATE_FLAG_ISOLATED_SPLIT_LOADING = 1 << 15;
 
     /**
-     * Private/hidden flags. See {@code PRIVATE_FLAG_...} constants.
-     * {@hide}
+     * Value for {@link #privateFlags}: When set, the application was installed as
+     * a virtual preload.
+     * @hide
      */
-    public int privateFlags;
+    public static final int PRIVATE_FLAG_VIRTUAL_PRELOAD = 1 << 16;
+
+    /** @hide */
+    @IntDef(flag = true, prefix = { "PRIVATE_FLAG_" }, value = {
+            PRIVATE_FLAG_HIDDEN,
+            PRIVATE_FLAG_CANT_SAVE_STATE,
+            PRIVATE_FLAG_FORWARD_LOCK,
+            PRIVATE_FLAG_PRIVILEGED,
+            PRIVATE_FLAG_HAS_DOMAIN_URLS,
+            PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE,
+            PRIVATE_FLAG_DIRECT_BOOT_AWARE,
+            PRIVATE_FLAG_INSTANT,
+            PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE,
+            PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER,
+            PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE,
+            PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE,
+            PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION,
+            PRIVATE_FLAG_BACKUP_IN_FOREGROUND,
+            PRIVATE_FLAG_STATIC_SHARED_LIBRARY,
+            PRIVATE_FLAG_ISOLATED_SPLIT_LOADING,
+            PRIVATE_FLAG_VIRTUAL_PRELOAD,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ApplicationInfoPrivateFlags {}
+
+    /**
+     * Private/hidden flags. See {@code PRIVATE_FLAG_...} constants.
+     * @hide
+     */
+    public @ApplicationInfoPrivateFlags int privateFlags;
 
     /**
      * @hide
@@ -1509,6 +1539,13 @@
     }
 
     /**
+     * Returns whether or not this application was installed as a virtual preload.
+     */
+    public boolean isVirtualPreload() {
+        return (privateFlags & PRIVATE_FLAG_VIRTUAL_PRELOAD) != 0;
+    }
+
+    /**
      * @hide
      */
     @Override protected ApplicationInfo getApplicationInfo() {
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index e8eca8c..8a12819 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -6901,6 +6901,11 @@
         } else {
             ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_INSTANT;
         }
+        if (state.virtualPreload) {
+            ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
+        } else {
+            ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
+        }
         if (state.hidden) {
             ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
         } else {
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index 470336c..069b2d4 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -21,10 +21,10 @@
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
-import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
-import static android.content.pm.PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
+import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
+import static android.content.pm.PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
 
 import android.util.ArraySet;
@@ -45,6 +45,7 @@
     public boolean hidden; // Is the app restricted by owner / admin
     public boolean suspended;
     public boolean instantApp;
+    public boolean virtualPreload;
     public int enabled;
     public String lastDisableAppCaller;
     public int domainVerificationStatus;
@@ -75,6 +76,7 @@
         hidden = o.hidden;
         suspended = o.suspended;
         instantApp = o.instantApp;
+        virtualPreload = o.virtualPreload;
         enabled = o.enabled;
         lastDisableAppCaller = o.lastDisableAppCaller;
         domainVerificationStatus = o.domainVerificationStatus;
@@ -194,6 +196,9 @@
         if (instantApp != oldState.instantApp) {
             return false;
         }
+        if (virtualPreload != oldState.virtualPreload) {
+            return false;
+        }
         if (enabled != oldState.enabled) {
             return false;
         }