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.
usage()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>
parseFqInstaceName(string fqInstanceName,Lambda && func)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.
FlushHALCoverage(string flushHal="")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>
main(int argc,char * argv[])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