summaryrefslogtreecommitdiff
path: root/libartpalette/apex/palette.cc
blob: 71fd39ddb4270a53ea63d33d12fe6577f3c05303 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "palette/palette.h"

#include <dlfcn.h>
#include <stdlib.h>

#include <android/log.h>
#include <android-base/macros.h>

namespace {

// Logging tag.
static constexpr const char* kLogTag = "libartpalette";

// Name of the palette library present in the /system partition.
static constexpr const char* kPaletteSystemLibrary = "libartpalette-system.so";

// Generic method used when a dynamically loaded palette instance does not
// support a method.
palette_status_t PaletteMethodNotSupported() {
  return PALETTE_STATUS_NOT_SUPPORTED;
}

// Declare type aliases for pointers to each function in the interface.
#define PALETTE_METHOD_TYPE_ALIAS(Name, ...) \
  using Name ## Method = palette_status_t(*)(__VA_ARGS__);
PALETTE_METHOD_LIST(PALETTE_METHOD_TYPE_ALIAS)
#undef PALETTE_METHOD_TYPE_ALIAS

// Singleton class responsible for dynamically loading the palette library and
// binding functions there to method pointers.
class PaletteLoader {
 public:
  static PaletteLoader& Instance() {
    static PaletteLoader instance;
    return instance;
  }

  // Accessor methods to get instances of palette methods.
#define PALETTE_LOADER_METHOD_ACCESSOR(Name, ...)                       \
  Name ## Method Get ## Name ## Method() const { return Name ## Method ## _; }
PALETTE_METHOD_LIST(PALETTE_LOADER_METHOD_ACCESSOR)
#undef PALETTE_LOADER_METHOD_ACCESSOR

 private:
  PaletteLoader();

  static void* OpenLibrary();
  static void* GetMethod(void* palette_lib, const char* name);

  // Handle to the palette library from dlopen().
  void* palette_lib_;

  // Fields to store pointers to palette methods.
#define PALETTE_LOADER_METHOD_FIELD(Name, ...) \
  const Name ## Method Name ## Method ## _;
  PALETTE_METHOD_LIST(PALETTE_LOADER_METHOD_FIELD)
#undef PALETTE_LOADER_METHOD_FIELD

  DISALLOW_COPY_AND_ASSIGN(PaletteLoader);
};

void* PaletteLoader::OpenLibrary() {
  void* handle = dlopen(kPaletteSystemLibrary, RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE);
  if (handle == nullptr) {
    // dlerror message includes details of error and file being opened.
    __android_log_assert(nullptr, kLogTag, "%s", dlerror());
  }
  return handle;
}

void* PaletteLoader::GetMethod(void* palette_lib, const char* name) {
  void* method = nullptr;
  if (palette_lib != nullptr) {
    method = dlsym(palette_lib, name);
  }
  if (method == nullptr) {
    return reinterpret_cast<void*>(PaletteMethodNotSupported);
  }
  // TODO(oth): consider new GetMethodSignature() in the Palette API which
  // would allow checking the validity of the type signatures.
  return method;
}

PaletteLoader::PaletteLoader() :
    palette_lib_(OpenLibrary())
#define PALETTE_LOADER_BIND_METHOD(Name, ...)                           \
    , Name ## Method ## _(reinterpret_cast<Name ## Method>(GetMethod(palette_lib_, #Name)))
    PALETTE_METHOD_LIST(PALETTE_LOADER_BIND_METHOD)
#undef PALETTE_LOADER_BIND_METHOD
{
}

}  // namespace

