/* * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "GpuStatsPuller.h" #include #include #include #include "logd/LogEvent.h" #include "stats_log_util.h" #include "statslog.h" namespace android { namespace os { namespace statsd { using android::util::ProtoReader; GpuStatsPuller::GpuStatsPuller(const int tagId) : StatsPuller(tagId) { } static sp getGpuService() { const sp binder = defaultServiceManager()->checkService(String16("gpu")); if (!binder) { ALOGE("Failed to get gpu service"); return nullptr; } return interface_cast(binder); } static bool pullGpuStatsGlobalInfo(const sp& gpuService, std::vector>* data) { std::vector stats; status_t status = gpuService->getGpuStatsGlobalInfo(&stats); if (status != OK) { return false; } data->clear(); data->reserve(stats.size()); for (const auto& info : stats) { std::shared_ptr event = make_shared( android::util::GPU_STATS_GLOBAL_INFO, getWallClockNs(), getElapsedRealtimeNs()); if (!event->write(info.driverPackageName)) return false; if (!event->write(info.driverVersionName)) return false; if (!event->write((int64_t)info.driverVersionCode)) return false; if (!event->write(info.driverBuildTime)) return false; if (!event->write((int64_t)info.glLoadingCount)) return false; if (!event->write((int64_t)info.glLoadingFailureCount)) return false; if (!event->write((int64_t)info.vkLoadingCount)) return false; if (!event->write((int64_t)info.vkLoadingFailureCount)) return false; if (!event->write(info.vulkanVersion)) return false; if (!event->write(info.cpuVulkanVersion)) return false; if (!event->write(info.glesVersion)) return false; if (!event->write((int64_t)info.angleLoadingCount)) return false; if (!event->write((int64_t)info.angleLoadingFailureCount)) return false; event->init(); data->emplace_back(event); } return true; } static bool pullGpuStatsAppInfo(const sp& gpuService, std::vector>* data) { std::vector stats; status_t status = gpuService->getGpuStatsAppInfo(&stats); if (status != OK) { return false; } data->clear(); data->reserve(stats.size()); for (const auto& info : stats) { std::shared_ptr event = make_shared( android::util::GPU_STATS_APP_INFO, getWallClockNs(), getElapsedRealtimeNs()); if (!event->write(info.appPackageName)) return false; if (!event->write((int64_t)info.driverVersionCode)) return false; if (!event->write(int64VectorToProtoByteString(info.glDriverLoadingTime))) return false; if (!event->write(int64VectorToProtoByteString(info.vkDriverLoadingTime))) return false; if (!event->write(int64VectorToProtoByteString(info.angleDriverLoadingTime))) return false; if (!event->write(info.cpuVulkanInUse)) return false; event->init(); data->emplace_back(event); } return true; } bool GpuStatsPuller::PullInternal(std::vector>* data) { const sp gpuService = getGpuService(); if (!gpuService) { return false; } switch (mTagId) { case android::util::GPU_STATS_GLOBAL_INFO: return pullGpuStatsGlobalInfo(gpuService, data); case android::util::GPU_STATS_APP_INFO: return pullGpuStatsAppInfo(gpuService, data); default: break; } return false; } static std::string protoOutputStreamToByteString(ProtoOutputStream& proto) { if (!proto.size()) return ""; std::string byteString; sp reader = proto.data(); while (reader->readBuffer() != nullptr) { const size_t toRead = reader->currentToRead(); byteString.append((char*)reader->readBuffer(), toRead); reader->move(toRead); } if (byteString.size() != proto.size()) return ""; return byteString; } std::string int64VectorToProtoByteString(const std::vector& value) { if (value.empty()) return ""; ProtoOutputStream proto; for (const auto& ele : value) { proto.write(android::util::FIELD_TYPE_INT64 | android::util::FIELD_COUNT_REPEATED | 1 /* field id */, (long long)ele); } return protoOutputStreamToByteString(proto); } } // namespace statsd } // namespace os } // namespace android