Merge "installd: Refactor RunDex2Oat to reduce variable life span"
diff --git a/cmds/installd/run_dex2oat.cpp b/cmds/installd/run_dex2oat.cpp
index 8cac58f..1572e3b 100644
--- a/cmds/installd/run_dex2oat.cpp
+++ b/cmds/installd/run_dex2oat.cpp
@@ -86,241 +86,22 @@
                             int dex_metadata_fd,
                             bool use_jitzygote_image,
                             const char* compilation_reason) {
-    // Get the relative path to the input file.
-    std::string input_basename = Basename(input_file_name);
+    PrepareBootImageAndBootClasspathFlags(use_jitzygote_image);
 
-    std::string dex2oat_Xms_arg = MapPropertyToArg("dalvik.vm.dex2oat-Xms", "-Xms%s");
-    std::string dex2oat_Xmx_arg = MapPropertyToArg("dalvik.vm.dex2oat-Xmx", "-Xmx%s");
+    PrepareInputFileFlags(zip_fd, oat_fd, input_vdex_fd, output_vdex_fd, image_fd, input_file_name,
+                          output_file_name, profile_fd, dex_metadata_fd, swap_fd,
+                          class_loader_context, class_loader_context_fds);
 
-    std::string threads_format = "-j%s";
-    std::string dex2oat_threads_arg = post_bootcomplete
-            ? (for_restore
-                ? MapPropertyToArgWithBackup(
-                        "dalvik.vm.restore-dex2oat-threads",
-                        "dalvik.vm.dex2oat-threads",
-                        threads_format)
-                : MapPropertyToArg("dalvik.vm.dex2oat-threads", threads_format))
-            : MapPropertyToArg("dalvik.vm.boot-dex2oat-threads", threads_format);
-    std::string cpu_set_format = "--cpu-set=%s";
-    std::string dex2oat_cpu_set_arg = post_bootcomplete
-            ? (for_restore
-                ? MapPropertyToArgWithBackup(
-                        "dalvik.vm.restore-dex2oat-cpu-set",
-                        "dalvik.vm.dex2oat-cpu-set",
-                        cpu_set_format)
-                : MapPropertyToArg("dalvik.vm.dex2oat-cpu-set", cpu_set_format))
-            : MapPropertyToArg("dalvik.vm.boot-dex2oat-cpu-set", cpu_set_format);
+    PrepareCompilerConfigFlags(input_vdex_fd, output_vdex_fd, instruction_set, compiler_filter,
+                               debuggable, target_sdk_version, enable_hidden_api_checks,
+                               generate_compact_dex, compilation_reason);
 
-    std::string bootclasspath;
-    char* dex2oat_bootclasspath = getenv("DEX2OATBOOTCLASSPATH");
-    if (dex2oat_bootclasspath != nullptr) {
-        bootclasspath = StringPrintf("-Xbootclasspath:%s", dex2oat_bootclasspath);
-    }
-    // If DEX2OATBOOTCLASSPATH is not in the environment, dex2oat is going to query
-    // BOOTCLASSPATH.
-
-    const std::string dex2oat_isa_features_key =
-            StringPrintf("dalvik.vm.isa.%s.features", instruction_set);
-    std::string instruction_set_features_arg =
-        MapPropertyToArg(dex2oat_isa_features_key, "--instruction-set-features=%s");
-
-    const std::string dex2oat_isa_variant_key =
-            StringPrintf("dalvik.vm.isa.%s.variant", instruction_set);
-    std::string instruction_set_variant_arg =
-        MapPropertyToArg(dex2oat_isa_variant_key, "--instruction-set-variant=%s");
-
-    const char* dex2oat_norelocation = "-Xnorelocate";
+    PrepareCompilerRuntimeAndPerfConfigFlags(post_bootcomplete, for_restore);
 
     const std::string dex2oat_flags = GetProperty("dalvik.vm.dex2oat-flags", "");
     std::vector<std::string> dex2oat_flags_args = SplitBySpaces(dex2oat_flags);
     ALOGV("dalvik.vm.dex2oat-flags=%s\n", dex2oat_flags.c_str());
 
-    // If we are booting without the real /data, don't spend time compiling.
-    std::string vold_decrypt = GetProperty("vold.decrypt", "");
-    bool skip_compilation = vold_decrypt == "trigger_restart_min_framework" ||
-                            vold_decrypt == "1";
-
-    std::string updatable_bcp_packages =
-        MapPropertyToArg("dalvik.vm.dex2oat-updatable-bcp-packages-file",
-                         "--updatable-bcp-packages-file=%s");
-    if (updatable_bcp_packages.empty()) {
-      // Make dex2oat fail by providing non-existent file name.
-      updatable_bcp_packages = "--updatable-bcp-packages-file=/nonx/updatable-bcp-packages.txt";
-    }
-
-    std::string resolve_startup_string_arg =
-            MapPropertyToArg("persist.device_config.runtime.dex2oat_resolve_startup_strings",
-                             "--resolve-startup-const-strings=%s");
-    if (resolve_startup_string_arg.empty()) {
-      // If empty, fall back to system property.
-      resolve_startup_string_arg =
-            MapPropertyToArg("dalvik.vm.dex2oat-resolve-startup-strings",
-                             "--resolve-startup-const-strings=%s");
-    }
-
-    const std::string image_block_size_arg =
-            MapPropertyToArg("dalvik.vm.dex2oat-max-image-block-size",
-                             "--max-image-block-size=%s");
-
-    const bool generate_debug_info = GetBoolProperty("debug.generate-debug-info", false);
-
-    std::string image_format_arg;
-    if (image_fd >= 0) {
-        image_format_arg = MapPropertyToArg("dalvik.vm.appimageformat", "--image-format=%s");
-    }
-
-    std::string dex2oat_large_app_threshold_arg =
-        MapPropertyToArg("dalvik.vm.dex2oat-very-large", "--very-large-app-threshold=%s");
-
-    bool generate_minidebug_info = kEnableMinidebugInfo &&
-            GetBoolProperty(kMinidebugInfoSystemProperty, kMinidebugInfoSystemPropertyDefault);
-
-    std::string boot_image;
-    if (use_jitzygote_image) {
-      boot_image = StringPrintf("--boot-image=%s", kJitZygoteImage);
-    } else {
-      boot_image = MapPropertyToArg("dalvik.vm.boot-image", "--boot-image=%s");
-    }
-
-    // clang FORTIFY doesn't let us use strlen in constant array bounds, so we
-    // use arraysize instead.
-    std::string zip_fd_arg = StringPrintf("--zip-fd=%d", zip_fd);
-    std::string zip_location_arg = StringPrintf("--zip-location=%s", input_basename.c_str());
-    std::string input_vdex_fd_arg = StringPrintf("--input-vdex-fd=%d", input_vdex_fd);
-    std::string output_vdex_fd_arg = StringPrintf("--output-vdex-fd=%d", output_vdex_fd);
-    std::string oat_fd_arg = StringPrintf("--oat-fd=%d", oat_fd);
-    std::string oat_location_arg = StringPrintf("--oat-location=%s", output_file_name);
-    std::string instruction_set_arg = StringPrintf("--instruction-set=%s", instruction_set);
-    std::string dex2oat_compiler_filter_arg;
-    std::string dex2oat_swap_fd;
-    std::string dex2oat_image_fd;
-    std::string target_sdk_version_arg;
-    if (target_sdk_version != 0) {
-        target_sdk_version_arg = StringPrintf("-Xtarget-sdk-version:%d", target_sdk_version);
-    }
-    std::string class_loader_context_arg;
-    std::string class_loader_context_fds_arg;
-    if (class_loader_context != nullptr) {
-        class_loader_context_arg = StringPrintf("--class-loader-context=%s",
-                                                class_loader_context);
-        if (!class_loader_context_fds.empty()) {
-            class_loader_context_fds_arg = StringPrintf("--class-loader-context-fds=%s",
-                                                        class_loader_context_fds.c_str());
-        }
-    }
-
-    if (swap_fd >= 0) {
-        dex2oat_swap_fd = StringPrintf("--swap-fd=%d", swap_fd);
-    }
-    if (image_fd >= 0) {
-        dex2oat_image_fd = StringPrintf("--app-image-fd=%d", image_fd);
-    }
-
-    // Compute compiler filter.
-    bool have_dex2oat_relocation_skip_flag = false;
-    if (skip_compilation) {
-        dex2oat_compiler_filter_arg = "--compiler-filter=extract";
-        have_dex2oat_relocation_skip_flag = true;
-    } else if (compiler_filter != nullptr) {
-        dex2oat_compiler_filter_arg = StringPrintf("--compiler-filter=%s", compiler_filter);
-    }
-
-    if (dex2oat_compiler_filter_arg.empty()) {
-        dex2oat_compiler_filter_arg = MapPropertyToArg("dalvik.vm.dex2oat-filter",
-                                                       "--compiler-filter=%s");
-    }
-
-    // Check whether all apps should be compiled debuggable.
-    if (!debuggable) {
-        debuggable = GetProperty("dalvik.vm.always_debuggable", "") == "1";
-    }
-    std::string profile_arg;
-    if (profile_fd != -1) {
-        profile_arg = StringPrintf("--profile-file-fd=%d", profile_fd);
-    }
-
-    // Get the directory of the apk to pass as a base classpath directory.
-    std::string base_dir;
-    std::string apk_dir(input_file_name);
-    unsigned long dir_index = apk_dir.rfind('/');
-    bool has_base_dir = dir_index != std::string::npos;
-    if (has_base_dir) {
-        apk_dir = apk_dir.substr(0, dir_index);
-        base_dir = StringPrintf("--classpath-dir=%s", apk_dir.c_str());
-    }
-
-    std::string dex_metadata_fd_arg = "--dm-fd=" + std::to_string(dex_metadata_fd);
-
-    std::string compilation_reason_arg = compilation_reason == nullptr
-            ? ""
-            : std::string("--compilation-reason=") + compilation_reason;
-
-    ALOGV("Running %s in=%s out=%s\n", dex2oat_bin_.c_str(), input_basename.c_str(),
-          output_file_name);
-
-    // Disable cdex if update input vdex is true since this combination of options is not
-    // supported.
-    const bool disable_cdex = !generate_compact_dex || (input_vdex_fd == output_vdex_fd);
-
-    AddArg(zip_fd_arg);
-    AddArg(zip_location_arg);
-    AddArg(input_vdex_fd_arg);
-    AddArg(output_vdex_fd_arg);
-    AddArg(oat_fd_arg);
-    AddArg(oat_location_arg);
-    AddArg(instruction_set_arg);
-
-    AddArg(instruction_set_variant_arg);
-    AddArg(instruction_set_features_arg);
-
-    AddArg(boot_image);
-
-    AddRuntimeArg(bootclasspath);
-    AddRuntimeArg(dex2oat_Xms_arg);
-    AddRuntimeArg(dex2oat_Xmx_arg);
-
-    AddArg(updatable_bcp_packages);
-    AddArg(resolve_startup_string_arg);
-    AddArg(image_block_size_arg);
-    AddArg(dex2oat_compiler_filter_arg);
-    AddArg(dex2oat_threads_arg);
-    AddArg(dex2oat_cpu_set_arg);
-    AddArg(dex2oat_swap_fd);
-    AddArg(dex2oat_image_fd);
-
-    if (generate_debug_info) {
-        AddArg("--generate-debug-info");
-    }
-    if (debuggable) {
-        AddArg("--debuggable");
-    }
-    AddArg(image_format_arg);
-    AddArg(dex2oat_large_app_threshold_arg);
-
-    if (have_dex2oat_relocation_skip_flag) {
-        AddRuntimeArg(dex2oat_norelocation);
-    }
-    AddArg(profile_arg);
-    AddArg(base_dir);
-    AddArg(class_loader_context_arg);
-    AddArg(class_loader_context_fds_arg);
-    if (generate_minidebug_info) {
-        AddArg(kMinidebugDex2oatFlag);
-    }
-    if (disable_cdex) {
-        AddArg(kDisableCompactDexFlag);
-    }
-    AddRuntimeArg(target_sdk_version_arg);
-    if (enable_hidden_api_checks) {
-        AddRuntimeArg("-Xhidden-api-policy:enabled");
-    }
-
-    if (dex_metadata_fd > -1) {
-        AddArg(dex_metadata_fd_arg);
-    }
-
-    AddArg(compilation_reason_arg);
-
     // Do not add args after dex2oat_flags, they should override others for debugging.
     for (auto it = dex2oat_flags_args.begin(); it != dex2oat_flags_args.end(); ++it) {
         AddArg(*it);
@@ -331,8 +112,240 @@
 
 RunDex2Oat::~RunDex2Oat() {}
 
+void RunDex2Oat::PrepareBootImageAndBootClasspathFlags(bool use_jitzygote_image) {
+    std::string boot_image;
+    if (use_jitzygote_image) {
+        boot_image = StringPrintf("--boot-image=%s", kJitZygoteImage);
+    } else {
+        boot_image = MapPropertyToArg("dalvik.vm.boot-image", "--boot-image=%s");
+    }
+    AddArg(boot_image);
+
+    // If DEX2OATBOOTCLASSPATH is not in the environment, dex2oat is going to query
+    // BOOTCLASSPATH.
+    char* dex2oat_bootclasspath = getenv("DEX2OATBOOTCLASSPATH");
+    if (dex2oat_bootclasspath != nullptr) {
+        AddRuntimeArg(StringPrintf("-Xbootclasspath:%s", dex2oat_bootclasspath));
+    }
+
+    std::string updatable_bcp_packages =
+            MapPropertyToArg("dalvik.vm.dex2oat-updatable-bcp-packages-file",
+                             "--updatable-bcp-packages-file=%s");
+    if (updatable_bcp_packages.empty()) {
+        // Make dex2oat fail by providing non-existent file name.
+        updatable_bcp_packages =
+                "--updatable-bcp-packages-file=/nonx/updatable-bcp-packages.txt";
+    }
+    AddArg(updatable_bcp_packages);
+}
+
+void RunDex2Oat::PrepareInputFileFlags(int zip_fd,
+                                       int oat_fd,
+                                       int input_vdex_fd,
+                                       int output_vdex_fd,
+                                       int image_fd,
+                                       const char* input_file_name,
+                                       const char* output_file_name,
+                                       int profile_fd,
+                                       int dex_metadata_fd,
+                                       int swap_fd,
+                                       const char* class_loader_context,
+                                       const std::string& class_loader_context_fds) {
+    std::string input_basename = Basename(input_file_name);
+    ALOGV("Running %s in=%s out=%s\n", dex2oat_bin_.c_str(), input_basename.c_str(),
+          output_file_name);
+
+    AddArg(StringPrintf("--zip-fd=%d", zip_fd));
+    AddArg(StringPrintf("--zip-location=%s", input_basename.c_str()));
+    AddArg(StringPrintf("--oat-fd=%d", oat_fd));
+    AddArg(StringPrintf("--oat-location=%s", output_file_name));
+    AddArg(StringPrintf("--input-vdex-fd=%d", input_vdex_fd));
+    AddArg(StringPrintf("--output-vdex-fd=%d", output_vdex_fd));
+
+    if (image_fd >= 0) {
+        AddArg(StringPrintf("--app-image-fd=%d", image_fd));
+        AddArg(MapPropertyToArg("dalvik.vm.appimageformat", "--image-format=%s"));
+    }
+    if (dex_metadata_fd > -1) {
+        AddArg("--dm-fd=" + std::to_string(dex_metadata_fd));
+    }
+    if (profile_fd != -1) {
+        AddArg(StringPrintf("--profile-file-fd=%d", profile_fd));
+    }
+    if (swap_fd >= 0) {
+        AddArg(StringPrintf("--swap-fd=%d", swap_fd));
+    }
+
+    // Get the directory of the apk to pass as a base classpath directory.
+    {
+        std::string apk_dir(input_file_name);
+        size_t dir_index = apk_dir.rfind('/');
+        if (dir_index != std::string::npos) {
+            apk_dir = apk_dir.substr(0, dir_index);
+            AddArg(StringPrintf("--classpath-dir=%s", apk_dir.c_str()));
+        }
+    }
+
+    if (class_loader_context != nullptr) {
+        AddArg(StringPrintf("--class-loader-context=%s", class_loader_context));
+        if (!class_loader_context_fds.empty()) {
+            AddArg(StringPrintf("--class-loader-context-fds=%s",
+                                class_loader_context_fds.c_str()));
+        }
+    }
+}
+
+void RunDex2Oat::PrepareCompilerConfigFlags(int input_vdex_fd,
+                                            int output_vdex_fd,
+                                            const char* instruction_set,
+                                            const char* compiler_filter,
+                                            bool debuggable,
+                                            int target_sdk_version,
+                                            bool enable_hidden_api_checks,
+                                            bool generate_compact_dex,
+                                            const char* compilation_reason) {
+    // Disable cdex if update input vdex is true since this combination of options is not
+    // supported.
+    const bool disable_cdex = !generate_compact_dex || (input_vdex_fd == output_vdex_fd);
+    if (disable_cdex) {
+        AddArg(kDisableCompactDexFlag);
+    }
+    
+    // ISA related
+    {
+        AddArg(StringPrintf("--instruction-set=%s", instruction_set));
+
+        const std::string dex2oat_isa_features_key =
+                StringPrintf("dalvik.vm.isa.%s.features", instruction_set);
+        std::string instruction_set_features_arg =
+                MapPropertyToArg(dex2oat_isa_features_key, "--instruction-set-features=%s");
+        AddArg(instruction_set_features_arg);
+
+        const std::string dex2oat_isa_variant_key =
+                StringPrintf("dalvik.vm.isa.%s.variant", instruction_set);
+        std::string instruction_set_variant_arg =
+                MapPropertyToArg(dex2oat_isa_variant_key, "--instruction-set-variant=%s");
+        AddArg(instruction_set_variant_arg);
+    }
+
+    // Compute compiler filter.
+    {
+        std::string dex2oat_compiler_filter_arg;
+        {
+            // If we are booting without the real /data, don't spend time compiling.
+            std::string vold_decrypt = GetProperty("vold.decrypt", "");
+            bool skip_compilation = vold_decrypt == "trigger_restart_min_framework" ||
+                    vold_decrypt == "1";
+
+            bool have_dex2oat_relocation_skip_flag = false;
+            if (skip_compilation) {
+                dex2oat_compiler_filter_arg = "--compiler-filter=extract";
+                have_dex2oat_relocation_skip_flag = true;
+            } else if (compiler_filter != nullptr) {
+                dex2oat_compiler_filter_arg = StringPrintf("--compiler-filter=%s",
+                                                           compiler_filter);
+            }
+            if (have_dex2oat_relocation_skip_flag) {
+                AddRuntimeArg("-Xnorelocate");
+            }
+        }
+
+        if (dex2oat_compiler_filter_arg.empty()) {
+            dex2oat_compiler_filter_arg = MapPropertyToArg("dalvik.vm.dex2oat-filter",
+                                                           "--compiler-filter=%s");
+        }
+        AddArg(dex2oat_compiler_filter_arg);
+
+        if (compilation_reason != nullptr) {
+            AddArg(std::string("--compilation-reason=") + compilation_reason);
+        }
+    }
+
+    AddArg(MapPropertyToArg("dalvik.vm.dex2oat-max-image-block-size",
+                            "--max-image-block-size=%s"));
+
+    AddArg(MapPropertyToArg("dalvik.vm.dex2oat-very-large",
+                            "--very-large-app-threshold=%s"));
+
+    std::string resolve_startup_string_arg = MapPropertyToArg(
+        "persist.device_config.runtime.dex2oat_resolve_startup_strings",
+        "--resolve-startup-const-strings=%s");
+    if (resolve_startup_string_arg.empty()) {
+        // If empty, fall back to system property.
+        resolve_startup_string_arg =
+                MapPropertyToArg("dalvik.vm.dex2oat-resolve-startup-strings",
+                                 "--resolve-startup-const-strings=%s");
+    }
+    AddArg(resolve_startup_string_arg);
+
+    // Debug related
+    {
+        // Check whether all apps should be compiled debuggable.
+        if (!debuggable) {
+            debuggable = GetProperty("dalvik.vm.always_debuggable", "") == "1";
+        }
+        if (debuggable) {
+            AddArg("--debuggable");
+        }
+
+        const bool generate_debug_info = GetBoolProperty("debug.generate-debug-info", false);
+        if (generate_debug_info) {
+            AddArg("--generate-debug-info");
+        }
+        {
+            bool generate_minidebug_info = kEnableMinidebugInfo &&
+                    GetBoolProperty(kMinidebugInfoSystemProperty,
+                                    kMinidebugInfoSystemPropertyDefault);
+            if (generate_minidebug_info) {
+                AddArg(kMinidebugDex2oatFlag);
+            }
+        }
+    }
+
+    if (target_sdk_version != 0) {
+        AddRuntimeArg(StringPrintf("-Xtarget-sdk-version:%d", target_sdk_version));
+    }
+
+    if (enable_hidden_api_checks) {
+        AddRuntimeArg("-Xhidden-api-policy:enabled");
+    }
+}
+
+void RunDex2Oat::PrepareCompilerRuntimeAndPerfConfigFlags(bool post_bootcomplete,
+                                                          bool for_restore) {
+    // CPU set
+    {
+        std::string cpu_set_format = "--cpu-set=%s";
+        std::string dex2oat_cpu_set_arg = post_bootcomplete
+                ? (for_restore
+                   ? MapPropertyToArgWithBackup(
+                           "dalvik.vm.restore-dex2oat-cpu-set",
+                           "dalvik.vm.dex2oat-cpu-set",
+                           cpu_set_format)
+                   : MapPropertyToArg("dalvik.vm.dex2oat-cpu-set", cpu_set_format))
+                : MapPropertyToArg("dalvik.vm.boot-dex2oat-cpu-set", cpu_set_format);
+        AddArg(dex2oat_cpu_set_arg);
+    }
+
+    // Number of threads
+    {
+        std::string threads_format = "-j%s";
+        std::string dex2oat_threads_arg = post_bootcomplete
+                ? (for_restore
+                   ? MapPropertyToArgWithBackup(
+                           "dalvik.vm.restore-dex2oat-threads",
+                           "dalvik.vm.dex2oat-threads",
+                           threads_format)
+                   : MapPropertyToArg("dalvik.vm.dex2oat-threads", threads_format))
+                : MapPropertyToArg("dalvik.vm.boot-dex2oat-threads", threads_format);
+        AddArg(dex2oat_threads_arg);
+    }
+
+    AddRuntimeArg(MapPropertyToArg("dalvik.vm.dex2oat-Xms", "-Xms%s"));
+    AddRuntimeArg(MapPropertyToArg("dalvik.vm.dex2oat-Xmx", "-Xmx%s"));
+}
+
 void RunDex2Oat::Exec(int exit_code) {
-    LOG(ERROR) << "RunDex2Oat::Exec";
     execv_helper_->Exec(exit_code);
 }
 
diff --git a/cmds/installd/run_dex2oat.h b/cmds/installd/run_dex2oat.h
index e4450b0..5453272 100644
--- a/cmds/installd/run_dex2oat.h
+++ b/cmds/installd/run_dex2oat.h
@@ -56,6 +56,30 @@
     void Exec(int exit_code);
 
   protected:
+    void PrepareBootImageAndBootClasspathFlags(bool use_jitzygote_image);
+    void PrepareInputFileFlags(int zip_fd,
+                               int oat_fd,
+                               int input_vdex_fd,
+                               int output_vdex_fd,
+                               int image_fd,
+                               const char* input_file_name,
+                               const char* output_file_name,
+                               int profile_fd,
+                               int dex_metadata_fd,
+                               int swap_fd,
+                               const char* class_loader_context,
+                               const std::string& class_loader_context_fds);
+    void PrepareCompilerConfigFlags(int input_vdex_fd,
+                                    int output_vdex_fd,
+                                    const char* instruction_set,
+                                    const char* compiler_filter,
+                                    bool debuggable,
+                                    int target_sdk_version,
+                                    bool enable_hidden_api_checks,
+                                    bool generate_compact_dex,
+                                    const char* compilation_reason);
+    void PrepareCompilerRuntimeAndPerfConfigFlags(bool post_bootcomplete, bool for_restore);
+
     virtual std::string GetProperty(const std::string& key, const std::string& default_value);
     virtual bool GetBoolProperty(const std::string& key, bool default_value);