Be more accepting of dex2oat errors.

- Narrow down the scope of caught exceptions. StaleDexCacheError has been
  removed (nobody was throwing it) and we shouldn't be catching the
  general "Exception".
- Make try {} catch blocks for IOExceptions more fine-grained, only
  surrounding the code that throws them.

And finally, don't return DEX_OPT_FAILED if installd couldn't run
dex2oat successfully. We return DEX_OPT_SKIPPED instead.

bug: 20888973
Change-Id: I25701e16157f42981ca767e343545cfe1d9cfbb2
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index a42e4e7..b505f7e 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -31,7 +31,6 @@
 import java.util.List;
 
 import dalvik.system.DexFile;
-import dalvik.system.StaleDexCacheError;
 
 import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
 import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
@@ -112,61 +111,60 @@
             }
 
             for (String path : paths) {
-                try {
-                    final int dexoptNeeded;
-                    if (forceDex) {
-                        dexoptNeeded = DexFile.DEX2OAT_NEEDED;
-                    } else {
-                        dexoptNeeded = DexFile.getDexOptNeeded(path,
-                                pkg.packageName, dexCodeInstructionSet, defer);
+                final int dexoptNeeded;
+                if (forceDex) {
+                    dexoptNeeded = DexFile.DEX2OAT_NEEDED;
+                } else {
+                    try {
+                        dexoptNeeded = DexFile.getDexOptNeeded(path, pkg.packageName,
+                                dexCodeInstructionSet, defer);
+                    } catch (IOException ioe) {
+                        Slog.w(TAG, "IOException reading apk: " + path, ioe);
+                        return DEX_OPT_FAILED;
                     }
+                }
 
-                    if (!forceDex && defer && dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
-                        // We're deciding to defer a needed dexopt. Don't bother dexopting for other
-                        // paths and instruction sets. We'll deal with them all together when we process
-                        // our list of deferred dexopts.
-                        addPackageForDeferredDexopt(pkg);
-                        return DEX_OPT_DEFERRED;
-                    }
+                if (!forceDex && defer && dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
+                    // We're deciding to defer a needed dexopt. Don't bother dexopting for other
+                    // paths and instruction sets. We'll deal with them all together when we process
+                    // our list of deferred dexopts.
+                    addPackageForDeferredDexopt(pkg);
+                    return DEX_OPT_DEFERRED;
+                }
 
-                    if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
-                        final String dexoptType;
-                        String oatDir = null;
-                        if (dexoptNeeded == DexFile.DEX2OAT_NEEDED) {
-                            dexoptType = "dex2oat";
+                if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
+                    final String dexoptType;
+                    String oatDir = null;
+                    if (dexoptNeeded == DexFile.DEX2OAT_NEEDED) {
+                        dexoptType = "dex2oat";
+                        try {
                             oatDir = createOatDirIfSupported(pkg, dexCodeInstructionSet);
-                        } else if (dexoptNeeded == DexFile.PATCHOAT_NEEDED) {
-                            dexoptType = "patchoat";
-                        } else if (dexoptNeeded == DexFile.SELF_PATCHOAT_NEEDED) {
-                            dexoptType = "self patchoat";
-                        } else {
-                            throw new IllegalStateException("Invalid dexopt needed: " + dexoptNeeded);
-                        }
-                        Log.i(TAG, "Running dexopt (" + dexoptType + ") on: " + path + " pkg="
-                                + pkg.applicationInfo.packageName + " isa=" + dexCodeInstructionSet
-                                + " vmSafeMode=" + vmSafeMode + " debuggable=" + debuggable
-                                + " oatDir = " + oatDir);
-                        final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
-                        final int ret = mPackageManagerService.mInstaller.dexopt(path, sharedGid,
-                                !pkg.isForwardLocked(), pkg.packageName, dexCodeInstructionSet,
-                                dexoptNeeded, vmSafeMode, debuggable, oatDir);
-                        if (ret < 0) {
+                        } catch (IOException ioe) {
+                            Slog.w(TAG, "Unable to create oatDir for package: " + pkg.packageName);
                             return DEX_OPT_FAILED;
                         }
+                    } else if (dexoptNeeded == DexFile.PATCHOAT_NEEDED) {
+                        dexoptType = "patchoat";
+                    } else if (dexoptNeeded == DexFile.SELF_PATCHOAT_NEEDED) {
+                        dexoptType = "self patchoat";
+                    } else {
+                        throw new IllegalStateException("Invalid dexopt needed: " + dexoptNeeded);
+                    }
+
+                    Log.i(TAG, "Running dexopt (" + dexoptType + ") on: " + path + " pkg="
+                            + pkg.applicationInfo.packageName + " isa=" + dexCodeInstructionSet
+                            + " vmSafeMode=" + vmSafeMode + " debuggable=" + debuggable
+                            + " oatDir = " + oatDir);
+                    final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
+                    final int ret = mPackageManagerService.mInstaller.dexopt(path, sharedGid,
+                            !pkg.isForwardLocked(), pkg.packageName, dexCodeInstructionSet,
+                            dexoptNeeded, vmSafeMode, debuggable, oatDir);
+
+                    // Dex2oat might fail due to compiler / verifier errors. We soldier on
+                    // regardless, and attempt to interpret the app as a safety net.
+                    if (ret == 0) {
                         performedDexOpt = true;
                     }
-                } catch (FileNotFoundException e) {
-                    Slog.w(TAG, "Apk not found for dexopt: " + path);
-                    return DEX_OPT_FAILED;
-                } catch (IOException e) {
-                    Slog.w(TAG, "IOException reading apk: " + path, e);
-                    return DEX_OPT_FAILED;
-                } catch (StaleDexCacheError e) {
-                    Slog.w(TAG, "StaleDexCacheError when reading apk: " + path, e);
-                    return DEX_OPT_FAILED;
-                } catch (Exception e) {
-                    Slog.w(TAG, "Exception when doing dexopt : ", e);
-                    return DEX_OPT_FAILED;
                 }
             }