/* * Copyright 2017 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 <android/hidl/manager/1.0/IServiceManager.h> #include <cutils/properties.h> #include <hidl/ServiceManagement.h> #include <iostream> using namespace std; using namespace android; const string kSysPropHalCoverage = "hal.coverage.enable"; // Print usage directions. void usage() { cout << "usage:\n"; cout << "vts_coverage_configure flush\t\t\t\t: to flush coverage on all " "HALs\n"; cout << "vts_coverage_configure flush <hal name>@<hal version>\t: to flush " "coverage on one HAL name/version instance" << std::endl; } // Parse the fully-qualified instance name and call the func with the interface // name, instance name, and HAL name. template <typename Lambda> bool parseFqInstaceName(string fqInstanceName, Lambda &&func) { string::size_type n = fqInstanceName.find("/"); if (n == std::string::npos || fqInstanceName.size() == n + 1) return false; string fqInterfaceName = fqInstanceName.substr(0, n); string instanceName = fqInstanceName.substr(n + 1, std::string::npos); n = fqInstanceName.find("::"); if (n == std::string::npos || fqInstanceName.size() == n + 1) return false; string halName = fqInstanceName.substr(0, n); std::forward<Lambda>(func)(fqInterfaceName, instanceName, halName); return true; } // Flush coverage on all HAL processes, or just the provided HAL name if // provided. bool FlushHALCoverage(string flushHal = "") { using ::android::hidl::base::V1_0::IBase; using ::android::hidl::manager::V1_0::IServiceManager; using ::android::hardware::hidl_string; using ::android::hardware::Return; sp<IServiceManager> sm = ::android::hardware::defaultServiceManager(); if (sm == nullptr) { cerr << "failed to get IServiceManager to poke HAL services." << std::endl; return false; } property_set(kSysPropHalCoverage.c_str(), "true"); auto listRet = sm->list([&](const auto &interfaces) { for (const string &fqInstanceName : interfaces) { hidl_string fqInterfaceName; hidl_string instanceName; string halName; auto cb = [&](string fqIface, string instance, string hal) { fqInterfaceName = fqIface; instanceName = instance; halName = hal; }; if (!parseFqInstaceName(fqInstanceName, cb)) continue; if (halName.find("android.hidl") == 0) continue; if (flushHal == "" || !flushHal.compare(halName)) { Return<sp<IBase>> interfaceRet = sm->get(fqInterfaceName, instanceName); if (!interfaceRet.isOk()) { cerr << "failed to get service " << fqInstanceName << ": " << interfaceRet.description() << std::endl; continue; } sp<IBase> interface = interfaceRet; auto notifyRet = interface->notifySyspropsChanged(); if (!notifyRet.isOk()) { cerr << "failed to notifySyspropsChanged on service " << fqInstanceName << ": " << notifyRet.description() << std::endl; } cout << "- flushed the coverage for HAL " << fqInstanceName << std::endl; } } }); property_set(kSysPropHalCoverage.c_str(), "false"); if (!listRet.isOk()) { cerr << "failed to list services: " << listRet.description() << std::endl; return false; } return true; } // The provided binary can be used to flush coverage on one or all HALs. // Usage examples: // To flush gcov and/or sancov coverage data on all hals: <binary> flush // To flush gcov and/or sancov coverage data on one hal: <binary> flush <hal // name>@<hal version> int main(int argc, char *argv[]) { bool flush_coverage = false; if (argc < 2) { usage(); return -1; } if (!strcmp(argv[1], "flush")) { flush_coverage = true; string halString = ""; if (argc == 3) { halString = string(argv[2]); } cout << "* flush coverage" << std::endl; if (!FlushHALCoverage(halString)) { cerr << "failed to flush coverage" << std::endl; } } else { usage(); } return 0; }