Merge "Retry compiling a previously failing package after update" into nyc-dev
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index da9cd8b..f6255af 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -89,6 +89,15 @@
         }
     }
 
+    public static void notifyPackageChanged(String packageName) {
+        // The idle maintanance job skips packages which previously failed to
+        // compile. The given package has changed and may successfully compile
+        // now. Remove it from the list of known failing packages.
+        synchronized (sFailedPackageNames) {
+            sFailedPackageNames.remove(packageName);
+        }
+    }
+
     // Returns the current battery level as a 0-100 integer.
     private int getBatteryLevel() {
         IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
@@ -170,7 +179,9 @@
                     }
                     // Conservatively add package to the list of failing ones in case performDexOpt
                     // never returns.
-                    sFailedPackageNames.add(pkg);
+                    synchronized (sFailedPackageNames) {
+                        sFailedPackageNames.add(pkg);
+                    }
                     // Optimize package if needed. Note that there can be no race between
                     // concurrent jobs because PackageDexOptimizer.performDexOpt is synchronized.
                     if (pm.performDexOpt(pkg,
@@ -179,7 +190,9 @@
                             PackageManagerService.REASON_BACKGROUND_DEXOPT,
                             /* force */ false)) {
                         // Dexopt succeeded, remove package from the list of failing ones.
-                        sFailedPackageNames.remove(pkg);
+                        synchronized (sFailedPackageNames) {
+                            sFailedPackageNames.remove(pkg);
+                        }
                     }
                 }
                 // Ran to completion, so we abandon our timeslice and do not reschedule.
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c81984e..bf41246 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -14516,7 +14516,6 @@
                 return;
             }
 
-
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
             // Do not run PackageDexOptimizer through the local performDexOpt
             // method because `pkg` is not in `mPackages` yet.
@@ -14524,10 +14523,15 @@
                     false /* checkProfiles */, getCompilerFilterForReason(REASON_INSTALL));
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
             if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
-                String msg = "Extracking package failed for " + pkgName;
+                String msg = "Extracting package failed for " + pkgName;
                 res.setError(INSTALL_FAILED_DEXOPT, msg);
                 return;
             }
+
+            // Notify BackgroundDexOptService that the package has been changed.
+            // If this is an update of a package which used to fail to compile,
+            // BDOS will remove it from its blacklist.
+            BackgroundDexOptService.notifyPackageChanged(pkg.packageName);
         }
 
         if (!args.doRename(res.returnCode, pkg, oldCodePath)) {