• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android {
64 
65 enum NativeLibrary {
66     LLNDK = 0,
67     VNDKSP = 1,
68 };
69 
70 static constexpr const char* kNativeLibrariesSystemConfigPath[] =
71         {"/apex/com.android.vndk.v{}/etc/llndk.libraries.{}.txt",
72          "/apex/com.android.vndk.v{}/etc/vndksp.libraries.{}.txt"};
73 
vndkVersionStr()74 static std::string vndkVersionStr() {
75 #ifdef __BIONIC__
76     return base::GetProperty("ro.vndk.version", "");
77 #endif
78     return "";
79 }
80 
insertVndkVersionStr(std::string * fileName)81 static void insertVndkVersionStr(std::string* fileName) {
82     LOG_ALWAYS_FATAL_IF(!fileName, "fileName should never be nullptr");
83     std::string version = vndkVersionStr();
84     size_t pos = fileName->find("{}");
85     while (pos != std::string::npos) {
86         fileName->replace(pos, 2, version);
87         pos = fileName->find("{}", pos + version.size());
88     }
89 }
90 
readConfig(const std::string & configFile,std::vector<std::string> * soNames)91 static bool readConfig(const std::string& configFile, std::vector<std::string>* soNames) {
92     // Read list of public native libraries from the config file.
93     std::string fileContent;
94     if (!base::ReadFileToString(configFile, &fileContent)) {
95         return false;
96     }
97 
98     std::vector<std::string> lines = base::Split(fileContent, "\n");
99 
100     for (auto& line : lines) {
101         auto trimmedLine = base::Trim(line);
102         if (!trimmedLine.empty()) {
103             soNames->push_back(trimmedLine);
104         }
105     }
106 
107     return true;
108 }
109 
getSystemNativeLibraries(NativeLibrary type)110 static const std::string getSystemNativeLibraries(NativeLibrary type) {
111     std::string nativeLibrariesSystemConfig = kNativeLibrariesSystemConfigPath[type];
112     insertVndkVersionStr(&nativeLibrariesSystemConfig);
113 
114     std::vector<std::string> soNames;
115     if (!readConfig(nativeLibrariesSystemConfig, &soNames)) {
116         ALOGE("Failed to retrieve library names from %s", nativeLibrariesSystemConfig.c_str());
117         return "";
118     }
119 
120     return base::Join(soNames, ':');
121 }
122 
getInstance()123 /*static*/ GraphicsEnv& GraphicsEnv::getInstance() {
124     static GraphicsEnv env;
125     return env;
126 }
127 
isDebuggable()128 bool GraphicsEnv::isDebuggable() {
129     return prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) > 0;
130 }
131 
setDriverPathAndSphalLibraries(const std::string path,const std::string sphalLibraries)132 void GraphicsEnv::setDriverPathAndSphalLibraries(const std::string path,
133                                                  const std::string sphalLibraries) {
134     if (!mDriverPath.empty() || !mSphalLibraries.empty()) {
135         ALOGV("ignoring attempt to change driver path from '%s' to '%s' or change sphal libraries "
136               "from '%s' to '%s'",
137               mDriverPath.c_str(), path.c_str(), mSphalLibraries.c_str(), sphalLibraries.c_str());
138         return;
139     }
140     ALOGV("setting driver path to '%s' and sphal libraries to '%s'", path.c_str(),
141           sphalLibraries.c_str());
142     mDriverPath = path;
143     mSphalLibraries = sphalLibraries;
144 }
145 
hintActivityLaunch()146 void GraphicsEnv::hintActivityLaunch() {
147     ATRACE_CALL();
148 
149     {
150         std::lock_guard<std::mutex> lock(mStatsLock);
151         if (mActivityLaunched) return;
152         mActivityLaunched = true;
153     }
154 
155     std::thread trySendGpuStatsThread([this]() {
156         // If there's already graphics driver preloaded in the process, just send
157         // the stats info to GpuStats directly through async binder.
158         std::lock_guard<std::mutex> lock(mStatsLock);
159         if (mGpuStats.glDriverToSend) {
160             mGpuStats.glDriverToSend = false;
161             sendGpuStatsLocked(GpuStatsInfo::Api::API_GL, true, mGpuStats.glDriverLoadingTime);
162         }
163         if (mGpuStats.vkDriverToSend) {
164             mGpuStats.vkDriverToSend = false;
165             sendGpuStatsLocked(GpuStatsInfo::Api::API_VK, true, mGpuStats.vkDriverLoadingTime);
166         }
167     });
168     trySendGpuStatsThread.detach();
169 }
170 
setGpuStats(const std::string & driverPackageName,const std::string & driverVersionName,uint64_t driverVersionCode,int64_t driverBuildTime,const std::string & appPackageName,const int vulkanVersion)171 void GraphicsEnv::setGpuStats(const std::string& driverPackageName,
172                               const std::string& driverVersionName, uint64_t driverVersionCode,
173                               int64_t driverBuildTime, const std::string& appPackageName,
174                               const int vulkanVersion) {
175     ATRACE_CALL();
176 
177     std::lock_guard<std::mutex> lock(mStatsLock);
178     ALOGV("setGpuStats:\n"
179           "\tdriverPackageName[%s]\n"
180           "\tdriverVersionName[%s]\n"
181           "\tdriverVersionCode[%" PRIu64 "]\n"
182           "\tdriverBuildTime[%" PRId64 "]\n"
183           "\tappPackageName[%s]\n"
184           "\tvulkanVersion[%d]\n",
185           driverPackageName.c_str(), driverVersionName.c_str(), driverVersionCode, driverBuildTime,
186           appPackageName.c_str(), vulkanVersion);
187 
188     mGpuStats.driverPackageName = driverPackageName;
189     mGpuStats.driverVersionName = driverVersionName;
190     mGpuStats.driverVersionCode = driverVersionCode;
191     mGpuStats.driverBuildTime = driverBuildTime;
192     mGpuStats.appPackageName = appPackageName;
193     mGpuStats.vulkanVersion = vulkanVersion;
194 }
195 
setDriverToLoad(GpuStatsInfo::Driver driver)196 void GraphicsEnv::setDriverToLoad(GpuStatsInfo::Driver driver) {
197     ATRACE_CALL();
198 
199     std::lock_guard<std::mutex> lock(mStatsLock);
200     switch (driver) {
201         case GpuStatsInfo::Driver::GL:
202         case GpuStatsInfo::Driver::GL_UPDATED:
203         case GpuStatsInfo::Driver::ANGLE: {
204             if (mGpuStats.glDriverToLoad == GpuStatsInfo::Driver::NONE ||
205                 mGpuStats.glDriverToLoad == GpuStatsInfo::Driver::GL) {
206                 mGpuStats.glDriverToLoad = driver;
207                 break;
208             }
209 
210             if (mGpuStats.glDriverFallback == GpuStatsInfo::Driver::NONE) {
211                 mGpuStats.glDriverFallback = driver;
212             }
213             break;
214         }
215         case GpuStatsInfo::Driver::VULKAN:
216         case GpuStatsInfo::Driver::VULKAN_UPDATED: {
217             if (mGpuStats.vkDriverToLoad == GpuStatsInfo::Driver::NONE ||
218                 mGpuStats.vkDriverToLoad == GpuStatsInfo::Driver::VULKAN) {
219                 mGpuStats.vkDriverToLoad = driver;
220                 break;
221             }
222 
223             if (mGpuStats.vkDriverFallback == GpuStatsInfo::Driver::NONE) {
224                 mGpuStats.vkDriverFallback = driver;
225             }
226             break;
227         }
228         default:
229             break;
230     }
231 }
232 
setDriverLoaded(GpuStatsInfo::Api api,bool isDriverLoaded,int64_t driverLoadingTime)233 void GraphicsEnv::setDriverLoaded(GpuStatsInfo::Api api, bool isDriverLoaded,
234                                   int64_t driverLoadingTime) {
235     ATRACE_CALL();
236 
237     std::lock_guard<std::mutex> lock(mStatsLock);
238     if (api == GpuStatsInfo::Api::API_GL) {
239         mGpuStats.glDriverToSend = true;
240         mGpuStats.glDriverLoadingTime = driverLoadingTime;
241     } else {
242         mGpuStats.vkDriverToSend = true;
243         mGpuStats.vkDriverLoadingTime = driverLoadingTime;
244     }
245 
246     sendGpuStatsLocked(api, isDriverLoaded, driverLoadingTime);
247 }
248 
getGpuService()249 static sp<IGpuService> getGpuService() {
250     static const sp<IBinder> binder = defaultServiceManager()->checkService(String16("gpu"));
251     if (!binder) {
252         ALOGE("Failed to get gpu service");
253         return nullptr;
254     }
255 
256     return interface_cast<IGpuService>(binder);
257 }
258 
readyToSendGpuStatsLocked()259 bool GraphicsEnv::readyToSendGpuStatsLocked() {
260     // Only send stats for processes having at least one activity launched and that process doesn't
261     // skip the GraphicsEnvironment setup.
262     return mActivityLaunched && !mGpuStats.appPackageName.empty();
263 }
264 
setTargetStats(const GpuStatsInfo::Stats stats,const uint64_t value)265 void GraphicsEnv::setTargetStats(const GpuStatsInfo::Stats stats, const uint64_t value) {
266     ATRACE_CALL();
267 
268     std::lock_guard<std::mutex> lock(mStatsLock);
269     if (!readyToSendGpuStatsLocked()) return;
270 
271     const sp<IGpuService> gpuService = getGpuService();
272     if (gpuService) {
273         gpuService->setTargetStats(mGpuStats.appPackageName, mGpuStats.driverVersionCode, stats,
274                                    value);
275     }
276 }
277 
sendGpuStatsLocked(GpuStatsInfo::Api api,bool isDriverLoaded,int64_t driverLoadingTime)278 void GraphicsEnv::sendGpuStatsLocked(GpuStatsInfo::Api api, bool isDriverLoaded,
279                                      int64_t driverLoadingTime) {
280     ATRACE_CALL();
281 
282     if (!readyToSendGpuStatsLocked()) return;
283 
284     ALOGV("sendGpuStats:\n"
285           "\tdriverPackageName[%s]\n"
286           "\tdriverVersionName[%s]\n"
287           "\tdriverVersionCode[%" PRIu64 "]\n"
288           "\tdriverBuildTime[%" PRId64 "]\n"
289           "\tappPackageName[%s]\n"
290           "\tvulkanVersion[%d]\n"
291           "\tapi[%d]\n"
292           "\tisDriverLoaded[%d]\n"
293           "\tdriverLoadingTime[%" PRId64 "]",
294           mGpuStats.driverPackageName.c_str(), mGpuStats.driverVersionName.c_str(),
295           mGpuStats.driverVersionCode, mGpuStats.driverBuildTime, mGpuStats.appPackageName.c_str(),
296           mGpuStats.vulkanVersion, static_cast<int32_t>(api), isDriverLoaded, driverLoadingTime);
297 
298     GpuStatsInfo::Driver driver = GpuStatsInfo::Driver::NONE;
299     bool isIntendedDriverLoaded = false;
300     if (api == GpuStatsInfo::Api::API_GL) {
301         driver = mGpuStats.glDriverToLoad;
302         isIntendedDriverLoaded =
303                 isDriverLoaded && (mGpuStats.glDriverFallback == GpuStatsInfo::Driver::NONE);
304     } else {
305         driver = mGpuStats.vkDriverToLoad;
306         isIntendedDriverLoaded =
307                 isDriverLoaded && (mGpuStats.vkDriverFallback == GpuStatsInfo::Driver::NONE);
308     }
309 
310     const sp<IGpuService> gpuService = getGpuService();
311     if (gpuService) {
312         gpuService->setGpuStats(mGpuStats.driverPackageName, mGpuStats.driverVersionName,
313                                 mGpuStats.driverVersionCode, mGpuStats.driverBuildTime,
314                                 mGpuStats.appPackageName, mGpuStats.vulkanVersion, driver,
315                                 isIntendedDriverLoaded, driverLoadingTime);
316     }
317 }
318 
setInjectLayersPrSetDumpable()319 bool GraphicsEnv::setInjectLayersPrSetDumpable() {
320     if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
321         return false;
322     }
323     return true;
324 }
325 
loadLibrary(std::string name)326 void* GraphicsEnv::loadLibrary(std::string name) {
327     const android_dlextinfo dlextinfo = {
328             .flags = ANDROID_DLEXT_USE_NAMESPACE,
329             .library_namespace = getAngleNamespace(),
330     };
331 
332     std::string libName = std::string("lib") + name + "_angle.so";
333 
334     void* so = android_dlopen_ext(libName.c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo);
335 
336     if (so) {
337         ALOGD("dlopen_ext from APK (%s) success at %p", libName.c_str(), so);
338         return so;
339     } else {
340         ALOGE("dlopen_ext(\"%s\") failed: %s", libName.c_str(), dlerror());
341     }
342 
343     return nullptr;
344 }
345 
checkAngleRules(void * so)346 bool GraphicsEnv::checkAngleRules(void* so) {
347     auto manufacturer = base::GetProperty("ro.product.manufacturer", "UNSET");
348     auto model = base::GetProperty("ro.product.model", "UNSET");
349 
350     auto ANGLEGetFeatureSupportUtilAPIVersion =
351             (fpANGLEGetFeatureSupportUtilAPIVersion)dlsym(so,
352                                                           "ANGLEGetFeatureSupportUtilAPIVersion");
353 
354     if (!ANGLEGetFeatureSupportUtilAPIVersion) {
355         ALOGW("Cannot find ANGLEGetFeatureSupportUtilAPIVersion function");
356         return false;
357     }
358 
359     // Negotiate the interface version by requesting most recent known to the platform
360     unsigned int versionToUse = CURRENT_ANGLE_API_VERSION;
361     if (!(ANGLEGetFeatureSupportUtilAPIVersion)(&versionToUse)) {
362         ALOGW("Cannot use ANGLE feature-support library, it is older than supported by EGL, "
363               "requested version %u",
364               versionToUse);
365         return false;
366     }
367 
368     // Add and remove versions below as needed
369     bool useAngle = false;
370     switch (versionToUse) {
371         case 2: {
372             ALOGV("Using version %d of ANGLE feature-support library", versionToUse);
373             void* rulesHandle = nullptr;
374             int rulesVersion = 0;
375             void* systemInfoHandle = nullptr;
376 
377             // Get the symbols for the feature-support-utility library:
378 #define GET_SYMBOL(symbol)                                                 \
379     fp##symbol symbol = (fp##symbol)dlsym(so, #symbol);                    \
380     if (!symbol) {                                                         \
381         ALOGW("Cannot find " #symbol " in ANGLE feature-support library"); \
382         break;                                                             \
383     }
384             GET_SYMBOL(ANGLEAndroidParseRulesString);
385             GET_SYMBOL(ANGLEGetSystemInfo);
386             GET_SYMBOL(ANGLEAddDeviceInfoToSystemInfo);
387             GET_SYMBOL(ANGLEShouldBeUsedForApplication);
388             GET_SYMBOL(ANGLEFreeRulesHandle);
389             GET_SYMBOL(ANGLEFreeSystemInfoHandle);
390 
391             // Parse the rules, obtain the SystemInfo, and evaluate the
392             // application against the rules:
393             if (!(ANGLEAndroidParseRulesString)(mRulesBuffer.data(), &rulesHandle, &rulesVersion)) {
394                 ALOGW("ANGLE feature-support library cannot parse rules file");
395                 break;
396             }
397             if (!(ANGLEGetSystemInfo)(&systemInfoHandle)) {
398                 ALOGW("ANGLE feature-support library cannot obtain SystemInfo");
399                 break;
400             }
401             if (!(ANGLEAddDeviceInfoToSystemInfo)(manufacturer.c_str(), model.c_str(),
402                                                   systemInfoHandle)) {
403                 ALOGW("ANGLE feature-support library cannot add device info to SystemInfo");
404                 break;
405             }
406             useAngle = (ANGLEShouldBeUsedForApplication)(rulesHandle, rulesVersion,
407                                                          systemInfoHandle, mAngleAppName.c_str());
408             (ANGLEFreeRulesHandle)(rulesHandle);
409             (ANGLEFreeSystemInfoHandle)(systemInfoHandle);
410         } break;
411 
412         default:
413             ALOGW("Version %u of ANGLE feature-support library is NOT supported.", versionToUse);
414     }
415 
416     ALOGV("Close temporarily-loaded ANGLE opt-in/out logic");
417     return useAngle;
418 }
419 
shouldUseAngle(std::string appName)420 bool GraphicsEnv::shouldUseAngle(std::string appName) {
421     if (appName != mAngleAppName) {
422         // Make sure we are checking the app we were init'ed for
423         ALOGE("App name does not match: expected '%s', got '%s'", mAngleAppName.c_str(),
424               appName.c_str());
425         return false;
426     }
427 
428     return shouldUseAngle();
429 }
430 
shouldUseAngle()431 bool GraphicsEnv::shouldUseAngle() {
432     // Make sure we are init'ed
433     if (mAngleAppName.empty()) {
434         ALOGV("App name is empty. setAngleInfo() has not been called to enable ANGLE.");
435         return false;
436     }
437 
438     return (mUseAngle == YES) ? true : false;
439 }
440 
updateUseAngle()441 void GraphicsEnv::updateUseAngle() {
442     mUseAngle = NO;
443 
444     const char* ANGLE_PREFER_ANGLE = "angle";
445     const char* ANGLE_PREFER_NATIVE = "native";
446 
447     if (mAngleDeveloperOptIn == ANGLE_PREFER_ANGLE) {
448         ALOGV("User set \"Developer Options\" to force the use of ANGLE");
449         mUseAngle = YES;
450     } else if (mAngleDeveloperOptIn == ANGLE_PREFER_NATIVE) {
451         ALOGV("User set \"Developer Options\" to force the use of Native");
452         mUseAngle = NO;
453     } else {
454         // The "Developer Options" value wasn't set to force the use of ANGLE.  Need to temporarily
455         // load ANGLE and call the updatable opt-in/out logic:
456         void* featureSo = loadLibrary("feature_support");
457         if (featureSo) {
458             ALOGV("loaded ANGLE's opt-in/out logic from namespace");
459             mUseAngle = checkAngleRules(featureSo) ? YES : NO;
460             dlclose(featureSo);
461             featureSo = nullptr;
462         } else {
463             ALOGV("Could not load the ANGLE opt-in/out logic, cannot use ANGLE.");
464         }
465     }
466 }
467 
setAngleInfo(const std::string path,const std::string appName,const std::string developerOptIn,const std::vector<std::string> eglFeatures,const int rulesFd,const long rulesOffset,const long rulesLength)468 void GraphicsEnv::setAngleInfo(const std::string path, const std::string appName,
469                                const std::string developerOptIn,
470                                const std::vector<std::string> eglFeatures, const int rulesFd,
471                                const long rulesOffset, const long rulesLength) {
472     if (mUseAngle != UNKNOWN) {
473         // We've already figured out an answer for this app, so just return.
474         ALOGV("Already evaluated the rules file for '%s': use ANGLE = %s", appName.c_str(),
475               (mUseAngle == YES) ? "true" : "false");
476         return;
477     }
478 
479     mAngleEglFeatures = std::move(eglFeatures);
480 
481     ALOGV("setting ANGLE path to '%s'", path.c_str());
482     mAnglePath = path;
483     ALOGV("setting ANGLE app name to '%s'", appName.c_str());
484     mAngleAppName = appName;
485     ALOGV("setting ANGLE application opt-in to '%s'", developerOptIn.c_str());
486     mAngleDeveloperOptIn = developerOptIn;
487 
488     lseek(rulesFd, rulesOffset, SEEK_SET);
489     mRulesBuffer = std::vector<char>(rulesLength + 1);
490     ssize_t numBytesRead = read(rulesFd, mRulesBuffer.data(), rulesLength);
491     if (numBytesRead < 0) {
492         ALOGE("Cannot read rules file: numBytesRead = %zd", numBytesRead);
493         numBytesRead = 0;
494     } else if (numBytesRead == 0) {
495         ALOGW("Empty rules file");
496     }
497     if (numBytesRead != rulesLength) {
498         ALOGW("Did not read all of the necessary bytes from the rules file."
499               "expected: %ld, got: %zd",
500               rulesLength, numBytesRead);
501     }
502     mRulesBuffer[numBytesRead] = '\0';
503 
504     // Update the current status of whether we should use ANGLE or not
505     updateUseAngle();
506 }
507 
setLayerPaths(NativeLoaderNamespace * appNamespace,const std::string layerPaths)508 void GraphicsEnv::setLayerPaths(NativeLoaderNamespace* appNamespace, const std::string layerPaths) {
509     if (mLayerPaths.empty()) {
510         mLayerPaths = layerPaths;
511         mAppNamespace = appNamespace;
512     } else {
513         ALOGV("Vulkan layer search path already set, not clobbering with '%s' for namespace %p'",
514               layerPaths.c_str(), appNamespace);
515     }
516 }
517 
getAppNamespace()518 NativeLoaderNamespace* GraphicsEnv::getAppNamespace() {
519     return mAppNamespace;
520 }
521 
getAngleAppName()522 std::string& GraphicsEnv::getAngleAppName() {
523     return mAngleAppName;
524 }
525 
getAngleEglFeatures()526 const std::vector<std::string>& GraphicsEnv::getAngleEglFeatures() {
527     return mAngleEglFeatures;
528 }
529 
getLayerPaths()530 const std::string& GraphicsEnv::getLayerPaths() {
531     return mLayerPaths;
532 }
533 
getDebugLayers()534 const std::string& GraphicsEnv::getDebugLayers() {
535     return mDebugLayers;
536 }
537 
getDebugLayersGLES()538 const std::string& GraphicsEnv::getDebugLayersGLES() {
539     return mDebugLayersGLES;
540 }
541 
setDebugLayers(const std::string layers)542 void GraphicsEnv::setDebugLayers(const std::string layers) {
543     mDebugLayers = layers;
544 }
545 
setDebugLayersGLES(const std::string layers)546 void GraphicsEnv::setDebugLayersGLES(const std::string layers) {
547     mDebugLayersGLES = layers;
548 }
549 
550 // Return true if all the required libraries from vndk and sphal namespace are
551 // linked to the updatable gfx driver namespace correctly.
linkDriverNamespaceLocked(android_namespace_t * vndkNamespace)552 bool GraphicsEnv::linkDriverNamespaceLocked(android_namespace_t* vndkNamespace) {
553     const std::string llndkLibraries = getSystemNativeLibraries(NativeLibrary::LLNDK);
554     if (llndkLibraries.empty()) {
555         return false;
556     }
557     if (!android_link_namespaces(mDriverNamespace, nullptr, llndkLibraries.c_str())) {
558         ALOGE("Failed to link default namespace[%s]", dlerror());
559         return false;
560     }
561 
562     const std::string vndkspLibraries = getSystemNativeLibraries(NativeLibrary::VNDKSP);
563     if (vndkspLibraries.empty()) {
564         return false;
565     }
566     if (!android_link_namespaces(mDriverNamespace, vndkNamespace, vndkspLibraries.c_str())) {
567         ALOGE("Failed to link vndk namespace[%s]", dlerror());
568         return false;
569     }
570 
571     if (mSphalLibraries.empty()) {
572         return true;
573     }
574 
575     // Make additional libraries in sphal to be accessible
576     auto sphalNamespace = android_get_exported_namespace("sphal");
577     if (!sphalNamespace) {
578         ALOGE("Depend on these libraries[%s] in sphal, but failed to get sphal namespace",
579               mSphalLibraries.c_str());
580         return false;
581     }
582 
583     if (!android_link_namespaces(mDriverNamespace, sphalNamespace, mSphalLibraries.c_str())) {
584         ALOGE("Failed to link sphal namespace[%s]", dlerror());
585         return false;
586     }
587 
588     return true;
589 }
590 
getDriverNamespace()591 android_namespace_t* GraphicsEnv::getDriverNamespace() {
592     std::lock_guard<std::mutex> lock(mNamespaceMutex);
593 
594     if (mDriverNamespace) {
595         return mDriverNamespace;
596     }
597 
598     if (mDriverPath.empty()) {
599         // For an application process, driver path is empty means this application is not opted in
600         // to use updatable driver. Application process doesn't have the ability to set up
601         // environment variables and hence before `getenv` call will return.
602         // For a process that is not an application process, if it's run from an environment,
603         // for example shell, where environment variables can be set, then it can opt into using
604         // udpatable driver by setting UPDATABLE_GFX_DRIVER to 1. By setting to 1 the developer
605         // driver will be used currently.
606         // TODO(b/159240322) Support the production updatable driver.
607         const char* id = getenv("UPDATABLE_GFX_DRIVER");
608         if (id == nullptr || std::strcmp(id, "1")) {
609             return nullptr;
610         }
611         const sp<IGpuService> gpuService = getGpuService();
612         if (!gpuService) {
613             return nullptr;
614         }
615         mDriverPath = gpuService->getUpdatableDriverPath();
616         if (mDriverPath.empty()) {
617             return nullptr;
618         }
619         mDriverPath.append(UPDATABLE_DRIVER_ABI);
620         ALOGI("Driver path is setup via UPDATABLE_GFX_DRIVER: %s", mDriverPath.c_str());
621     }
622 
623     auto vndkNamespace = android_get_exported_namespace("vndk");
624     if (!vndkNamespace) {
625         return nullptr;
626     }
627 
628     mDriverNamespace = android_create_namespace("gfx driver",
629                                                 mDriverPath.c_str(), // ld_library_path
630                                                 mDriverPath.c_str(), // default_library_path
631                                                 ANDROID_NAMESPACE_TYPE_ISOLATED,
632                                                 nullptr, // permitted_when_isolated_path
633                                                 nullptr);
634 
635     if (!linkDriverNamespaceLocked(vndkNamespace)) {
636         mDriverNamespace = nullptr;
637     }
638 
639     return mDriverNamespace;
640 }
641 
getDriverPath() const642 std::string GraphicsEnv::getDriverPath() const {
643     return mDriverPath;
644 }
645 
getAngleNamespace()646 android_namespace_t* GraphicsEnv::getAngleNamespace() {
647     std::lock_guard<std::mutex> lock(mNamespaceMutex);
648 
649     if (mAngleNamespace) {
650         return mAngleNamespace;
651     }
652 
653     if (mAnglePath.empty()) {
654         ALOGV("mAnglePath is empty, not creating ANGLE namespace");
655         return nullptr;
656     }
657 
658     mAngleNamespace = android_create_namespace("ANGLE",
659                                                nullptr,            // ld_library_path
660                                                mAnglePath.c_str(), // default_library_path
661                                                ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED,
662                                                nullptr, // permitted_when_isolated_path
663                                                nullptr);
664 
665     ALOGD_IF(!mAngleNamespace, "Could not create ANGLE namespace from default");
666 
667     return mAngleNamespace;
668 }
669 
670 } // namespace android
671