blob: ed5d5c1095f0012c429f7c3c0c10c9116730872a [file] [log] [blame]
Jesse Hall90b25ed2016-12-12 12:56:46 -08001/*
2 * Copyright 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
Yiwei Zhangcb9d4e42019-02-06 20:22:59 -080017#define ATRACE_TAG ATRACE_TAG_GRAPHICS
18
Jesse Hall90b25ed2016-12-12 12:56:46 -080019//#define LOG_NDEBUG 1
20#define LOG_TAG "GraphicsEnv"
Yiwei Zhangcb9d4e42019-02-06 20:22:59 -080021
Jiyong Park27c39e12017-05-08 13:00:02 +090022#include <graphicsenv/GraphicsEnv.h>
Jesse Hall90b25ed2016-12-12 12:56:46 -080023
Yiwei Zhang64d89212018-11-27 19:58:29 -080024#include <dlfcn.h>
Tim Van Patten5f744f12018-12-12 11:46:21 -070025#include <unistd.h>
Yiwei Zhang64d89212018-11-27 19:58:29 -080026
27#include <android-base/file.h>
28#include <android-base/properties.h>
29#include <android-base/strings.h>
30#include <android/dlext.h>
Yiwei Zhangcb9d4e42019-02-06 20:22:59 -080031#include <binder/IServiceManager.h>
Yiwei Zhangcb9d4e42019-02-06 20:22:59 -080032#include <graphicsenv/IGpuService.h>
Yiwei Zhang64d89212018-11-27 19:58:29 -080033#include <log/log.h>
Yiwei Zhang49b9ac72019-08-05 16:57:17 -070034#include <nativeloader/dlext_namespaces.h>
Cody Northrop629ce4e2018-10-15 07:22:09 -060035#include <sys/prctl.h>
Yiwei Zhangcb9d4e42019-02-06 20:22:59 -080036#include <utils/Trace.h>
Cody Northrop629ce4e2018-10-15 07:22:09 -060037
Tim Van Patten5f744f12018-12-12 11:46:21 -070038#include <memory>
Tim Van Patten5f744f12018-12-12 11:46:21 -070039#include <string>
Yiwei Zhang3c74da92019-06-28 10:16:49 -070040#include <thread>
Tim Van Patten5f744f12018-12-12 11:46:21 -070041
Peiyong Lin0acbfdc2020-06-17 18:47:12 -070042// TODO(b/159240322): Extend this to x86 ABI.
43#if defined(__LP64__)
44#define UPDATABLE_DRIVER_ABI "arm64-v8a"
45#else
46#define UPDATABLE_DRIVER_ABI "armeabi-v7a"
47#endif // defined(__LP64__)
48
Tim Van Patten5f744f12018-12-12 11:46:21 -070049// TODO(ianelliott@): Get the following from an ANGLE header:
50#define CURRENT_ANGLE_API_VERSION 2 // Current API verion we are targetting
51// Version-2 API:
52typedef bool (*fpANGLEGetFeatureSupportUtilAPIVersion)(unsigned int* versionToUse);
53typedef bool (*fpANGLEAndroidParseRulesString)(const char* rulesString, void** rulesHandle,
54 int* rulesVersion);
55typedef bool (*fpANGLEGetSystemInfo)(void** handle);
56typedef bool (*fpANGLEAddDeviceInfoToSystemInfo)(const char* deviceMfr, const char* deviceModel,
57 void* handle);
58typedef bool (*fpANGLEShouldBeUsedForApplication)(void* rulesHandle, int rulesVersion,
59 void* systemInfoHandle, const char* appName);
60typedef bool (*fpANGLEFreeRulesHandle)(void* handle);
61typedef bool (*fpANGLEFreeSystemInfoHandle)(void* handle);
62
Kiyoung Kimc0e3ed32023-08-11 11:22:15 +090063namespace {
64static bool isVndkEnabled() {
65#ifdef __BIONIC__
Kiyoung Kim77f37092023-09-26 10:41:47 +090066 static bool isVndkEnabled = android::base::GetProperty("ro.vndk.version", "") != "";
Kiyoung Kimc0e3ed32023-08-11 11:22:15 +090067 return isVndkEnabled;
68#endif
69 return false;
70}
71} // namespace
72
Jesse Hall90b25ed2016-12-12 12:56:46 -080073namespace android {
74
Yiwei Zhang64d89212018-11-27 19:58:29 -080075enum NativeLibrary {
76 LLNDK = 0,
77 VNDKSP = 1,
78};
79
Jooyung Han78396802020-02-23 03:02:43 +090080static constexpr const char* kNativeLibrariesSystemConfigPath[] =
81 {"/apex/com.android.vndk.v{}/etc/llndk.libraries.{}.txt",
82 "/apex/com.android.vndk.v{}/etc/vndksp.libraries.{}.txt"};
Yiwei Zhang64d89212018-11-27 19:58:29 -080083
Kiyoung Kimc0e3ed32023-08-11 11:22:15 +090084static const char* kLlndkLibrariesTxtPath = "/system/etc/llndk.libraries.txt";
85
Yiwei Zhang64d89212018-11-27 19:58:29 -080086static std::string vndkVersionStr() {
87#ifdef __BIONIC__
Michael Hoisied1023f22020-03-26 22:52:58 -070088 return base::GetProperty("ro.vndk.version", "");
Yiwei Zhang64d89212018-11-27 19:58:29 -080089#endif
90 return "";
91}
92
93static void insertVndkVersionStr(std::string* fileName) {
94 LOG_ALWAYS_FATAL_IF(!fileName, "fileName should never be nullptr");
Jooyung Han78396802020-02-23 03:02:43 +090095 std::string version = vndkVersionStr();
96 size_t pos = fileName->find("{}");
97 while (pos != std::string::npos) {
98 fileName->replace(pos, 2, version);
99 pos = fileName->find("{}", pos + version.size());
Yiwei Zhang64d89212018-11-27 19:58:29 -0800100 }
Yiwei Zhang64d89212018-11-27 19:58:29 -0800101}
102
103static bool readConfig(const std::string& configFile, std::vector<std::string>* soNames) {
104 // Read list of public native libraries from the config file.
105 std::string fileContent;
106 if (!base::ReadFileToString(configFile, &fileContent)) {
107 return false;
108 }
109
110 std::vector<std::string> lines = base::Split(fileContent, "\n");
111
112 for (auto& line : lines) {
113 auto trimmedLine = base::Trim(line);
114 if (!trimmedLine.empty()) {
115 soNames->push_back(trimmedLine);
116 }
117 }
118
119 return true;
120}
121
122static const std::string getSystemNativeLibraries(NativeLibrary type) {
Kiyoung Kimc0e3ed32023-08-11 11:22:15 +0900123 std::string nativeLibrariesSystemConfig = "";
124
125 if (!isVndkEnabled() && type == NativeLibrary::LLNDK) {
126 nativeLibrariesSystemConfig = kLlndkLibrariesTxtPath;
127 } else {
128 nativeLibrariesSystemConfig = kNativeLibrariesSystemConfigPath[type];
129 insertVndkVersionStr(&nativeLibrariesSystemConfig);
130 }
Yiwei Zhang64d89212018-11-27 19:58:29 -0800131
132 std::vector<std::string> soNames;
133 if (!readConfig(nativeLibrariesSystemConfig, &soNames)) {
134 ALOGE("Failed to retrieve library names from %s", nativeLibrariesSystemConfig.c_str());
135 return "";
136 }
137
138 return base::Join(soNames, ':');
139}
140
Peiyong Linef20e4e2023-07-03 02:33:00 +0000141static sp<IGpuService> getGpuService() {
142 static const sp<IBinder> binder = defaultServiceManager()->checkService(String16("gpu"));
143 if (!binder) {
144 ALOGE("Failed to get gpu service");
145 return nullptr;
146 }
147
148 return interface_cast<IGpuService>(binder);
149}
150
Jesse Hall90b25ed2016-12-12 12:56:46 -0800151/*static*/ GraphicsEnv& GraphicsEnv::getInstance() {
152 static GraphicsEnv env;
153 return env;
154}
155
Yiwei Zhang6a674c92019-11-08 11:55:36 -0800156bool GraphicsEnv::isDebuggable() {
Cody Northrop383832f2022-11-01 13:54:57 -0600157 // This flag determines if the application is marked debuggable
158 bool appDebuggable = prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) > 0;
159
160 // This flag is set only in `debuggable` builds of the platform
161#if defined(ANDROID_DEBUGGABLE)
162 bool platformDebuggable = true;
163#else
164 bool platformDebuggable = false;
165#endif
166
167 ALOGV("GraphicsEnv::isDebuggable returning appDebuggable=%s || platformDebuggable=%s",
168 appDebuggable ? "true" : "false", platformDebuggable ? "true" : "false");
169
170 return appDebuggable || platformDebuggable;
Cody Northrop629ce4e2018-10-15 07:22:09 -0600171}
172
Peiyong Linef20e4e2023-07-03 02:33:00 +0000173/**
174 * APIs for updatable graphics drivers
175 */
176
Peiyong Lin2f51e752023-06-15 22:35:14 +0000177void GraphicsEnv::setDriverPathAndSphalLibraries(const std::string& path,
178 const std::string& sphalLibraries) {
Yiwei Zhang6ef84942019-02-14 12:28:12 -0800179 if (!mDriverPath.empty() || !mSphalLibraries.empty()) {
180 ALOGV("ignoring attempt to change driver path from '%s' to '%s' or change sphal libraries "
181 "from '%s' to '%s'",
182 mDriverPath.c_str(), path.c_str(), mSphalLibraries.c_str(), sphalLibraries.c_str());
Jesse Hall90b25ed2016-12-12 12:56:46 -0800183 return;
184 }
Yiwei Zhang6ef84942019-02-14 12:28:12 -0800185 ALOGV("setting driver path to '%s' and sphal libraries to '%s'", path.c_str(),
186 sphalLibraries.c_str());
Jesse Hall90b25ed2016-12-12 12:56:46 -0800187 mDriverPath = path;
Yiwei Zhang6ef84942019-02-14 12:28:12 -0800188 mSphalLibraries = sphalLibraries;
Jesse Hall90b25ed2016-12-12 12:56:46 -0800189}
190
Peiyong Linef20e4e2023-07-03 02:33:00 +0000191// Return true if all the required libraries from vndk and sphal namespace are
192// linked to the driver namespace correctly.
193bool GraphicsEnv::linkDriverNamespaceLocked(android_namespace_t* destNamespace,
194 android_namespace_t* vndkNamespace,
195 const std::string& sharedSphalLibraries) {
196 const std::string llndkLibraries = getSystemNativeLibraries(NativeLibrary::LLNDK);
197 if (llndkLibraries.empty()) {
198 return false;
199 }
200 if (!android_link_namespaces(destNamespace, nullptr, llndkLibraries.c_str())) {
201 ALOGE("Failed to link default namespace[%s]", dlerror());
202 return false;
203 }
204
205 const std::string vndkspLibraries = getSystemNativeLibraries(NativeLibrary::VNDKSP);
206 if (vndkspLibraries.empty()) {
207 return false;
208 }
209 if (!android_link_namespaces(destNamespace, vndkNamespace, vndkspLibraries.c_str())) {
210 ALOGE("Failed to link vndk namespace[%s]", dlerror());
211 return false;
212 }
213
214 if (sharedSphalLibraries.empty()) {
215 return true;
216 }
217
218 // Make additional libraries in sphal to be accessible
219 auto sphalNamespace = android_get_exported_namespace("sphal");
220 if (!sphalNamespace) {
221 ALOGE("Depend on these libraries[%s] in sphal, but failed to get sphal namespace",
222 sharedSphalLibraries.c_str());
223 return false;
224 }
225
226 if (!android_link_namespaces(destNamespace, sphalNamespace, sharedSphalLibraries.c_str())) {
227 ALOGE("Failed to link sphal namespace[%s]", dlerror());
228 return false;
229 }
230
231 return true;
232}
233
234android_namespace_t* GraphicsEnv::getDriverNamespace() {
235 std::lock_guard<std::mutex> lock(mNamespaceMutex);
236
237 if (mDriverNamespace) {
238 return mDriverNamespace;
239 }
240
241 if (mDriverPath.empty()) {
242 // For an application process, driver path is empty means this application is not opted in
243 // to use updatable driver. Application process doesn't have the ability to set up
244 // environment variables and hence before `getenv` call will return.
245 // For a process that is not an application process, if it's run from an environment,
246 // for example shell, where environment variables can be set, then it can opt into using
247 // udpatable driver by setting UPDATABLE_GFX_DRIVER to 1. By setting to 1 the developer
248 // driver will be used currently.
249 // TODO(b/159240322) Support the production updatable driver.
250 const char* id = getenv("UPDATABLE_GFX_DRIVER");
251 if (id == nullptr || std::strcmp(id, "1") != 0) {
252 return nullptr;
253 }
254 const sp<IGpuService> gpuService = getGpuService();
255 if (!gpuService) {
256 return nullptr;
257 }
258 mDriverPath = gpuService->getUpdatableDriverPath();
259 if (mDriverPath.empty()) {
260 return nullptr;
261 }
262 mDriverPath.append(UPDATABLE_DRIVER_ABI);
263 ALOGI("Driver path is setup via UPDATABLE_GFX_DRIVER: %s", mDriverPath.c_str());
264 }
265
266 auto vndkNamespace = android_get_exported_namespace("vndk");
267 if (!vndkNamespace) {
268 return nullptr;
269 }
270
271 mDriverNamespace = android_create_namespace("updatable gfx driver",
272 mDriverPath.c_str(), // ld_library_path
273 mDriverPath.c_str(), // default_library_path
274 ANDROID_NAMESPACE_TYPE_ISOLATED,
275 nullptr, // permitted_when_isolated_path
276 nullptr);
277
278 if (!linkDriverNamespaceLocked(mDriverNamespace, vndkNamespace, mSphalLibraries)) {
279 mDriverNamespace = nullptr;
280 }
281
282 return mDriverNamespace;
283}
284
285std::string GraphicsEnv::getDriverPath() const {
286 return mDriverPath;
287}
288
289/**
290 * APIs for GpuStats
291 */
292
Yiwei Zhang5c640c12019-05-08 18:29:38 -0700293void GraphicsEnv::hintActivityLaunch() {
294 ATRACE_CALL();
295
Yiwei Zhangd3819382020-01-07 19:53:56 -0800296 {
297 std::lock_guard<std::mutex> lock(mStatsLock);
298 if (mActivityLaunched) return;
299 mActivityLaunched = true;
300 }
301
Yiwei Zhang3c74da92019-06-28 10:16:49 -0700302 std::thread trySendGpuStatsThread([this]() {
303 // If there's already graphics driver preloaded in the process, just send
304 // the stats info to GpuStats directly through async binder.
305 std::lock_guard<std::mutex> lock(mStatsLock);
306 if (mGpuStats.glDriverToSend) {
307 mGpuStats.glDriverToSend = false;
Yiwei Zhang27ab3ac2019-07-02 18:10:55 -0700308 sendGpuStatsLocked(GpuStatsInfo::Api::API_GL, true, mGpuStats.glDriverLoadingTime);
Yiwei Zhang3c74da92019-06-28 10:16:49 -0700309 }
310 if (mGpuStats.vkDriverToSend) {
311 mGpuStats.vkDriverToSend = false;
Yiwei Zhang27ab3ac2019-07-02 18:10:55 -0700312 sendGpuStatsLocked(GpuStatsInfo::Api::API_VK, true, mGpuStats.vkDriverLoadingTime);
Yiwei Zhang3c74da92019-06-28 10:16:49 -0700313 }
314 });
315 trySendGpuStatsThread.detach();
Yiwei Zhang5c640c12019-05-08 18:29:38 -0700316}
317
Greg Kaiser210bb7e2019-02-12 12:40:05 -0800318void GraphicsEnv::setGpuStats(const std::string& driverPackageName,
Yiwei Zhangd9861812019-02-13 11:51:55 -0800319 const std::string& driverVersionName, uint64_t driverVersionCode,
Yiwei Zhang794d2952019-05-06 17:43:59 -0700320 int64_t driverBuildTime, const std::string& appPackageName,
321 const int vulkanVersion) {
Yiwei Zhangcb9d4e42019-02-06 20:22:59 -0800322 ATRACE_CALL();
323
Yiwei Zhangd9861812019-02-13 11:51:55 -0800324 std::lock_guard<std::mutex> lock(mStatsLock);
Yiwei Zhangcb9d4e42019-02-06 20:22:59 -0800325 ALOGV("setGpuStats:\n"
326 "\tdriverPackageName[%s]\n"
327 "\tdriverVersionName[%s]\n"
Yiwei Zhang96c01712019-02-19 16:00:25 -0800328 "\tdriverVersionCode[%" PRIu64 "]\n"
329 "\tdriverBuildTime[%" PRId64 "]\n"
Yiwei Zhang794d2952019-05-06 17:43:59 -0700330 "\tappPackageName[%s]\n"
331 "\tvulkanVersion[%d]\n",
Yiwei Zhang96c01712019-02-19 16:00:25 -0800332 driverPackageName.c_str(), driverVersionName.c_str(), driverVersionCode, driverBuildTime,
Yiwei Zhang794d2952019-05-06 17:43:59 -0700333 appPackageName.c_str(), vulkanVersion);
Yiwei Zhangcb9d4e42019-02-06 20:22:59 -0800334
Yiwei Zhangd9861812019-02-13 11:51:55 -0800335 mGpuStats.driverPackageName = driverPackageName;
336 mGpuStats.driverVersionName = driverVersionName;
337 mGpuStats.driverVersionCode = driverVersionCode;
Yiwei Zhang96c01712019-02-19 16:00:25 -0800338 mGpuStats.driverBuildTime = driverBuildTime;
Yiwei Zhangd9861812019-02-13 11:51:55 -0800339 mGpuStats.appPackageName = appPackageName;
Yiwei Zhang794d2952019-05-06 17:43:59 -0700340 mGpuStats.vulkanVersion = vulkanVersion;
Yiwei Zhang8c8c1812019-02-04 18:56:38 -0800341}
342
Yiwei Zhang27ab3ac2019-07-02 18:10:55 -0700343void GraphicsEnv::setDriverToLoad(GpuStatsInfo::Driver driver) {
Yiwei Zhangd9861812019-02-13 11:51:55 -0800344 ATRACE_CALL();
345
346 std::lock_guard<std::mutex> lock(mStatsLock);
347 switch (driver) {
Yiwei Zhang27ab3ac2019-07-02 18:10:55 -0700348 case GpuStatsInfo::Driver::GL:
349 case GpuStatsInfo::Driver::GL_UPDATED:
350 case GpuStatsInfo::Driver::ANGLE: {
Yiwei Zhang472cab02019-08-05 17:57:41 -0700351 if (mGpuStats.glDriverToLoad == GpuStatsInfo::Driver::NONE ||
352 mGpuStats.glDriverToLoad == GpuStatsInfo::Driver::GL) {
Yiwei Zhangd9861812019-02-13 11:51:55 -0800353 mGpuStats.glDriverToLoad = driver;
354 break;
355 }
356
Yiwei Zhang27ab3ac2019-07-02 18:10:55 -0700357 if (mGpuStats.glDriverFallback == GpuStatsInfo::Driver::NONE) {
Yiwei Zhangd9861812019-02-13 11:51:55 -0800358 mGpuStats.glDriverFallback = driver;
359 }
360 break;
361 }
Yiwei Zhang27ab3ac2019-07-02 18:10:55 -0700362 case GpuStatsInfo::Driver::VULKAN:
363 case GpuStatsInfo::Driver::VULKAN_UPDATED: {
Yiwei Zhang472cab02019-08-05 17:57:41 -0700364 if (mGpuStats.vkDriverToLoad == GpuStatsInfo::Driver::NONE ||
365 mGpuStats.vkDriverToLoad == GpuStatsInfo::Driver::VULKAN) {
Yiwei Zhangd9861812019-02-13 11:51:55 -0800366 mGpuStats.vkDriverToLoad = driver;
367 break;
368 }
369
Yiwei Zhang27ab3ac2019-07-02 18:10:55 -0700370 if (mGpuStats.vkDriverFallback == GpuStatsInfo::Driver::NONE) {
Yiwei Zhangd9861812019-02-13 11:51:55 -0800371 mGpuStats.vkDriverFallback = driver;
372 }
373 break;
374 }
375 default:
376 break;
377 }
378}
379
Yiwei Zhang27ab3ac2019-07-02 18:10:55 -0700380void GraphicsEnv::setDriverLoaded(GpuStatsInfo::Api api, bool isDriverLoaded,
Yiwei Zhang5c640c12019-05-08 18:29:38 -0700381 int64_t driverLoadingTime) {
Yiwei Zhangd9861812019-02-13 11:51:55 -0800382 ATRACE_CALL();
383
384 std::lock_guard<std::mutex> lock(mStatsLock);
Yiwei Zhang27ab3ac2019-07-02 18:10:55 -0700385 if (api == GpuStatsInfo::Api::API_GL) {
Yiwei Zhangd3819382020-01-07 19:53:56 -0800386 mGpuStats.glDriverToSend = true;
Yiwei Zhang5c640c12019-05-08 18:29:38 -0700387 mGpuStats.glDriverLoadingTime = driverLoadingTime;
Yiwei Zhangd9861812019-02-13 11:51:55 -0800388 } else {
Yiwei Zhangd3819382020-01-07 19:53:56 -0800389 mGpuStats.vkDriverToSend = true;
Yiwei Zhang5c640c12019-05-08 18:29:38 -0700390 mGpuStats.vkDriverLoadingTime = driverLoadingTime;
Yiwei Zhangd9861812019-02-13 11:51:55 -0800391 }
392
Yiwei Zhang5c640c12019-05-08 18:29:38 -0700393 sendGpuStatsLocked(api, isDriverLoaded, driverLoadingTime);
Yiwei Zhangd9861812019-02-13 11:51:55 -0800394}
395
Serdar Kocdemirb2901c92022-11-17 00:39:05 +0000396// Hash function to calculate hash for null-terminated Vulkan extension names
397// We store hash values of the extensions, rather than the actual names or
398// indices to be able to support new extensions easily, avoid creating
399// a table of 'known' extensions inside Android and reduce the runtime overhead.
400static uint64_t calculateExtensionHash(const char* word) {
401 if (!word) {
402 return 0;
403 }
404 const size_t wordLen = strlen(word);
405 const uint32_t seed = 167;
406 uint64_t hash = 0;
407 for (size_t i = 0; i < wordLen; i++) {
408 hash = (hash * seed) + word[i];
409 }
410 return hash;
411}
412
413void GraphicsEnv::setVulkanInstanceExtensions(uint32_t enabledExtensionCount,
414 const char* const* ppEnabledExtensionNames) {
415 ATRACE_CALL();
416 if (enabledExtensionCount == 0 || ppEnabledExtensionNames == nullptr) {
417 return;
418 }
419
420 const uint32_t maxNumStats = android::GpuStatsAppInfo::MAX_NUM_EXTENSIONS;
421 uint64_t extensionHashes[maxNumStats];
422 const uint32_t numStats = std::min(enabledExtensionCount, maxNumStats);
423 for(uint32_t i = 0; i < numStats; i++) {
424 extensionHashes[i] = calculateExtensionHash(ppEnabledExtensionNames[i]);
425 }
426 setTargetStatsArray(android::GpuStatsInfo::Stats::VULKAN_INSTANCE_EXTENSION,
427 extensionHashes, numStats);
428}
429
430void GraphicsEnv::setVulkanDeviceExtensions(uint32_t enabledExtensionCount,
431 const char* const* ppEnabledExtensionNames) {
432 ATRACE_CALL();
433 if (enabledExtensionCount == 0 || ppEnabledExtensionNames == nullptr) {
434 return;
435 }
436
437 const uint32_t maxNumStats = android::GpuStatsAppInfo::MAX_NUM_EXTENSIONS;
438 uint64_t extensionHashes[maxNumStats];
439 const uint32_t numStats = std::min(enabledExtensionCount, maxNumStats);
440 for(uint32_t i = 0; i < numStats; i++) {
441 extensionHashes[i] = calculateExtensionHash(ppEnabledExtensionNames[i]);
442 }
443 setTargetStatsArray(android::GpuStatsInfo::Stats::VULKAN_DEVICE_EXTENSION,
444 extensionHashes, numStats);
445}
446
Yiwei Zhangd3819382020-01-07 19:53:56 -0800447bool GraphicsEnv::readyToSendGpuStatsLocked() {
448 // Only send stats for processes having at least one activity launched and that process doesn't
449 // skip the GraphicsEnvironment setup.
450 return mActivityLaunched && !mGpuStats.appPackageName.empty();
451}
452
Yiwei Zhangbcba4112019-07-03 13:39:32 -0700453void GraphicsEnv::setTargetStats(const GpuStatsInfo::Stats stats, const uint64_t value) {
Serdar Kocdemirb2901c92022-11-17 00:39:05 +0000454 return setTargetStatsArray(stats, &value, 1);
455}
456
457void GraphicsEnv::setTargetStatsArray(const GpuStatsInfo::Stats stats, const uint64_t* values,
458 const uint32_t valueCount) {
Yiwei Zhang8c5e3bd2019-05-09 14:34:19 -0700459 ATRACE_CALL();
460
Yiwei Zhang8c5e3bd2019-05-09 14:34:19 -0700461 std::lock_guard<std::mutex> lock(mStatsLock);
Yiwei Zhangd3819382020-01-07 19:53:56 -0800462 if (!readyToSendGpuStatsLocked()) return;
463
Yiwei Zhang8c5e3bd2019-05-09 14:34:19 -0700464 const sp<IGpuService> gpuService = getGpuService();
465 if (gpuService) {
Serdar Kocdemirb2901c92022-11-17 00:39:05 +0000466 gpuService->setTargetStatsArray(mGpuStats.appPackageName, mGpuStats.driverVersionCode,
467 stats, values, valueCount);
Yiwei Zhang8c5e3bd2019-05-09 14:34:19 -0700468 }
469}
470
Yiwei Zhang27ab3ac2019-07-02 18:10:55 -0700471void GraphicsEnv::sendGpuStatsLocked(GpuStatsInfo::Api api, bool isDriverLoaded,
Yiwei Zhangd9861812019-02-13 11:51:55 -0800472 int64_t driverLoadingTime) {
Yiwei Zhangcb9d4e42019-02-06 20:22:59 -0800473 ATRACE_CALL();
474
Yiwei Zhangd3819382020-01-07 19:53:56 -0800475 if (!readyToSendGpuStatsLocked()) return;
Yiwei Zhangcb9d4e42019-02-06 20:22:59 -0800476
477 ALOGV("sendGpuStats:\n"
478 "\tdriverPackageName[%s]\n"
479 "\tdriverVersionName[%s]\n"
Yiwei Zhang96c01712019-02-19 16:00:25 -0800480 "\tdriverVersionCode[%" PRIu64 "]\n"
481 "\tdriverBuildTime[%" PRId64 "]\n"
Yiwei Zhangd9861812019-02-13 11:51:55 -0800482 "\tappPackageName[%s]\n"
Yiwei Zhang794d2952019-05-06 17:43:59 -0700483 "\tvulkanVersion[%d]\n"
Yiwei Zhang5c640c12019-05-08 18:29:38 -0700484 "\tapi[%d]\n"
Yiwei Zhangd9861812019-02-13 11:51:55 -0800485 "\tisDriverLoaded[%d]\n"
Yiwei Zhang96c01712019-02-19 16:00:25 -0800486 "\tdriverLoadingTime[%" PRId64 "]",
Yiwei Zhangcb9d4e42019-02-06 20:22:59 -0800487 mGpuStats.driverPackageName.c_str(), mGpuStats.driverVersionName.c_str(),
Yiwei Zhang96c01712019-02-19 16:00:25 -0800488 mGpuStats.driverVersionCode, mGpuStats.driverBuildTime, mGpuStats.appPackageName.c_str(),
Yiwei Zhang5c640c12019-05-08 18:29:38 -0700489 mGpuStats.vulkanVersion, static_cast<int32_t>(api), isDriverLoaded, driverLoadingTime);
490
Yiwei Zhang27ab3ac2019-07-02 18:10:55 -0700491 GpuStatsInfo::Driver driver = GpuStatsInfo::Driver::NONE;
Yiwei Zhang5c640c12019-05-08 18:29:38 -0700492 bool isIntendedDriverLoaded = false;
Yiwei Zhang27ab3ac2019-07-02 18:10:55 -0700493 if (api == GpuStatsInfo::Api::API_GL) {
Yiwei Zhang5c640c12019-05-08 18:29:38 -0700494 driver = mGpuStats.glDriverToLoad;
495 isIntendedDriverLoaded =
Yiwei Zhang27ab3ac2019-07-02 18:10:55 -0700496 isDriverLoaded && (mGpuStats.glDriverFallback == GpuStatsInfo::Driver::NONE);
Yiwei Zhang5c640c12019-05-08 18:29:38 -0700497 } else {
498 driver = mGpuStats.vkDriverToLoad;
499 isIntendedDriverLoaded =
Yiwei Zhang27ab3ac2019-07-02 18:10:55 -0700500 isDriverLoaded && (mGpuStats.vkDriverFallback == GpuStatsInfo::Driver::NONE);
Yiwei Zhang5c640c12019-05-08 18:29:38 -0700501 }
Yiwei Zhangcb9d4e42019-02-06 20:22:59 -0800502
Yiwei Zhangd9861812019-02-13 11:51:55 -0800503 const sp<IGpuService> gpuService = getGpuService();
504 if (gpuService) {
505 gpuService->setGpuStats(mGpuStats.driverPackageName, mGpuStats.driverVersionName,
Yiwei Zhang96c01712019-02-19 16:00:25 -0800506 mGpuStats.driverVersionCode, mGpuStats.driverBuildTime,
Yiwei Zhang794d2952019-05-06 17:43:59 -0700507 mGpuStats.appPackageName, mGpuStats.vulkanVersion, driver,
Yiwei Zhang5c640c12019-05-08 18:29:38 -0700508 isIntendedDriverLoaded, driverLoadingTime);
Yiwei Zhangcb9d4e42019-02-06 20:22:59 -0800509 }
Yiwei Zhangcb9d4e42019-02-06 20:22:59 -0800510}
511
Adam Bodnar0afcca02019-09-17 13:23:17 -0700512bool GraphicsEnv::setInjectLayersPrSetDumpable() {
513 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
514 return false;
515 }
516 return true;
517}
518
Peiyong Linef20e4e2023-07-03 02:33:00 +0000519/**
520 * APIs for ANGLE
521 */
522
Tim Van Patten5f744f12018-12-12 11:46:21 -0700523bool GraphicsEnv::shouldUseAngle() {
524 // Make sure we are init'ed
Peiyong Lin2f51e752023-06-15 22:35:14 +0000525 if (mPackageName.empty()) {
526 ALOGV("Package name is empty. setAngleInfo() has not been called to enable ANGLE.");
Tim Van Patten5f744f12018-12-12 11:46:21 -0700527 return false;
528 }
529
Peiyong Lin17190c92023-06-21 07:03:47 +0000530 return mShouldUseAngle;
Tim Van Patten5f744f12018-12-12 11:46:21 -0700531}
532
Peiyong Lin2df5a002023-08-01 23:31:34 +0000533// Set ANGLE information.
534// If path is "system", it means system ANGLE must be used for the process.
535// If shouldUseNativeDriver is true, it means native GLES drivers must be used for the process.
536// If path is set to nonempty and shouldUseNativeDriver is true, ANGLE will be used regardless.
537void GraphicsEnv::setAngleInfo(const std::string& path, const bool shouldUseNativeDriver,
Peiyong Lin17190c92023-06-21 07:03:47 +0000538 const std::string& packageName,
Tim Van Pattena53dcb22021-05-21 17:51:59 -0600539 const std::vector<std::string> eglFeatures) {
Peiyong Lin17190c92023-06-21 07:03:47 +0000540 if (mShouldUseAngle) {
541 // ANGLE is already set up for this application process, even if the application
542 // needs to switch from apk to system or vice versa, the application process must
543 // be killed and relaunch so that the loader can properly load ANGLE again.
544 // The architecture does not support runtime switch between drivers, so just return.
545 ALOGE("ANGLE is already set for %s", packageName.c_str());
Tim Van Patten8bd24e92019-02-08 10:16:40 -0700546 return;
547 }
548
Peiyong Lin2f707e62020-09-26 13:52:10 -0700549 mAngleEglFeatures = std::move(eglFeatures);
Tim Van Patten5f744f12018-12-12 11:46:21 -0700550 ALOGV("setting ANGLE path to '%s'", path.c_str());
Peiyong Lin17190c92023-06-21 07:03:47 +0000551 mAnglePath = std::move(path);
Peiyong Lin2f51e752023-06-15 22:35:14 +0000552 ALOGV("setting app package name to '%s'", packageName.c_str());
Peiyong Lin17190c92023-06-21 07:03:47 +0000553 mPackageName = std::move(packageName);
Peiyong Lin2df5a002023-08-01 23:31:34 +0000554 if (mAnglePath == "system") {
555 mShouldUseSystemAngle = true;
556 }
557 if (!mAnglePath.empty()) {
558 mShouldUseAngle = true;
559 }
560 mShouldUseNativeDriver = shouldUseNativeDriver;
Cody Northrop1f00e172018-04-02 11:23:31 -0600561}
562
Peiyong Lin2f51e752023-06-15 22:35:14 +0000563std::string& GraphicsEnv::getPackageName() {
564 return mPackageName;
Cody Northrop04e70432018-09-06 10:34:58 -0600565}
566
Peiyong Lin2f707e62020-09-26 13:52:10 -0700567const std::vector<std::string>& GraphicsEnv::getAngleEglFeatures() {
568 return mAngleEglFeatures;
569}
570
Cody Northrop1f00e172018-04-02 11:23:31 -0600571android_namespace_t* GraphicsEnv::getAngleNamespace() {
Cody Northrop3892cfa2019-01-30 10:03:12 -0700572 std::lock_guard<std::mutex> lock(mNamespaceMutex);
Cody Northrop1f00e172018-04-02 11:23:31 -0600573
Cody Northrop3892cfa2019-01-30 10:03:12 -0700574 if (mAngleNamespace) {
575 return mAngleNamespace;
576 }
577
Peiyong Line88e0ba2023-06-28 15:09:09 +0000578 if (mAnglePath.empty() && !mShouldUseSystemAngle) {
Peiyong Lin17190c92023-06-21 07:03:47 +0000579 ALOGV("mAnglePath is empty and not using system ANGLE, abort creating ANGLE namespace");
Cody Northrop3892cfa2019-01-30 10:03:12 -0700580 return nullptr;
581 }
582
Peiyong Lin17190c92023-06-21 07:03:47 +0000583 // Construct the search paths for system ANGLE.
584 const char* const defaultLibraryPaths =
585#if defined(__LP64__)
586 "/vendor/lib64/egl:/system/lib64/egl";
587#else
588 "/vendor/lib/egl:/system/lib/egl";
589#endif
590
591 // If the application process will run on top of system ANGLE, construct the namespace
592 // with sphal namespace being the parent namespace so that search paths and libraries
593 // are properly inherited.
594 mAngleNamespace =
595 android_create_namespace("ANGLE",
Peiyong Line88e0ba2023-06-28 15:09:09 +0000596 mShouldUseSystemAngle ? defaultLibraryPaths
597 : mAnglePath.c_str(), // ld_library_path
598 mShouldUseSystemAngle
599 ? defaultLibraryPaths
600 : mAnglePath.c_str(), // default_library_path
Peiyong Lin17190c92023-06-21 07:03:47 +0000601 ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED,
602 nullptr, // permitted_when_isolated_path
Peiyong Line88e0ba2023-06-28 15:09:09 +0000603 mShouldUseSystemAngle ? android_get_exported_namespace("sphal")
604 : nullptr); // parent
Cody Northrop3892cfa2019-01-30 10:03:12 -0700605
606 ALOGD_IF(!mAngleNamespace, "Could not create ANGLE namespace from default");
Cody Northrop1f00e172018-04-02 11:23:31 -0600607
Peiyong Line88e0ba2023-06-28 15:09:09 +0000608 if (!mShouldUseSystemAngle) {
Peiyong Lin17190c92023-06-21 07:03:47 +0000609 return mAngleNamespace;
610 }
611
612 auto vndkNamespace = android_get_exported_namespace("vndk");
613 if (!vndkNamespace) {
614 return nullptr;
615 }
616
617 if (!linkDriverNamespaceLocked(mAngleNamespace, vndkNamespace, "")) {
618 mAngleNamespace = nullptr;
619 }
620
Cody Northrop1f00e172018-04-02 11:23:31 -0600621 return mAngleNamespace;
622}
623
Yuxin Hub69e9882023-04-13 03:51:41 +0000624void GraphicsEnv::nativeToggleAngleAsSystemDriver(bool enabled) {
625 const sp<IGpuService> gpuService = getGpuService();
626 if (!gpuService) {
627 ALOGE("No GPU service");
628 return;
629 }
630 gpuService->toggleAngleAsSystemDriver(enabled);
631}
632
Peiyong Line88e0ba2023-06-28 15:09:09 +0000633bool GraphicsEnv::shouldUseSystemAngle() {
634 return mShouldUseSystemAngle;
635}
636
Peiyong Lin2df5a002023-08-01 23:31:34 +0000637bool GraphicsEnv::shouldUseNativeDriver() {
638 return mShouldUseNativeDriver;
639}
640
Peiyong Linef20e4e2023-07-03 02:33:00 +0000641/**
642 * APIs for debuggable layers
643 */
644
645void GraphicsEnv::setLayerPaths(NativeLoaderNamespace* appNamespace,
646 const std::string& layerPaths) {
647 if (mLayerPaths.empty()) {
648 mLayerPaths = layerPaths;
649 mAppNamespace = appNamespace;
650 } else {
651 ALOGV("Vulkan layer search path already set, not clobbering with '%s' for namespace %p'",
652 layerPaths.c_str(), appNamespace);
653 }
654}
655
656NativeLoaderNamespace* GraphicsEnv::getAppNamespace() {
657 return mAppNamespace;
658}
659
660const std::string& GraphicsEnv::getLayerPaths() {
661 return mLayerPaths;
662}
663
664const std::string& GraphicsEnv::getDebugLayers() {
665 return mDebugLayers;
666}
667
668const std::string& GraphicsEnv::getDebugLayersGLES() {
669 return mDebugLayersGLES;
670}
671
672void GraphicsEnv::setDebugLayers(const std::string& layers) {
673 mDebugLayers = layers;
674}
675
676void GraphicsEnv::setDebugLayersGLES(const std::string& layers) {
677 mDebugLayersGLES = layers;
678}
679
Jesse Hall90b25ed2016-12-12 12:56:46 -0800680} // namespace android