xref: /aosp_15_r20/frameworks/native/libs/graphicsenv/GraphicsEnv.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1 /*
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 
17 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
18 
19 //#define LOG_NDEBUG 1
20 #define LOG_TAG "GraphicsEnv"
21 
22 #include <graphicsenv/GraphicsEnv.h>
23 
24 #include <dlfcn.h>
25 #include <unistd.h>
26 
27 #include <android-base/file.h>
28 #include <android-base/properties.h>
29 #include <android-base/strings.h>
30 #include <android/dlext.h>
31 #include <binder/IServiceManager.h>
32 #include <graphicsenv/IGpuService.h>
33 #include <log/log.h>
34 #include <nativeloader/dlext_namespaces.h>
35 #include <sys/prctl.h>
36 #include <utils/Trace.h>
37 
38 #include <memory>
39 #include <string>
40 #include <thread>
41 
42 // 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 
49 // 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:
52 typedef bool (*fpANGLEGetFeatureSupportUtilAPIVersion)(unsigned int* versionToUse);
53 typedef bool (*fpANGLEAndroidParseRulesString)(const char* rulesString, void** rulesHandle,
54                                                int* rulesVersion);
55 typedef bool (*fpANGLEGetSystemInfo)(void** handle);
56 typedef bool (*fpANGLEAddDeviceInfoToSystemInfo)(const char* deviceMfr, const char* deviceModel,
57                                                  void* handle);
58 typedef bool (*fpANGLEShouldBeUsedForApplication)(void* rulesHandle, int rulesVersion,
59                                                   void* systemInfoHandle, const char* appName);
60 typedef bool (*fpANGLEFreeRulesHandle)(void* handle);
61 typedef bool (*fpANGLEFreeSystemInfoHandle)(void* handle);
62 
63 namespace {
isVndkEnabled()64 static bool isVndkEnabled() {
65 #ifdef __BIONIC__
66     static bool isVndkEnabled = android::base::GetProperty("ro.vndk.version", "") != "";
67     return isVndkEnabled;
68 #endif
69     return false;
70 }
71 } // namespace
72 
73 namespace android {
74 
75 enum NativeLibrary {
76     LLNDK = 0,
77     VNDKSP = 1,
78 };
79 
80 static constexpr const char* kNativeLibrariesSystemConfigPath[] =
81         {"/apex/com.android.vndk.v{}/etc/llndk.libraries.{}.txt",
82          "/apex/com.android.vndk.v{}/etc/vndksp.libraries.{}.txt"};
83 
84 static const char* kLlndkLibrariesTxtPath = "/system/etc/llndk.libraries.txt";
85 
86 // List of libraries that were previously available via VNDK-SP,
87 // and are now available via SPHAL.
88 // On modern devices that lack the VNDK APEX, the device no longer
89 // contains a helpful list of these libraries on the filesystem as above.
90 // See system/sepolicy/vendor/file_contexts
91 static const char* kFormerlyVndkspLibrariesList =
92     "android.hardware.common-V2-ndk.so:"
93     "android.hardware.common.fmq-V1-ndk.so:"
94     "android.hardware.graphics.allocator-V2-ndk.so:"
95     "android.hardware.graphics.common-V6-ndk.so:"
96     "[email protected]:"
97     "[email protected]:"
98     "[email protected]:"
99     "android.hardware.graphics.composer3-V1-ndk.so:"
100     "[email protected]:"
101     "[email protected]:"
102     "[email protected]:"
103     "[email protected]:"
104     "[email protected]:"
105     "[email protected]:"
106     "[email protected]:"
107     "[email protected]:"
108     "[email protected]:"
109     "libRSCpuRef.so:"
110     "libRSDriver.so:"
111     "libRS_internal.so:"
112     "libbacktrace.so:"
113     "libbase.so:"
114     "libbcinfo.so:"
115     "libblas.so:"
116     "libc++.so:"
117     "libcompiler_rt.so:"
118     "libcutils.so:"
119     "libdmabufheap.so:"
120     "libft2.so:"
121     "libgralloctypes.so:"
122     "libhardware.so:"
123     "libhidlbase.so:"
124     "libhidlmemory.so:"
125     "libion.so:"
126     "libjsoncpp.so:"
127     "liblzma.so:"
128     "libpng.so:"
129     "libprocessgroup.so:"
130     "libunwindstack.so:"
131     "libutils.so:"
132     "libutilscallstack.so:"
133     "libz.so";
134 
vndkVersionStr()135 static std::string vndkVersionStr() {
136 #ifdef __BIONIC__
137     return base::GetProperty("ro.vndk.version", "");
138 #endif
139     return "";
140 }
141 
insertVndkVersionStr(std::string * fileName)142 static void insertVndkVersionStr(std::string* fileName) {
143     LOG_ALWAYS_FATAL_IF(!fileName, "fileName should never be nullptr");
144     std::string version = vndkVersionStr();
145     size_t pos = fileName->find("{}");
146     while (pos != std::string::npos) {
147         fileName->replace(pos, 2, version);
148         pos = fileName->find("{}", pos + version.size());
149     }
150 }
151 
readConfig(const std::string & configFile,std::vector<std::string> * soNames)152 static bool readConfig(const std::string& configFile, std::vector<std::string>* soNames) {
153     // Read list of public native libraries from the config file.
154     std::string fileContent;
155     if (!base::ReadFileToString(configFile, &fileContent)) {
156         return false;
157     }
158 
159     std::vector<std::string> lines = base::Split(fileContent, "\n");
160 
161     for (auto& line : lines) {
162         auto trimmedLine = base::Trim(line);
163         if (!trimmedLine.empty()) {
164             soNames->push_back(trimmedLine);
165         }
166     }
167 
168     return true;
169 }
170 
getSystemNativeLibraries(NativeLibrary type)171 static const std::string getSystemNativeLibraries(NativeLibrary type) {
172     std::string nativeLibrariesSystemConfig = "";
173 
174     if (!isVndkEnabled()) {
175         if (type == NativeLibrary::VNDKSP) {
176             return kFormerlyVndkspLibrariesList;
177         } else {
178             nativeLibrariesSystemConfig = kLlndkLibrariesTxtPath;
179         }
180     } else {
181         nativeLibrariesSystemConfig = kNativeLibrariesSystemConfigPath[type];
182         insertVndkVersionStr(&nativeLibrariesSystemConfig);
183     }
184 
185     std::vector<std::string> soNames;
186     if (!readConfig(nativeLibrariesSystemConfig, &soNames)) {
187         ALOGE("Failed to retrieve library names from %s", nativeLibrariesSystemConfig.c_str());
188         return "";
189     }
190 
191     return base::Join(soNames, ':');
192 }
193 
getGpuService()194 static sp<IGpuService> getGpuService() {
195     static const sp<IBinder> binder = defaultServiceManager()->checkService(String16("gpu"));
196     if (!binder) {
197         ALOGE("Failed to get gpu service");
198         return nullptr;
199     }
200 
201     return interface_cast<IGpuService>(binder);
202 }
203 
getInstance()204 /*static*/ GraphicsEnv& GraphicsEnv::getInstance() {
205     static GraphicsEnv env;
206     return env;
207 }
208 
isDebuggable()209 bool GraphicsEnv::isDebuggable() {
210     // This flag determines if the application is marked debuggable
211     bool appDebuggable = prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) > 0;
212 
213     // This flag is set only in `debuggable` builds of the platform
214 #if defined(ANDROID_DEBUGGABLE)
215     bool platformDebuggable = true;
216 #else
217     bool platformDebuggable = false;
218 #endif
219 
220     ALOGV("GraphicsEnv::isDebuggable returning appDebuggable=%s || platformDebuggable=%s",
221           appDebuggable ? "true" : "false", platformDebuggable ? "true" : "false");
222 
223     return appDebuggable || platformDebuggable;
224 }
225 
226 /**
227  * APIs for updatable graphics drivers
228  */
229 
setDriverPathAndSphalLibraries(const std::string & path,const std::string & sphalLibraries)230 void GraphicsEnv::setDriverPathAndSphalLibraries(const std::string& path,
231                                                  const std::string& sphalLibraries) {
232     if (!mDriverPath.empty() || !mSphalLibraries.empty()) {
233         ALOGV("ignoring attempt to change driver path from '%s' to '%s' or change sphal libraries "
234               "from '%s' to '%s'",
235               mDriverPath.c_str(), path.c_str(), mSphalLibraries.c_str(), sphalLibraries.c_str());
236         return;
237     }
238     ALOGV("setting driver path to '%s' and sphal libraries to '%s'", path.c_str(),
239           sphalLibraries.c_str());
240     mDriverPath = path;
241     mSphalLibraries = sphalLibraries;
242 }
243 
244 // Return true if all the required libraries from vndk and sphal namespace are
245 // linked to the driver namespace correctly.
linkDriverNamespaceLocked(android_namespace_t * destNamespace,android_namespace_t * vndkNamespace,const std::string & sharedSphalLibraries)246 bool GraphicsEnv::linkDriverNamespaceLocked(android_namespace_t* destNamespace,
247                                             android_namespace_t* vndkNamespace,
248                                             const std::string& sharedSphalLibraries) {
249     const std::string llndkLibraries = getSystemNativeLibraries(NativeLibrary::LLNDK);
250     if (llndkLibraries.empty()) {
251         return false;
252     }
253     if (!android_link_namespaces(destNamespace, nullptr, llndkLibraries.c_str())) {
254         ALOGE("Failed to link default namespace[%s]", dlerror());
255         return false;
256     }
257 
258     const std::string vndkspLibraries = getSystemNativeLibraries(NativeLibrary::VNDKSP);
259     if (vndkspLibraries.empty()) {
260         return false;
261     }
262     if (!android_link_namespaces(destNamespace, vndkNamespace, vndkspLibraries.c_str())) {
263         ALOGE("Failed to link vndk namespace[%s]", dlerror());
264         return false;
265     }
266 
267     if (sharedSphalLibraries.empty()) {
268         return true;
269     }
270 
271     // Make additional libraries in sphal to be accessible
272     auto sphalNamespace = android_get_exported_namespace("sphal");
273     if (!sphalNamespace) {
274         ALOGE("Depend on these libraries[%s] in sphal, but failed to get sphal namespace",
275               sharedSphalLibraries.c_str());
276         return false;
277     }
278 
279     if (!android_link_namespaces(destNamespace, sphalNamespace, sharedSphalLibraries.c_str())) {
280         ALOGE("Failed to link sphal namespace[%s]", dlerror());
281         return false;
282     }
283 
284     return true;
285 }
286 
getDriverNamespace()287 android_namespace_t* GraphicsEnv::getDriverNamespace() {
288     std::lock_guard<std::mutex> lock(mNamespaceMutex);
289 
290     if (mDriverNamespace) {
291         return mDriverNamespace;
292     }
293 
294     if (mDriverPath.empty()) {
295         // For an application process, driver path is empty means this application is not opted in
296         // to use updatable driver. Application process doesn't have the ability to set up
297         // environment variables and hence before `getenv` call will return.
298         // For a process that is not an application process, if it's run from an environment,
299         // for example shell, where environment variables can be set, then it can opt into using
300         // udpatable driver by setting UPDATABLE_GFX_DRIVER to 1. By setting to 1 the developer
301         // driver will be used currently.
302         // TODO(b/159240322) Support the production updatable driver.
303         const char* id = getenv("UPDATABLE_GFX_DRIVER");
304         if (id == nullptr || std::strcmp(id, "1") != 0) {
305             return nullptr;
306         }
307         const sp<IGpuService> gpuService = getGpuService();
308         if (!gpuService) {
309             return nullptr;
310         }
311         mDriverPath = gpuService->getUpdatableDriverPath();
312         if (mDriverPath.empty()) {
313             return nullptr;
314         }
315         mDriverPath.append(UPDATABLE_DRIVER_ABI);
316         ALOGI("Driver path is setup via UPDATABLE_GFX_DRIVER: %s", mDriverPath.c_str());
317     }
318 
319     auto vndkNamespace = android_get_exported_namespace(isVndkEnabled() ? "vndk" : "sphal");
320     if (!vndkNamespace) {
321         mDriverNamespace = nullptr;
322         return mDriverNamespace;
323     }
324 
325     mDriverNamespace = android_create_namespace("updatable gfx driver",
326                                                 mDriverPath.c_str(), // ld_library_path
327                                                 mDriverPath.c_str(), // default_library_path
328                                                 ANDROID_NAMESPACE_TYPE_ISOLATED,
329                                                 nullptr, // permitted_when_isolated_path
330                                                 nullptr);
331 
332     if (!linkDriverNamespaceLocked(mDriverNamespace, vndkNamespace, mSphalLibraries)) {
333         mDriverNamespace = nullptr;
334     }
335 
336     return mDriverNamespace;
337 }
338 
getDriverPath() const339 std::string GraphicsEnv::getDriverPath() const {
340     return mDriverPath;
341 }
342 
343 /**
344  * APIs for GpuStats
345  */
346 
hintActivityLaunch()347 void GraphicsEnv::hintActivityLaunch() {
348     ATRACE_CALL();
349 
350     {
351         std::lock_guard<std::mutex> lock(mStatsLock);
352         if (mActivityLaunched) return;
353         mActivityLaunched = true;
354     }
355 
356     std::thread trySendGpuStatsThread([this]() {
357         // If there's already graphics driver preloaded in the process, just send
358         // the stats info to GpuStats directly through async binder.
359         std::lock_guard<std::mutex> lock(mStatsLock);
360         if (mGpuStats.glDriverToSend) {
361             mGpuStats.glDriverToSend = false;
362             sendGpuStatsLocked(GpuStatsInfo::Api::API_GL, true, mGpuStats.glDriverLoadingTime);
363         }
364         if (mGpuStats.vkDriverToSend) {
365             mGpuStats.vkDriverToSend = false;
366             sendGpuStatsLocked(GpuStatsInfo::Api::API_VK, true, mGpuStats.vkDriverLoadingTime);
367         }
368     });
369     trySendGpuStatsThread.detach();
370 }
371 
setGpuStats(const std::string & driverPackageName,const std::string & driverVersionName,uint64_t driverVersionCode,int64_t driverBuildTime,const std::string & appPackageName,const int vulkanVersion)372 void GraphicsEnv::setGpuStats(const std::string& driverPackageName,
373                               const std::string& driverVersionName, uint64_t driverVersionCode,
374                               int64_t driverBuildTime, const std::string& appPackageName,
375                               const int vulkanVersion) {
376     ATRACE_CALL();
377 
378     std::lock_guard<std::mutex> lock(mStatsLock);
379     ALOGV("setGpuStats:\n"
380           "\tdriverPackageName[%s]\n"
381           "\tdriverVersionName[%s]\n"
382           "\tdriverVersionCode[%" PRIu64 "]\n"
383           "\tdriverBuildTime[%" PRId64 "]\n"
384           "\tappPackageName[%s]\n"
385           "\tvulkanVersion[%d]\n",
386           driverPackageName.c_str(), driverVersionName.c_str(), driverVersionCode, driverBuildTime,
387           appPackageName.c_str(), vulkanVersion);
388 
389     mGpuStats.driverPackageName = driverPackageName;
390     mGpuStats.driverVersionName = driverVersionName;
391     mGpuStats.driverVersionCode = driverVersionCode;
392     mGpuStats.driverBuildTime = driverBuildTime;
393     mGpuStats.appPackageName = appPackageName;
394     mGpuStats.vulkanVersion = vulkanVersion;
395 }
396 
setDriverToLoad(GpuStatsInfo::Driver driver)397 void GraphicsEnv::setDriverToLoad(GpuStatsInfo::Driver driver) {
398     ATRACE_CALL();
399 
400     std::lock_guard<std::mutex> lock(mStatsLock);
401     switch (driver) {
402         case GpuStatsInfo::Driver::GL:
403         case GpuStatsInfo::Driver::GL_UPDATED:
404         case GpuStatsInfo::Driver::ANGLE:
405             mGpuStats.glDriverToLoad = driver;
406             break;
407 
408         case GpuStatsInfo::Driver::VULKAN:
409         case GpuStatsInfo::Driver::VULKAN_UPDATED: {
410             if (mGpuStats.vkDriverToLoad == GpuStatsInfo::Driver::NONE ||
411                 mGpuStats.vkDriverToLoad == GpuStatsInfo::Driver::VULKAN) {
412                 mGpuStats.vkDriverToLoad = driver;
413                 break;
414             }
415 
416             if (mGpuStats.vkDriverFallback == GpuStatsInfo::Driver::NONE) {
417                 mGpuStats.vkDriverFallback = driver;
418             }
419             break;
420         }
421         default:
422             break;
423     }
424 }
425 
setDriverLoaded(GpuStatsInfo::Api api,bool isDriverLoaded,int64_t driverLoadingTime)426 void GraphicsEnv::setDriverLoaded(GpuStatsInfo::Api api, bool isDriverLoaded,
427                                   int64_t driverLoadingTime) {
428     ATRACE_CALL();
429 
430     std::lock_guard<std::mutex> lock(mStatsLock);
431     if (api == GpuStatsInfo::Api::API_GL) {
432         mGpuStats.glDriverToSend = true;
433         mGpuStats.glDriverLoadingTime = driverLoadingTime;
434     } else {
435         mGpuStats.vkDriverToSend = true;
436         mGpuStats.vkDriverLoadingTime = driverLoadingTime;
437     }
438 
439     sendGpuStatsLocked(api, isDriverLoaded, driverLoadingTime);
440 }
441 
442 // Hash function to calculate hash for null-terminated Vulkan extension names
443 // We store hash values of the extensions, rather than the actual names or
444 // indices to be able to support new extensions easily, avoid creating
445 // a table of 'known' extensions inside Android and reduce the runtime overhead.
calculateExtensionHash(const char * word)446 static uint64_t calculateExtensionHash(const char* word) {
447     if (!word) {
448         return 0;
449     }
450     const size_t wordLen = strlen(word);
451     const uint32_t seed = 167;
452     uint64_t hash = 0;
453     for (size_t i = 0; i < wordLen; i++) {
454         hash = (hash * seed) + word[i];
455     }
456     return hash;
457 }
458 
setVulkanInstanceExtensions(uint32_t enabledExtensionCount,const char * const * ppEnabledExtensionNames)459 void GraphicsEnv::setVulkanInstanceExtensions(uint32_t enabledExtensionCount,
460                                               const char* const* ppEnabledExtensionNames) {
461     ATRACE_CALL();
462     if (enabledExtensionCount == 0 || ppEnabledExtensionNames == nullptr) {
463         return;
464     }
465 
466     const uint32_t maxNumStats = android::GpuStatsAppInfo::MAX_NUM_EXTENSIONS;
467     uint64_t extensionHashes[maxNumStats];
468     const uint32_t numStats = std::min(enabledExtensionCount, maxNumStats);
469     for(uint32_t i = 0; i < numStats; i++) {
470         extensionHashes[i] = calculateExtensionHash(ppEnabledExtensionNames[i]);
471     }
472     setTargetStatsArray(android::GpuStatsInfo::Stats::VULKAN_INSTANCE_EXTENSION,
473                         extensionHashes, numStats);
474 }
475 
setVulkanDeviceExtensions(uint32_t enabledExtensionCount,const char * const * ppEnabledExtensionNames)476 void GraphicsEnv::setVulkanDeviceExtensions(uint32_t enabledExtensionCount,
477                                             const char* const* ppEnabledExtensionNames) {
478     ATRACE_CALL();
479     if (enabledExtensionCount == 0 || ppEnabledExtensionNames == nullptr) {
480         return;
481     }
482 
483     const uint32_t maxNumStats = android::GpuStatsAppInfo::MAX_NUM_EXTENSIONS;
484     uint64_t extensionHashes[maxNumStats];
485     const uint32_t numStats = std::min(enabledExtensionCount, maxNumStats);
486     for(uint32_t i = 0; i < numStats; i++) {
487         extensionHashes[i] = calculateExtensionHash(ppEnabledExtensionNames[i]);
488     }
489     setTargetStatsArray(android::GpuStatsInfo::Stats::VULKAN_DEVICE_EXTENSION,
490                         extensionHashes, numStats);
491 }
492 
addVulkanEngineName(const char * engineName)493 void GraphicsEnv::addVulkanEngineName(const char* engineName) {
494     ATRACE_CALL();
495     if (engineName == nullptr) {
496         return;
497     }
498     std::lock_guard<std::mutex> lock(mStatsLock);
499     if (!readyToSendGpuStatsLocked()) return;
500 
501     const sp<IGpuService> gpuService = getGpuService();
502     if (gpuService) {
503         gpuService->addVulkanEngineName(mGpuStats.appPackageName, mGpuStats.driverVersionCode,
504                                         engineName);
505     }
506 }
507 
readyToSendGpuStatsLocked()508 bool GraphicsEnv::readyToSendGpuStatsLocked() {
509     // Only send stats for processes having at least one activity launched and that process doesn't
510     // skip the GraphicsEnvironment setup.
511     return mActivityLaunched && !mGpuStats.appPackageName.empty();
512 }
513 
setTargetStats(const GpuStatsInfo::Stats stats,const uint64_t value)514 void GraphicsEnv::setTargetStats(const GpuStatsInfo::Stats stats, const uint64_t value) {
515     return setTargetStatsArray(stats, &value, 1);
516 }
517 
setTargetStatsArray(const GpuStatsInfo::Stats stats,const uint64_t * values,const uint32_t valueCount)518 void GraphicsEnv::setTargetStatsArray(const GpuStatsInfo::Stats stats, const uint64_t* values,
519                                       const uint32_t valueCount) {
520     ATRACE_CALL();
521 
522     std::lock_guard<std::mutex> lock(mStatsLock);
523     if (!readyToSendGpuStatsLocked()) return;
524 
525     const sp<IGpuService> gpuService = getGpuService();
526     if (gpuService) {
527         gpuService->setTargetStatsArray(mGpuStats.appPackageName, mGpuStats.driverVersionCode,
528                                         stats, values, valueCount);
529     }
530 }
531 
sendGpuStatsLocked(GpuStatsInfo::Api api,bool isDriverLoaded,int64_t driverLoadingTime)532 void GraphicsEnv::sendGpuStatsLocked(GpuStatsInfo::Api api, bool isDriverLoaded,
533                                      int64_t driverLoadingTime) {
534     ATRACE_CALL();
535 
536     if (!readyToSendGpuStatsLocked()) return;
537 
538     ALOGV("sendGpuStats:\n"
539           "\tdriverPackageName[%s]\n"
540           "\tdriverVersionName[%s]\n"
541           "\tdriverVersionCode[%" PRIu64 "]\n"
542           "\tdriverBuildTime[%" PRId64 "]\n"
543           "\tappPackageName[%s]\n"
544           "\tvulkanVersion[%d]\n"
545           "\tapi[%d]\n"
546           "\tisDriverLoaded[%d]\n"
547           "\tdriverLoadingTime[%" PRId64 "]",
548           mGpuStats.driverPackageName.c_str(), mGpuStats.driverVersionName.c_str(),
549           mGpuStats.driverVersionCode, mGpuStats.driverBuildTime, mGpuStats.appPackageName.c_str(),
550           mGpuStats.vulkanVersion, static_cast<int32_t>(api), isDriverLoaded, driverLoadingTime);
551 
552     GpuStatsInfo::Driver driver = GpuStatsInfo::Driver::NONE;
553     bool isIntendedDriverLoaded = false;
554     if (api == GpuStatsInfo::Api::API_GL) {
555         driver = mGpuStats.glDriverToLoad;
556         isIntendedDriverLoaded = isDriverLoaded;
557     } else {
558         driver = mGpuStats.vkDriverToLoad;
559         isIntendedDriverLoaded =
560                 isDriverLoaded && (mGpuStats.vkDriverFallback == GpuStatsInfo::Driver::NONE);
561     }
562 
563     const sp<IGpuService> gpuService = getGpuService();
564     if (gpuService) {
565         gpuService->setGpuStats(mGpuStats.driverPackageName, mGpuStats.driverVersionName,
566                                 mGpuStats.driverVersionCode, mGpuStats.driverBuildTime,
567                                 mGpuStats.appPackageName, mGpuStats.vulkanVersion, driver,
568                                 isIntendedDriverLoaded, driverLoadingTime);
569     }
570 }
571 
setInjectLayersPrSetDumpable()572 bool GraphicsEnv::setInjectLayersPrSetDumpable() {
573     if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
574         return false;
575     }
576     return true;
577 }
578 
579 /**
580  * APIs for ANGLE
581  */
582 
shouldUseAngle()583 bool GraphicsEnv::shouldUseAngle() {
584     // Make sure we are init'ed
585     if (mPackageName.empty()) {
586         ALOGV("Package name is empty. setAngleInfo() has not been called to enable ANGLE.");
587         return false;
588     }
589 
590     return mShouldUseAngle;
591 }
592 
593 // Set ANGLE information.
594 // If path is "system", it means system ANGLE must be used for the process.
595 // If shouldUseNativeDriver is true, it means native GLES drivers must be used for the process.
596 // If path is set to nonempty and shouldUseNativeDriver is true, ANGLE will be used regardless.
setAngleInfo(const std::string & path,const bool shouldUseNativeDriver,const std::string & packageName,const std::vector<std::string> eglFeatures)597 void GraphicsEnv::setAngleInfo(const std::string& path, const bool shouldUseNativeDriver,
598                                const std::string& packageName,
599                                const std::vector<std::string> eglFeatures) {
600     if (mShouldUseAngle) {
601         // ANGLE is already set up for this application process, even if the application
602         // needs to switch from apk to system or vice versa, the application process must
603         // be killed and relaunch so that the loader can properly load ANGLE again.
604         // The architecture does not support runtime switch between drivers, so just return.
605         ALOGE("ANGLE is already set for %s", packageName.c_str());
606         return;
607     }
608 
609     mAngleEglFeatures = std::move(eglFeatures);
610     ALOGV("setting ANGLE path to '%s'", path.c_str());
611     mAnglePath = std::move(path);
612     ALOGV("setting app package name to '%s'", packageName.c_str());
613     mPackageName = std::move(packageName);
614     if (mAnglePath == "system") {
615         mShouldUseSystemAngle = true;
616     }
617     if (!mAnglePath.empty()) {
618         mShouldUseAngle = true;
619     }
620     mShouldUseNativeDriver = shouldUseNativeDriver;
621 }
622 
getPackageName()623 std::string& GraphicsEnv::getPackageName() {
624     return mPackageName;
625 }
626 
getAngleEglFeatures()627 const std::vector<std::string>& GraphicsEnv::getAngleEglFeatures() {
628     return mAngleEglFeatures;
629 }
630 
getAngleNamespace()631 android_namespace_t* GraphicsEnv::getAngleNamespace() {
632     std::lock_guard<std::mutex> lock(mNamespaceMutex);
633 
634     if (mAngleNamespace) {
635         return mAngleNamespace;
636     }
637 
638     // If ANGLE path is not set, it means ANGLE should not be used for this process;
639     // or if ANGLE path is set and set to use system ANGLE, then a namespace is not needed
640     // because:
641     //     1) if the default OpenGL ES driver is already ANGLE, then the loader will skip;
642     //     2) if the default OpenGL ES driver is native, then there's no symbol conflict;
643     //     3) if there's no OpenGL ES driver is preloaded, then there's no symbol conflict.
644     if (mAnglePath.empty() || mShouldUseSystemAngle) {
645         ALOGV("mAnglePath is empty or use system ANGLE, abort creating ANGLE namespace");
646         return nullptr;
647     }
648 
649     // Construct the search paths for system ANGLE.
650     const char* const defaultLibraryPaths =
651 #if defined(__LP64__)
652             "/vendor/lib64/egl:/system/lib64";
653 #else
654             "/vendor/lib/egl:/system/lib";
655 #endif
656 
657     // If the application process will run on top of system ANGLE, construct the namespace
658     // with sphal namespace being the parent namespace so that search paths and libraries
659     // are properly inherited.
660     mAngleNamespace =
661             android_create_namespace("ANGLE",
662                                      mShouldUseSystemAngle ? defaultLibraryPaths
663                                                            : mAnglePath.c_str(), // ld_library_path
664                                      mShouldUseSystemAngle
665                                              ? defaultLibraryPaths
666                                              : mAnglePath.c_str(), // default_library_path
667                                      ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED,
668                                      nullptr, // permitted_when_isolated_path
669                                      mShouldUseSystemAngle ? android_get_exported_namespace("sphal")
670                                                            : nullptr); // parent
671 
672     ALOGD_IF(!mAngleNamespace, "Could not create ANGLE namespace from default");
673 
674     if (!mShouldUseSystemAngle) {
675         return mAngleNamespace;
676     }
677 
678     auto vndkNamespace = android_get_exported_namespace(isVndkEnabled() ? "vndk" : "sphal");
679     if (!vndkNamespace) {
680         mAngleNamespace = nullptr;
681         return mAngleNamespace;
682     }
683 
684     if (!linkDriverNamespaceLocked(mAngleNamespace, vndkNamespace, "")) {
685         mAngleNamespace = nullptr;
686     }
687 
688     return mAngleNamespace;
689 }
690 
nativeToggleAngleAsSystemDriver(bool enabled)691 void GraphicsEnv::nativeToggleAngleAsSystemDriver(bool enabled) {
692     const sp<IGpuService> gpuService = getGpuService();
693     if (!gpuService) {
694         ALOGE("No GPU service");
695         return;
696     }
697     gpuService->toggleAngleAsSystemDriver(enabled);
698 }
699 
shouldUseSystemAngle()700 bool GraphicsEnv::shouldUseSystemAngle() {
701     return mShouldUseSystemAngle;
702 }
703 
shouldUseNativeDriver()704 bool GraphicsEnv::shouldUseNativeDriver() {
705     return mShouldUseNativeDriver;
706 }
707 
708 /**
709  * APIs for debuggable layers
710  */
711 
setLayerPaths(NativeLoaderNamespace * appNamespace,const std::string & layerPaths)712 void GraphicsEnv::setLayerPaths(NativeLoaderNamespace* appNamespace,
713                                 const std::string& layerPaths) {
714     if (mLayerPaths.empty()) {
715         mLayerPaths = layerPaths;
716         mAppNamespace = appNamespace;
717     } else {
718         ALOGV("Vulkan layer search path already set, not clobbering with '%s' for namespace %p'",
719               layerPaths.c_str(), appNamespace);
720     }
721 }
722 
getAppNamespace()723 NativeLoaderNamespace* GraphicsEnv::getAppNamespace() {
724     return mAppNamespace;
725 }
726 
getLayerPaths()727 const std::string& GraphicsEnv::getLayerPaths() {
728     return mLayerPaths;
729 }
730 
getDebugLayers()731 const std::string& GraphicsEnv::getDebugLayers() {
732     return mDebugLayers;
733 }
734 
getDebugLayersGLES()735 const std::string& GraphicsEnv::getDebugLayersGLES() {
736     return mDebugLayersGLES;
737 }
738 
setDebugLayers(const std::string & layers)739 void GraphicsEnv::setDebugLayers(const std::string& layers) {
740     mDebugLayers = layers;
741 }
742 
setDebugLayersGLES(const std::string & layers)743 void GraphicsEnv::setDebugLayersGLES(const std::string& layers) {
744     mDebugLayersGLES = layers;
745 }
746 
747 } // namespace android
748