1 /*
2 * Copyright (C) 2017 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 "runtime_callbacks.h"
18
19 #include <algorithm>
20
21 #include "art_method.h"
22 #include "base/macros.h"
23 #include "class_linker.h"
24 #include "thread.h"
25
26 namespace art {
27
AddThreadLifecycleCallback(ThreadLifecycleCallback * cb)28 void RuntimeCallbacks::AddThreadLifecycleCallback(ThreadLifecycleCallback* cb) {
29 thread_callbacks_.push_back(cb);
30 }
31
32 template <typename T>
33 ALWAYS_INLINE
Remove(T * cb,std::vector<T * > * data)34 static inline void Remove(T* cb, std::vector<T*>* data) {
35 auto it = std::find(data->begin(), data->end(), cb);
36 if (it != data->end()) {
37 data->erase(it);
38 }
39 }
40
RemoveThreadLifecycleCallback(ThreadLifecycleCallback * cb)41 void RuntimeCallbacks::RemoveThreadLifecycleCallback(ThreadLifecycleCallback* cb) {
42 Remove(cb, &thread_callbacks_);
43 }
44
ThreadStart(Thread * self)45 void RuntimeCallbacks::ThreadStart(Thread* self) {
46 for (ThreadLifecycleCallback* cb : thread_callbacks_) {
47 cb->ThreadStart(self);
48 }
49 }
50
ThreadDeath(Thread * self)51 void RuntimeCallbacks::ThreadDeath(Thread* self) {
52 for (ThreadLifecycleCallback* cb : thread_callbacks_) {
53 cb->ThreadDeath(self);
54 }
55 }
56
AddClassLoadCallback(ClassLoadCallback * cb)57 void RuntimeCallbacks::AddClassLoadCallback(ClassLoadCallback* cb) {
58 class_callbacks_.push_back(cb);
59 }
60
RemoveClassLoadCallback(ClassLoadCallback * cb)61 void RuntimeCallbacks::RemoveClassLoadCallback(ClassLoadCallback* cb) {
62 Remove(cb, &class_callbacks_);
63 }
64
ClassLoad(Handle<mirror::Class> klass)65 void RuntimeCallbacks::ClassLoad(Handle<mirror::Class> klass) {
66 for (ClassLoadCallback* cb : class_callbacks_) {
67 cb->ClassLoad(klass);
68 }
69 }
70
ClassPreDefine(const char * descriptor,Handle<mirror::Class> temp_class,Handle<mirror::ClassLoader> loader,const DexFile & initial_dex_file,const DexFile::ClassDef & initial_class_def,DexFile const ** final_dex_file,DexFile::ClassDef const ** final_class_def)71 void RuntimeCallbacks::ClassPreDefine(const char* descriptor,
72 Handle<mirror::Class> temp_class,
73 Handle<mirror::ClassLoader> loader,
74 const DexFile& initial_dex_file,
75 const DexFile::ClassDef& initial_class_def,
76 /*out*/DexFile const** final_dex_file,
77 /*out*/DexFile::ClassDef const** final_class_def) {
78 DexFile const* current_dex_file = &initial_dex_file;
79 DexFile::ClassDef const* current_class_def = &initial_class_def;
80 for (ClassLoadCallback* cb : class_callbacks_) {
81 DexFile const* new_dex_file = nullptr;
82 DexFile::ClassDef const* new_class_def = nullptr;
83 cb->ClassPreDefine(descriptor,
84 temp_class,
85 loader,
86 *current_dex_file,
87 *current_class_def,
88 &new_dex_file,
89 &new_class_def);
90 if ((new_dex_file != nullptr && new_dex_file != current_dex_file) ||
91 (new_class_def != nullptr && new_class_def != current_class_def)) {
92 DCHECK(new_dex_file != nullptr && new_class_def != nullptr);
93 current_dex_file = new_dex_file;
94 current_class_def = new_class_def;
95 }
96 }
97 *final_dex_file = current_dex_file;
98 *final_class_def = current_class_def;
99 }
100
ClassPrepare(Handle<mirror::Class> temp_klass,Handle<mirror::Class> klass)101 void RuntimeCallbacks::ClassPrepare(Handle<mirror::Class> temp_klass, Handle<mirror::Class> klass) {
102 for (ClassLoadCallback* cb : class_callbacks_) {
103 cb->ClassPrepare(temp_klass, klass);
104 }
105 }
106
AddRuntimeSigQuitCallback(RuntimeSigQuitCallback * cb)107 void RuntimeCallbacks::AddRuntimeSigQuitCallback(RuntimeSigQuitCallback* cb) {
108 sigquit_callbacks_.push_back(cb);
109 }
110
RemoveRuntimeSigQuitCallback(RuntimeSigQuitCallback * cb)111 void RuntimeCallbacks::RemoveRuntimeSigQuitCallback(RuntimeSigQuitCallback* cb) {
112 Remove(cb, &sigquit_callbacks_);
113 }
114
SigQuit()115 void RuntimeCallbacks::SigQuit() {
116 for (RuntimeSigQuitCallback* cb : sigquit_callbacks_) {
117 cb->SigQuit();
118 }
119 }
120
AddRuntimePhaseCallback(RuntimePhaseCallback * cb)121 void RuntimeCallbacks::AddRuntimePhaseCallback(RuntimePhaseCallback* cb) {
122 phase_callbacks_.push_back(cb);
123 }
124
RemoveRuntimePhaseCallback(RuntimePhaseCallback * cb)125 void RuntimeCallbacks::RemoveRuntimePhaseCallback(RuntimePhaseCallback* cb) {
126 Remove(cb, &phase_callbacks_);
127 }
128
NextRuntimePhase(RuntimePhaseCallback::RuntimePhase phase)129 void RuntimeCallbacks::NextRuntimePhase(RuntimePhaseCallback::RuntimePhase phase) {
130 for (RuntimePhaseCallback* cb : phase_callbacks_) {
131 cb->NextRuntimePhase(phase);
132 }
133 }
134
AddMethodCallback(MethodCallback * cb)135 void RuntimeCallbacks::AddMethodCallback(MethodCallback* cb) {
136 method_callbacks_.push_back(cb);
137 }
138
RemoveMethodCallback(MethodCallback * cb)139 void RuntimeCallbacks::RemoveMethodCallback(MethodCallback* cb) {
140 Remove(cb, &method_callbacks_);
141 }
142
RegisterNativeMethod(ArtMethod * method,const void * in_cur_method,void ** new_method)143 void RuntimeCallbacks::RegisterNativeMethod(ArtMethod* method,
144 const void* in_cur_method,
145 /*out*/void** new_method) {
146 void* cur_method = const_cast<void*>(in_cur_method);
147 *new_method = cur_method;
148 for (MethodCallback* cb : method_callbacks_) {
149 cb->RegisterNativeMethod(method, cur_method, new_method);
150 if (*new_method != nullptr) {
151 cur_method = *new_method;
152 }
153 }
154 }
155
156 } // namespace art
157