[installd] Pass --compilation-reason to dex2oat

Test: installd_dexopt_test, installd_otapreopt_test
Bug: 73102540

Change-Id: I22854f040c08ea3207860f29b374c66fe2f21750
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 0d50b9b..fe510a2 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -1906,7 +1906,8 @@
         const std::unique_ptr<std::string>& classLoaderContext,
         const std::unique_ptr<std::string>& seInfo, bool downgrade, int32_t targetSdkVersion,
         const std::unique_ptr<std::string>& profileName,
-        const std::unique_ptr<std::string>& dexMetadataPath) {
+        const std::unique_ptr<std::string>& dexMetadataPath,
+        const std::unique_ptr<std::string>& compilationReason) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_UUID(uuid);
     if (packageName && *packageName != "*") {
@@ -1924,9 +1925,10 @@
     const char* se_info = getCStr(seInfo);
     const char* profile_name = getCStr(profileName);
     const char* dm_path = getCStr(dexMetadataPath);
+    const char* compilation_reason = getCStr(compilationReason);
     int res = android::installd::dexopt(apk_path, uid, pkgname, instruction_set, dexoptNeeded,
             oat_dir, dexFlags, compiler_filter, volume_uuid, class_loader_context, se_info,
-            downgrade, targetSdkVersion, profile_name, dm_path);
+            downgrade, targetSdkVersion, profile_name, dm_path, compilation_reason);
     return res ? error(res, "Failed to dexopt") : ok();
 }
 
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 22b1d12..2a31967 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -86,7 +86,8 @@
             const std::unique_ptr<std::string>& classLoaderContext,
             const std::unique_ptr<std::string>& seInfo, bool downgrade,
             int32_t targetSdkVersion, const std::unique_ptr<std::string>& profileName,
-            const std::unique_ptr<std::string>& dexMetadataPath);
+            const std::unique_ptr<std::string>& dexMetadataPath,
+            const std::unique_ptr<std::string>& compilationReason);
 
     binder::Status rmdex(const std::string& codePath, const std::string& instructionSet);
 
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index e07c847..0c364bd 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -53,7 +53,8 @@
             @nullable @utf8InCpp String sharedLibraries,
             @nullable @utf8InCpp String seInfo, boolean downgrade, int targetSdkVersion,
             @nullable @utf8InCpp String profileName,
-            @nullable @utf8InCpp String dexMetadataPath);
+            @nullable @utf8InCpp String dexMetadataPath,
+            @nullable @utf8InCpp String compilationReason);
 
     void rmdex(@utf8InCpp String codePath, @utf8InCpp String instructionSet);
 
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 2a7ad61..9f1cd45 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -224,7 +224,7 @@
         const char* instruction_set, const char* compiler_filter,
         bool debuggable, bool post_bootcomplete, bool background_job_compile, int profile_fd,
         const char* class_loader_context, int target_sdk_version, bool enable_hidden_api_checks,
-        int dex_metadata_fd) {
+        int dex_metadata_fd, const char* compilation_reason) {
     static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
 
     if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
@@ -423,6 +423,10 @@
 
     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, relative_input_file_name, output_file_name);
 
     // Disable cdex if update input vdex is true since this combination of options is not
@@ -453,7 +457,8 @@
                      + (generate_minidebug_info ? 1 : 0)
                      + (target_sdk_version != 0 ? 2 : 0)
                      + (enable_hidden_api_checks ? 2 : 0)
-                     + (dex_metadata_fd > -1 ? 1 : 0)];
+                     + (dex_metadata_fd > -1 ? 1 : 0)
+                     + (compilation_reason != nullptr ? 1 : 0)];
     int i = 0;
     argv[i++] = dex2oat_bin;
     argv[i++] = zip_fd_arg;
@@ -535,6 +540,10 @@
     if (dex_metadata_fd > -1) {
         argv[i++] = dex_metadata_fd_arg.c_str();
     }
+
+    if(compilation_reason != nullptr) {
+        argv[i++] = compilation_reason_arg.c_str();
+    }
     // Do not add after dex2oat_flags, they should override others for debugging.
     argv[i] = NULL;
 
@@ -1865,7 +1874,7 @@
         int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
         const char* volume_uuid, const char* class_loader_context, const char* se_info,
         bool downgrade, int target_sdk_version, const char* profile_name,
