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