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 #include <android/hidl/manager/1.0/IServiceManager.h> 17 #include <cutils/properties.h> 18 #include <hidl/ServiceManagement.h> 19 #include <iostream> 20 21 using namespace std; 22 using namespace android; 23 24 const string kSysPropHalCoverage = "hal.coverage.enable"; 25 26 // Print usage directions. 27 void usage() { 28 cout << "usage:\n"; 29 cout << "vts_coverage_configure flush\t\t\t\t: to flush coverage on all " 30 "HALs\n"; 31 cout << "vts_coverage_configure flush <hal name>@<hal version>\t: to flush " 32 "coverage on one HAL name/version instance" 33 << std::endl; 34 } 35 36 // Parse the fully-qualified instance name and call the func with the interface 37 // name, instance name, and HAL name. 38 template <typename Lambda> 39 bool parseFqInstaceName(string fqInstanceName, Lambda &&func) { 40 string::size_type n = fqInstanceName.find("/"); 41 if (n == std::string::npos || fqInstanceName.size() == n + 1) return false; 42 43 string fqInterfaceName = fqInstanceName.substr(0, n); 44 string instanceName = fqInstanceName.substr(n + 1, std::string::npos); 45 46 n = fqInstanceName.find("::"); 47 if (n == std::string::npos || fqInstanceName.size() == n + 1) return false; 48 string halName = fqInstanceName.substr(0, n); 49 std::forward<Lambda>(func)(fqInterfaceName, instanceName, halName); 50 return true; 51 } 52 53 // Flush coverage on all HAL processes, or just the provided HAL name if 54 // provided. 55 bool FlushHALCoverage(string flushHal = "") { 56 using ::android::hidl::base::V1_0::IBase; 57 using ::android::hidl::manager::V1_0::IServiceManager; 58 using ::android::hardware::hidl_string; 59 using ::android::hardware::Return; 60 61 sp<IServiceManager> sm = ::android::hardware::defaultServiceManager(); 62 63 if (sm == nullptr) { 64 cerr << "failed to get IServiceManager to poke HAL services." << std::endl; 65 return false; 66 } 67 property_set(kSysPropHalCoverage.c_str(), "true"); 68 auto listRet = sm->list([&](const auto &interfaces) { 69 for (const string &fqInstanceName : interfaces) { 70 hidl_string fqInterfaceName; 71 hidl_string instanceName; 72 string halName; 73 74 auto cb = [&](string fqIface, string instance, string hal) { 75 fqInterfaceName = fqIface; 76 instanceName = instance; 77 halName = hal; 78 }; 79 if (!parseFqInstaceName(fqInstanceName, cb)) continue; 80 if (halName.find("android.hidl") == 0) continue; 81 if (flushHal == "" || !flushHal.compare(halName)) { 82 Return<sp<IBase>> interfaceRet = sm->get(fqInterfaceName, instanceName); 83 if (!interfaceRet.isOk()) { 84 cerr << "failed to get service " << fqInstanceName << ": " 85 << interfaceRet.description() << std::endl; 86 continue; 87 } 88 sp<IBase> interface = interfaceRet; 89 auto notifyRet = interface->notifySyspropsChanged(); 90 if (!notifyRet.isOk()) { 91 cerr << "failed to notifySyspropsChanged on service " 92 << fqInstanceName << ": " << notifyRet.description() 93 << std::endl; 94 } 95 cout << "- flushed the coverage for HAL " << fqInstanceName 96 << std::endl; 97 } 98 } 99 }); 100 property_set(kSysPropHalCoverage.c_str(), "false"); 101 if (!listRet.isOk()) { 102 cerr << "failed to list services: " << listRet.description() << std::endl; 103 return false; 104 } 105 return true; 106 } 107 108 // The provided binary can be used to flush coverage on one or all HALs. 109 // Usage examples: 110 // To flush gcov and/or sancov coverage data on all hals: <binary> flush 111 // To flush gcov and/or sancov coverage data on one hal: <binary> flush <hal 112 // name>@<hal version> 113 int main(int argc, char *argv[]) { 114 bool flush_coverage = false; 115 if (argc < 2) { 116 usage(); 117 return -1; 118 } 119 if (!strcmp(argv[1], "flush")) { 120 flush_coverage = true; 121 string halString = ""; 122 if (argc == 3) { 123 halString = string(argv[2]); 124 } 125 cout << "* flush coverage" << std::endl; 126 if (!FlushHALCoverage(halString)) { 127 cerr << "failed to flush coverage" << std::endl; 128 } 129 } else { 130 usage(); 131 } 132 return 0; 133 } 134