1 /*
2 * Copyright (C) 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
17 #include "VtsTrebleVintfTestBase.h"
18
19 #include <chrono>
20 #include <condition_variable>
21 #include <functional>
22 #include <future>
23 #include <iostream>
24 #include <map>
25 #include <mutex>
26 #include <set>
27 #include <sstream>
28 #include <string>
29 #include <thread>
30 #include <vector>
31
32 #include <android-base/logging.h>
33 #include <android-base/strings.h>
34 #include <android/hidl/manager/1.0/IServiceManager.h>
35 #include <gtest/gtest.h>
36 #include <hidl-hash/Hash.h>
37 #include <hidl-util/FQName.h>
38 #include <hidl-util/FqInstance.h>
39 #include <hidl/HidlTransportUtils.h>
40 #include <hidl/ServiceManagement.h>
41 #include <procpartition/procpartition.h>
42 #include <vintf/HalManifest.h>
43 #include <vintf/VintfObject.h>
44 #include <vintf/parse_string.h>
45
46 #include "SingleManifestTest.h"
47 #include "utils.h"
48
49 namespace android {
50 namespace vintf {
51 namespace testing {
52
53 using android::FqInstance;
54 using android::FQName;
55 using android::Hash;
56 using android::sp;
57 using android::hardware::hidl_array;
58 using android::hardware::hidl_string;
59 using android::hardware::hidl_vec;
60 using android::hardware::Return;
61 using android::hidl::base::V1_0::IBase;
62 using android::hidl::manager::V1_0::IServiceManager;
63 using android::procpartition::Partition;
64 using android::vintf::HalManifest;
65 using android::vintf::Level;
66 using android::vintf::ManifestHal;
67 using android::vintf::Transport;
68 using android::vintf::Version;
69 using android::vintf::VintfObject;
70 using android::vintf::operator<<;
71 using android::vintf::to_string;
72 using android::vintf::toFQNameString;
73
74 using std::cout;
75 using std::endl;
76 using std::map;
77 using std::set;
78 using std::string;
79 using std::vector;
80
SetUp()81 void VtsTrebleVintfTestBase::SetUp() {
82 default_manager_ = ::android::hardware::defaultServiceManager();
83 ASSERT_NE(default_manager_, nullptr)
84 << "Failed to get default service manager." << endl;
85 }
86
ForEachHidlHalInstance(const HalManifestPtr & manifest,HidlVerifyFn fn)87 void VtsTrebleVintfTestBase::ForEachHidlHalInstance(
88 const HalManifestPtr &manifest, HidlVerifyFn fn) {
89 manifest->forEachInstance([manifest, fn](const auto &manifest_instance) {
90 if (manifest_instance.format() != HalFormat::HIDL) {
91 return true; // continue to next instance
92 }
93 const FQName fq_name{manifest_instance.package(),
94 to_string(manifest_instance.version()),
95 manifest_instance.interface()};
96 const Transport transport = manifest_instance.transport();
97 const std::string instance_name = manifest_instance.instance();
98
99 auto future_result =
100 std::async([&]() { fn(fq_name, instance_name, transport); });
101 auto timeout = std::chrono::seconds(1);
102 std::future_status status = future_result.wait_for(timeout);
103 if (status != std::future_status::ready) {
104 cout << "Timed out on: " << fq_name.string() << " " << instance_name
105 << endl;
106 }
107 return true; // continue to next instance
108 });
109 }
110
ForEachAidlHalInstance(const HalManifestPtr & manifest,AidlVerifyFn fn)111 void VtsTrebleVintfTestBase::ForEachAidlHalInstance(
112 const HalManifestPtr &manifest, AidlVerifyFn fn) {
113 manifest->forEachInstance([manifest, fn](const auto &manifest_instance) {
114 if (manifest_instance.format() != HalFormat::AIDL) {
115 return true; // continue to next instance
116 }
117 const std::string &package = manifest_instance.package();
118 const std::string &interface = manifest_instance.interface();
119 const std::string &instance = manifest_instance.instance();
120
121 auto future_result =
122 std::async([&]() { fn(package, interface, instance); });
123 auto timeout = std::chrono::seconds(1);
124 std::future_status status = future_result.wait_for(timeout);
125 if (status != std::future_status::ready) {
126 cout << "Timed out on: " << package << "." << interface << "/" << instance
127 << endl;
128 }
129 return true; // continue to next instance
130 });
131 }
132
GetHalService(const FQName & fq_name,const string & instance_name,Transport transport,bool log)133 sp<IBase> VtsTrebleVintfTestBase::GetHalService(const FQName &fq_name,
134 const string &instance_name,
135 Transport transport, bool log) {
136 return GetHalService(fq_name.string(), instance_name, transport, log);
137 }
138
GetHalService(const string & fq_name,const string & instance_name,Transport transport,bool log)139 sp<IBase> VtsTrebleVintfTestBase::GetHalService(const string &fq_name,
140 const string &instance_name,
141 Transport transport, bool log) {
142 using android::hardware::details::getRawServiceInternal;
143
144 if (log) {
145 cout << "Getting: " << fq_name << "/" << instance_name << endl;
146 }
147
148 // getService blocks until a service is available. In 100% of other cases
149 // where getService is used, it should be called directly. However, this test
150 // enforces that various services are actually available when they are
151 // declared, it must make a couple of precautions in case the service isn't
152 // actually available so that the proper failure can be reported.
153
154 auto task = std::packaged_task<sp<IBase>()>([fq_name, instance_name]() {
155 return getRawServiceInternal(fq_name, instance_name, true /* retry */,
156 false /* getStub */);
157 });
158 auto max_time = std::chrono::seconds(1);
159
160 std::future<sp<IBase>> future = task.get_future();
161 std::thread(std::move(task)).detach();
162 auto status = future.wait_for(max_time);
163
164 if (status != std::future_status::ready) return nullptr;
165
166 sp<IBase> base = future.get();
167 if (base == nullptr) return nullptr;
168
169 bool wantRemote = transport == Transport::HWBINDER;
170 if (base->isRemote() != wantRemote) return nullptr;
171
172 return base;
173 }
174
GetInstanceNames(const sp<IServiceManager> & manager,const FQName & fq_name)175 vector<string> VtsTrebleVintfTestBase::GetInstanceNames(
176 const sp<IServiceManager> &manager, const FQName &fq_name) {
177 vector<string> ret;
178 auto status =
179 manager->listByInterface(fq_name.string(), [&](const auto &out) {
180 for (const auto &e : out) ret.push_back(e);
181 });
182 EXPECT_TRUE(status.isOk()) << status.description();
183 return ret;
184 }
185
GetInterfaceChain(const sp<IBase> & service)186 vector<string> VtsTrebleVintfTestBase::GetInterfaceChain(
187 const sp<IBase> &service) {
188 vector<string> iface_chain{};
189 service->interfaceChain([&iface_chain](const hidl_vec<hidl_string> &chain) {
190 for (const auto &iface_name : chain) {
191 iface_chain.push_back(iface_name);
192 }
193 });
194 return iface_chain;
195 }
196
GetPartition(sp<IBase> hal_service)197 Partition VtsTrebleVintfTestBase::GetPartition(sp<IBase> hal_service) {
198 Partition partition = Partition::UNKNOWN;
199 auto ret = hal_service->getDebugInfo(
200 [&](const auto &info) { partition = PartitionOfProcess(info.pid); });
201 EXPECT_TRUE(ret.isOk());
202 return partition;
203 }
204
GetPassthroughHals(HalManifestPtr manifest)205 set<string> VtsTrebleVintfTestBase::GetPassthroughHals(
206 HalManifestPtr manifest) {
207 std::set<std::string> manifest_passthrough_hals_;
208
209 auto add_manifest_hals = [&manifest_passthrough_hals_](
210 const FQName &fq_name,
211 const string &instance_name,
212 Transport transport) {
213 if (transport == Transport::HWBINDER) {
214 // ignore
215 } else if (transport == Transport::PASSTHROUGH) {
216 // 1.n in manifest => 1.0, 1.1, ... 1.n are all served (if they exist)
217 FQName fq = fq_name;
218 while (true) {
219 manifest_passthrough_hals_.insert(fq.string() + "/" + instance_name);
220 if (fq.getPackageMinorVersion() <= 0) break;
221 fq = fq.downRev();
222 }
223 } else {
224 ADD_FAILURE() << "Unrecognized transport: " << transport;
225 }
226 };
227 ForEachHidlHalInstance(manifest, add_manifest_hals);
228 return manifest_passthrough_hals_;
229 }
230
GetHwbinderHals(HalManifestPtr manifest)231 set<string> VtsTrebleVintfTestBase::GetHwbinderHals(HalManifestPtr manifest) {
232 std::set<std::string> manifest_hwbinder_hals_;
233
234 auto add_manifest_hals = [&manifest_hwbinder_hals_](
235 const FQName &fq_name,
236 const string &instance_name,
237 Transport transport) {
238 if (transport == Transport::HWBINDER) {
239 // 1.n in manifest => 1.0, 1.1, ... 1.n are all served (if they exist)
240 FQName fq = fq_name;
241 while (true) {
242 manifest_hwbinder_hals_.insert(fq.string() + "/" + instance_name);
243 if (fq.getPackageMinorVersion() <= 0) break;
244 fq = fq.downRev();
245 }
246 } else if (transport == Transport::PASSTHROUGH) {
247 // ignore
248 } else {
249 ADD_FAILURE() << "Unrecognized transport: " << transport;
250 }
251 };
252 ForEachHidlHalInstance(manifest, add_manifest_hals);
253 return manifest_hwbinder_hals_;
254 }
255
256 } // namespace testing
257 } // namespace vintf
258 } // namespace android
259