xref: /aosp_15_r20/frameworks/native/services/gpuservice/GpuService.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker  * Copyright 2016 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker  *
4*38e8c45fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker  *
8*38e8c45fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker  *
10*38e8c45fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker  * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker  */
16*38e8c45fSAndroid Build Coastguard Worker 
17*38e8c45fSAndroid Build Coastguard Worker #define ATRACE_TAG ATRACE_TAG_GRAPHICS
18*38e8c45fSAndroid Build Coastguard Worker 
19*38e8c45fSAndroid Build Coastguard Worker #include "gpuservice/GpuService.h"
20*38e8c45fSAndroid Build Coastguard Worker 
21*38e8c45fSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
22*38e8c45fSAndroid Build Coastguard Worker #include <android-base/properties.h>
23*38e8c45fSAndroid Build Coastguard Worker #include <binder/IPCThreadState.h>
24*38e8c45fSAndroid Build Coastguard Worker #include <binder/IResultReceiver.h>
25*38e8c45fSAndroid Build Coastguard Worker #include <binder/Parcel.h>
26*38e8c45fSAndroid Build Coastguard Worker #include <binder/PermissionCache.h>
27*38e8c45fSAndroid Build Coastguard Worker #include <cutils/properties.h>
28*38e8c45fSAndroid Build Coastguard Worker #include <gpumem/GpuMem.h>
29*38e8c45fSAndroid Build Coastguard Worker #include <gpuwork/GpuWork.h>
30*38e8c45fSAndroid Build Coastguard Worker #include <gpustats/GpuStats.h>
31*38e8c45fSAndroid Build Coastguard Worker #include <private/android_filesystem_config.h>
32*38e8c45fSAndroid Build Coastguard Worker #include <tracing/GpuMemTracer.h>
33*38e8c45fSAndroid Build Coastguard Worker #include <utils/String8.h>
34*38e8c45fSAndroid Build Coastguard Worker #include <utils/Trace.h>
35*38e8c45fSAndroid Build Coastguard Worker #include <vkjson.h>
36*38e8c45fSAndroid Build Coastguard Worker #include <vkprofiles.h>
37*38e8c45fSAndroid Build Coastguard Worker 
38*38e8c45fSAndroid Build Coastguard Worker #include <thread>
39*38e8c45fSAndroid Build Coastguard Worker #include <memory>
40*38e8c45fSAndroid Build Coastguard Worker 
41*38e8c45fSAndroid Build Coastguard Worker namespace android {
42*38e8c45fSAndroid Build Coastguard Worker 
43*38e8c45fSAndroid Build Coastguard Worker using base::StringAppendF;
44*38e8c45fSAndroid Build Coastguard Worker 
45*38e8c45fSAndroid Build Coastguard Worker namespace {
46*38e8c45fSAndroid Build Coastguard Worker status_t cmdHelp(int out);
47*38e8c45fSAndroid Build Coastguard Worker status_t cmdVkjson(int out, int err);
48*38e8c45fSAndroid Build Coastguard Worker status_t cmdVkprofiles(int out, int err);
49*38e8c45fSAndroid Build Coastguard Worker void dumpGameDriverInfo(std::string* result);
50*38e8c45fSAndroid Build Coastguard Worker } // namespace
51*38e8c45fSAndroid Build Coastguard Worker 
52*38e8c45fSAndroid Build Coastguard Worker const String16 sDump("android.permission.DUMP");
53*38e8c45fSAndroid Build Coastguard Worker const String16 sAccessGpuServicePermission("android.permission.ACCESS_GPU_SERVICE");
54*38e8c45fSAndroid Build Coastguard Worker const std::string sAngleGlesDriverSuffix = "angle";
55*38e8c45fSAndroid Build Coastguard Worker 
56*38e8c45fSAndroid Build Coastguard Worker const char* const GpuService::SERVICE_NAME = "gpu";
57*38e8c45fSAndroid Build Coastguard Worker 
GpuService()58*38e8c45fSAndroid Build Coastguard Worker GpuService::GpuService()
59*38e8c45fSAndroid Build Coastguard Worker       : mGpuMem(std::make_shared<GpuMem>()),
60*38e8c45fSAndroid Build Coastguard Worker         mGpuWork(std::make_shared<gpuwork::GpuWork>()),
61*38e8c45fSAndroid Build Coastguard Worker         mGpuStats(std::make_unique<GpuStats>()),
62*38e8c45fSAndroid Build Coastguard Worker         mGpuMemTracer(std::make_unique<GpuMemTracer>()) {
63*38e8c45fSAndroid Build Coastguard Worker 
64*38e8c45fSAndroid Build Coastguard Worker     mGpuMemAsyncInitThread = std::make_unique<std::thread>([this] (){
65*38e8c45fSAndroid Build Coastguard Worker         mGpuMem->initialize();
66*38e8c45fSAndroid Build Coastguard Worker         mGpuMemTracer->initialize(mGpuMem);
67*38e8c45fSAndroid Build Coastguard Worker     });
68*38e8c45fSAndroid Build Coastguard Worker 
69*38e8c45fSAndroid Build Coastguard Worker     mGpuWorkAsyncInitThread = std::make_unique<std::thread>([this]() {
70*38e8c45fSAndroid Build Coastguard Worker         mGpuWork->initialize();
71*38e8c45fSAndroid Build Coastguard Worker     });
72*38e8c45fSAndroid Build Coastguard Worker };
73*38e8c45fSAndroid Build Coastguard Worker 
~GpuService()74*38e8c45fSAndroid Build Coastguard Worker GpuService::~GpuService() {
75*38e8c45fSAndroid Build Coastguard Worker     mGpuMem->stop();
76*38e8c45fSAndroid Build Coastguard Worker     mGpuWork->stop();
77*38e8c45fSAndroid Build Coastguard Worker 
78*38e8c45fSAndroid Build Coastguard Worker     mGpuWorkAsyncInitThread->join();
79*38e8c45fSAndroid Build Coastguard Worker     mGpuMemAsyncInitThread->join();
80*38e8c45fSAndroid Build Coastguard Worker }
81*38e8c45fSAndroid Build Coastguard Worker 
setGpuStats(const std::string & driverPackageName,const std::string & driverVersionName,uint64_t driverVersionCode,int64_t driverBuildTime,const std::string & appPackageName,const int32_t vulkanVersion,GpuStatsInfo::Driver driver,bool isDriverLoaded,int64_t driverLoadingTime)82*38e8c45fSAndroid Build Coastguard Worker void GpuService::setGpuStats(const std::string& driverPackageName,
83*38e8c45fSAndroid Build Coastguard Worker                              const std::string& driverVersionName, uint64_t driverVersionCode,
84*38e8c45fSAndroid Build Coastguard Worker                              int64_t driverBuildTime, const std::string& appPackageName,
85*38e8c45fSAndroid Build Coastguard Worker                              const int32_t vulkanVersion, GpuStatsInfo::Driver driver,
86*38e8c45fSAndroid Build Coastguard Worker                              bool isDriverLoaded, int64_t driverLoadingTime) {
87*38e8c45fSAndroid Build Coastguard Worker     mGpuStats->insertDriverStats(driverPackageName, driverVersionName, driverVersionCode,
88*38e8c45fSAndroid Build Coastguard Worker                                  driverBuildTime, appPackageName, vulkanVersion, driver,
89*38e8c45fSAndroid Build Coastguard Worker                                  isDriverLoaded, driverLoadingTime);
90*38e8c45fSAndroid Build Coastguard Worker }
91*38e8c45fSAndroid Build Coastguard Worker 
setTargetStats(const std::string & appPackageName,const uint64_t driverVersionCode,const GpuStatsInfo::Stats stats,const uint64_t value)92*38e8c45fSAndroid Build Coastguard Worker void GpuService::setTargetStats(const std::string& appPackageName, const uint64_t driverVersionCode,
93*38e8c45fSAndroid Build Coastguard Worker                                 const GpuStatsInfo::Stats stats, const uint64_t value) {
94*38e8c45fSAndroid Build Coastguard Worker     mGpuStats->insertTargetStats(appPackageName, driverVersionCode, stats, value);
95*38e8c45fSAndroid Build Coastguard Worker }
96*38e8c45fSAndroid Build Coastguard Worker 
setTargetStatsArray(const std::string & appPackageName,const uint64_t driverVersionCode,const GpuStatsInfo::Stats stats,const uint64_t * values,const uint32_t valueCount)97*38e8c45fSAndroid Build Coastguard Worker void GpuService::setTargetStatsArray(const std::string& appPackageName,
98*38e8c45fSAndroid Build Coastguard Worker                                 const uint64_t driverVersionCode, const GpuStatsInfo::Stats stats,
99*38e8c45fSAndroid Build Coastguard Worker                                 const uint64_t* values, const uint32_t valueCount) {
100*38e8c45fSAndroid Build Coastguard Worker     mGpuStats->insertTargetStatsArray(appPackageName, driverVersionCode, stats, values, valueCount);
101*38e8c45fSAndroid Build Coastguard Worker }
102*38e8c45fSAndroid Build Coastguard Worker 
addVulkanEngineName(const std::string & appPackageName,const uint64_t driverVersionCode,const char * engineName)103*38e8c45fSAndroid Build Coastguard Worker void GpuService::addVulkanEngineName(const std::string& appPackageName,
104*38e8c45fSAndroid Build Coastguard Worker                                      const uint64_t driverVersionCode,
105*38e8c45fSAndroid Build Coastguard Worker                                      const char* engineName) {
106*38e8c45fSAndroid Build Coastguard Worker     mGpuStats->addVulkanEngineName(appPackageName, driverVersionCode, engineName);
107*38e8c45fSAndroid Build Coastguard Worker }
108*38e8c45fSAndroid Build Coastguard Worker 
toggleAngleAsSystemDriver(bool enabled)109*38e8c45fSAndroid Build Coastguard Worker void GpuService::toggleAngleAsSystemDriver(bool enabled) {
110*38e8c45fSAndroid Build Coastguard Worker     IPCThreadState* ipc = IPCThreadState::self();
111*38e8c45fSAndroid Build Coastguard Worker     const int pid = ipc->getCallingPid();
112*38e8c45fSAndroid Build Coastguard Worker     const int uid = ipc->getCallingUid();
113*38e8c45fSAndroid Build Coastguard Worker 
114*38e8c45fSAndroid Build Coastguard Worker     // only system_server with the ACCESS_GPU_SERVICE permission is allowed to set
115*38e8c45fSAndroid Build Coastguard Worker     // persist.graphics.egl
116*38e8c45fSAndroid Build Coastguard Worker     if (uid != AID_SYSTEM ||
117*38e8c45fSAndroid Build Coastguard Worker         !PermissionCache::checkPermission(sAccessGpuServicePermission, pid, uid)) {
118*38e8c45fSAndroid Build Coastguard Worker         ALOGE("Permission Denial: can't set persist.graphics.egl from setAngleAsSystemDriver() "
119*38e8c45fSAndroid Build Coastguard Worker                 "pid=%d, uid=%d\n", pid, uid);
120*38e8c45fSAndroid Build Coastguard Worker         return;
121*38e8c45fSAndroid Build Coastguard Worker     }
122*38e8c45fSAndroid Build Coastguard Worker 
123*38e8c45fSAndroid Build Coastguard Worker     std::lock_guard<std::mutex> lock(mLock);
124*38e8c45fSAndroid Build Coastguard Worker     if (enabled) {
125*38e8c45fSAndroid Build Coastguard Worker         android::base::SetProperty("persist.graphics.egl", sAngleGlesDriverSuffix);
126*38e8c45fSAndroid Build Coastguard Worker     } else {
127*38e8c45fSAndroid Build Coastguard Worker         android::base::SetProperty("persist.graphics.egl", "");
128*38e8c45fSAndroid Build Coastguard Worker     }
129*38e8c45fSAndroid Build Coastguard Worker }
130*38e8c45fSAndroid Build Coastguard Worker 
131*38e8c45fSAndroid Build Coastguard Worker 
setUpdatableDriverPath(const std::string & driverPath)132*38e8c45fSAndroid Build Coastguard Worker void GpuService::setUpdatableDriverPath(const std::string& driverPath) {
133*38e8c45fSAndroid Build Coastguard Worker     IPCThreadState* ipc = IPCThreadState::self();
134*38e8c45fSAndroid Build Coastguard Worker     const int pid = ipc->getCallingPid();
135*38e8c45fSAndroid Build Coastguard Worker     const int uid = ipc->getCallingUid();
136*38e8c45fSAndroid Build Coastguard Worker 
137*38e8c45fSAndroid Build Coastguard Worker     // only system_server is allowed to set updatable driver path
138*38e8c45fSAndroid Build Coastguard Worker     if (uid != AID_SYSTEM) {
139*38e8c45fSAndroid Build Coastguard Worker         ALOGE("Permission Denial: can't set updatable driver path from pid=%d, uid=%d\n", pid, uid);
140*38e8c45fSAndroid Build Coastguard Worker         return;
141*38e8c45fSAndroid Build Coastguard Worker     }
142*38e8c45fSAndroid Build Coastguard Worker 
143*38e8c45fSAndroid Build Coastguard Worker     std::lock_guard<std::mutex> lock(mLock);
144*38e8c45fSAndroid Build Coastguard Worker     mDeveloperDriverPath = driverPath;
145*38e8c45fSAndroid Build Coastguard Worker }
146*38e8c45fSAndroid Build Coastguard Worker 
getUpdatableDriverPath()147*38e8c45fSAndroid Build Coastguard Worker std::string GpuService::getUpdatableDriverPath() {
148*38e8c45fSAndroid Build Coastguard Worker     std::lock_guard<std::mutex> lock(mLock);
149*38e8c45fSAndroid Build Coastguard Worker     return mDeveloperDriverPath;
150*38e8c45fSAndroid Build Coastguard Worker }
151*38e8c45fSAndroid Build Coastguard Worker 
shellCommand(int,int out,int err,std::vector<String16> & args)152*38e8c45fSAndroid Build Coastguard Worker status_t GpuService::shellCommand(int /*in*/, int out, int err, std::vector<String16>& args) {
153*38e8c45fSAndroid Build Coastguard Worker     ATRACE_CALL();
154*38e8c45fSAndroid Build Coastguard Worker 
155*38e8c45fSAndroid Build Coastguard Worker     ALOGV("shellCommand");
156*38e8c45fSAndroid Build Coastguard Worker     for (size_t i = 0, n = args.size(); i < n; i++)
157*38e8c45fSAndroid Build Coastguard Worker         ALOGV("  arg[%zu]: '%s'", i, String8(args[i]).c_str());
158*38e8c45fSAndroid Build Coastguard Worker 
159*38e8c45fSAndroid Build Coastguard Worker     if (args.size() >= 1) {
160*38e8c45fSAndroid Build Coastguard Worker         if (args[0] == String16("vkjson")) return cmdVkjson(out, err);
161*38e8c45fSAndroid Build Coastguard Worker         if (args[0] == String16("vkprofiles")) return cmdVkprofiles(out, err);
162*38e8c45fSAndroid Build Coastguard Worker         if (args[0] == String16("help")) return cmdHelp(out);
163*38e8c45fSAndroid Build Coastguard Worker     }
164*38e8c45fSAndroid Build Coastguard Worker     // no command, or unrecognized command
165*38e8c45fSAndroid Build Coastguard Worker     cmdHelp(err);
166*38e8c45fSAndroid Build Coastguard Worker     return BAD_VALUE;
167*38e8c45fSAndroid Build Coastguard Worker }
168*38e8c45fSAndroid Build Coastguard Worker 
doDump(int fd,const Vector<String16> & args,bool)169*38e8c45fSAndroid Build Coastguard Worker status_t GpuService::doDump(int fd, const Vector<String16>& args, bool /*asProto*/) {
170*38e8c45fSAndroid Build Coastguard Worker     std::string result;
171*38e8c45fSAndroid Build Coastguard Worker 
172*38e8c45fSAndroid Build Coastguard Worker     IPCThreadState* ipc = IPCThreadState::self();
173*38e8c45fSAndroid Build Coastguard Worker     const int pid = ipc->getCallingPid();
174*38e8c45fSAndroid Build Coastguard Worker     const int uid = ipc->getCallingUid();
175*38e8c45fSAndroid Build Coastguard Worker 
176*38e8c45fSAndroid Build Coastguard Worker     if ((uid != AID_SHELL) && !PermissionCache::checkPermission(sDump, pid, uid)) {
177*38e8c45fSAndroid Build Coastguard Worker         StringAppendF(&result, "Permission Denial: can't dump gpu from pid=%d, uid=%d\n", pid, uid);
178*38e8c45fSAndroid Build Coastguard Worker     } else {
179*38e8c45fSAndroid Build Coastguard Worker         bool dumpAll = true;
180*38e8c45fSAndroid Build Coastguard Worker         bool dumpDriverInfo = false;
181*38e8c45fSAndroid Build Coastguard Worker         bool dumpMem = false;
182*38e8c45fSAndroid Build Coastguard Worker         bool dumpStats = false;
183*38e8c45fSAndroid Build Coastguard Worker         bool dumpWork = false;
184*38e8c45fSAndroid Build Coastguard Worker         size_t numArgs = args.size();
185*38e8c45fSAndroid Build Coastguard Worker 
186*38e8c45fSAndroid Build Coastguard Worker         if (numArgs) {
187*38e8c45fSAndroid Build Coastguard Worker             for (size_t index = 0; index < numArgs; ++index) {
188*38e8c45fSAndroid Build Coastguard Worker                 if (args[index] == String16("--gpustats")) {
189*38e8c45fSAndroid Build Coastguard Worker                     dumpStats = true;
190*38e8c45fSAndroid Build Coastguard Worker                 } else if (args[index] == String16("--gpudriverinfo")) {
191*38e8c45fSAndroid Build Coastguard Worker                     dumpDriverInfo = true;
192*38e8c45fSAndroid Build Coastguard Worker                 } else if (args[index] == String16("--gpumem")) {
193*38e8c45fSAndroid Build Coastguard Worker                     dumpMem = true;
194*38e8c45fSAndroid Build Coastguard Worker                 } else if (args[index] == String16("--gpuwork")) {
195*38e8c45fSAndroid Build Coastguard Worker                     dumpWork = true;
196*38e8c45fSAndroid Build Coastguard Worker                 }
197*38e8c45fSAndroid Build Coastguard Worker             }
198*38e8c45fSAndroid Build Coastguard Worker             dumpAll = !(dumpDriverInfo || dumpMem || dumpStats || dumpWork);
199*38e8c45fSAndroid Build Coastguard Worker         }
200*38e8c45fSAndroid Build Coastguard Worker 
201*38e8c45fSAndroid Build Coastguard Worker         if (dumpAll || dumpDriverInfo) {
202*38e8c45fSAndroid Build Coastguard Worker             dumpGameDriverInfo(&result);
203*38e8c45fSAndroid Build Coastguard Worker             result.append("\n");
204*38e8c45fSAndroid Build Coastguard Worker         }
205*38e8c45fSAndroid Build Coastguard Worker         if (dumpAll || dumpMem) {
206*38e8c45fSAndroid Build Coastguard Worker             mGpuMem->dump(args, &result);
207*38e8c45fSAndroid Build Coastguard Worker             result.append("\n");
208*38e8c45fSAndroid Build Coastguard Worker         }
209*38e8c45fSAndroid Build Coastguard Worker         if (dumpAll || dumpStats) {
210*38e8c45fSAndroid Build Coastguard Worker             mGpuStats->dump(args, &result);
211*38e8c45fSAndroid Build Coastguard Worker             result.append("\n");
212*38e8c45fSAndroid Build Coastguard Worker         }
213*38e8c45fSAndroid Build Coastguard Worker          if (dumpAll || dumpWork) {
214*38e8c45fSAndroid Build Coastguard Worker             mGpuWork->dump(args, &result);
215*38e8c45fSAndroid Build Coastguard Worker             result.append("\n");
216*38e8c45fSAndroid Build Coastguard Worker         }
217*38e8c45fSAndroid Build Coastguard Worker     }
218*38e8c45fSAndroid Build Coastguard Worker 
219*38e8c45fSAndroid Build Coastguard Worker     write(fd, result.c_str(), result.size());
220*38e8c45fSAndroid Build Coastguard Worker     return NO_ERROR;
221*38e8c45fSAndroid Build Coastguard Worker }
222*38e8c45fSAndroid Build Coastguard Worker 
223*38e8c45fSAndroid Build Coastguard Worker namespace {
224*38e8c45fSAndroid Build Coastguard Worker 
cmdHelp(int out)225*38e8c45fSAndroid Build Coastguard Worker status_t cmdHelp(int out) {
226*38e8c45fSAndroid Build Coastguard Worker     FILE* outs = fdopen(out, "w");
227*38e8c45fSAndroid Build Coastguard Worker     if (!outs) {
228*38e8c45fSAndroid Build Coastguard Worker         ALOGE("gpuservice: failed to create out stream: %s (%d)", strerror(errno), errno);
229*38e8c45fSAndroid Build Coastguard Worker         return BAD_VALUE;
230*38e8c45fSAndroid Build Coastguard Worker     }
231*38e8c45fSAndroid Build Coastguard Worker     fprintf(outs,
232*38e8c45fSAndroid Build Coastguard Worker             "GPU Service commands:\n"
233*38e8c45fSAndroid Build Coastguard Worker             "  vkjson      dump Vulkan properties as JSON\n"
234*38e8c45fSAndroid Build Coastguard Worker             "  vkprofiles  print support for select Vulkan profiles\n");
235*38e8c45fSAndroid Build Coastguard Worker     fclose(outs);
236*38e8c45fSAndroid Build Coastguard Worker     return NO_ERROR;
237*38e8c45fSAndroid Build Coastguard Worker }
238*38e8c45fSAndroid Build Coastguard Worker 
cmdVkjson(int out,int)239*38e8c45fSAndroid Build Coastguard Worker status_t cmdVkjson(int out, int /*err*/) {
240*38e8c45fSAndroid Build Coastguard Worker     dprintf(out, "%s\n", VkJsonInstanceToJson(VkJsonGetInstance()).c_str());
241*38e8c45fSAndroid Build Coastguard Worker     return NO_ERROR;
242*38e8c45fSAndroid Build Coastguard Worker }
243*38e8c45fSAndroid Build Coastguard Worker 
cmdVkprofiles(int out,int)244*38e8c45fSAndroid Build Coastguard Worker status_t cmdVkprofiles(int out, int /*err*/) {
245*38e8c45fSAndroid Build Coastguard Worker     dprintf(out, "%s\n", android::vkprofiles::vkProfiles().c_str());
246*38e8c45fSAndroid Build Coastguard Worker     return NO_ERROR;
247*38e8c45fSAndroid Build Coastguard Worker }
248*38e8c45fSAndroid Build Coastguard Worker 
dumpGameDriverInfo(std::string * result)249*38e8c45fSAndroid Build Coastguard Worker void dumpGameDriverInfo(std::string* result) {
250*38e8c45fSAndroid Build Coastguard Worker     if (!result) return;
251*38e8c45fSAndroid Build Coastguard Worker 
252*38e8c45fSAndroid Build Coastguard Worker     char stableGameDriver[PROPERTY_VALUE_MAX] = {};
253*38e8c45fSAndroid Build Coastguard Worker     property_get("ro.gfx.driver.0", stableGameDriver, "unsupported");
254*38e8c45fSAndroid Build Coastguard Worker     StringAppendF(result, "Stable Game Driver: %s\n", stableGameDriver);
255*38e8c45fSAndroid Build Coastguard Worker 
256*38e8c45fSAndroid Build Coastguard Worker     char preReleaseGameDriver[PROPERTY_VALUE_MAX] = {};
257*38e8c45fSAndroid Build Coastguard Worker     property_get("ro.gfx.driver.1", preReleaseGameDriver, "unsupported");
258*38e8c45fSAndroid Build Coastguard Worker     StringAppendF(result, "Pre-release Game Driver: %s\n", preReleaseGameDriver);
259*38e8c45fSAndroid Build Coastguard Worker }
260*38e8c45fSAndroid Build Coastguard Worker 
261*38e8c45fSAndroid Build Coastguard Worker } // anonymous namespace
262*38e8c45fSAndroid Build Coastguard Worker 
263*38e8c45fSAndroid Build Coastguard Worker } // namespace android
264