summaryrefslogtreecommitdiff
path: root/libartpalette
diff options
context:
space:
mode:
Diffstat (limited to 'libartpalette')
-rw-r--r--libartpalette/Android.bp12
-rw-r--r--libartpalette/apex/palette.cc13
-rw-r--r--libartpalette/apex/palette_test.cc92
-rw-r--r--libartpalette/include/palette/palette.h23
-rw-r--r--libartpalette/include/palette/palette_method_list.h93
-rw-r--r--libartpalette/include/palette/palette_types.h2
-rw-r--r--libartpalette/libartpalette.map (renamed from libartpalette/libartpalette.map.txt)33
-rw-r--r--libartpalette/system/palette_fake.cc12
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;
+}