-        const char* dex_metadata_path) {
+        const char* dex_metadata_path, const char* compilation_reason) {
     CHECK(pkgname != nullptr);
     CHECK(pkgname[0] != 0);
     if ((dexopt_flags & ~DEXOPT_MASK) != 0) {
@@ -1994,7 +2003,8 @@
                     class_loader_context,
                     target_sdk_version,
                     enable_hidden_api_checks,
-                    dex_metadata_fd.get());
+                    dex_metadata_fd.get(),
+                    compilation_reason);
         _exit(68);   /* only get here on exec failure */
     } else {
         int res = wait_child(pid);
diff --git a/cmds/installd/dexopt.h b/cmds/installd/dexopt.h
index ae1412e..62f9467 100644
--- a/cmds/installd/dexopt.h
+++ b/cmds/installd/dexopt.h
@@ -106,7 +106,7 @@
         int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
         const char* volume_uuid, const char* class_loader_context, const char* se_info,
         bool downgrade, int target_sdk_version, const char* profile_name,
-        const char* dexMetadataPath);
+        const char* dexMetadataPath, const char* compilation_reason);
 
 bool calculate_oat_file_path_default(char path[PKG_PATH_MAX], const char *oat_dir,
         const char *apk_path, const char *instruction_set);
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index f2d1b33..9680352 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -582,7 +582,8 @@
                       parameters_.downgrade,
                       parameters_.target_sdk_version,
                       parameters_.profile_name,
-                      parameters_.dex_metadata_path);
+                      parameters_.dex_metadata_path,
+                      parameters_.compilation_reason);
     }
 
     int RunPreopt() {
diff --git a/cmds/installd/otapreopt_parameters.cpp b/cmds/installd/otapreopt_parameters.cpp
index 1f85728..802d5d7 100644
--- a/cmds/installd/otapreopt_parameters.cpp
+++ b/cmds/installd/otapreopt_parameters.cpp
@@ -112,6 +112,29 @@
     return (input & old_mask) != 0 ? new_mask : 0;
 }
 
+void OTAPreoptParameters::SetDefaultsForPostV1Arguments() {
+    // Set se_info to null. It is only relevant for secondary dex files, which we won't
+    // receive from a v1 A side.
+    se_info = nullptr;
+
+    // Set downgrade to false. It is only relevant when downgrading compiler
+    // filter, which is not the case during ota.
+    downgrade = false;
+
+    // Set target_sdk_version to 0, ie the platform SDK version. This is
+    // conservative and may force some classes to verify at runtime.
+    target_sdk_version = 0;
+
+    // Set the profile name to the primary apk profile.
+    profile_name = "primary.prof";
+
+    // By default we don't have a dex metadata file.
+    dex_metadata_path = nullptr;
+
+    // The compilation reason is ab-ota (match the system property pm.dexopt.ab-ota)
+    compilation_reason = "ab-ota";
+}
+
 bool OTAPreoptParameters::ReadArgumentsV1(const char** argv) {
     // Check for "dexopt".
     if (argv[2] == nullptr) {
@@ -203,23 +226,7 @@
         return false;
     }
 
-    // Set se_info to null. It is only relevant for secondary dex files, which we won't
-    // receive from a v1 A side.
-    se_info = nullptr;
-
-    // Set downgrade to false. It is only relevant when downgrading compiler
-    // filter, which is not the case during ota.
-    downgrade = false;
-
-    // Set target_sdk_version to 0, ie the platform SDK version. This is
-    // conservative and may force some classes to verify at runtime.
-    target_sdk_version = 0;
-
-    // Set the profile name to the primary apk profile.
-    profile_name = "primary.prof";
-
-    // By default we don't have a dex metadata file.
-    dex_metadata_path = nullptr;
+    SetDefaultsForPostV1Arguments();
 
     return true;
 }
@@ -232,6 +239,7 @@
         case 4: num_args_expected = 13; break;
         case 5: num_args_expected = 14; break;
         case 6: num_args_expected = 15; break;
+        case 7: num_args_expected = 16; break;
         default:
             LOG(ERROR) << "Don't know how to read arguments for version " << version;
             return false;
@@ -263,20 +271,7 @@
     // The number of arguments is OK.
     // Configure the default values for the parameters that were added after V1.
     // The default values will be overwritten in case they are passed as arguments.
