1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "palette/palette.h"
18
19 #include <dlfcn.h>
20 #include <stdlib.h>
21
22 #include <android/log.h>
23 #include <android-base/macros.h>
24
25 namespace {
26
27 // Logging tag.
28 static constexpr const char* kLogTag = "libartpalette";
29
30 // Name of the palette library present in the /system partition.
31 static constexpr const char* kPaletteSystemLibrary = "libartpalette-system.so";
32
33 // Generic method used when a dynamically loaded palette instance does not
34 // support a method.
PaletteMethodNotSupported()35 palette_status_t PaletteMethodNotSupported() {
36 return PALETTE_STATUS_NOT_SUPPORTED;
37 }
38
39 // Declare type aliases for pointers to each function in the interface.
40 #define PALETTE_METHOD_TYPE_ALIAS(Name, ...) \
41 using Name ## Method = palette_status_t(*)(__VA_ARGS__);
42 PALETTE_METHOD_LIST(PALETTE_METHOD_TYPE_ALIAS)
43 #undef PALETTE_METHOD_TYPE_ALIAS
44
45 // Singleton class responsible for dynamically loading the palette library and
46 // binding functions there to method pointers.
47 class PaletteLoader {
48 public:
Instance()49 static PaletteLoader& Instance() {
50 static PaletteLoader instance;
51 return instance;
52 }
53
54 // Accessor methods to get instances of palette methods.
55 #define PALETTE_LOADER_METHOD_ACCESSOR(Name, ...) \
56 Name ## Method Get ## Name ## Method() const { return Name ## Method ## _; }
57 PALETTE_METHOD_LIST(PALETTE_LOADER_METHOD_ACCESSOR)
58 #undef PALETTE_LOADER_METHOD_ACCESSOR
59
60 private:
61 PaletteLoader();
62
63 static void* OpenLibrary();
64 static void* GetMethod(void* palette_lib, const char* name);
65
66 // Handle to the palette library from dlopen().
67 void* palette_lib_;
68
69 // Fields to store pointers to palette methods.
70 #define PALETTE_LOADER_METHOD_FIELD(Name, ...) \
71 const Name ## Method Name ## Method ## _;
72 PALETTE_METHOD_LIST(PALETTE_LOADER_METHOD_FIELD)
73 #undef PALETTE_LOADER_METHOD_FIELD
74
75 DISALLOW_COPY_AND_ASSIGN(PaletteLoader);
76 };
77
OpenLibrary()78 void* PaletteLoader::OpenLibrary() {
79 void* handle = dlopen(kPaletteSystemLibrary, RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE);
80 if (handle == nullptr) {
81 // dlerror message includes details of error and file being opened.
82 __android_log_assert(nullptr, kLogTag, "%s", dlerror());
83 }
84 return handle;
85 }
86
GetMethod(void * palette_lib,const char * name)87 void* PaletteLoader::GetMethod(void* palette_lib, const char* name) {
88 void* method = nullptr;
89 if (palette_lib != nullptr) {
90 method = dlsym(palette_lib, name);
91 }
92 if (method == nullptr) {
93 return reinterpret_cast<void*>(PaletteMethodNotSupported);
94 }
95 // TODO(oth): consider new GetMethodSignature() in the Palette API which
96 // would allow checking the validity of the type signatures.
97 return method;
98 }
99
PaletteLoader()100 PaletteLoader::PaletteLoader() :
101 palette_lib_(OpenLibrary())
102 #define PALETTE_LOADER_BIND_METHOD(Name, ...) \
103 , Name ## Method ## _(reinterpret_cast<Name ## Method>(GetMethod(palette_lib_, #Name)))
104 PALETTE_METHOD_LIST(PALETTE_LOADER_BIND_METHOD)
105 #undef PALETTE_LOADER_BIND_METHOD
106 {
107 }
108
109 } // namespace
110
111 extern "C" {
112
113 // Methods in version 1 API, corresponding to SDK level 31.
114
PaletteSchedSetPriority(int32_t tid,int32_t java_priority)115 palette_status_t PaletteSchedSetPriority(int32_t tid, int32_t java_priority) {
116 PaletteSchedSetPriorityMethod m = PaletteLoader::Instance().GetPaletteSchedSetPriorityMethod();
117 return m(tid, java_priority);
118 }
119
PaletteSchedGetPriority(int32_t tid,int32_t * java_priority)120 palette_status_t PaletteSchedGetPriority(int32_t tid, /*out*/int32_t* java_priority) {
121 PaletteSchedGetPriorityMethod m = PaletteLoader::Instance().GetPaletteSchedGetPriorityMethod();
122 return m(tid, java_priority);
123 }
124
PaletteWriteCrashThreadStacks(const char * stack,size_t stack_len)125 palette_status_t PaletteWriteCrashThreadStacks(/*in*/const char* stack, size_t stack_len) {
126 PaletteWriteCrashThreadStacksMethod m =
127 PaletteLoader::Instance().GetPaletteWriteCrashThreadStacksMethod();
128 return m(stack, stack_len);
129 }
130
PaletteTraceEnabled(bool * enabled)131 palette_status_t PaletteTraceEnabled(/*out*/bool* enabled) {
132 PaletteTraceEnabledMethod m = PaletteLoader::Instance().GetPaletteTraceEnabledMethod();
133 return m(enabled);
134 }
135
PaletteTraceBegin(const char * name)136 palette_status_t PaletteTraceBegin(/*in*/const char* name) {
137 PaletteTraceBeginMethod m = PaletteLoader::Instance().GetPaletteTraceBeginMethod();
138 return m(name);
139 }
140
PaletteTraceEnd()141 palette_status_t PaletteTraceEnd() {
142 PaletteTraceEndMethod m = PaletteLoader::Instance().GetPaletteTraceEndMethod();
143 return m();
144 }
145
PaletteTraceIntegerValue(const char * name,int32_t value)146 palette_status_t PaletteTraceIntegerValue(/*in*/const char* name, int32_t value) {
147 PaletteTraceIntegerValueMethod m = PaletteLoader::Instance().GetPaletteTraceIntegerValueMethod();
148 return m(name, value);
149 }
150
PaletteAshmemCreateRegion(const char * name,size_t size,int * fd)151 palette_status_t PaletteAshmemCreateRegion(const char* name, size_t size, int* fd) {
152 PaletteAshmemCreateRegionMethod m =
153 PaletteLoader::Instance().GetPaletteAshmemCreateRegionMethod();
154 return m(name, size, fd);
155 }
156
PaletteAshmemSetProtRegion(int fd,int prot)157 palette_status_t PaletteAshmemSetProtRegion(int fd, int prot) {
158 PaletteAshmemSetProtRegionMethod m =
159 PaletteLoader::Instance().GetPaletteAshmemSetProtRegionMethod();
160 return m(fd, prot);
161 }
162
PaletteCreateOdrefreshStagingDirectory(const char ** staging_dir)163 palette_status_t PaletteCreateOdrefreshStagingDirectory(const char** staging_dir) {
164 PaletteCreateOdrefreshStagingDirectoryMethod m =
165 PaletteLoader::Instance().GetPaletteCreateOdrefreshStagingDirectoryMethod();
166 return m(staging_dir);
167 }
168
PaletteShouldReportDex2oatCompilation(bool * value)169 palette_status_t PaletteShouldReportDex2oatCompilation(bool* value) {
170 PaletteShouldReportDex2oatCompilationMethod m =
171 PaletteLoader::Instance().GetPaletteShouldReportDex2oatCompilationMethod();
172 return m(value);
173 }
174
PaletteNotifyStartDex2oatCompilation(int source_fd,int art_fd,int oat_fd,int vdex_fd)175 palette_status_t PaletteNotifyStartDex2oatCompilation(int source_fd,
176 int art_fd,
177 int oat_fd,
178 int vdex_fd) {
179 PaletteNotifyStartDex2oatCompilationMethod m =
180 PaletteLoader::Instance().GetPaletteNotifyStartDex2oatCompilationMethod();
181 return m(source_fd, art_fd, oat_fd, vdex_fd);
182 }
183
PaletteNotifyEndDex2oatCompilation(int source_fd,int art_fd,int oat_fd,int vdex_fd)184 palette_status_t PaletteNotifyEndDex2oatCompilation(int source_fd,
185 int art_fd,
186 int oat_fd,
187 int vdex_fd) {
188 PaletteNotifyEndDex2oatCompilationMethod m =
189 PaletteLoader::Instance().GetPaletteNotifyEndDex2oatCompilationMethod();
190 return m(source_fd, art_fd, oat_fd, vdex_fd);
191 }
192
PaletteNotifyDexFileLoaded(const char * path)193 palette_status_t PaletteNotifyDexFileLoaded(const char* path) {
194 PaletteNotifyDexFileLoadedMethod m =
195 PaletteLoader::Instance().GetPaletteNotifyDexFileLoadedMethod();
196 return m(path);
197 }
198
PaletteNotifyOatFileLoaded(const char * path)199 palette_status_t PaletteNotifyOatFileLoaded(const char* path) {
200 PaletteNotifyOatFileLoadedMethod m =
201 PaletteLoader::Instance().GetPaletteNotifyOatFileLoadedMethod();
202 return m(path);
203 }
204
PaletteShouldReportJniInvocations(bool * value)205 palette_status_t PaletteShouldReportJniInvocations(bool* value) {
206 PaletteShouldReportJniInvocationsMethod m =
207 PaletteLoader::Instance().GetPaletteShouldReportJniInvocationsMethod();
208 return m(value);
209 }
210
PaletteNotifyBeginJniInvocation(JNIEnv * env)211 palette_status_t PaletteNotifyBeginJniInvocation(JNIEnv* env) {
212 PaletteNotifyBeginJniInvocationMethod m =
213 PaletteLoader::Instance().GetPaletteNotifyBeginJniInvocationMethod();
214 return m(env);
215 }
216
PaletteNotifyEndJniInvocation(JNIEnv * env)217 palette_status_t PaletteNotifyEndJniInvocation(JNIEnv* env) {
218 PaletteNotifyEndJniInvocationMethod m =
219 PaletteLoader::Instance().GetPaletteNotifyEndJniInvocationMethod();
220 return m(env);
221 }
222
223 // Methods in version 2 API, corresponding to SDK level 33.
224
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)225 palette_status_t PaletteReportLockContention(JNIEnv* env,
226 int32_t wait_ms,
227 const char* filename,
228 int32_t line_number,
229 const char* method_name,
230 const char* owner_filename,
231 int32_t owner_line_number,
232 const char* owner_method_name,
233 const char* proc_name,
234 const char* thread_name) {
235 PaletteReportLockContentionMethod m =
236 PaletteLoader::Instance().GetPaletteReportLockContentionMethod();
237 return m(env,
238 wait_ms,
239 filename,
240 line_number,
241 method_name,
242 owner_filename,
243 owner_line_number,
244 owner_method_name,
245 proc_name,
246 thread_name);
247 }
248
249 // Methods in version 3 API, corresponding to SDK level 34.
250
PaletteSetTaskProfiles(int32_t tid,const char * const profiles[],size_t profiles_len)251 palette_status_t PaletteSetTaskProfiles(int32_t tid,
252 const char* const profiles[],
253 size_t profiles_len) {
254 PaletteSetTaskProfilesMethod m = PaletteLoader::Instance().GetPaletteSetTaskProfilesMethod();
255 return m(tid, profiles, profiles_len);
256 }
257
258 } // extern "C"
259