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