1 /*
2  * Copyright 2019 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 #include "GpuStatsPuller.h"
18 
19 #include <binder/IServiceManager.h>
20 #include <graphicsenv/GpuStatsInfo.h>
21 #include <graphicsenv/IGpuService.h>
22 
23 #include "logd/LogEvent.h"
24 
25 #include "stats_log_util.h"
26 #include "statslog.h"
27 
28 namespace android {
29 namespace os {
30 namespace statsd {
31 
32 using android::util::ProtoReader;
33 
GpuStatsPuller(const int tagId)34 GpuStatsPuller::GpuStatsPuller(const int tagId) : StatsPuller(tagId) {
35 }
36 
getGpuService()37 static sp<IGpuService> getGpuService() {
38     const sp<IBinder> binder = defaultServiceManager()->checkService(String16("gpu"));
39     if (!binder) {
40         ALOGE("Failed to get gpu service");
41         return nullptr;
42     }
43 
44     return interface_cast<IGpuService>(binder);
45 }
46 
pullGpuStatsGlobalInfo(const sp<IGpuService> & gpuService,std::vector<std::shared_ptr<LogEvent>> * data)47 static bool pullGpuStatsGlobalInfo(const sp<IGpuService>& gpuService,
48                                    std::vector<std::shared_ptr<LogEvent>>* data) {
49     std::vector<GpuStatsGlobalInfo> stats;
50     status_t status = gpuService->getGpuStatsGlobalInfo(&stats);
51     if (status != OK) {
52         return false;
53     }
54 
55     data->clear();
56     data->reserve(stats.size());
57     for (const auto& info : stats) {
58         std::shared_ptr<LogEvent> event = make_shared<LogEvent>(
59                 android::util::GPU_STATS_GLOBAL_INFO, getWallClockNs(), getElapsedRealtimeNs());
60         if (!event->write(info.driverPackageName)) return false;
61         if (!event->write(info.driverVersionName)) return false;
62         if (!event->write((int64_t)info.driverVersionCode)) return false;
63         if (!event->write(info.driverBuildTime)) return false;
64         if (!event->write((int64_t)info.glLoadingCount)) return false;
65         if (!event->write((int64_t)info.glLoadingFailureCount)) return false;
66         if (!event->write((int64_t)info.vkLoadingCount)) return false;
67         if (!event->write((int64_t)info.vkLoadingFailureCount)) return false;
68         if (!event->write(info.vulkanVersion)) return false;
69         if (!event->write(info.cpuVulkanVersion)) return false;
70         if (!event->write(info.glesVersion)) return false;
71         if (!event->write((int64_t)info.angleLoadingCount)) return false;
72         if (!event->write((int64_t)info.angleLoadingFailureCount)) return false;
73         event->init();
74         data->emplace_back(event);
75     }
76 
77     return true;
78 }
79 
pullGpuStatsAppInfo(const sp<IGpuService> & gpuService,std::vector<std::shared_ptr<LogEvent>> * data)80 static bool pullGpuStatsAppInfo(const sp<IGpuService>& gpuService,
81                                 std::vector<std::shared_ptr<LogEvent>>* data) {
82     std::vector<GpuStatsAppInfo> stats;
83     status_t status = gpuService->getGpuStatsAppInfo(&stats);
84     if (status != OK) {
85         return false;
86     }
87 
88     data->clear();
89     data->reserve(stats.size());
90     for (const auto& info : stats) {
91         std::shared_ptr<LogEvent> event = make_shared<LogEvent>(
92                 android::util::GPU_STATS_APP_INFO, getWallClockNs(), getElapsedRealtimeNs());
93         if (!event->write(info.appPackageName)) return false;
94         if (!event->write((int64_t)info.driverVersionCode)) return false;
95         if (!event->write(int64VectorToProtoByteString(info.glDriverLoadingTime))) return false;
96         if (!event->write(int64VectorToProtoByteString(info.vkDriverLoadingTime))) return false;
97         if (!event->write(int64VectorToProtoByteString(info.angleDriverLoadingTime))) return false;
98         if (!event->write(info.cpuVulkanInUse)) return false;
99         event->init();
100         data->emplace_back(event);
101     }
102 
103     return true;
104 }
105 
PullInternal(std::vector<std::shared_ptr<LogEvent>> * data)106 bool GpuStatsPuller::PullInternal(std::vector<std::shared_ptr<LogEvent>>* data) {
107     const sp<IGpuService> gpuService = getGpuService();
108     if (!gpuService) {
109         return false;
110     }
111 
112     switch (mTagId) {
113         case android::util::GPU_STATS_GLOBAL_INFO:
114             return pullGpuStatsGlobalInfo(gpuService, data);
115         case android::util::GPU_STATS_APP_INFO:
116             return pullGpuStatsAppInfo(gpuService, data);
117         default:
118             break;
119     }
120 
121     return false;
122 }
123 
protoOutputStreamToByteString(ProtoOutputStream & proto)124 static std::string protoOutputStreamToByteString(ProtoOutputStream& proto) {
125     if (!proto.size()) return "";
126 
127     std::string byteString;
128     sp<ProtoReader> reader = proto.data();
129     while (reader->readBuffer() != nullptr) {
130         const size_t toRead = reader->currentToRead();
131         byteString.append((char*)reader->readBuffer(), toRead);
132         reader->move(toRead);
133     }
134 
135     if (byteString.size() != proto.size()) return "";
136 
137     return byteString;
138 }
139 
int64VectorToProtoByteString(const std::vector<int64_t> & value)140 std::string int64VectorToProtoByteString(const std::vector<int64_t>& value) {
141     if (value.empty()) return "";
142 
143     ProtoOutputStream proto;
144     for (const auto& ele : value) {
145         proto.write(android::util::FIELD_TYPE_INT64 | android::util::FIELD_COUNT_REPEATED |
146                             1 /* field id */,
147                     (long long)ele);
148     }
149 
150     return protoOutputStreamToByteString(proto);
151 }
152 
153 }  // namespace statsd
154 }  // namespace os
155 }  // namespace android
156