resolve merge conflicts of 8ef0ace to nyc-mr1-dev-plus-aosp

Change-Id: I6feac17131e040011eb9f243bcd70640b0e8417f
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index 69f89b3..bc03eb1 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -688,8 +688,10 @@
   return count;
 }
 
-static void run_patchoat(int input_fd, int oat_fd, const char* input_file_name,
-    const char* output_file_name, const char *pkgname ATTRIBUTE_UNUSED, const char *instruction_set)
+static void run_patchoat(int input_oat_fd, int input_vdex_fd, int out_oat_fd, int out_vdex_fd,
+    const char* input_oat_file_name, const char* input_vdex_file_name,
+    const char* output_oat_file_name, const char* output_vdex_file_name,
+    const char *pkgname ATTRIBUTE_UNUSED, const char *instruction_set)
 {
     static const int MAX_INT_LEN = 12;      // '-'+10dig+'\0' -OR- 0x+8dig
     static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
@@ -703,35 +705,44 @@
 
     /* input_file_name/input_fd should be the .odex/.oat file that is precompiled. I think*/
     char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN];
-    char output_oat_fd_arg[strlen("--output-oat-fd=") + MAX_INT_LEN];
     char input_oat_fd_arg[strlen("--input-oat-fd=") + MAX_INT_LEN];
+    char input_vdex_fd_arg[strlen("--input-vdex-fd=") + MAX_INT_LEN];
+    char output_oat_fd_arg[strlen("--output-oat-fd=") + MAX_INT_LEN];
+    char output_vdex_fd_arg[strlen("--output-vdex-fd=") + MAX_INT_LEN];
     const char* patched_image_location_arg = "--patched-image-location=/system/framework/boot.art";
     // The caller has already gotten all the locks we need.
     const char* no_lock_arg = "--no-lock-output";
     sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set);
-    sprintf(output_oat_fd_arg, "--output-oat-fd=%d", oat_fd);
-    sprintf(input_oat_fd_arg, "--input-oat-fd=%d", input_fd);
-    ALOGV("Running %s isa=%s in-fd=%d (%s) out-fd=%d (%s)\n",
-          PATCHOAT_BIN, instruction_set, input_fd, input_file_name, oat_fd, output_file_name);
+    sprintf(output_oat_fd_arg, "--output-oat-fd=%d", out_oat_fd);
+    sprintf(input_oat_fd_arg, "--input-oat-fd=%d", input_oat_fd);
+    ALOGV("Running %s isa=%s in-oat-fd=%d (%s) in-vdex-fd=%d (%s) "
+          "out-oat-fd=%d (%s) out-vdex-fd=%d (%s)\n",
+          PATCHOAT_BIN, instruction_set,
+          input_oat_fd, input_oat_file_name,
+          input_vdex_fd, input_vdex_file_name,
+          out_oat_fd, output_oat_file_name,
+          out_vdex_fd, output_vdex_file_name);
 
     /* patchoat, patched-image-location, no-lock, isa, input-fd, output-fd */
-    char* argv[7];
+    char* argv[9];
     argv[0] = (char*) PATCHOAT_BIN;
     argv[1] = (char*) patched_image_location_arg;
     argv[2] = (char*) no_lock_arg;
     argv[3] = instruction_set_arg;
-    argv[4] = output_oat_fd_arg;
-    argv[5] = input_oat_fd_arg;
-    argv[6] = NULL;
+    argv[4] = input_oat_fd_arg;
+    argv[5] = input_vdex_fd_arg;
+    argv[6] = output_oat_fd_arg;
+    argv[7] = output_vdex_fd_arg;
+    argv[8] = NULL;
 
     execv(PATCHOAT_BIN, (char* const *)argv);
     ALOGE("execv(%s) failed: %s\n", PATCHOAT_BIN, strerror(errno));
 }
 
-static void run_dex2oat(int zip_fd, int oat_fd, int image_fd, const char* input_file_name,
-        const char* output_file_name, int swap_fd, const char *instruction_set,
-        const char* compiler_filter, bool vm_safe_mode, bool debuggable, bool post_bootcomplete,
-        int profile_fd, const char* shared_libraries) {
+static void run_dex2oat(int zip_fd, int oat_fd, int vdex_fd, int image_fd,
+        const char* input_file_name, const char* output_file_name, int swap_fd,
+        const char *instruction_set, const char* compiler_filter, bool vm_safe_mode,
+        bool debuggable, bool post_bootcomplete, int profile_fd, const char* shared_libraries) {
     static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
 
     if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
@@ -812,6 +823,7 @@
 
     char zip_fd_arg[strlen("--zip-fd=") + MAX_INT_LEN];
     char zip_location_arg[strlen("--zip-location=") + PKG_PATH_MAX];
+    char vdex_fd_arg[strlen("--vdex-fd=") + MAX_INT_LEN];
     char oat_fd_arg[strlen("--oat-fd=") + MAX_INT_LEN];
     char oat_location_arg[strlen("--oat-location=") + PKG_PATH_MAX];
     char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN];
@@ -827,6 +839,7 @@
 
     sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd);
     sprintf(zip_location_arg, "--zip-location=%s", input_file_name);
