Increase coverage of libartpalette-system native API.
- Call PaletteAshmemCreateRegion and PaletteAshmemSetProtRegion, which
don't get exercised on memfd capable kernels.
- Call PaletteNotify{Begin,End}JniInvocation regardless of what the
ShouldReport gate function says. Start a VM to give them a valid
JNIEnv argument.
- Add a CTS test to run dex2oat with a new special flag to make it call
PaletteNotify{Start,End}Dex2oatCompilation regardless of what the
ShouldReport gate function says. This way they get valid fd's for the
oat and vdex files.
Test: m cts cts-tradefed
cts-tradefed run commandAndExit cts \
--module art_standalone_dex2oat_cts_tests
cts-tradefed run commandAndExit cts \
--module art_standalone_libartpalette_tests
with log messages in the hook functions in palette_android_partner.cc
to verify that they are called.
Test: art/tools/run-gtests.sh \
/apex/com.android.art/bin/art/{x86,x86_64}/art_libartpalette_tests
in device chroot test environment
Test: m test-art-host-gtest-art_libartpalette_tests
Bug: 206657952
Change-Id: I91f3182f15d234dbaca2a4357442efd2e957373f
diff --git a/dex2oat/Android.bp b/dex2oat/Android.bp
index 5bc986b..254df02 100644
--- a/dex2oat/Android.bp
+++ b/dex2oat/Android.bp
@@ -577,3 +577,19 @@
],
test_config: "art_standalone_dex2oat_tests.xml",
}
+
+// Counterpart to art_standalone_dex2oat_tests for tests that go into CTS.
+art_cc_test {
+ name: "art_standalone_dex2oat_cts_tests",
+ defaults: ["art_standalone_gtest_defaults"],
+ srcs: ["dex2oat_cts_test.cc"],
+ data: [
+ ":art-gtest-jars-Main",
+ ":art-gtest-jars-MainStripped",
+ ":art-gtest-jars-MultiDex",
+ ":art-gtest-jars-MultiDexModifiedSecondary",
+ ":art-gtest-jars-Nested",
+ ],
+ test_config: "art_standalone_dex2oat_cts_tests.xml",
+ test_suites: ["cts"],
+}
diff --git a/dex2oat/art_standalone_dex2oat_cts_tests.xml b/dex2oat/art_standalone_dex2oat_cts_tests.xml
new file mode 100644
index 0000000..b61c3f3
--- /dev/null
+++ b/dex2oat/art_standalone_dex2oat_cts_tests.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs art_standalone_dex2oat_cts_tests.">
+ <option name="test-suite-tag" value="cts" />
+ <option name="config-descriptor:metadata" key="component" value="art" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+ <option name="cleanup" value="true" />
+ <option name="push" value="art_standalone_dex2oat_cts_tests->/data/local/tmp/art_standalone_dex2oat_cts_tests/art_standalone_dex2oat_cts_tests" />
+ <option name="append-bitness" value="true" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+ <option name="cleanup" value="true" />
+ <option name="push" value="art-gtest-jars-Main.jar->/data/local/tmp/art_standalone_dex2oat_cts_tests/art-gtest-jars-Main.jar" />
+ <option name="push" value="art-gtest-jars-MainStripped.jar->/data/local/tmp/art_standalone_dex2oat_cts_tests/art-gtest-jars-MainStripped.jar" />
+ <option name="push" value="art-gtest-jars-MultiDex.jar->/data/local/tmp/art_standalone_dex2oat_cts_tests/art-gtest-jars-MultiDex.jar" />
+ <option name="push" value="art-gtest-jars-MultiDexModifiedSecondary.jar->/data/local/tmp/art_standalone_dex2oat_cts_tests/art-gtest-jars-MultiDexModifiedSecondary.jar" />
+ <option name="push" value="art-gtest-jars-Nested.jar->/data/local/tmp/art_standalone_dex2oat_cts_tests/art-gtest-jars-Nested.jar" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp/art_standalone_dex2oat_cts_tests" />
+ <option name="module-name" value="art_standalone_dex2oat_cts_tests" />
+ <option name="ld-library-path-32" value="/apex/com.android.art/lib" />
+ <option name="ld-library-path-64" value="/apex/com.android.art/lib64" />
+ </test>
+
+ <!-- When this test is run in a Mainline context (e.g. with `mts-tradefed`), only enable it if
+ one of the Mainline modules below is present on the device used for testing. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+ <!-- ART Mainline Module (internal version). -->
+ <option name="mainline-module-package-name" value="com.google.android.art" />
+ <!-- ART Mainline Module (external (AOSP) version). -->
+ <option name="mainline-module-package-name" value="com.android.art" />
+ </object>
+
+ <!-- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
+</configuration>
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index a3bab85..ee65241 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -546,7 +546,8 @@
check_linkage_conditions_(false),
crash_on_linkage_violation_(false),
compile_individually_(false),
- profile_load_attempted_(false) {}
+ profile_load_attempted_(false),
+ should_report_dex2oat_compilation_(false) {}
~Dex2Oat() {
// Log completion time before deleting the runtime_, because this accesses
@@ -1202,6 +1203,9 @@
thread_count_ = 1;
}
+ PaletteShouldReportDex2oatCompilation(&should_report_dex2oat_compilation_);
+ AssignTrueIfExists(args, M::ForcePaletteCompilationHooks, &should_report_dex2oat_compilation_);
+
ProcessOptions(parser_options.get());
}
@@ -2404,10 +2408,9 @@
class ScopedDex2oatReporting {
public:
- explicit ScopedDex2oatReporting(const Dex2Oat& dex2oat) {
- bool should_report = false;
- PaletteShouldReportDex2oatCompilation(&should_report);
- if (should_report) {
+ explicit ScopedDex2oatReporting(const Dex2Oat& dex2oat) :
+ should_report_(dex2oat.should_report_dex2oat_compilation_) {
+ if (should_report_) {
if (dex2oat.zip_fd_ != -1) {
zip_dup_fd_.reset(DupCloexecOrError(dex2oat.zip_fd_));
if (zip_dup_fd_ < 0) {
@@ -2439,9 +2442,7 @@
~ScopedDex2oatReporting() {
if (!error_reporting_) {
- bool should_report = false;
- PaletteShouldReportDex2oatCompilation(&should_report);
- if (should_report) {
+ if (should_report_) {
PaletteNotifyEndDex2oatCompilation(zip_dup_fd_,
image_dup_fd_,
oat_dup_fd_,
@@ -2466,6 +2467,7 @@
android::base::unique_fd zip_dup_fd_;
android::base::unique_fd image_dup_fd_;
bool error_reporting_ = false;
+ bool should_report_;
};
private:
@@ -2952,6 +2954,9 @@
// Whether or we attempted to load the profile (if given).
bool profile_load_attempted_;
+ // Whether PaletteNotify{Start,End}Dex2oatCompilation should be called.
+ bool should_report_dex2oat_compilation_;
+
DISALLOW_IMPLICIT_CONSTRUCTORS(Dex2Oat);
};
diff --git a/dex2oat/dex2oat_cts_test.cc b/dex2oat/dex2oat_cts_test.cc
new file mode 100644
index 0000000..41c7015
--- /dev/null
+++ b/dex2oat/dex2oat_cts_test.cc
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "dex2oat_environment_test.h"
+
+namespace art {
+
+class Dex2oatCtsTest : public Dex2oatEnvironmentTest {};
+
+// Run dex2oat with --enable-palette-compilation-hooks to force calls to
+// PaletteNotify{Start,End}Dex2oatCompilation.
+TEST_F(Dex2oatCtsTest, CompilationHooks) {
+ const std::string dex_location = GetTestDexFileName("Main");
+ const std::string oat_location = GetScratchDir() + "/base.oat";
+ const std::string vdex_location = GetScratchDir() + "/base.vdex";
+
+ std::vector<std::string> args;
+ args.emplace_back("--dex-file=" + dex_location);
+
+ std::unique_ptr<File> oat_file(OS::CreateEmptyFile(oat_location.c_str()));
+ ASSERT_NE(oat_file, nullptr) << oat_location;
+ args.emplace_back("--oat-fd=" + std::to_string(oat_file->Fd()));
+ args.emplace_back("--oat-location=" + oat_location);
+
+ std::unique_ptr<File> vdex_file(OS::CreateEmptyFile(vdex_location.c_str()));
+ ASSERT_NE(vdex_file, nullptr) << vdex_location;
+ args.emplace_back("--output-vdex-fd=" + std::to_string(vdex_file->Fd()));
+
+ args.emplace_back("--force-palette-compilation-hooks");
+
+ std::string output = "";
+ std::string error_msg;
+ int res = Dex2Oat(args, &output, &error_msg);
+ EXPECT_EQ(res, 0) << error_msg;
+ EXPECT_EQ(oat_file->FlushCloseOrErase(), 0);
+ EXPECT_EQ(vdex_file->FlushCloseOrErase(), 0);
+}
+
+} // namespace art
diff --git a/dex2oat/dex2oat_options.cc b/dex2oat/dex2oat_options.cc
index 6749fc5..b6fa71e 100644
--- a/dex2oat/dex2oat_options.cc
+++ b/dex2oat/dex2oat_options.cc
@@ -437,7 +437,10 @@
.IntoKey(M::ApexVersions)
.Define("--force-jit-zygote")
.WithHelp("Optimizes the app to be executed in an environment that uses JIT Zygote.")
- .IntoKey(M::ForceJitZygote);
+ .IntoKey(M::ForceJitZygote)
+ .Define("--force-palette-compilation-hooks")
+ .WithHelp("Force PaletteNotify{Start,End}Dex2oatCompilation calls.")
+ .IntoKey(M::ForcePaletteCompilationHooks);
AddCompilerOptionsArgumentParserOptions<Dex2oatArgumentMap>(*parser_builder);
diff --git a/dex2oat/dex2oat_options.def b/dex2oat/dex2oat_options.def
index d878088..43a2b22 100644
--- a/dex2oat/dex2oat_options.def
+++ b/dex2oat/dex2oat_options.def
@@ -102,5 +102,6 @@
DEX2OAT_OPTIONS_KEY (std::string, PublicSdk)
DEX2OAT_OPTIONS_KEY (Unit, ForceAllowOjInlines)
DEX2OAT_OPTIONS_KEY (std::string, ApexVersions)
+DEX2OAT_OPTIONS_KEY (Unit, ForcePaletteCompilationHooks)
#undef DEX2OAT_OPTIONS_KEY
diff --git a/libartpalette/Android.bp b/libartpalette/Android.bp
index 51a9dab..1516ec6 100644
--- a/libartpalette/Android.bp
+++ b/libartpalette/Android.bp
@@ -122,7 +122,10 @@
art_cc_defaults {
name: "art_libartpalette_tests_defaults",
srcs: ["apex/palette_test.cc"],
- shared_libs: ["libartpalette"],
+ shared_libs: [
+ "libartpalette",
+ "libnativehelper",
+ ],
}
// Version of ART gtest `art_libartpalette_tests` bundled with the ART APEX on target.
diff --git a/libartpalette/apex/palette_test.cc b/libartpalette/apex/palette_test.cc
index e6018ee..a604998 100644
--- a/libartpalette/apex/palette_test.cc
+++ b/libartpalette/apex/palette_test.cc
@@ -16,8 +16,10 @@
#include "palette/palette.h"
-#include <unistd.h>
+#include <jni.h>
+#include <sys/mman.h>
#include <sys/syscall.h>
+#include <unistd.h>
#include "gtest/gtest.h"
@@ -55,3 +57,37 @@
EXPECT_EQ(PALETTE_STATUS_OK, PaletteTraceEnd());
EXPECT_EQ(PALETTE_STATUS_OK, PaletteTraceIntegerValue("Beans", /*value=*/ 3));
}
+
+TEST_F(PaletteClientTest, Ashmem) {
+#ifndef ART_TARGET_ANDROID
+ GTEST_SKIP() << "ashmem is only supported on Android";
+#else
+ int fd;
+ EXPECT_EQ(PALETTE_STATUS_OK, PaletteAshmemCreateRegion("ashmem-test", 4096, &fd));
+ EXPECT_EQ(PALETTE_STATUS_OK, PaletteAshmemSetProtRegion(fd, PROT_READ | PROT_EXEC));
+ EXPECT_EQ(0, close(fd));
+#endif
+}
+
+TEST_F(PaletteClientTest, JniInvocation) {
+#ifndef ART_TARGET_ANDROID
+ GTEST_SKIP() << "Not starting a VM on host";
+#else
+ bool enabled;
+ EXPECT_EQ(PALETTE_STATUS_OK, PaletteShouldReportJniInvocations(&enabled));
+
+ JavaVMInitArgs init_args;
+ init_args.version = JNI_VERSION_1_6;
+ init_args.nOptions = 0;
+ init_args.options = nullptr;
+ init_args.ignoreUnrecognized = JNI_FALSE;
+ JavaVM* vm = nullptr;
+ JNIEnv* env = nullptr;
+ ASSERT_EQ(JNI_OK, JNI_CreateJavaVM(&vm, &env, &init_args));
+
+ PaletteNotifyBeginJniInvocation(env);
+ PaletteNotifyEndJniInvocation(env);
+
+ vm->DestroyJavaVM();
+#endif
+}