Merge "Do not create oat directory for an app in ASEC container"
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 4a087da..3b6c9bd 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -916,6 +916,11 @@
         return (flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
     }
 
+    /** @hide */
+    public boolean isInternal() {
+        return (flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0;
+    }
+
     /**
      * @hide
      */
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 4c36fa6..955ea348 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -199,7 +199,8 @@
     @Nullable
     private String createOatDirIfSupported(PackageParser.Package pkg, String dexInstructionSet)
             throws IOException {
-        if (pkg.isSystemApp() && !pkg.isUpdatedSystemApp()) {
+        if ((pkg.isSystemApp() && !pkg.isUpdatedSystemApp()) || pkg.isForwardLocked()
+                || (!pkg.applicationInfo.isInternal())) {
             return null;
         }
         File codePath = new File(pkg.codePath);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 3f0e8b0..c365bbc 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -10254,7 +10254,7 @@
         boolean forwardLocked = ((installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
         boolean onSd = ((installFlags & PackageManager.INSTALL_EXTERNAL) != 0);
         boolean replace = false;
-        final int scanFlags = SCAN_NEW_INSTALL | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE;
+        int scanFlags = SCAN_NEW_INSTALL | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE;
         // Result object to be returned
         res.returnCode = PackageManager.INSTALL_SUCCEEDED;
 
@@ -10421,13 +10421,18 @@
             return;
         }
 
-        // Run dexopt before old package gets removed, to minimize time when app is not available
-        int result = mPackageDexOptimizer
-                .performDexOpt(pkg, null /* instruction sets */, true /* forceDex */,
-                        false /* defer */, false /* inclDependencies */);
-        if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
-            res.setError(INSTALL_FAILED_DEXOPT, "Dexopt failed for " + pkg.codePath);
-            return;
+        // If app directory is not writable, dexopt will be called after the rename
+        if (!forwardLocked && pkg.applicationInfo.isInternal()) {
+            // Enable SCAN_NO_DEX flag to skip dexopt at a later stage
+            scanFlags |= SCAN_NO_DEX;
+            // Run dexopt before old package gets removed, to minimize time when app is unavailable
+            int result = mPackageDexOptimizer
+                    .performDexOpt(pkg, null /* instruction sets */, true /* forceDex */,
+                            false /* defer */, false /* inclDependencies */);
+            if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
+                res.setError(INSTALL_FAILED_DEXOPT, "Dexopt failed for " + pkg.codePath);
+                return;
+            }
         }
 
         if (!args.doRename(res.returnCode, pkg, oldCodePath)) {
@@ -10435,13 +10440,12 @@
             return;
         }
 
-        // Call with SCAN_NO_DEX, since dexopt has already been made
         if (replace) {
-            replacePackageLI(pkg, parseFlags, scanFlags | SCAN_REPLACING | SCAN_NO_DEX, args.user,
+            replacePackageLI(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user,
                     installerPackageName, res);
         } else {
-            installNewPackageLI(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES
-                            | SCAN_NO_DEX, args.user, installerPackageName, res);
+            installNewPackageLI(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,
+                    args.user, installerPackageName, res);
         }
         synchronized (mPackages) {
             final PackageSetting ps = mSettings.mPackages.get(pkgName);