extern "C" {

palette_status_t PaletteSchedSetPriority(int32_t tid, int32_t java_priority) {
  PaletteSchedSetPriorityMethod m = PaletteLoader::Instance().GetPaletteSchedSetPriorityMethod();
  return m(tid, java_priority);
}

palette_status_t PaletteSchedGetPriority(int32_t tid, /*out*/int32_t* java_priority) {
  PaletteSchedGetPriorityMethod m = PaletteLoader::Instance().GetPaletteSchedGetPriorityMethod();
  return m(tid, java_priority);
}

palette_status_t PaletteWriteCrashThreadStacks(/*in*/const char* stack, size_t stack_len) {
  PaletteWriteCrashThreadStacksMethod m =
      PaletteLoader::Instance().GetPaletteWriteCrashThreadStacksMethod();
  return m(stack, stack_len);
}

palette_status_t PaletteTraceEnabled(/*out*/bool* enabled) {
  PaletteTraceEnabledMethod m = PaletteLoader::Instance().GetPaletteTraceEnabledMethod();
  return m(enabled);
}

palette_status_t PaletteTraceBegin(/*in*/const char* name) {
  PaletteTraceBeginMethod m = PaletteLoader::Instance().GetPaletteTraceBeginMethod();
  return m(name);
}

palette_status_t PaletteTraceEnd() {
  PaletteTraceEndMethod m = PaletteLoader::Instance().GetPaletteTraceEndMethod();
  return m();
}

palette_status_t PaletteTraceIntegerValue(/*in*/const char* name, int32_t value) {
  PaletteTraceIntegerValueMethod m = PaletteLoader::Instance().GetPaletteTraceIntegerValueMethod();
  return m(name, value);
}

palette_status_t PaletteAshmemCreateRegion(const char* name, size_t size, int* fd) {
  PaletteAshmemCreateRegionMethod m =
      PaletteLoader::Instance().GetPaletteAshmemCreateRegionMethod();
  return m(name, size, fd);
}

palette_status_t PaletteAshmemSetProtRegion(int fd, int prot) {
  PaletteAshmemSetProtRegionMethod m =
      PaletteLoader::Instance().GetPaletteAshmemSetProtRegionMethod();
  return m(fd, prot);
}

palette_status_t PaletteCreateOdrefreshStagingDirectory(const char** staging_dir) {
  PaletteCreateOdrefreshStagingDirectoryMethod m =
      PaletteLoader::Instance().GetPaletteCreateOdrefreshStagingDirectoryMethod();
  return m(staging_dir);
}

palette_status_t PaletteShouldReportDex2oatCompilation(bool* value) {
  PaletteShouldReportDex2oatCompilationMethod m =
      PaletteLoader::Instance().GetPaletteShouldReportDex2oatCompilationMethod();
  return m(value);
}

palette_status_t PaletteNotifyStartDex2oatCompilation(int source_fd,
                                                      int art_fd,
                                                      int oat_fd,
                                                      int vdex_fd) {
  PaletteNotifyStartDex2oatCompilationMethod m =
      PaletteLoader::Instance().GetPaletteNotifyStartDex2oatCompilationMethod();
  return m(source_fd, art_fd, oat_fd, vdex_fd);
}

palette_status_t PaletteNotifyEndDex2oatCompilation(int source_fd,
                                                    int art_fd,
                                                    int oat_fd,
                                                    int vdex_fd) {
  PaletteNotifyEndDex2oatCompilationMethod m =
      PaletteLoader::Instance().GetPaletteNotifyEndDex2oatCompilationMethod();
  return m(source_fd, art_fd, oat_fd, vdex_fd);
}

palette_status_t PaletteNotifyDexFileLoaded(const char* path) {
  PaletteNotifyDexFileLoadedMethod m =
      PaletteLoader::Instance().GetPaletteNotifyDexFileLoadedMethod();
  return m(path);
}

palette_status_t PaletteNotifyOatFileLoaded(const char* path) {
  PaletteNotifyOatFileLoadedMethod m =
      PaletteLoader::Instance().GetPaletteNotifyOatFileLoadedMethod();
  return m(path);
}

palette_status_t PaletteShouldReportJniInvocations(bool* value) {
  PaletteShouldReportJniInvocationsMethod m =
      PaletteLoader::Instance().GetPaletteShouldReportJniInvocationsMethod();
  return m(value);
}

palette_status_t PaletteNotifyBeginJniInvocation(JNIEnv* env) {
  PaletteNotifyBeginJniInvocationMethod m =
      PaletteLoader::Instance().GetPaletteNotifyBeginJniInvocationMethod();
  return m(env);
}

palette_status_t PaletteNotifyEndJniInvocation(JNIEnv* env) {
  PaletteNotifyEndJniInvocationMethod m =
      PaletteLoader::Instance().GetPaletteNotifyEndJniInvocationMethod();
  return m(env);
}

}  // extern "C"