1 /*
2 * Copyright (C) 2018 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 <jni.h>
18
19 #include "perfetto/ext/traced/traced.h"
20 #include "perfetto/ext/tracing/ipc/default_socket.h"
21
22 #include "perfetto/ext/base/unix_task_runner.h"
23
24 #include "test/fake_producer.h"
25
26 namespace {
27
28 static std::mutex g_mutex;
29
30 // These variables are guarded by the above mutex.
31 static perfetto::base::UnixTaskRunner* g_activity_tr = nullptr;
32 static perfetto::base::UnixTaskRunner* g_service_tr = nullptr;
33 static perfetto::base::UnixTaskRunner* g_isolated_service_tr = nullptr;
34
35 } // namespace
36
37 namespace perfetto {
38 namespace {
39
ListenAndRespond(const std::string & name,base::UnixTaskRunner ** tr)40 void ListenAndRespond(const std::string& name, base::UnixTaskRunner** tr) {
41 // Note that this lock is unlocked by a post task in the middle of the
42 // function instead of at the end of this function.
43 std::unique_lock<std::mutex> lock(g_mutex);
44
45 // Ensure that we don't create multiple instances of the same producer.
46 // If the passed task runner is non-null, that means it's still running
47 // so we don't need to create another instance.
48 if (*tr)
49 return;
50
51 // Post a task to unlock the mutex when the runner has started executing
52 // tasks.
53 base::UnixTaskRunner task_runner;
54 task_runner.PostTask([tr, &lock, &task_runner]() {
55 *tr = &task_runner;
56 lock.unlock();
57 });
58
59 FakeProducer producer(name, &task_runner);
60 producer.Connect(
61 GetProducerSocket(), [] {}, [] {}, [] {});
62 task_runner.Run();
63
64 // Cleanup the task runner again to remove outside visibilty so we can
65 // create new instances of the producer.
66 {
67 std::lock_guard<std::mutex> guard(g_mutex);
68 *tr = nullptr;
69 }
70 }
71
72 } // namespace
73 } // namespace perfetto
74
75 extern "C" JNIEXPORT void JNICALL
Java_android_perfetto_producer_ProducerActivity_quitTaskRunner(JNIEnv *,jclass)76 Java_android_perfetto_producer_ProducerActivity_quitTaskRunner(JNIEnv*,
77 jclass) {
78 std::lock_guard<std::mutex> guard(g_mutex);
79 if (g_activity_tr) {
80 g_activity_tr->Quit();
81 }
82 }
83
84 extern "C" JNIEXPORT void JNICALL
Java_android_perfetto_producer_ProducerIsolatedService_quitTaskRunner(JNIEnv *,jclass)85 Java_android_perfetto_producer_ProducerIsolatedService_quitTaskRunner(JNIEnv*,
86 jclass) {
87 std::lock_guard<std::mutex> guard(g_mutex);
88 if (g_isolated_service_tr) {
89 g_isolated_service_tr->Quit();
90 }
91 }
92
93 extern "C" JNIEXPORT void JNICALL
Java_android_perfetto_producer_ProducerService_quitTaskRunner(JNIEnv *,jclass)94 Java_android_perfetto_producer_ProducerService_quitTaskRunner(JNIEnv*, jclass) {
95 std::lock_guard<std::mutex> guard(g_mutex);
96 if (g_service_tr) {
97 g_service_tr->Quit();
98 }
99 }
100
101 extern "C" JNIEXPORT void JNICALL
Java_android_perfetto_producer_ProducerActivity_setupProducer(JNIEnv *,jclass)102 Java_android_perfetto_producer_ProducerActivity_setupProducer(JNIEnv*, jclass) {
103 perfetto::ListenAndRespond("android.perfetto.cts.ProducerActivity",
104 &g_activity_tr);
105 }
106
107 extern "C" JNIEXPORT void JNICALL
Java_android_perfetto_producer_ProducerIsolatedService_setupProducer(JNIEnv *,jclass)108 Java_android_perfetto_producer_ProducerIsolatedService_setupProducer(JNIEnv*,
109 jclass) {
110 perfetto::ListenAndRespond("android.perfetto.cts.ProducerIsolatedService",
111 &g_isolated_service_tr);
112 }
113
114 extern "C" JNIEXPORT void JNICALL
Java_android_perfetto_producer_ProducerService_setupProducer(JNIEnv *,jclass)115 Java_android_perfetto_producer_ProducerService_setupProducer(JNIEnv*, jclass) {
116 perfetto::ListenAndRespond("android.perfetto.cts.ProducerService",
117 &g_service_tr);
118 }
119