1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2017 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker *
10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker */
16*795d594fSAndroid Build Coastguard Worker
17*795d594fSAndroid Build Coastguard Worker #include "runtime_callbacks.h"
18*795d594fSAndroid Build Coastguard Worker
19*795d594fSAndroid Build Coastguard Worker #include <signal.h>
20*795d594fSAndroid Build Coastguard Worker #include <sys/types.h>
21*795d594fSAndroid Build Coastguard Worker #include <unistd.h>
22*795d594fSAndroid Build Coastguard Worker
23*795d594fSAndroid Build Coastguard Worker #include <initializer_list>
24*795d594fSAndroid Build Coastguard Worker #include <memory>
25*795d594fSAndroid Build Coastguard Worker #include <mutex>
26*795d594fSAndroid Build Coastguard Worker #include <string>
27*795d594fSAndroid Build Coastguard Worker
28*795d594fSAndroid Build Coastguard Worker #include "jni.h"
29*795d594fSAndroid Build Coastguard Worker
30*795d594fSAndroid Build Coastguard Worker #include "art_method-alloc-inl.h"
31*795d594fSAndroid Build Coastguard Worker #include "base/mem_map.h"
32*795d594fSAndroid Build Coastguard Worker #include "base/mutex.h"
33*795d594fSAndroid Build Coastguard Worker #include "class_linker.h"
34*795d594fSAndroid Build Coastguard Worker #include "common_runtime_test.h"
35*795d594fSAndroid Build Coastguard Worker #include "dex/class_reference.h"
36*795d594fSAndroid Build Coastguard Worker #include "handle.h"
37*795d594fSAndroid Build Coastguard Worker #include "handle_scope-inl.h"
38*795d594fSAndroid Build Coastguard Worker #include "mirror/class-alloc-inl.h"
39*795d594fSAndroid Build Coastguard Worker #include "mirror/class_loader.h"
40*795d594fSAndroid Build Coastguard Worker #include "monitor-inl.h"
41*795d594fSAndroid Build Coastguard Worker #include "nativehelper/scoped_local_ref.h"
42*795d594fSAndroid Build Coastguard Worker #include "obj_ptr-inl.h"
43*795d594fSAndroid Build Coastguard Worker #include "runtime.h"
44*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
45*795d594fSAndroid Build Coastguard Worker #include "thread-inl.h"
46*795d594fSAndroid Build Coastguard Worker #include "thread_list.h"
47*795d594fSAndroid Build Coastguard Worker #include "well_known_classes-inl.h"
48*795d594fSAndroid Build Coastguard Worker
49*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
50*795d594fSAndroid Build Coastguard Worker
51*795d594fSAndroid Build Coastguard Worker class RuntimeCallbacksTest : public CommonRuntimeTest {
52*795d594fSAndroid Build Coastguard Worker protected:
SetUp()53*795d594fSAndroid Build Coastguard Worker void SetUp() override {
54*795d594fSAndroid Build Coastguard Worker CommonRuntimeTest::SetUp();
55*795d594fSAndroid Build Coastguard Worker
56*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
57*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(self);
58*795d594fSAndroid Build Coastguard Worker ScopedThreadSuspension sts(self, ThreadState::kWaitingForDebuggerToAttach);
59*795d594fSAndroid Build Coastguard Worker ScopedSuspendAll ssa("RuntimeCallbacksTest SetUp");
60*795d594fSAndroid Build Coastguard Worker AddListener();
61*795d594fSAndroid Build Coastguard Worker }
62*795d594fSAndroid Build Coastguard Worker
TearDown()63*795d594fSAndroid Build Coastguard Worker void TearDown() override {
64*795d594fSAndroid Build Coastguard Worker {
65*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
66*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(self);
67*795d594fSAndroid Build Coastguard Worker ScopedThreadSuspension sts(self, ThreadState::kWaitingForDebuggerToAttach);
68*795d594fSAndroid Build Coastguard Worker ScopedSuspendAll ssa("RuntimeCallbacksTest TearDown");
69*795d594fSAndroid Build Coastguard Worker RemoveListener();
70*795d594fSAndroid Build Coastguard Worker }
71*795d594fSAndroid Build Coastguard Worker
72*795d594fSAndroid Build Coastguard Worker CommonRuntimeTest::TearDown();
73*795d594fSAndroid Build Coastguard Worker }
74*795d594fSAndroid Build Coastguard Worker
75*795d594fSAndroid Build Coastguard Worker virtual void AddListener() REQUIRES(Locks::mutator_lock_) = 0;
76*795d594fSAndroid Build Coastguard Worker virtual void RemoveListener() REQUIRES(Locks::mutator_lock_) = 0;
77*795d594fSAndroid Build Coastguard Worker
MakeExecutable(ObjPtr<mirror::Class> klass)78*795d594fSAndroid Build Coastguard Worker void MakeExecutable(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) {
79*795d594fSAndroid Build Coastguard Worker CHECK(klass != nullptr);
80*795d594fSAndroid Build Coastguard Worker PointerSize pointer_size = class_linker_->GetImagePointerSize();
81*795d594fSAndroid Build Coastguard Worker for (auto& m : klass->GetMethods(pointer_size)) {
82*795d594fSAndroid Build Coastguard Worker if (!m.IsAbstract()) {
83*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetInstrumentation()->InitializeMethodsCode(&m, /*aot_code=*/ nullptr);
84*795d594fSAndroid Build Coastguard Worker }
85*795d594fSAndroid Build Coastguard Worker }
86*795d594fSAndroid Build Coastguard Worker }
87*795d594fSAndroid Build Coastguard Worker };
88*795d594fSAndroid Build Coastguard Worker
89*795d594fSAndroid Build Coastguard Worker class ThreadLifecycleCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest {
90*795d594fSAndroid Build Coastguard Worker public:
PthreadsCallback(void * arg)91*795d594fSAndroid Build Coastguard Worker static void* PthreadsCallback([[maybe_unused]] void* arg) {
92*795d594fSAndroid Build Coastguard Worker // Attach.
93*795d594fSAndroid Build Coastguard Worker Runtime* runtime = Runtime::Current();
94*795d594fSAndroid Build Coastguard Worker CHECK(runtime->AttachCurrentThread("ThreadLifecycle test thread", true, nullptr, false));
95*795d594fSAndroid Build Coastguard Worker
96*795d594fSAndroid Build Coastguard Worker // Detach.
97*795d594fSAndroid Build Coastguard Worker runtime->DetachCurrentThread();
98*795d594fSAndroid Build Coastguard Worker
99*795d594fSAndroid Build Coastguard Worker // Die...
100*795d594fSAndroid Build Coastguard Worker return nullptr;
101*795d594fSAndroid Build Coastguard Worker }
102*795d594fSAndroid Build Coastguard Worker
103*795d594fSAndroid Build Coastguard Worker protected:
AddListener()104*795d594fSAndroid Build Coastguard Worker void AddListener() override REQUIRES(Locks::mutator_lock_) {
105*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetRuntimeCallbacks()->AddThreadLifecycleCallback(&cb_);
106*795d594fSAndroid Build Coastguard Worker }
RemoveListener()107*795d594fSAndroid Build Coastguard Worker void RemoveListener() override REQUIRES(Locks::mutator_lock_) {
108*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetRuntimeCallbacks()->RemoveThreadLifecycleCallback(&cb_);
109*795d594fSAndroid Build Coastguard Worker }
110*795d594fSAndroid Build Coastguard Worker
111*795d594fSAndroid Build Coastguard Worker enum CallbackState {
112*795d594fSAndroid Build Coastguard Worker kBase,
113*795d594fSAndroid Build Coastguard Worker kStarted,
114*795d594fSAndroid Build Coastguard Worker kDied,
115*795d594fSAndroid Build Coastguard Worker kWrongStart,
116*795d594fSAndroid Build Coastguard Worker kWrongDeath,
117*795d594fSAndroid Build Coastguard Worker };
118*795d594fSAndroid Build Coastguard Worker
119*795d594fSAndroid Build Coastguard Worker struct Callback : public ThreadLifecycleCallback {
ThreadStartart::ThreadLifecycleCallbackRuntimeCallbacksTest::Callback120*795d594fSAndroid Build Coastguard Worker void ThreadStart(Thread* self) override {
121*795d594fSAndroid Build Coastguard Worker {
122*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(self);
123*795d594fSAndroid Build Coastguard Worker LOG(DEBUG) << "ThreadStart callback for thread: " << self->GetThreadName();
124*795d594fSAndroid Build Coastguard Worker }
125*795d594fSAndroid Build Coastguard Worker if (state == CallbackState::kBase) {
126*795d594fSAndroid Build Coastguard Worker state = CallbackState::kStarted;
127*795d594fSAndroid Build Coastguard Worker stored_self = self;
128*795d594fSAndroid Build Coastguard Worker } else {
129*795d594fSAndroid Build Coastguard Worker state = CallbackState::kWrongStart;
130*795d594fSAndroid Build Coastguard Worker }
131*795d594fSAndroid Build Coastguard Worker }
132*795d594fSAndroid Build Coastguard Worker
ThreadDeathart::ThreadLifecycleCallbackRuntimeCallbacksTest::Callback133*795d594fSAndroid Build Coastguard Worker void ThreadDeath(Thread* self) override {
134*795d594fSAndroid Build Coastguard Worker {
135*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(self);
136*795d594fSAndroid Build Coastguard Worker LOG(DEBUG) << "ThreadDeath callback for thread: " << self->GetThreadName();
137*795d594fSAndroid Build Coastguard Worker }
138*795d594fSAndroid Build Coastguard Worker if (state == CallbackState::kStarted && self == stored_self) {
139*795d594fSAndroid Build Coastguard Worker state = CallbackState::kDied;
140*795d594fSAndroid Build Coastguard Worker } else {
141*795d594fSAndroid Build Coastguard Worker state = CallbackState::kWrongDeath;
142*795d594fSAndroid Build Coastguard Worker }
143*795d594fSAndroid Build Coastguard Worker }
144*795d594fSAndroid Build Coastguard Worker
145*795d594fSAndroid Build Coastguard Worker Thread* stored_self;
146*795d594fSAndroid Build Coastguard Worker CallbackState state = CallbackState::kBase;
147*795d594fSAndroid Build Coastguard Worker };
148*795d594fSAndroid Build Coastguard Worker
149*795d594fSAndroid Build Coastguard Worker Callback cb_;
150*795d594fSAndroid Build Coastguard Worker };
151*795d594fSAndroid Build Coastguard Worker
TEST_F(ThreadLifecycleCallbackRuntimeCallbacksTest,ThreadLifecycleCallbackJava)152*795d594fSAndroid Build Coastguard Worker TEST_F(ThreadLifecycleCallbackRuntimeCallbacksTest, ThreadLifecycleCallbackJava) {
153*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
154*795d594fSAndroid Build Coastguard Worker
155*795d594fSAndroid Build Coastguard Worker self->TransitionFromSuspendedToRunnable();
156*795d594fSAndroid Build Coastguard Worker bool started = runtime_->Start();
157*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(started);
158*795d594fSAndroid Build Coastguard Worker // Make sure the workers are done starting so we don't get callbacks for them.
159*795d594fSAndroid Build Coastguard Worker runtime_->WaitForThreadPoolWorkersToStart();
160*795d594fSAndroid Build Coastguard Worker
161*795d594fSAndroid Build Coastguard Worker // The metrics reporting thread will sometimes be slow to start. Synchronously requesting a
162*795d594fSAndroid Build Coastguard Worker // metrics report forces us to wait until the thread has started.
163*795d594fSAndroid Build Coastguard Worker runtime_->RequestMetricsReport(/*synchronous=*/true);
164*795d594fSAndroid Build Coastguard Worker
165*795d594fSAndroid Build Coastguard Worker cb_.state = CallbackState::kBase; // Ignore main thread attach.
166*795d594fSAndroid Build Coastguard Worker
167*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(self);
168*795d594fSAndroid Build Coastguard Worker MakeExecutable(WellKnownClasses::java_lang_Thread.Get());
169*795d594fSAndroid Build Coastguard Worker
170*795d594fSAndroid Build Coastguard Worker StackHandleScope<3u> hs(self);
171*795d594fSAndroid Build Coastguard Worker Handle<mirror::String> thread_name = hs.NewHandle(
172*795d594fSAndroid Build Coastguard Worker mirror::String::AllocFromModifiedUtf8(self, "ThreadLifecycleCallback test thread"));
173*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(thread_name != nullptr);
174*795d594fSAndroid Build Coastguard Worker
175*795d594fSAndroid Build Coastguard Worker Handle<mirror::Object> thread_group =
176*795d594fSAndroid Build Coastguard Worker hs.NewHandle(soa.Decode<mirror::Object>(runtime_->GetMainThreadGroup()));
177*795d594fSAndroid Build Coastguard Worker Handle<mirror::Object> thread =
178*795d594fSAndroid Build Coastguard Worker WellKnownClasses::java_lang_Thread_init->NewObject<'L', 'L', 'I', 'Z'>(
179*795d594fSAndroid Build Coastguard Worker hs, self, thread_group, thread_name, kMinThreadPriority, /*daemon=*/ false);
180*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(self->IsExceptionPending());
181*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(thread != nullptr);
182*795d594fSAndroid Build Coastguard Worker
183*795d594fSAndroid Build Coastguard Worker ArtMethod* start_method =
184*795d594fSAndroid Build Coastguard Worker thread->GetClass()->FindClassMethod("start", "()V", kRuntimePointerSize);
185*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(start_method != nullptr);
186*795d594fSAndroid Build Coastguard Worker
187*795d594fSAndroid Build Coastguard Worker start_method->InvokeVirtual<'V'>(self, thread.Get());
188*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(self->IsExceptionPending());
189*795d594fSAndroid Build Coastguard Worker
190*795d594fSAndroid Build Coastguard Worker ArtMethod* join_method = thread->GetClass()->FindClassMethod("join", "()V", kRuntimePointerSize);
191*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(join_method != nullptr);
192*795d594fSAndroid Build Coastguard Worker
193*795d594fSAndroid Build Coastguard Worker join_method->InvokeFinal<'V'>(self, thread.Get());
194*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(self->IsExceptionPending());
195*795d594fSAndroid Build Coastguard Worker
196*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(cb_.state, CallbackState::kDied);
197*795d594fSAndroid Build Coastguard Worker }
198*795d594fSAndroid Build Coastguard Worker
TEST_F(ThreadLifecycleCallbackRuntimeCallbacksTest,ThreadLifecycleCallbackAttach)199*795d594fSAndroid Build Coastguard Worker TEST_F(ThreadLifecycleCallbackRuntimeCallbacksTest, ThreadLifecycleCallbackAttach) {
200*795d594fSAndroid Build Coastguard Worker std::string error_msg;
201*795d594fSAndroid Build Coastguard Worker MemMap stack = MemMap::MapAnonymous("ThreadLifecycleCallback Thread",
202*795d594fSAndroid Build Coastguard Worker 128 * gPageSize, // Just some small stack.
203*795d594fSAndroid Build Coastguard Worker PROT_READ | PROT_WRITE,
204*795d594fSAndroid Build Coastguard Worker /*low_4gb=*/ false,
205*795d594fSAndroid Build Coastguard Worker &error_msg);
206*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(stack.IsValid()) << error_msg;
207*795d594fSAndroid Build Coastguard Worker
208*795d594fSAndroid Build Coastguard Worker const char* reason = "ThreadLifecycleCallback test thread";
209*795d594fSAndroid Build Coastguard Worker pthread_attr_t attr;
210*795d594fSAndroid Build Coastguard Worker CHECK_PTHREAD_CALL(pthread_attr_init, (&attr), reason);
211*795d594fSAndroid Build Coastguard Worker CHECK_PTHREAD_CALL(pthread_attr_setstack, (&attr, stack.Begin(), stack.Size()), reason);
212*795d594fSAndroid Build Coastguard Worker pthread_t pthread;
213*795d594fSAndroid Build Coastguard Worker CHECK_PTHREAD_CALL(pthread_create,
214*795d594fSAndroid Build Coastguard Worker (&pthread,
215*795d594fSAndroid Build Coastguard Worker &attr,
216*795d594fSAndroid Build Coastguard Worker &ThreadLifecycleCallbackRuntimeCallbacksTest::PthreadsCallback,
217*795d594fSAndroid Build Coastguard Worker this),
218*795d594fSAndroid Build Coastguard Worker reason);
219*795d594fSAndroid Build Coastguard Worker CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attr), reason);
220*795d594fSAndroid Build Coastguard Worker
221*795d594fSAndroid Build Coastguard Worker CHECK_PTHREAD_CALL(pthread_join, (pthread, nullptr), "ThreadLifecycleCallback test shutdown");
222*795d594fSAndroid Build Coastguard Worker
223*795d594fSAndroid Build Coastguard Worker // Detach is not a ThreadDeath event, so we expect to be in state Started.
224*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(cb_.state == CallbackState::kStarted) << static_cast<int>(cb_.state);
225*795d594fSAndroid Build Coastguard Worker }
226*795d594fSAndroid Build Coastguard Worker
227*795d594fSAndroid Build Coastguard Worker class ClassLoadCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest {
228*795d594fSAndroid Build Coastguard Worker protected:
AddListener()229*795d594fSAndroid Build Coastguard Worker void AddListener() override REQUIRES(Locks::mutator_lock_) {
230*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetRuntimeCallbacks()->AddClassLoadCallback(&cb_);
231*795d594fSAndroid Build Coastguard Worker }
RemoveListener()232*795d594fSAndroid Build Coastguard Worker void RemoveListener() override REQUIRES(Locks::mutator_lock_) {
233*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetRuntimeCallbacks()->RemoveClassLoadCallback(&cb_);
234*795d594fSAndroid Build Coastguard Worker }
235*795d594fSAndroid Build Coastguard Worker
Expect(std::initializer_list<const char * > list)236*795d594fSAndroid Build Coastguard Worker bool Expect(std::initializer_list<const char*> list) {
237*795d594fSAndroid Build Coastguard Worker if (cb_.data.size() != list.size()) {
238*795d594fSAndroid Build Coastguard Worker PrintError(list);
239*795d594fSAndroid Build Coastguard Worker return false;
240*795d594fSAndroid Build Coastguard Worker }
241*795d594fSAndroid Build Coastguard Worker
242*795d594fSAndroid Build Coastguard Worker if (!std::equal(cb_.data.begin(), cb_.data.end(), list.begin())) {
243*795d594fSAndroid Build Coastguard Worker PrintError(list);
244*795d594fSAndroid Build Coastguard Worker return false;
245*795d594fSAndroid Build Coastguard Worker }
246*795d594fSAndroid Build Coastguard Worker
247*795d594fSAndroid Build Coastguard Worker return true;
248*795d594fSAndroid Build Coastguard Worker }
249*795d594fSAndroid Build Coastguard Worker
PrintError(std::initializer_list<const char * > list)250*795d594fSAndroid Build Coastguard Worker void PrintError(std::initializer_list<const char*> list) {
251*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << "Expected:";
252*795d594fSAndroid Build Coastguard Worker for (const char* expected : list) {
253*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << " " << expected;
254*795d594fSAndroid Build Coastguard Worker }
255*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << "Found:";
256*795d594fSAndroid Build Coastguard Worker for (const auto& s : cb_.data) {
257*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << " " << s;
258*795d594fSAndroid Build Coastguard Worker }
259*795d594fSAndroid Build Coastguard Worker }
260*795d594fSAndroid Build Coastguard Worker
261*795d594fSAndroid Build Coastguard Worker struct Callback : public ClassLoadCallback {
ClassPreDefineart::ClassLoadCallbackRuntimeCallbacksTest::Callback262*795d594fSAndroid Build Coastguard Worker void ClassPreDefine(const char* descriptor,
263*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] Handle<mirror::Class> klass,
264*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] Handle<mirror::ClassLoader> class_loader,
265*795d594fSAndroid Build Coastguard Worker const DexFile& initial_dex_file,
266*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] const dex::ClassDef& initial_class_def,
267*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] /*out*/ DexFile const** final_dex_file,
268*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] /*out*/ dex::ClassDef const** final_class_def) override
269*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
270*795d594fSAndroid Build Coastguard Worker const std::string& location = initial_dex_file.GetLocation();
271*795d594fSAndroid Build Coastguard Worker std::string event =
272*795d594fSAndroid Build Coastguard Worker std::string("PreDefine:") + descriptor + " <" +
273*795d594fSAndroid Build Coastguard Worker location.substr(location.rfind('/') + 1, location.size()) + ">";
274*795d594fSAndroid Build Coastguard Worker data.push_back(event);
275*795d594fSAndroid Build Coastguard Worker }
276*795d594fSAndroid Build Coastguard Worker
ClassLoadart::ClassLoadCallbackRuntimeCallbacksTest::Callback277*795d594fSAndroid Build Coastguard Worker void ClassLoad(Handle<mirror::Class> klass) override REQUIRES_SHARED(Locks::mutator_lock_) {
278*795d594fSAndroid Build Coastguard Worker std::string tmp;
279*795d594fSAndroid Build Coastguard Worker std::string event = std::string("Load:") + klass->GetDescriptor(&tmp);
280*795d594fSAndroid Build Coastguard Worker data.push_back(event);
281*795d594fSAndroid Build Coastguard Worker }
282*795d594fSAndroid Build Coastguard Worker
ClassPrepareart::ClassLoadCallbackRuntimeCallbacksTest::Callback283*795d594fSAndroid Build Coastguard Worker void ClassPrepare(Handle<mirror::Class> temp_klass,
284*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> klass) override REQUIRES_SHARED(Locks::mutator_lock_) {
285*795d594fSAndroid Build Coastguard Worker std::string tmp, tmp2;
286*795d594fSAndroid Build Coastguard Worker std::string event = std::string("Prepare:") + klass->GetDescriptor(&tmp)
287*795d594fSAndroid Build Coastguard Worker + "[" + temp_klass->GetDescriptor(&tmp2) + "]";
288*795d594fSAndroid Build Coastguard Worker data.push_back(event);
289*795d594fSAndroid Build Coastguard Worker }
290*795d594fSAndroid Build Coastguard Worker
291*795d594fSAndroid Build Coastguard Worker std::vector<std::string> data;
292*795d594fSAndroid Build Coastguard Worker };
293*795d594fSAndroid Build Coastguard Worker
294*795d594fSAndroid Build Coastguard Worker Callback cb_;
295*795d594fSAndroid Build Coastguard Worker };
296*795d594fSAndroid Build Coastguard Worker
TEST_F(ClassLoadCallbackRuntimeCallbacksTest,ClassLoadCallback)297*795d594fSAndroid Build Coastguard Worker TEST_F(ClassLoadCallbackRuntimeCallbacksTest, ClassLoadCallback) {
298*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
299*795d594fSAndroid Build Coastguard Worker jobject jclass_loader = LoadDex("XandY");
300*795d594fSAndroid Build Coastguard Worker cb_.data.clear(); // Clear class loading records from `LoadDex()`, if any.
301*795d594fSAndroid Build Coastguard Worker VariableSizedHandleScope hs(soa.Self());
302*795d594fSAndroid Build Coastguard Worker Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
303*795d594fSAndroid Build Coastguard Worker soa.Decode<mirror::ClassLoader>(jclass_loader)));
304*795d594fSAndroid Build Coastguard Worker
305*795d594fSAndroid Build Coastguard Worker const char* descriptor_y = "LY;";
306*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> h_Y = hs.NewHandle(FindClass(descriptor_y, class_loader));
307*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(h_Y != nullptr);
308*795d594fSAndroid Build Coastguard Worker
309*795d594fSAndroid Build Coastguard Worker bool expect1 = Expect({ "PreDefine:LY; <art-gtest-jars-XandY.jar>",
310*795d594fSAndroid Build Coastguard Worker "PreDefine:LX; <art-gtest-jars-XandY.jar>",
311*795d594fSAndroid Build Coastguard Worker "Load:LX;",
312*795d594fSAndroid Build Coastguard Worker "Prepare:LX;[LX;]",
313*795d594fSAndroid Build Coastguard Worker "Load:LY;",
314*795d594fSAndroid Build Coastguard Worker "Prepare:LY;[LY;]" });
315*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(expect1);
316*795d594fSAndroid Build Coastguard Worker
317*795d594fSAndroid Build Coastguard Worker cb_.data.clear();
318*795d594fSAndroid Build Coastguard Worker
319*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(class_linker_->EnsureInitialized(Thread::Current(), h_Y, true, true));
320*795d594fSAndroid Build Coastguard Worker
321*795d594fSAndroid Build Coastguard Worker bool expect2 = Expect({ "PreDefine:LY$Z; <art-gtest-jars-XandY.jar>",
322*795d594fSAndroid Build Coastguard Worker "Load:LY$Z;",
323*795d594fSAndroid Build Coastguard Worker "Prepare:LY$Z;[LY$Z;]" });
324*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(expect2);
325*795d594fSAndroid Build Coastguard Worker }
326*795d594fSAndroid Build Coastguard Worker
327*795d594fSAndroid Build Coastguard Worker class RuntimeSigQuitCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest {
328*795d594fSAndroid Build Coastguard Worker protected:
AddListener()329*795d594fSAndroid Build Coastguard Worker void AddListener() override REQUIRES(Locks::mutator_lock_) {
330*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetRuntimeCallbacks()->AddRuntimeSigQuitCallback(&cb_);
331*795d594fSAndroid Build Coastguard Worker }
RemoveListener()332*795d594fSAndroid Build Coastguard Worker void RemoveListener() override REQUIRES(Locks::mutator_lock_) {
333*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetRuntimeCallbacks()->RemoveRuntimeSigQuitCallback(&cb_);
334*795d594fSAndroid Build Coastguard Worker }
335*795d594fSAndroid Build Coastguard Worker
336*795d594fSAndroid Build Coastguard Worker struct Callback : public RuntimeSigQuitCallback {
SigQuitart::RuntimeSigQuitCallbackRuntimeCallbacksTest::Callback337*795d594fSAndroid Build Coastguard Worker void SigQuit() override {
338*795d594fSAndroid Build Coastguard Worker ++sigquit_count;
339*795d594fSAndroid Build Coastguard Worker }
340*795d594fSAndroid Build Coastguard Worker
341*795d594fSAndroid Build Coastguard Worker size_t sigquit_count = 0;
342*795d594fSAndroid Build Coastguard Worker };
343*795d594fSAndroid Build Coastguard Worker
344*795d594fSAndroid Build Coastguard Worker Callback cb_;
345*795d594fSAndroid Build Coastguard Worker };
346*795d594fSAndroid Build Coastguard Worker
TEST_F(RuntimeSigQuitCallbackRuntimeCallbacksTest,SigQuit)347*795d594fSAndroid Build Coastguard Worker TEST_F(RuntimeSigQuitCallbackRuntimeCallbacksTest, SigQuit) {
348*795d594fSAndroid Build Coastguard Worker // The runtime needs to be started for the signal handler.
349*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
350*795d594fSAndroid Build Coastguard Worker
351*795d594fSAndroid Build Coastguard Worker self->TransitionFromSuspendedToRunnable();
352*795d594fSAndroid Build Coastguard Worker bool started = runtime_->Start();
353*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(started);
354*795d594fSAndroid Build Coastguard Worker
355*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(0u, cb_.sigquit_count);
356*795d594fSAndroid Build Coastguard Worker
357*795d594fSAndroid Build Coastguard Worker kill(getpid(), SIGQUIT);
358*795d594fSAndroid Build Coastguard Worker
359*795d594fSAndroid Build Coastguard Worker // Try a few times.
360*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i != 30; ++i) {
361*795d594fSAndroid Build Coastguard Worker if (cb_.sigquit_count == 0) {
362*795d594fSAndroid Build Coastguard Worker sleep(1);
363*795d594fSAndroid Build Coastguard Worker } else {
364*795d594fSAndroid Build Coastguard Worker break;
365*795d594fSAndroid Build Coastguard Worker }
366*795d594fSAndroid Build Coastguard Worker }
367*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(1u, cb_.sigquit_count);
368*795d594fSAndroid Build Coastguard Worker }
369*795d594fSAndroid Build Coastguard Worker
370*795d594fSAndroid Build Coastguard Worker class RuntimePhaseCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest {
371*795d594fSAndroid Build Coastguard Worker protected:
AddListener()372*795d594fSAndroid Build Coastguard Worker void AddListener() override REQUIRES(Locks::mutator_lock_) {
373*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetRuntimeCallbacks()->AddRuntimePhaseCallback(&cb_);
374*795d594fSAndroid Build Coastguard Worker }
RemoveListener()375*795d594fSAndroid Build Coastguard Worker void RemoveListener() override REQUIRES(Locks::mutator_lock_) {
376*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetRuntimeCallbacks()->RemoveRuntimePhaseCallback(&cb_);
377*795d594fSAndroid Build Coastguard Worker }
378*795d594fSAndroid Build Coastguard Worker
TearDown()379*795d594fSAndroid Build Coastguard Worker void TearDown() override {
380*795d594fSAndroid Build Coastguard Worker // Bypass RuntimeCallbacksTest::TearDown, as the runtime is already gone.
381*795d594fSAndroid Build Coastguard Worker CommonRuntimeTest::TearDown();
382*795d594fSAndroid Build Coastguard Worker }
383*795d594fSAndroid Build Coastguard Worker
384*795d594fSAndroid Build Coastguard Worker struct Callback : public RuntimePhaseCallback {
NextRuntimePhaseart::RuntimePhaseCallbackRuntimeCallbacksTest::Callback385*795d594fSAndroid Build Coastguard Worker void NextRuntimePhase(RuntimePhaseCallback::RuntimePhase p) override {
386*795d594fSAndroid Build Coastguard Worker if (p == RuntimePhaseCallback::RuntimePhase::kInitialAgents) {
387*795d594fSAndroid Build Coastguard Worker if (start_seen > 0 || init_seen > 0 || death_seen > 0) {
388*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected order";
389*795d594fSAndroid Build Coastguard Worker }
390*795d594fSAndroid Build Coastguard Worker ++initial_agents_seen;
391*795d594fSAndroid Build Coastguard Worker } else if (p == RuntimePhaseCallback::RuntimePhase::kStart) {
392*795d594fSAndroid Build Coastguard Worker if (init_seen > 0 || death_seen > 0) {
393*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Init seen before start.";
394*795d594fSAndroid Build Coastguard Worker }
395*795d594fSAndroid Build Coastguard Worker ++start_seen;
396*795d594fSAndroid Build Coastguard Worker } else if (p == RuntimePhaseCallback::RuntimePhase::kInit) {
397*795d594fSAndroid Build Coastguard Worker ++init_seen;
398*795d594fSAndroid Build Coastguard Worker } else if (p == RuntimePhaseCallback::RuntimePhase::kDeath) {
399*795d594fSAndroid Build Coastguard Worker ++death_seen;
400*795d594fSAndroid Build Coastguard Worker } else {
401*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unknown phase " << static_cast<uint32_t>(p);
402*795d594fSAndroid Build Coastguard Worker }
403*795d594fSAndroid Build Coastguard Worker }
404*795d594fSAndroid Build Coastguard Worker
405*795d594fSAndroid Build Coastguard Worker size_t initial_agents_seen = 0;
406*795d594fSAndroid Build Coastguard Worker size_t start_seen = 0;
407*795d594fSAndroid Build Coastguard Worker size_t init_seen = 0;
408*795d594fSAndroid Build Coastguard Worker size_t death_seen = 0;
409*795d594fSAndroid Build Coastguard Worker };
410*795d594fSAndroid Build Coastguard Worker
411*795d594fSAndroid Build Coastguard Worker Callback cb_;
412*795d594fSAndroid Build Coastguard Worker };
413*795d594fSAndroid Build Coastguard Worker
TEST_F(RuntimePhaseCallbackRuntimeCallbacksTest,Phases)414*795d594fSAndroid Build Coastguard Worker TEST_F(RuntimePhaseCallbackRuntimeCallbacksTest, Phases) {
415*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0u, cb_.initial_agents_seen);
416*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0u, cb_.start_seen);
417*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0u, cb_.init_seen);
418*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0u, cb_.death_seen);
419*795d594fSAndroid Build Coastguard Worker
420*795d594fSAndroid Build Coastguard Worker // Start the runtime.
421*795d594fSAndroid Build Coastguard Worker {
422*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
423*795d594fSAndroid Build Coastguard Worker self->TransitionFromSuspendedToRunnable();
424*795d594fSAndroid Build Coastguard Worker bool started = runtime_->Start();
425*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(started);
426*795d594fSAndroid Build Coastguard Worker }
427*795d594fSAndroid Build Coastguard Worker
428*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0u, cb_.initial_agents_seen);
429*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(1u, cb_.start_seen);
430*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(1u, cb_.init_seen);
431*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0u, cb_.death_seen);
432*795d594fSAndroid Build Coastguard Worker
433*795d594fSAndroid Build Coastguard Worker // Delete the runtime.
434*795d594fSAndroid Build Coastguard Worker runtime_.reset();
435*795d594fSAndroid Build Coastguard Worker
436*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0u, cb_.initial_agents_seen);
437*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(1u, cb_.start_seen);
438*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(1u, cb_.init_seen);
439*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(1u, cb_.death_seen);
440*795d594fSAndroid Build Coastguard Worker }
441*795d594fSAndroid Build Coastguard Worker
442*795d594fSAndroid Build Coastguard Worker class MonitorWaitCallbacksTest : public RuntimeCallbacksTest {
443*795d594fSAndroid Build Coastguard Worker protected:
AddListener()444*795d594fSAndroid Build Coastguard Worker void AddListener() override REQUIRES(Locks::mutator_lock_) {
445*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetRuntimeCallbacks()->AddMonitorCallback(&cb_);
446*795d594fSAndroid Build Coastguard Worker }
RemoveListener()447*795d594fSAndroid Build Coastguard Worker void RemoveListener() override REQUIRES(Locks::mutator_lock_) {
448*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetRuntimeCallbacks()->RemoveMonitorCallback(&cb_);
449*795d594fSAndroid Build Coastguard Worker }
450*795d594fSAndroid Build Coastguard Worker
451*795d594fSAndroid Build Coastguard Worker struct Callback : public MonitorCallback {
IsInterestingObjectart::MonitorWaitCallbacksTest::Callback452*795d594fSAndroid Build Coastguard Worker bool IsInterestingObject(ObjPtr<mirror::Object> obj)
453*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
454*795d594fSAndroid Build Coastguard Worker if (!obj->IsClass()) {
455*795d594fSAndroid Build Coastguard Worker return false;
456*795d594fSAndroid Build Coastguard Worker }
457*795d594fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(ref_guard_);
458*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> k = obj->AsClass();
459*795d594fSAndroid Build Coastguard Worker ClassReference test = { &k->GetDexFile(), k->GetDexClassDefIndex() };
460*795d594fSAndroid Build Coastguard Worker return ref_ == test;
461*795d594fSAndroid Build Coastguard Worker }
462*795d594fSAndroid Build Coastguard Worker
SetInterestingObjectart::MonitorWaitCallbacksTest::Callback463*795d594fSAndroid Build Coastguard Worker void SetInterestingObject(ObjPtr<mirror::Object> obj)
464*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
465*795d594fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(ref_guard_);
466*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> k = obj->AsClass();
467*795d594fSAndroid Build Coastguard Worker ref_ = { &k->GetDexFile(), k->GetDexClassDefIndex() };
468*795d594fSAndroid Build Coastguard Worker }
469*795d594fSAndroid Build Coastguard Worker
MonitorContendedLockingart::MonitorWaitCallbacksTest::Callback470*795d594fSAndroid Build Coastguard Worker void MonitorContendedLocking([[maybe_unused]] Monitor* mon) override
471*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {}
472*795d594fSAndroid Build Coastguard Worker
MonitorContendedLockedart::MonitorWaitCallbacksTest::Callback473*795d594fSAndroid Build Coastguard Worker void MonitorContendedLocked([[maybe_unused]] Monitor* mon) override
474*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {}
475*795d594fSAndroid Build Coastguard Worker
ObjectWaitStartart::MonitorWaitCallbacksTest::Callback476*795d594fSAndroid Build Coastguard Worker void ObjectWaitStart(Handle<mirror::Object> obj, [[maybe_unused]] int64_t millis) override
477*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
478*795d594fSAndroid Build Coastguard Worker if (IsInterestingObject(obj.Get())) {
479*795d594fSAndroid Build Coastguard Worker saw_wait_start_ = true;
480*795d594fSAndroid Build Coastguard Worker }
481*795d594fSAndroid Build Coastguard Worker }
482*795d594fSAndroid Build Coastguard Worker
MonitorWaitFinishedart::MonitorWaitCallbacksTest::Callback483*795d594fSAndroid Build Coastguard Worker void MonitorWaitFinished(Monitor* m, [[maybe_unused]] bool timed_out) override
484*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
485*795d594fSAndroid Build Coastguard Worker if (IsInterestingObject(m->GetObject())) {
486*795d594fSAndroid Build Coastguard Worker saw_wait_finished_ = true;
487*795d594fSAndroid Build Coastguard Worker }
488*795d594fSAndroid Build Coastguard Worker }
489*795d594fSAndroid Build Coastguard Worker
490*795d594fSAndroid Build Coastguard Worker std::mutex ref_guard_;
491*795d594fSAndroid Build Coastguard Worker ClassReference ref_ = {nullptr, 0};
492*795d594fSAndroid Build Coastguard Worker bool saw_wait_start_ = false;
493*795d594fSAndroid Build Coastguard Worker bool saw_wait_finished_ = false;
494*795d594fSAndroid Build Coastguard Worker };
495*795d594fSAndroid Build Coastguard Worker
496*795d594fSAndroid Build Coastguard Worker Callback cb_;
497*795d594fSAndroid Build Coastguard Worker };
498*795d594fSAndroid Build Coastguard Worker
499*795d594fSAndroid Build Coastguard Worker // TODO It would be good to have more tests for this but due to the multi-threaded nature of the
500*795d594fSAndroid Build Coastguard Worker // callbacks this is difficult. For now the run-tests 1931 & 1932 should be sufficient.
TEST_F(MonitorWaitCallbacksTest,WaitUnlocked)501*795d594fSAndroid Build Coastguard Worker TEST_F(MonitorWaitCallbacksTest, WaitUnlocked) {
502*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(cb_.saw_wait_finished_);
503*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(cb_.saw_wait_start_);
504*795d594fSAndroid Build Coastguard Worker {
505*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
506*795d594fSAndroid Build Coastguard Worker self->TransitionFromSuspendedToRunnable();
507*795d594fSAndroid Build Coastguard Worker bool started = runtime_->Start();
508*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(started);
509*795d594fSAndroid Build Coastguard Worker {
510*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(self);
511*795d594fSAndroid Build Coastguard Worker cb_.SetInterestingObject(WellKnownClasses::java_util_Collections.Get());
512*795d594fSAndroid Build Coastguard Worker Monitor::Wait(
513*795d594fSAndroid Build Coastguard Worker self,
514*795d594fSAndroid Build Coastguard Worker // Just a random class
515*795d594fSAndroid Build Coastguard Worker WellKnownClasses::java_util_Collections.Get(),
516*795d594fSAndroid Build Coastguard Worker /*ms=*/0,
517*795d594fSAndroid Build Coastguard Worker /*ns=*/0,
518*795d594fSAndroid Build Coastguard Worker /*interruptShouldThrow=*/false,
519*795d594fSAndroid Build Coastguard Worker /*why=*/ThreadState::kWaiting);
520*795d594fSAndroid Build Coastguard Worker }
521*795d594fSAndroid Build Coastguard Worker }
522*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(cb_.saw_wait_start_);
523*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(cb_.saw_wait_finished_);
524*795d594fSAndroid Build Coastguard Worker }
525*795d594fSAndroid Build Coastguard Worker
526*795d594fSAndroid Build Coastguard Worker } // namespace art
527