+    sprintf(vdex_fd_arg, "--vdex-fd=%d", vdex_fd);
     sprintf(oat_fd_arg, "--oat-fd=%d", oat_fd);
     sprintf(oat_location_arg, "--oat-location=%s", output_file_name);
     sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set);
@@ -889,7 +902,7 @@
 
     ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, input_file_name, output_file_name);
 
-    const char* argv[7  // program name, mandatory arguments and the final NULL
+    const char* argv[8  // program name, mandatory arguments and the final NULL
                      + (have_dex2oat_isa_variant ? 1 : 0)
                      + (have_dex2oat_isa_features ? 1 : 0)
                      + (have_dex2oat_Xms_flag ? 2 : 0)
@@ -910,6 +923,7 @@
     argv[i++] = DEX2OAT_BIN;
     argv[i++] = zip_fd_arg;
     argv[i++] = zip_location_arg;
+    argv[i++] = vdex_fd_arg;
     argv[i++] = oat_fd_arg;
     argv[i++] = oat_location_arg;
     argv[i++] = instruction_set_arg;
@@ -1367,31 +1381,40 @@
     return true;
 }
 
-// Translate the given oat path to an art (app image) path. An empty string
-// denotes an error.
-static std::string create_image_filename(const std::string& oat_path) {
-  // A standard dalvik-cache entry. Replace ".dex" with ".art."
+static std::string replace_file_extension(const std::string& oat_path, const std::string& new_ext) {
+  // A standard dalvik-cache entry. Replace ".dex" with `new_ext`.
   if (EndsWith(oat_path, ".dex")) {
-    std::string art_path = oat_path;
-    art_path.replace(art_path.length() - strlen("dex"), strlen("dex"), "art");
-    CHECK(EndsWith(art_path, ".art"));
-    return art_path;
+    std::string new_path = oat_path;
+    new_path.replace(new_path.length() - strlen(".dex"), strlen(".dex"), new_ext);
+    CHECK(EndsWith(new_path, new_ext.c_str()));
+    return new_path;
   }
 
   // An odex entry. Not that this may not be an extension, e.g., in the OTA
   // case (where the base name will have an extension for the B artifact).
   size_t odex_pos = oat_path.rfind(".odex");
   if (odex_pos != std::string::npos) {
-    std::string art_path = oat_path;
-    art_path.replace(odex_pos, strlen(".odex"), ".art");
-    CHECK_NE(art_path.find(".art"), std::string::npos);
-    return art_path;
+    std::string new_path = oat_path;
+    new_path.replace(odex_pos, strlen(".odex"), new_ext);
+    CHECK_NE(new_path.find(new_ext), std::string::npos);
+    return new_path;
   }
 
   // Don't know how to handle this.
   return "";
 }
 
+// Translate the given oat path to an art (app image) path. An empty string
+// denotes an error.
+static std::string create_image_filename(const std::string& oat_path) {
+    return replace_file_extension(oat_path, ".art");
+}
+
+// Translate the given oat path to a vdex path. An empty string denotes an error.
+static std::string create_vdex_filename(const std::string& oat_path) {
+    return replace_file_extension(oat_path, ".vdex");
+}
+
 static bool add_extension_to_file_name(char* file_name, const char* extension) {
     if (strlen(file_name) + strlen(extension) + 1 > PKG_PATH_MAX) {
         return false;
@@ -1427,7 +1450,7 @@
 }
 
 static bool create_oat_out_path(const char* apk_path, const char* instruction_set,
-            const char* oat_dir, /*out*/ char* out_path) {
+            const char* oat_dir, /*out*/ char* out_oat_path) {
     // Early best-effort check whether we can fit the the path into our buffers.
     // Note: the cache path will require an additional 5 bytes for ".swap", but we'll try to run
     // without a swap file, if necessary. Reference profiles file also add an extra ".prof"
@@ -1442,11 +1465,11 @@
             ALOGE("invalid oat_dir '%s'\n", oat_dir);
             return false;
         }
-        if (!calculate_oat_file_path(out_path, oat_dir, apk_path, instruction_set)) {
+        if (!calculate_oat_file_path(out_oat_path, oat_dir, apk_path, instruction_set)) {
             return false;
         }
     } else {
-        if (!create_cache_path(out_path, apk_path, instruction_set)) {
+        if (!create_cache_path(out_oat_path, apk_path, instruction_set)) {
             return false;
         }
     }
@@ -1588,8 +1611,8 @@
         LOG_FATAL("dexopt flags contains unknown fields\n");
     }
 
-    char out_path[PKG_PATH_MAX];
-    if (!create_oat_out_path(apk_path, instruction_set, oat_dir, out_path)) {
+    char out_oat_path[PKG_PATH_MAX];
+    if (!create_oat_out_path(apk_path, instruction_set, oat_dir, out_oat_path)) {
         return false;
     }
 
@@ -1608,7 +1631,7 @@
             break;
 
         case DEXOPT_SELF_PATCHOAT_NEEDED:
-            input_file = out_path;
+            input_file = out_oat_path;
             break;
 
         default:
@@ -1620,21 +1643,57 @@
     memset(&input_stat, 0, sizeof(input_stat));
     stat(input_file, &input_stat);
 
+    // Open the input file. If running dex2oat, `input_file` is the APK. If running
+    // patchoat, it is the OAT file to be relocated.
     base::unique_fd input_fd(open(input_file, O_RDONLY, 0));
     if (input_fd.get() < 0) {
         ALOGE("installd cannot open '%s' for input during dexopt\n", input_file);
         return -1;
     }
 
-    const std::string out_path_str(out_path);
-    Dex2oatFileWrapper<std::function<void ()>> out_fd(
-            open_output_file(out_path, /*recreate*/true, /*permissions*/0644),
-            [out_path_str]() { unlink(out_path_str.c_str()); });
-    if (out_fd.get() < 0) {
-        ALOGE("installd cannot open '%s' for output during dexopt\n", out_path);
+    // If invoking patchoat, open the VDEX associated with the OAT too.
+    std::string in_vdex_path_str;
+    base::unique_fd input_vdex_fd;
+    if (dexopt_needed == DEXOPT_PATCHOAT_NEEDED
+        || dexopt_needed == DEXOPT_SELF_PATCHOAT_NEEDED) {
+        in_vdex_path_str = create_vdex_filename(input_file);
+        if (in_vdex_path_str.empty()) {
+            return -1;
+        }
+        input_vdex_fd.reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0));
+        if (input_vdex_fd.get() < 0) {
+            ALOGE("installd cannot open '%s' for input during dexopt\n", in_vdex_path_str.c_str());
+            return -1;
+        }
+    }
+
+    // Create the output OAT file.
+    const std::string out_oat_path_str(out_oat_path);
+    Dex2oatFileWrapper<std::function<void ()>> out_oat_fd(
+            open_output_file(out_oat_path, /*recreate*/true, /*permissions*/0644),
+            [out_oat_path_str]() { unlink(out_oat_path_str.c_str()); });
+    if (out_oat_fd.get() < 0) {
+        ALOGE("installd cannot open '%s' for output during dexopt\n", out_oat_path);
         return -1;
     }
-    if (!set_permissions_and_ownership(out_fd.get(), is_public, uid, out_path)) {
+    if (!set_permissions_and_ownership(out_oat_fd.get(), is_public, uid, out_oat_path)) {
+        return -1;
+    }
+
+    // Infer the name of the output VDEX and create it.
+    const std::string out_vdex_path_str = create_vdex_filename(out_oat_path_str);
+    if (out_vdex_path_str.empty()) {
+        return -1;
+    }
+    Dex2oatFileWrapper<std::function<void ()>> out_vdex_fd(
+            open_output_file(out_vdex_path_str.c_str(), /*recreate*/true, /*permissions*/0644),
+            [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
+    if (out_vdex_fd.get() < 0) {
+        ALOGE("installd cannot open '%s' for output during dexopt\n", out_vdex_path_str.c_str());
+        return -1;
+    }
+    if (!set_permissions_and_ownership(out_vdex_fd.get(), is_public,
+                uid, out_vdex_path_str.c_str())) {
         return -1;
     }
 
@@ -1643,7 +1702,7 @@
     if (ShouldUseSwapFileForDexopt()) {
         // Make sure there really is enough space.
         char swap_file_name[PKG_PATH_MAX];
-        strcpy(swap_file_name, out_path);
+        strcpy(swap_file_name, out_oat_path);
         if (add_extension_to_file_name(swap_file_name, ".swap")) {
             swap_fd.reset(open_output_file(swap_file_name, /*recreate*/true, /*permissions*/0600));
         }
@@ -1661,8 +1720,8 @@
 
     // Avoid generating an app image for extract only since it will not contain any classes.
     Dex2oatFileWrapper<std::function<void ()>> image_fd;
-    const std::string image_path = create_image_filename(out_path);
-    if (!image_path.empty()) {
+    const std::string image_path = create_image_filename(out_oat_path);
+    if (dexopt_needed == DEXOPT_DEX2OAT_NEEDED && !image_path.empty()) {
         char app_image_format[kPropertyValueMax];
         bool have_app_image_format =
                 get_property("dalvik.vm.appimageformat", app_image_format, NULL) > 0;
@@ -1707,27 +1766,32 @@
         drop_capabilities(uid);
 
         SetDex2OatAndPatchOatScheduling(boot_complete);
-        if (flock(out_fd.get(), LOCK_EX | LOCK_NB) != 0) {
-            ALOGE("flock(%s) failed: %s\n", out_path, strerror(errno));
+        if (flock(out_oat_fd.get(), LOCK_EX | LOCK_NB) != 0) {
+            ALOGE("flock(%s) failed: %s\n", out_oat_path, strerror(errno));
             _exit(67);
         }
 
         if (dexopt_needed == DEXOPT_PATCHOAT_NEEDED
             || dexopt_needed == DEXOPT_SELF_PATCHOAT_NEEDED) {
             run_patchoat(input_fd.get(),
-                         out_fd.get(),
+                         input_vdex_fd.get(),
+                         out_oat_fd.get(),
+                         out_vdex_fd.get(),
                          input_file,
-                         out_path,
+                         in_vdex_path_str.c_str(),
+                         out_oat_path,
+                         out_vdex_path_str.c_str(),
                          pkgname,
                          instruction_set);
         } else if (dexopt_needed == DEXOPT_DEX2OAT_NEEDED) {
             // Pass dex2oat the relative path to the input file.
             const char *input_file_name = get_location_from_path(input_file);
             run_dex2oat(input_fd.get(),
-                        out_fd.get(),
+                        out_oat_fd.get(),
+                        out_vdex_fd.get(),
                         image_fd.get(),
                         input_file_name,
-                        out_path,
+                        out_oat_path,
                         swap_fd.get(),
                         instruction_set,
                         compiler_filter,
@@ -1754,10 +1818,11 @@
     struct utimbuf ut;
     ut.actime = input_stat.st_atime;
     ut.modtime = input_stat.st_mtime;
-    utime(out_path, &ut);
+    utime(out_oat_path, &ut);
 
     // We've been successful, don't delete output.
-    out_fd.SetCleanup(false);
+    out_oat_fd.SetCleanup(false);
+    out_vdex_fd.SetCleanup(false);
     image_fd.SetCleanup(false);
     reference_profile_fd.SetCleanup(false);
 
@@ -2162,36 +2227,41 @@
     if (!calculate_oat_file_path(a_path, oat_dir, apk_path, instruction_set)) {
         return -1;
     }
+    const std::string a_vdex_path = create_vdex_filename(a_path);
     const std::string a_image_path = create_image_filename(a_path);
 
     // B path = A path + slot suffix.
     const std::string b_path = StringPrintf("%s.%s", a_path, slot_suffix.c_str());
+    const std::string b_vdex_path = StringPrintf("%s.%s", a_vdex_path.c_str(), slot_suffix.c_str());
     const std::string b_image_path = StringPrintf("%s.%s",
                                                   a_image_path.c_str(),
                                                   slot_suffix.c_str());
 
-    bool oat_success = move_ab_path(b_path, a_path);
-    bool success;
+    bool success = true;
+    if (move_ab_path(b_path, a_path)) {
+        if (move_ab_path(b_vdex_path, a_vdex_path)) {
+            // Note: we can live without an app image. As such, ignore failure to move the image file.
+            //       If we decide to require the app image, or the app image being moved correctly,
+            //       then change accordingly.
+            constexpr bool kIgnoreAppImageFailure = true;
 
-    if (oat_success) {
-        // Note: we can live without an app image. As such, ignore failure to move the image file.
-        //       If we decide to require the app image, or the app image being moved correctly,
-        //       then change accordingly.
-        constexpr bool kIgnoreAppImageFailure = true;
-
-        bool art_success = true;
-        if (!a_image_path.empty()) {
-            art_success = move_ab_path(b_image_path, a_image_path);
-            if (!art_success) {
-                unlink(a_image_path.c_str());
+            if (!a_image_path.empty()) {
+                if (!move_ab_path(b_image_path, a_image_path)) {
+                    unlink(a_image_path.c_str());
+                    if (!kIgnoreAppImageFailure) {
+                        success = false;
+                    }
+                }
             }
+        } else {
+            // Cleanup: delete B image, ignore errors.
+            unlink(b_image_path.c_str());
+            success = false;
         }
-
-        success = art_success || kIgnoreAppImageFailure;
     } else {
         // Cleanup: delete B image, ignore errors.
+        unlink(b_vdex_path.c_str());
         unlink(b_image_path.c_str());
-
         success = false;
     }