Home | History | Annotate | Download | only in apex
      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