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 <chrono>
18 #include <functional>
19 #include <future>
20 #include <iostream>
21 #include <map>
22 #include <set>
23 #include <sstream>
24 #include <string>
25 #include <thread>
26 #include <vector>
27 
28 #include <android/hidl/manager/1.0/IServiceManager.h>
29 #include <gtest/gtest.h>
30 #include <hidl-hash/Hash.h>
31 #include <hidl-util/FQName.h>
32 #include <hidl/ServiceManagement.h>
33 #include <vintf/HalManifest.h>
34 #include <vintf/VintfObject.h>
35 #include <vintf/parse_string.h>
36 
37 #include "VtsTrebleVintfTestBase.h"
38 
39 namespace android {
40 namespace vintf {
41 namespace testing {
42 namespace legacy {
43 
44 using android::FQName;
45 using android::Hash;
46 using android::sp;
47 using android::hardware::hidl_array;
48 using android::hardware::hidl_string;
49 using android::hardware::hidl_vec;
50 using android::hidl::manager::V1_0::IServiceManager;
51 using android::vintf::HalManifest;
52 using android::vintf::to_string;
53 using android::vintf::Transport;
54 using android::vintf::Version;
55 using android::vintf::VintfObject;
56 
57 using std::cout;
58 using std::endl;
59 using std::map;
60 using std::set;
61 using std::string;
62 using std::vector;
63 using HalVerifyFn =
64     std::function<void(const FQName &fq_name, const string &instance_name)>;
65 
66 // Returns true iff HAL interface is exempt from following rules:
67 // 1. If an interface is declared in VINTF, it has to be served on the device.
IsExempt(const FQName & fq_iface_name)68 static bool IsExempt(const FQName &fq_iface_name) {
69   static const set<string> exempt_hals_ = {};
70   string hal_name = fq_iface_name.package();
71   // Radio-releated and non-Google HAL interfaces are given exemptions.
72   return exempt_hals_.find(hal_name) != exempt_hals_.end() ||
73          !IsAndroidPlatformInterface(fq_iface_name);
74 }
75 
76 class VtsTrebleVintfTest : public ::testing::Test {
77  public:
SetUp()78   virtual void SetUp() override {
79     default_manager_ = ::android::hardware::defaultServiceManager();
80     ASSERT_NE(default_manager_, nullptr)
81         << "Failed to get default service manager." << endl;
82 
83     passthrough_manager_ = ::android::hardware::getPassthroughServiceManager();
84     ASSERT_NE(passthrough_manager_, nullptr)
85         << "Failed to get passthrough service manager." << endl;
86 
87     vendor_manifest_ = VintfObject::GetDeviceHalManifest();
88     ASSERT_NE(vendor_manifest_, nullptr)
89         << "Failed to get vendor HAL manifest." << endl;
90   }
91 
92   // Applies given function to each HAL instance in VINTF.
93   void ForEachHalInstance(HalVerifyFn);
94   // Retrieves an existing HAL service.
95   sp<android::hidl::base::V1_0::IBase> GetHalService(
96       const FQName &fq_name, const string &instance_name);
97 
98   // Default service manager.
99   sp<IServiceManager> default_manager_;
100   // Passthrough service manager.
101   sp<IServiceManager> passthrough_manager_;
102   // Vendor hal manifest.
103   std::shared_ptr<const HalManifest> vendor_manifest_;
104 };
105 
ForEachHalInstance(HalVerifyFn fn)106 void VtsTrebleVintfTest::ForEachHalInstance(HalVerifyFn fn) {
107   vendor_manifest_->forEachInstance([fn](const auto &manifest_instance) {
108     const FQName fq_name{manifest_instance.package(),
109                          to_string(manifest_instance.version()),
110                          manifest_instance.interface()};
111     const std::string instance_name = manifest_instance.instance();
112 
113     auto future_result = std::async([&]() { fn(fq_name, instance_name); });
114     auto timeout = std::chrono::milliseconds(500);
115     std::future_status status = future_result.wait_for(timeout);
116     if (status != std::future_status::ready) {
117       cout << "Timed out on: " << fq_name.string() << " " << instance_name
118            << endl;
119     }
120     return true;  // continue to next instance
121   });
122 }
123 
GetHalService(const FQName & fq_name,const string & instance_name)124 sp<android::hidl::base::V1_0::IBase> VtsTrebleVintfTest::GetHalService(
125     const FQName &fq_name, const string &instance_name) {
126   string hal_name = fq_name.package();
127   Version version{fq_name.getPackageMajorVersion(),
128                   fq_name.getPackageMinorVersion()};
129   string iface_name = fq_name.name();
130   string fq_iface_name = fq_name.string();
131   cout << "Getting service of: " << fq_iface_name << endl;
132 
133   Transport transport = vendor_manifest_->getTransport(
134       hal_name, version, iface_name, instance_name);
135 
136   return VtsTrebleVintfTestBase::GetHalService(fq_name, instance_name,
137                                                transport);
138 }
139 
140 // Tests that no HAL outside of the allowed set is specified as passthrough in
141 // VINTF.
TEST_F(VtsTrebleVintfTest,HalsAreBinderized)142 TEST_F(VtsTrebleVintfTest, HalsAreBinderized) {
143   // Verifies that HAL is binderized unless it's allowed to be passthrough.
144   HalVerifyFn is_binderized = [this](const FQName &fq_name,
145                                      const string &instance_name) {
146     cout << "Verifying transport method of: " << fq_name.string() << endl;
147     string hal_name = fq_name.package();
148     Version version{fq_name.getPackageMajorVersion(),
149                     fq_name.getPackageMinorVersion()};
150     string iface_name = fq_name.name();
151 
152     Transport transport = vendor_manifest_->getTransport(
153         hal_name, version, iface_name, instance_name);
154 
155     EXPECT_NE(transport, Transport::EMPTY)
156         << hal_name << " has no transport specified in VINTF.";
157 
158     if (transport == Transport::PASSTHROUGH) {
159       EXPECT_NE(kPassthroughHals.find(hal_name), kPassthroughHals.end())
160           << hal_name << " can't be passthrough under Treble rules.";
161     }
162   };
163 
164   ForEachHalInstance(is_binderized);
165 }
166 
167 // Tests that all HALs specified in the VINTF are available through service
168 // manager.
TEST_F(VtsTrebleVintfTest,VintfHalsAreServed)169 TEST_F(VtsTrebleVintfTest, VintfHalsAreServed) {
170   // Verifies that HAL is available through service manager.
171   HalVerifyFn is_available = [this](const FQName &fq_name,
172                                     const string &instance_name) {
173     if (IsExempt(fq_name)) {
174       cout << fq_name.string() << " is exempt for O-MR1 vendor." << endl;
175       return;
176     }
177 
178     sp<android::hidl::base::V1_0::IBase> hal_service =
179         GetHalService(fq_name, instance_name);
180     EXPECT_NE(hal_service, nullptr)
181         << fq_name.string() << " not available." << endl;
182   };
183 
184   ForEachHalInstance(is_available);
185 }
186 
187 // Tests that HAL interfaces are officially released.
TEST_F(VtsTrebleVintfTest,InterfacesAreReleased)188 TEST_F(VtsTrebleVintfTest, InterfacesAreReleased) {
189   // Verifies that HAL are released by fetching the hash of the interface and
190   // comparing it to the set of known hashes of released interfaces.
191   HalVerifyFn is_released = [this](const FQName &fq_name,
192                                    const string &instance_name) {
193     sp<android::hidl::base::V1_0::IBase> hal_service =
194         GetHalService(fq_name, instance_name);
195 
196     if (hal_service == nullptr) {
197       if (IsExempt(fq_name)) {
198         cout << fq_name.string() << " is exempt for O-MR1 vendor." << endl;
199       } else {
200         ADD_FAILURE() << fq_name.package() << " not available." << endl;
201       }
202       return;
203     }
204 
205     vector<string> iface_chain{};
206     hal_service->interfaceChain(
207         [&iface_chain](const hidl_vec<hidl_string> &chain) {
208           for (const auto &iface_name : chain) {
209             iface_chain.push_back(iface_name);
210           }
211         });
212 
213     vector<string> hash_chain{};
214     hal_service->getHashChain(
215         [&hash_chain](const hidl_vec<HashCharArray> &chain) {
216           for (const HashCharArray &hash_array : chain) {
217             vector<uint8_t> hash{hash_array.data(),
218                                  hash_array.data() + hash_array.size()};
219             hash_chain.push_back(Hash::hexString(hash));
220           }
221         });
222 
223     ASSERT_EQ(iface_chain.size(), hash_chain.size());
224     for (size_t i = 0; i < iface_chain.size(); ++i) {
225       FQName fq_iface_name;
226       if (!FQName::parse(iface_chain[i], &fq_iface_name)) {
227         ADD_FAILURE() << "Could not parse iface name " << iface_chain[i]
228                       << " from interface chain of " << fq_name.string();
229         return;
230       }
231       string hash = hash_chain[i];
232 
233       if (IsAndroidPlatformInterface(fq_iface_name)) {
234         set<string> released_hashes = ReleasedHashes(fq_iface_name);
235         EXPECT_NE(released_hashes.find(hash), released_hashes.end())
236             << "Hash not found. This interface was not released." << endl
237             << "Interface name: " << fq_iface_name.string() << endl
238             << "Hash: " << hash << endl;
239       }
240     }
241   };
242 
243   ForEachHalInstance(is_released);
244 }
245 
246 }  // namespace legacy
247 }  // namespace testing
248 }  // namespace vintf
249 }  // namespace android
250