1 /*
2  * Copyright 2020 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 
18 #define LOG_TAG "GpuProfilingData"
19 
20 #include <chrono>
21 #include <csignal>
22 #include <string>
23 #include <thread>
24 #include <unistd.h>
25 #include <vector>
26 
27 #include <android/log.h>
28 #include <dlfcn.h>
29 
30 #define ALOGI(msg, ...)                                                        \
31   __android_log_print(ANDROID_LOG_INFO, LOG_TAG, (msg), __VA_ARGS__)
32 #define ALOGE(msg, ...)                                                        \
33   __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, (msg), __VA_ARGS__)
34 #define ALOGD(msg, ...)                                                        \
35   __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, (msg), __VA_ARGS__)
36 #define REQUIRE_SUCCESS(fn, name)                                              \
37   do {                                                                         \
38     if (VK_SUCCESS != fn) {                                                    \
39       ALOGE("Vulkan Error in %s", name);                                       \
40       return -1;                                                               \
41     }                                                                          \
42   } while (0)
43 
44 namespace {
45 
46 typedef void (*FN_PTR)(void);
47 
48 /**
49  * Load the vendor provided counter producer library.
50  * startCounterProducer is a thin rewrite of the same producer loading logic in
51  * github.com/google/agi
52  */
53 
startCounterProducer()54 int startCounterProducer() {
55   ALOGI("%s", "Loading producer library");
56   char *error;
57   std::string libDir = sizeof(void *) == 8 ? "lib64" : "lib";
58   std::string producerPath = "/vendor/" + libDir + "/libgpudataproducer.so";
59 
60   ALOGI("Trying %s", producerPath.c_str());
61   void *handle = dlopen(producerPath.c_str(), RTLD_GLOBAL);
62   if ((error = dlerror()) != nullptr || handle == nullptr) {
63     ALOGE("Error loading lib: %s", error);
64     return -1;
65   }
66 
67   FN_PTR startFunc = (FN_PTR)dlsym(handle, "start");
68   if ((error = dlerror()) != nullptr) {
69     ALOGE("Error looking for start symbol: %s", error);
70     dlclose(handle);
71     return -1;
72   }
73 
74   if (startFunc == nullptr) {
75     ALOGE("Did not find the producer library %s", producerPath.c_str());
76     ALOGE("LD_LIBRARY_PATH=%s", getenv("LD_LIBRARY_PATH"));
77     return -1;
78   }
79 
80   ALOGI("Calling start at %p", startFunc);
81   (*startFunc)();
82   ALOGI("Producer %s has exited.", producerPath.c_str());
83   dlclose(handle);
84   return 0;
85 }
86 
87 volatile std::sig_atomic_t done = 0;
88 
89 } // anonymous namespace
90 
main()91 int main() {
92   std::signal(SIGTERM, [](int /*signal*/) {
93     ALOGI("%s", "SIGTERM received");
94     done = 1;
95   });
96   std::thread dummy([&]() {
97     int result = startCounterProducer();
98     ALOGI("%s %d", "startCounterProducer returned", result);
99   });
100   ALOGI("%s", "Waiting for host");
101   while (!done) {
102     std::this_thread::sleep_for(std::chrono::milliseconds(100));
103   }
104   return 0;
105 }
106