-
-    // Set downgrade to false. It is only relevant when downgrading compiler
-    // filter, which is not the case during ota.
-    downgrade = false;
-
-    // Set target_sdk_version to 0, ie the platform SDK version. This is
-    // conservative and may force some classes to verify at runtime.
-    target_sdk_version = 0;
-
-    // Set the profile name to the primary apk profile.
-    profile_name = "primary.prof";
-
-    // By default we don't have a dex metadata file.
-    dex_metadata_path = nullptr;
+    SetDefaultsForPostV1Arguments();
 
     for (size_t param_index = 0; param_index < num_args_actual; ++param_index) {
         const char* param = argv[dexopt_index + 1 + param_index];
@@ -341,6 +336,10 @@
                 dex_metadata_path = ParseNull(param);
                 break;
 
+            case 15:
+                compilation_reason = ParseNull(param);
+                break;
+
             default:
                 LOG(FATAL) << "Should not get here. Did you call ReadArguments "
                         << "with the right expectation? index=" << param_index
diff --git a/cmds/installd/otapreopt_parameters.h b/cmds/installd/otapreopt_parameters.h
index 0f3bb8c..a2f6e44 100644
--- a/cmds/installd/otapreopt_parameters.h
+++ b/cmds/installd/otapreopt_parameters.h
@@ -31,6 +31,7 @@
     bool ReadArgumentsV1(const char** argv);
     bool ReadArgumentsPostV1(uint32_t version, const char** argv, bool versioned);
 
+    void SetDefaultsForPostV1Arguments();
     const char* apk_path;
     uid_t uid;
     const char* pkgName;
@@ -46,6 +47,7 @@
     int target_sdk_version;
     const char* profile_name;
     const char* dex_metadata_path;
+    const char* compilation_reason;
 
     std::string target_slot;
 
@@ -56,4 +58,4 @@
 }  // namespace installd
 }  // namespace android
 
-#endif  //  OTAPREOPT_PARAMETERS_H_
\ No newline at end of file
+#endif  //  OTAPREOPT_PARAMETERS_H_
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index 5a82965..2629144 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -264,6 +264,7 @@
         int32_t target_sdk_version = 0;  // default
         std::unique_ptr<std::string> profile_name_ptr = nullptr;
         std::unique_ptr<std::string> dm_path_ptr = nullptr;
+        std::unique_ptr<std::string> compilation_reason_ptr = nullptr;
 
         binder::Status result = service_->dexopt(path,
                                                  uid,
@@ -279,7 +280,8 @@
                                                  downgrade,
                                                  target_sdk_version,
                                                  profile_name_ptr,
-                                                 dm_path_ptr);
+                                                 dm_path_ptr,
+                                                 compilation_reason_ptr);
         ASSERT_EQ(should_binder_call_succeed, result.isOk());
         int expected_access = should_dex_be_compiled ? 0 : -1;
         std::string odex = GetSecondaryDexArtifact(path, "odex");
@@ -369,6 +371,7 @@
         if (dm_path != nullptr) {
             dm_path_ptr.reset(new std::string(dm_path));
         }
+        std::unique_ptr<std::string> compilation_reason_ptr(new std::string("test-reason"));
 
         bool prof_result;
         binder::Status prof_binder_result = service_->prepareAppProfile(
@@ -392,7 +395,8 @@
                                                  downgrade,
                                                  target_sdk_version,
                                                  profile_name_ptr,
-                                                 dm_path_ptr);
+                                                 dm_path_ptr,
+                                                 compilation_reason_ptr);
         ASSERT_EQ(should_binder_call_succeed, result.isOk());
 
         if (!should_binder_call_succeed) {
diff --git a/cmds/installd/tests/installd_otapreopt_test.cpp b/cmds/installd/tests/installd_otapreopt_test.cpp
index 8b8dde1..82bf932 100644
--- a/cmds/installd/tests/installd_otapreopt_test.cpp
+++ b/cmds/installd/tests/installd_otapreopt_test.cpp
@@ -90,6 +90,11 @@
         } else {
             ASSERT_EQ(params.dex_metadata_path, nullptr);
         }
+        if (version > 6) {
+            ASSERT_STREQ(params.compilation_reason, ParseNull(args[i++]));
+        } else {
+            ASSERT_STREQ(params.compilation_reason, "ab-ota");
+        }
     }
 
     const char* getVersionCStr(uint32_t version) {
@@ -100,6 +105,7 @@
             case 4: return "4";
             case 5: return "5";
             case 6: return "6";
+            case 7: return "7";
         }
         return nullptr;
     }
@@ -138,6 +144,9 @@
         if (version > 5) {
             args.push_back("dex_metadata.dm");  // dex_metadata_path
         }
+        if (version > 6) {
+            args.push_back("ab-ota-test");  // compilation_reason
+        }
         args.push_back(nullptr);  // we have to end with null.
         return args;
     }
@@ -178,6 +187,10 @@
     VerifyReadArguments(6, true);
 }
 
+TEST_F(OTAPreoptTest, ReadArgumentsV7) {
+    VerifyReadArguments(7, true);
+}
+
 TEST_F(OTAPreoptTest, ReadArgumentsFailToManyArgs) {
     OTAPreoptParameters params;
     std::vector<const char*> args = getArgs(5, true);