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 
ForEachHalInstance(const HalManifestPtr & manifest,HalVerifyFn fn)87 void VtsTrebleVintfTestBase::ForEachHalInstance(const HalManifestPtr &manifest,
88                                                 HalVerifyFn fn) {
89   manifest->forEachInstance([manifest, fn](const auto &manifest_instance) {
90     const FQName fq_name{manifest_instance.package(),
91                          to_string(manifest_instance.version()),
92                          manifest_instance.interface()};
93     const Transport transport = manifest_instance.transport();
94     const std::string instance_name = manifest_instance.instance();
95 
96     auto future_result =
97         std::async([&]() { fn(fq_name, instance_name, transport); });
98     auto timeout = std::chrono::seconds(1);
99     std::future_status status = future_result.wait_for(timeout);
100     if (status != std::future_status::ready) {
101       cout << "Timed out on: " << fq_name.string() << " " << instance_name
102            << endl;
103     }
104     return true;  // continue to next instance
105   });
106 }
107 
GetHalService(const FQName & fq_name,const string & instance_name,Transport transport,bool log)108 sp<IBase> VtsTrebleVintfTestBase::GetHalService(const FQName &fq_name,
109                                                 const string &instance_name,
110                                                 Transport transport, bool log) {
111   return GetHalService(fq_name.string(), instance_name, transport, log);
112 }
113 
GetHalService(const string & fq_name,const string & instance_name,Transport transport,bool log)114 sp<IBase> VtsTrebleVintfTestBase::GetHalService(const string &fq_name,
115                                                 const string &instance_name,
116                                                 Transport transport, bool log) {
117   using android::hardware::details::getRawServiceInternal;
118 
119   if (log) {
120     cout << "Getting: " << fq_name << "/" << instance_name << endl;
121   }
122 
123   // getService blocks until a service is available. In 100% of other cases
124   // where getService is used, it should be called directly. However, this test
125   // enforces that various services are actually available when they are
126   // declared, it must make a couple of precautions in case the service isn't
127   // actually available so that the proper failure can be reported.
128 
129   auto task = std::packaged_task<sp<IBase>()>([fq_name, instance_name]() {
130     return getRawServiceInternal(fq_name, instance_name, true /* retry */,
131                                  false /* getStub */);
132   });
133   auto max_time = std::chrono::milliseconds(500);
134 
135   // TODO(b/114157425): remove once android.hardware.renderscript@1.0-impl.so
136   // dlopen time reduced to normal level
137   if (fq_name == "android.hardware.renderscript@1.0::IDevice") {
138     max_time = std::chrono::seconds(1);
139   }
140 
141   std::future<sp<IBase>> future = task.get_future();
142   std::thread(std::move(task)).detach();
143   auto status = future.wait_for(max_time);
144 
145   if (status != std::future_status::ready) return nullptr;
146 
147   sp<IBase> base = future.get();
148   if (base == nullptr) return nullptr;
149 
150   bool wantRemote = transport == Transport::HWBINDER;
151   if (base->isRemote() != wantRemote) return nullptr;
152 
153   return base;
154 }
155 
GetInstanceNames(const sp<IServiceManager> & manager,const FQName & fq_name)156 vector<string> VtsTrebleVintfTestBase::GetInstanceNames(
157     const sp<IServiceManager> &manager, const FQName &fq_name) {
158   vector<string> ret;
159   auto status =
160       manager->listByInterface(fq_name.string(), [&](const auto &out) {
161         for (const auto &e : out) ret.push_back(e);
162       });
163   EXPECT_TRUE(status.isOk()) << status.description();
164   return ret;
165 }
166 
GetInterfaceChain(const sp<IBase> & service)167 vector<string> VtsTrebleVintfTestBase::GetInterfaceChain(
168     const sp<IBase> &service) {
169   vector<string> iface_chain{};
170   service->interfaceChain([&iface_chain](const hidl_vec<hidl_string> &chain) {
171     for (const auto &iface_name : chain) {
172       iface_chain.push_back(iface_name);
173     }
174   });
175   return iface_chain;
176 }
177 
GetPartition(sp<IBase> hal_service)178 Partition VtsTrebleVintfTestBase::GetPartition(sp<IBase> hal_service) {
179   Partition partition = Partition::UNKNOWN;
180   auto ret = hal_service->getDebugInfo(
181       [&](const auto &info) { partition = PartitionOfProcess(info.pid); });
182   EXPECT_TRUE(ret.isOk());
183   return partition;
184 }
185 
GetPassthroughHals(HalManifestPtr manifest)186 set<string> VtsTrebleVintfTestBase::GetPassthroughHals(
187     HalManifestPtr manifest) {
188   std::set<std::string> manifest_passthrough_hals_;
189 
190   auto add_manifest_hals = [&manifest_passthrough_hals_](
191                                const FQName &fq_name,
192                                const string &instance_name,
193                                Transport transport) {
194     if (transport == Transport::HWBINDER) {
195       // ignore
196     } else if (transport == Transport::PASSTHROUGH) {
197       // 1.n in manifest => 1.0, 1.1, ... 1.n are all served (if they exist)
198       FQName fq = fq_name;
199       while (true) {
200         manifest_passthrough_hals_.insert(fq.string() + "/" + instance_name);
201         if (fq.getPackageMinorVersion() <= 0) break;
202         fq = fq.downRev();
203       }
204     } else {
205       ADD_FAILURE() << "Unrecognized transport: " << transport;
206     }
207   };
208   ForEachHalInstance(manifest, add_manifest_hals);
209   return manifest_passthrough_hals_;
210 }
211 
GetHwbinderHals(HalManifestPtr manifest)212 set<string> VtsTrebleVintfTestBase::GetHwbinderHals(HalManifestPtr manifest) {
213   std::set<std::string> manifest_hwbinder_hals_;
214 
215   auto add_manifest_hals = [&manifest_hwbinder_hals_](
216                                const FQName &fq_name,
217                                const string &instance_name,
218                                Transport transport) {
219     if (transport == Transport::HWBINDER) {
220       // 1.n in manifest => 1.0, 1.1, ... 1.n are all served (if they exist)
221       FQName fq = fq_name;
222       while (true) {
223         manifest_hwbinder_hals_.insert(fq.string() + "/" + instance_name);
224         if (fq.getPackageMinorVersion() <= 0) break;
225         fq = fq.downRev();
226       }
227     } else if (transport == Transport::PASSTHROUGH) {
228       // ignore
229     } else {
230       ADD_FAILURE() << "Unrecognized transport: " << transport;
231     }
232   };
233   ForEachHalInstance(manifest, add_manifest_hals);
234   return manifest_hwbinder_hals_;
235 }
236 
237 }  // namespace testing
238 }  // namespace vintf
239 }  // namespace android
240