diff options
Diffstat (limited to 'libartpalette')
| -rw-r--r-- | libartpalette/Android.bp | 12 | ||||
| -rw-r--r-- | libartpalette/apex/palette.cc | 13 | ||||
| -rw-r--r-- | libartpalette/apex/palette_test.cc | 92 | ||||
| -rw-r--r-- | libartpalette/include/palette/palette.h | 23 | ||||
| -rw-r--r-- | libartpalette/include/palette/palette_method_list.h | 93 | ||||
| -rw-r--r-- | libartpalette/include/palette/palette_types.h | 2 | ||||
| -rw-r--r-- | libartpalette/libartpalette.map (renamed from libartpalette/libartpalette.map.txt) | 33 | ||||
| -rw-r--r-- | libartpalette/system/palette_fake.cc | 12 |
8 files changed, 211 insertions, 69 deletions
diff --git a/libartpalette/Android.bp b/libartpalette/Android.bp index 37464f0832..e6aae64b64 100644 --- a/libartpalette/Android.bp +++ b/libartpalette/Android.bp @@ -58,6 +58,9 @@ art_cc_library { "libbase_headers", "jni_headers", ], + export_header_lib_headers: [ + "jni_headers", + ], target: { // Targets supporting dlopen build the client library which loads // and binds the methods in the libartpalette-system library. @@ -66,7 +69,7 @@ art_cc_library { runtime_libs: ["libartpalette-system"], srcs: ["apex/palette.cc"], shared_libs: ["liblog"], - version_script: "libartpalette.map.txt", + version_script: "libartpalette.map", }, host_linux: { header_libs: ["libbase_headers"], @@ -77,7 +80,7 @@ art_cc_library { "liblog", ], }, - version_script: "libartpalette.map.txt", + version_script: "libartpalette.map", }, // Targets without support for dlopen just use the sources for // the system library which actually implements functionality. @@ -115,6 +118,11 @@ art_cc_defaults { "libartpalette", "libnativehelper", ], + target: { + android: { + static_libs: ["libmodules-utils-build"], + }, + }, } // Version of ART gtest `art_libartpalette_tests` bundled with the ART APEX on target. diff --git a/libartpalette/apex/palette.cc b/libartpalette/apex/palette.cc index 75a3878028..dadb4702b6 100644 --- a/libartpalette/apex/palette.cc +++ b/libartpalette/apex/palette.cc @@ -110,6 +110,8 @@ PaletteLoader::PaletteLoader() : extern "C" { +// Methods in version 1 API, corresponding to SDK level 31. + palette_status_t PaletteSchedSetPriority(int32_t tid, int32_t java_priority) { PaletteSchedSetPriorityMethod m = PaletteLoader::Instance().GetPaletteSchedSetPriorityMethod(); return m(tid, java_priority); @@ -218,6 +220,8 @@ palette_status_t PaletteNotifyEndJniInvocation(JNIEnv* env) { return m(env); } +// Methods in version 2 API, corresponding to SDK level 33. + palette_status_t PaletteReportLockContention(JNIEnv* env, int32_t wait_ms, const char* filename, @@ -242,4 +246,13 @@ palette_status_t PaletteReportLockContention(JNIEnv* env, thread_name); } +// Methods in version 3 API, corresponding to SDK level 34. + +palette_status_t PaletteSetTaskProfiles(int32_t tid, + const char* const profiles[], + size_t profiles_len) { + PaletteSetTaskProfilesMethod m = PaletteLoader::Instance().GetPaletteSetTaskProfilesMethod(); + return m(tid, profiles, profiles_len); +} + } // extern "C" diff --git a/libartpalette/apex/palette_test.cc b/libartpalette/apex/palette_test.cc index 0bcc09329b..63072c491b 100644 --- a/libartpalette/apex/palette_test.cc +++ b/libartpalette/apex/palette_test.cc @@ -21,6 +21,14 @@ #include <sys/syscall.h> #include <unistd.h> +#include <filesystem> + +#ifdef ART_TARGET_ANDROID +#include "android-modules-utils/sdk_level.h" +#include "android/api-level.h" +#endif + +#include "base/common_art_test.h" #include "gtest/gtest.h" namespace { @@ -33,6 +41,17 @@ pid_t GetTid() { #endif // __BIONIC__ } +#ifdef ART_TARGET_ANDROID +bool PaletteSetTaskProfilesIsSupported(palette_status_t res) { + if (android::modules::sdklevel::IsAtLeastU()) { + return true; + } + EXPECT_EQ(PALETTE_STATUS_NOT_SUPPORTED, res) + << "Device API level: " << android_get_device_api_level(); + return false; +} +#endif + } // namespace class PaletteClientTest : public testing::Test {}; @@ -69,23 +88,27 @@ TEST_F(PaletteClientTest, Ashmem) { #endif } -TEST_F(PaletteClientTest, JniInvocation) { -#ifndef ART_TARGET_ANDROID - // On host we need to set up a boot classpath and pass it in here. Let's not - // bother since this test is only for native API coverage on target. - GTEST_SKIP() << "Will only spin up a VM on Android"; -#else +class PaletteClientJniTest : public art::CommonArtTest {}; + +TEST_F(PaletteClientJniTest, JniInvocation) { bool enabled; EXPECT_EQ(PALETTE_STATUS_OK, PaletteShouldReportJniInvocations(&enabled)); - JavaVMInitArgs vm_args; + std::string boot_class_path_string = + GetClassPathOption("-Xbootclasspath:", GetLibCoreDexFileNames()); + std::string boot_class_path_locations_string = + GetClassPathOption("-Xbootclasspath-locations:", GetLibCoreDexLocations()); + JavaVMOption options[] = { - {.optionString = "-verbose:jni", .extraInfo = nullptr}, + {.optionString = boot_class_path_string.c_str(), .extraInfo = nullptr}, + {.optionString = boot_class_path_locations_string.c_str(), .extraInfo = nullptr}, + }; + JavaVMInitArgs vm_args = { + .version = JNI_VERSION_1_6, + .nOptions = std::size(options), + .options = options, + .ignoreUnrecognized = JNI_TRUE, }; - vm_args.version = JNI_VERSION_1_6; - vm_args.nOptions = std::size(options); - vm_args.options = options; - vm_args.ignoreUnrecognized = JNI_TRUE; JavaVM* jvm = nullptr; JNIEnv* env = nullptr; @@ -96,5 +119,50 @@ TEST_F(PaletteClientTest, JniInvocation) { PaletteNotifyEndJniInvocation(env); EXPECT_EQ(JNI_OK, jvm->DestroyJavaVM()); +} + +TEST_F(PaletteClientTest, SetTaskProfiles) { +#ifndef ART_TARGET_ANDROID + GTEST_SKIP() << "SetTaskProfiles is only supported on Android"; +#else + if (!std::filesystem::exists("/sys/fs/cgroup/cgroup.controllers")) { + // This is intended to detect ART chroot setups, where SetTaskProfiles won't work. + GTEST_SKIP() << "Kernel cgroup support missing"; + } + + const char* profiles[] = {"ProcessCapacityHigh", "TimerSlackNormal"}; + palette_status_t res = PaletteSetTaskProfiles(GetTid(), &profiles[0], 2); + if (PaletteSetTaskProfilesIsSupported(res)) { + // SetTaskProfiles will only work fully if we run as root. Otherwise it'll + // return false which is mapped to PALETTE_STATUS_FAILED_CHECK_LOG. + if (getuid() == 0) { + EXPECT_EQ(PALETTE_STATUS_OK, res); + } else { + EXPECT_EQ(PALETTE_STATUS_FAILED_CHECK_LOG, res); + } + } +#endif +} + +TEST_F(PaletteClientTest, SetTaskProfilesCpp) { +#ifndef ART_TARGET_ANDROID + GTEST_SKIP() << "SetTaskProfiles is only supported on Android"; +#else + if (!std::filesystem::exists("/sys/fs/cgroup/cgroup.controllers")) { + // This is intended to detect ART chroot setups, where SetTaskProfiles won't work. + GTEST_SKIP() << "Kernel cgroup support missing"; + } + + std::vector<std::string> profiles = {"ProcessCapacityHigh", "TimerSlackNormal"}; + palette_status_t res = PaletteSetTaskProfiles(GetTid(), profiles); + if (PaletteSetTaskProfilesIsSupported(res)) { + // SetTaskProfiles will only work fully if we run as root. Otherwise it'll + // return false which is mapped to PALETTE_STATUS_FAILED_CHECK_LOG. + if (getuid() == 0) { + EXPECT_EQ(PALETTE_STATUS_OK, res); + } else { + EXPECT_EQ(PALETTE_STATUS_FAILED_CHECK_LOG, res); + } + } #endif } diff --git a/libartpalette/include/palette/palette.h b/libartpalette/include/palette/palette.h index 3e12b141b6..e9e47e951f 100644 --- a/libartpalette/include/palette/palette.h +++ b/libartpalette/include/palette/palette.h @@ -17,11 +17,11 @@ #ifndef ART_LIBARTPALETTE_INCLUDE_PALETTE_PALETTE_H_ #define ART_LIBARTPALETTE_INCLUDE_PALETTE_PALETTE_H_ +#include <sys/cdefs.h> + #include "palette_types.h" -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus +__BEGIN_DECLS // Palette method signatures are defined in palette_method_list.h. @@ -31,8 +31,25 @@ extern "C" { PALETTE_METHOD_LIST(PALETTE_METHOD_DECLARATION) #undef PALETTE_METHOD_DECLARATION +__END_DECLS + +// C++ wrappers + #ifdef __cplusplus + +#include <string> +#include <vector> + +static inline palette_status_t PaletteSetTaskProfiles(int tid, + const std::vector<std::string>& profiles) { + std::vector<const char*> profile_c_strs; + profile_c_strs.reserve(profiles.size()); + for (const std::string& p : profiles) { + profile_c_strs.push_back(p.c_str()); + } + return PaletteSetTaskProfiles(tid, profile_c_strs.data(), profile_c_strs.size()); } + #endif // __cplusplus #endif // ART_LIBARTPALETTE_INCLUDE_PALETTE_PALETTE_H_ diff --git a/libartpalette/include/palette/palette_method_list.h b/libartpalette/include/palette/palette_method_list.h index 066f24fb54..e22e828a60 100644 --- a/libartpalette/include/palette/palette_method_list.h +++ b/libartpalette/include/palette/palette_method_list.h @@ -23,45 +23,58 @@ #include "jni.h" -// Methods in version 1 API -#define PALETTE_METHOD_LIST(M) \ - M(PaletteSchedSetPriority, int32_t tid, int32_t java_priority) \ - M(PaletteSchedGetPriority, int32_t tid, /*out*/int32_t* java_priority) \ - M(PaletteWriteCrashThreadStacks, const char* stacks, size_t stacks_len) \ - M(PaletteTraceEnabled, /*out*/bool* enabled) \ - M(PaletteTraceBegin, const char* name) \ - M(PaletteTraceEnd) \ - M(PaletteTraceIntegerValue, const char* name, int32_t value) \ - M(PaletteAshmemCreateRegion, const char* name, size_t size, int* fd) \ - M(PaletteAshmemSetProtRegion, int, int) \ - /* Create the staging directory for on-device signing. */ \ - /* `staging_dir` is updated to point to a constant string in the */ \ - /* palette implementation. */ \ - /* This method is not thread-safe. */ \ - M(PaletteCreateOdrefreshStagingDirectory, /*out*/const char** staging_dir)\ - M(PaletteShouldReportDex2oatCompilation, bool*) \ - M(PaletteNotifyStartDex2oatCompilation, int source_fd, \ - int art_fd, \ - int oat_fd, \ - int vdex_fd) \ - M(PaletteNotifyEndDex2oatCompilation, int source_fd, \ - int art_fd, \ - int oat_fd, \ - int vdex_fd) \ - M(PaletteNotifyDexFileLoaded, const char* path) \ - M(PaletteNotifyOatFileLoaded, const char* path) \ - M(PaletteShouldReportJniInvocations, bool*) \ - M(PaletteNotifyBeginJniInvocation, JNIEnv* env) \ - M(PaletteNotifyEndJniInvocation, JNIEnv* env) \ - M(PaletteReportLockContention, JNIEnv* env, \ - int32_t wait_ms, \ - const char* filename, \ - int32_t line_number, \ - const char* method_name, \ - const char* owner_filename, \ - int32_t owner_line_number, \ - const char* owner_method_name, \ - const char* proc_name, \ - const char* thread_name) \ +#define PALETTE_METHOD_LIST(M) \ + /* Methods in version 1 API, corresponding to SDK level 31. */ \ + M(PaletteSchedSetPriority, int32_t tid, int32_t java_priority) \ + M(PaletteSchedGetPriority, int32_t tid, /*out*/ int32_t* java_priority) \ + M(PaletteWriteCrashThreadStacks, const char* stacks, size_t stacks_len) \ + M(PaletteTraceEnabled, /*out*/ bool* enabled) \ + M(PaletteTraceBegin, const char* name) \ + M(PaletteTraceEnd) \ + M(PaletteTraceIntegerValue, const char* name, int32_t value) \ + M(PaletteAshmemCreateRegion, const char* name, size_t size, int* fd) \ + M(PaletteAshmemSetProtRegion, int, int) \ + /* Create the staging directory for on-device signing. */ \ + /* `staging_dir` is updated to point to a constant string in the */ \ + /* palette implementation. */ \ + /* This method is not thread-safe. */ \ + M(PaletteCreateOdrefreshStagingDirectory, /*out*/ const char** staging_dir) \ + M(PaletteShouldReportDex2oatCompilation, bool*) \ + M(PaletteNotifyStartDex2oatCompilation, int source_fd, int art_fd, int oat_fd, int vdex_fd) \ + M(PaletteNotifyEndDex2oatCompilation, int source_fd, int art_fd, int oat_fd, int vdex_fd) \ + M(PaletteNotifyDexFileLoaded, const char* path) \ + M(PaletteNotifyOatFileLoaded, const char* path) \ + M(PaletteShouldReportJniInvocations, bool*) \ + M(PaletteNotifyBeginJniInvocation, JNIEnv* env) \ + M(PaletteNotifyEndJniInvocation, JNIEnv* env) \ + \ + /* Methods in version 2 API, corresponding to SDK level 33. */ \ + M(PaletteReportLockContention, \ + JNIEnv* env, \ + int32_t wait_ms, \ + const char* filename, \ + int32_t line_number, \ + const char* method_name, \ + const char* owner_filename, \ + int32_t owner_line_number, \ + const char* owner_method_name, \ + const char* proc_name, \ + const char* thread_name) \ + \ + /* Methods in version 3 API, corresponding to SDK level 34. */ \ + \ + /* Calls through to SetTaskProfiles in libprocessgroup to set the */ \ + /* [task profile](https:/-/source.android.com/docs/core/perf/cgroups#task-profiles-file) */ \ + /* for the given thread id. */ \ + /* */ \ + /* @param tid The thread id. */ \ + /* @param profiles An array of pointers to C strings that list the task profiles to set. */ \ + /* @param profiles_len The number of elements in profiles. */ \ + /* @return PALETTE_STATUS_OK if the call succeeded. */ \ + /* PALETTE_STATUS_FAILED_CHECK_LOG if it failed. */ \ + /* PALETTE_STATUS_NOT_SUPPORTED if the implementation no longer supports this */ \ + /* call. This can happen at any future SDK level since this function wraps an */ \ + /* internal unstable API. */ \ + M(PaletteSetTaskProfiles, int32_t tid, const char* const profiles[], size_t profiles_len) #endif // ART_LIBARTPALETTE_INCLUDE_PALETTE_PALETTE_METHOD_LIST_H_ diff --git a/libartpalette/include/palette/palette_types.h b/libartpalette/include/palette/palette_types.h index 905a341d4d..3c0254479f 100644 --- a/libartpalette/include/palette/palette_types.h +++ b/libartpalette/include/palette/palette_types.h @@ -23,7 +23,7 @@ extern "C" { #endif // __cplusplus -typedef int32_t palette_status_t; +using palette_status_t = int32_t; // Palette function return value when the function completed successfully. #define PALETTE_STATUS_OK ((palette_status_t) 0) diff --git a/libartpalette/libartpalette.map.txt b/libartpalette/libartpalette.map index 6401010abe..11824cb46d 100644 --- a/libartpalette/libartpalette.map.txt +++ b/libartpalette/libartpalette.map @@ -14,12 +14,12 @@ # limitations under the License. # -LIBARTPALETTE_1 { +LIBARTPALETTE_1 { # introduced=31 global: # --- VERSION 01 API --- PaletteSchedSetPriority; # apex PaletteSchedGetPriority; # apex - PaletteWriteCrashThreadStacks; #apex + PaletteWriteCrashThreadStacks; # apex PaletteTraceEnabled; # apex PaletteTraceBegin; # apex PaletteTraceEnd; # apex @@ -27,16 +27,27 @@ LIBARTPALETTE_1 { PaletteAshmemCreateRegion; # apex PaletteAshmemSetProtRegion; # apex PaletteCreateOdrefreshStagingDirectory; # apex - PaletteShouldReportDex2oatCompilation; #apex - PaletteNotifyStartDex2oatCompilation; #apex - PaletteNotifyEndDex2oatCompilation; #apex - PaletteNotifyDexFileLoaded; #apex - PaletteNotifyOatFileLoaded; #apex - PaletteShouldReportJniInvocations; #apex - PaletteNotifyBeginJniInvocation; #apex - PaletteNotifyEndJniInvocation; #apex - PaletteReportLockContention; #apex + PaletteShouldReportDex2oatCompilation; # apex + PaletteNotifyStartDex2oatCompilation; # apex + PaletteNotifyEndDex2oatCompilation; # apex + PaletteNotifyDexFileLoaded; # apex + PaletteNotifyOatFileLoaded; # apex + PaletteShouldReportJniInvocations; # apex + PaletteNotifyBeginJniInvocation; # apex + PaletteNotifyEndJniInvocation; # apex local: *; }; + +LIBARTPALETTE_2 { # introduced=33 + global: + # --- VERSION 02 API --- + PaletteReportLockContention; # apex +} LIBARTPALETTE_1; + +LIBARTPALETTE_3 { # introduced=UpsideDownCake + global: + # --- VERSION 03 API --- + PaletteSetTaskProfiles; # apex +} LIBARTPALETTE_2; diff --git a/libartpalette/system/palette_fake.cc b/libartpalette/system/palette_fake.cc index bbf8f2dd8c..743a4db37e 100644 --- a/libartpalette/system/palette_fake.cc +++ b/libartpalette/system/palette_fake.cc @@ -25,6 +25,8 @@ #include "palette_system.h" +// Methods in version 1 API, corresponding to SDK level 31. + // Cached thread priority for testing. No thread priorities are ever affected. static std::mutex g_tid_priority_map_mutex; static std::map<int32_t, int32_t> g_tid_priority_map; @@ -129,6 +131,8 @@ palette_status_t PaletteNotifyEndJniInvocation(JNIEnv* env ATTRIBUTE_UNUSED) { return PALETTE_STATUS_OK; } +// Methods in version 2 API, corresponding to SDK level 33. + palette_status_t PaletteReportLockContention(JNIEnv* env ATTRIBUTE_UNUSED, int32_t wait_ms ATTRIBUTE_UNUSED, const char* filename ATTRIBUTE_UNUSED, @@ -141,3 +145,11 @@ palette_status_t PaletteReportLockContention(JNIEnv* env ATTRIBUTE_UNUSED, const char* thread_name ATTRIBUTE_UNUSED) { return PALETTE_STATUS_OK; } + +// Methods in version 3 API, corresponding to SDK level 34. + +palette_status_t PaletteSetTaskProfiles(int32_t tid ATTRIBUTE_UNUSED, + const char* const profiles[] ATTRIBUTE_UNUSED, + size_t profiles_len ATTRIBUTE_UNUSED) { + return PALETTE_STATUS_OK; +} |