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. 35 enum PaletteStatus PaletteMethodNotSupported() { 36 return PaletteStatus::kNotSupported; 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 = PaletteStatus(*)(__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: 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 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 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 sanity checking the type signatures. 97 return method; 98 } 99 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 enum PaletteStatus PaletteGetVersion(/*out*/int32_t* version) { 114 PaletteGetVersionMethod m = PaletteLoader::Instance().GetPaletteGetVersionMethod(); 115 return m(version); 116 } 117 118 enum PaletteStatus PaletteSchedSetPriority(int32_t tid, int32_t java_priority) { 119 PaletteSchedSetPriorityMethod m = PaletteLoader::Instance().GetPaletteSchedSetPriorityMethod(); 120 return m(tid, java_priority); 121 } 122 123 enum PaletteStatus PaletteSchedGetPriority(int32_t tid, /*out*/int32_t* java_priority) { 124 PaletteSchedGetPriorityMethod m = PaletteLoader::Instance().GetPaletteSchedGetPriorityMethod(); 125 return m(tid, java_priority); 126 } 127 128 enum PaletteStatus PaletteWriteCrashThreadStacks(/*in*/const char* stack, size_t stack_len) { 129 PaletteWriteCrashThreadStacksMethod m = 130 PaletteLoader::Instance().GetPaletteWriteCrashThreadStacksMethod(); 131 return m(stack, stack_len); 132 } 133 134 enum PaletteStatus PaletteTraceEnabled(/*out*/int32_t* enabled) { 135 PaletteTraceEnabledMethod m = PaletteLoader::Instance().GetPaletteTraceEnabledMethod(); 136 return m(enabled); 137 } 138 139 enum PaletteStatus PaletteTraceBegin(/*in*/const char* name) { 140 PaletteTraceBeginMethod m = PaletteLoader::Instance().GetPaletteTraceBeginMethod(); 141 return m(name); 142 } 143 144 enum PaletteStatus PaletteTraceEnd() { 145 PaletteTraceEndMethod m = PaletteLoader::Instance().GetPaletteTraceEndMethod(); 146 return m(); 147 } 148 149 enum PaletteStatus PaletteTraceIntegerValue(/*in*/const char* name, int32_t value) { 150 PaletteTraceIntegerValueMethod m = PaletteLoader::Instance().GetPaletteTraceIntegerValueMethod(); 151 return m(name, value); 152 } 153 154 } // extern "C" 155