Improve priority ordering of apps when performing boot dexopt.

Added core apps and updated system apps.

Bug: 17641843
Change-Id: Ia00ea3399cf1e1acaef45ff8df8f754442de5185
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index 765b2a9..b66bd01 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -235,6 +235,9 @@
     public int installLocation = INSTALL_LOCATION_INTERNAL_ONLY;
 
     /** @hide */
+    public boolean coreApp;
+
+    /** @hide */
     public boolean requiredForAllUsers;
 
     /** @hide */
@@ -293,6 +296,7 @@
         dest.writeTypedArray(reqFeatures, parcelableFlags);
         dest.writeTypedArray(featureGroups, parcelableFlags);
         dest.writeInt(installLocation);
+        dest.writeInt(coreApp ? 1 : 0);
         dest.writeInt(requiredForAllUsers ? 1 : 0);
         dest.writeString(restrictedAccountType);
         dest.writeString(requiredAccountType);
@@ -337,6 +341,7 @@
         reqFeatures = source.createTypedArray(FeatureInfo.CREATOR);
         featureGroups = source.createTypedArray(FeatureGroupInfo.CREATOR);
         installLocation = source.readInt();
+        coreApp = source.readInt() != 0;
         requiredForAllUsers = source.readInt() != 0;
         restrictedAccountType = source.readString();
         requiredAccountType = source.readString();
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 3364741..ca4ff6a 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -415,6 +415,7 @@
         pi.sharedUserLabel = p.mSharedUserLabel;
         pi.applicationInfo = generateApplicationInfo(p, flags, state, userId);
         pi.installLocation = p.installLocation;
+        pi.coreApp = p.coreApp;
         if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0
                 || (pi.applicationInfo.flags&ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
             pi.requiredForAllUsers = p.mRequiredForAllUsers;
@@ -1384,6 +1385,8 @@
                 PARSE_DEFAULT_INSTALL_LOCATION);
         pkg.applicationInfo.installLocation = pkg.installLocation;
 
+        pkg.coreApp = attrs.getAttributeBooleanValue(null, "coreApp", false);
+
         sa.recycle();
 
         /* Set the global "forward lock" flag */
@@ -4267,6 +4270,8 @@
 
         public int installLocation;
 
+        public boolean coreApp;
+
         /* An app that's required for all users and cannot be uninstalled for a user */
         public boolean mRequiredForAllUsers;
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index d8be6b6..1059f0b 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -4475,12 +4475,26 @@
             // Sort apps by importance for dexopt ordering. Important apps are given more priority
             // in case the device runs out of space.
             ArrayList<PackageParser.Package> sortedPkgs = new ArrayList<PackageParser.Package>();
+            // Give priority to core apps.
+            for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
+                PackageParser.Package pkg = it.next();
+                if (pkg.coreApp) {
+                    if (DEBUG_DEXOPT) {
+                        Log.i(TAG, "Adding core app " + sortedPkgs.size() + ": " + pkg.packageName);
+                    }
+                    sortedPkgs.add(pkg);
+                    it.remove();
+                }
+            }
             // Give priority to system apps that listen for pre boot complete.
             Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
             HashSet<String> pkgNames = getPackageNamesForIntent(intent);
             for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
                 PackageParser.Package pkg = it.next();
                 if (pkgNames.contains(pkg.packageName)) {
+                    if (DEBUG_DEXOPT) {
+                        Log.i(TAG, "Adding pre boot system app " + sortedPkgs.size() + ": " + pkg.packageName);
+                    }
                     sortedPkgs.add(pkg);
                     it.remove();
                 }
@@ -4488,7 +4502,21 @@
             // Give priority to system apps.
             for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
                 PackageParser.Package pkg = it.next();
-                if (isSystemApp(pkg)) {
+                if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
+                    if (DEBUG_DEXOPT) {
+                        Log.i(TAG, "Adding system app " + sortedPkgs.size() + ": " + pkg.packageName);
+                    }
+                    sortedPkgs.add(pkg);
+                    it.remove();
+                }
+            }
+            // Give priority to updated system apps.
+            for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
+                PackageParser.Package pkg = it.next();
+                if (isUpdatedSystemApp(pkg)) {
+                    if (DEBUG_DEXOPT) {
+                        Log.i(TAG, "Adding updated system app " + sortedPkgs.size() + ": " + pkg.packageName);
+                    }
                     sortedPkgs.add(pkg);
                     it.remove();
                 }
@@ -4499,6 +4527,9 @@
             for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
                 PackageParser.Package pkg = it.next();
                 if (pkgNames.contains(pkg.packageName)) {
+                    if (DEBUG_DEXOPT) {
+                        Log.i(TAG, "Adding boot app " + sortedPkgs.size() + ": " + pkg.packageName);
+                    }
                     sortedPkgs.add(pkg);
                     it.remove();
                 }
@@ -4513,6 +4544,9 @@
             int i = 0;
             int total = sortedPkgs.size();
             for (PackageParser.Package pkg : sortedPkgs) {
+                if (DEBUG_DEXOPT) {
+                    Log.i(TAG, "Adding app " + sortedPkgs.size() + ": " + pkg.packageName);
+                }
                 performBootDexOpt(pkg, ++i, total);
             }
         }
@@ -5136,6 +5170,9 @@
 
         if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+        } else {
+            // Only allow system apps to be flagged as core apps.
+            pkg.coreApp = false;
         }
 
         if ((parseFlags&PackageParser.PARSE_IS_PRIVILEGED) != 0) {