1 /*
2  * Copyright (C) 2018 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 "SingleManifestTest.h"
18 
19 #include <aidl/metadata.h>
20 #include <android-base/properties.h>
21 #include <android-base/strings.h>
22 #include <binder/IServiceManager.h>
23 #include <binder/Parcel.h>
24 #include <binder/Status.h>
25 #include <gmock/gmock.h>
26 #include <hidl-util/FqInstance.h>
27 #include <hidl/HidlTransportUtils.h>
28 #include <vintf/parse_string.h>
29 
30 #include <algorithm>
31 
32 #include "utils.h"
33 
34 using ::testing::AnyOf;
35 
36 namespace android {
37 namespace vintf {
38 namespace testing {
39 
40 using android::FqInstance;
41 using android::vintf::toFQNameString;
42 
43 // For devices that launched <= Android O-MR1, systems/hals/implementations
44 // were delivered to companies which either don't start up on device boot.
LegacyAndExempt(const FQName & fq_name)45 bool LegacyAndExempt(const FQName &fq_name) {
46   return GetShippingApiLevel() <= 27 && !IsAndroidPlatformInterface(fq_name);
47 }
48 
FailureHalMissing(const FQName & fq_name,const std::string & instance)49 void FailureHalMissing(const FQName &fq_name, const std::string &instance) {
50   if (LegacyAndExempt(fq_name)) {
51     cout << "[  WARNING ] " << fq_name.string() << "/" << instance
52          << " not available but is exempted because it is legacy. It is still "
53             "recommended to fix this."
54          << endl;
55   } else {
56     ADD_FAILURE() << fq_name.string() << "/" << instance << " not available.";
57   }
58 }
59 
FailureHashMissing(const FQName & fq_name,bool vehicle_hal_in_automotive_device)60 void FailureHashMissing(const FQName &fq_name,
61                         bool vehicle_hal_in_automotive_device) {
62   if (LegacyAndExempt(fq_name)) {
63     cout << "[  WARNING ] " << fq_name.string()
64          << " has an empty hash but is exempted because it is legacy. It is "
65             "still recommended to fix this. This is because it was compiled "
66             "without being frozen in a corresponding current.txt file."
67          << endl;
68   } else if (vehicle_hal_in_automotive_device) {
69     cout << "[  WARNING ] " << fq_name.string()
70          << " has an empty hash but is exempted because it is IVehicle in an"
71             "automotive device."
72          << endl;
73   } else {
74     ADD_FAILURE()
75         << fq_name.string()
76         << " has an empty hash. This is because it was compiled "
77            "without being frozen in a corresponding current.txt file.";
78   }
79 }
80 
81 template <typename It>
RangeInstancesToString(const std::pair<It,It> & range)82 static string RangeInstancesToString(const std::pair<It, It> &range) {
83   std::stringstream ss;
84   for (auto it = range.first; it != range.second; ++it) {
85     if (it != range.first) ss << ", ";
86     ss << it->second.string();
87   }
88   return ss.str();
89 }
90 
91 template <typename Container>
InstancesToString(const Container & container)92 static string InstancesToString(const Container &container) {
93   std::stringstream ss;
94   for (auto it = container.begin(); it != container.end(); ++it) {
95     if (it != container.begin()) ss << ", ";
96     ss << *it;
97   }
98   return ss.str();
99 }
100 
ToFqInstance(const string & interface,const string & instance)101 static FqInstance ToFqInstance(const string &interface,
102                                const string &instance) {
103   FqInstance fq_interface;
104   FqInstance ret;
105 
106   if (!fq_interface.setTo(interface)) {
107     ADD_FAILURE() << interface << " is not a valid FQName";
108     return ret;
109   }
110   if (!ret.setTo(fq_interface.getPackage(), fq_interface.getMajorVersion(),
111                  fq_interface.getMinorVersion(), fq_interface.getInterface(),
112                  instance)) {
113     ADD_FAILURE() << "Cannot convert to FqInstance: " << interface << "/"
114                   << instance;
115   }
116   return ret;
117 }
118 
119 // Given android.foo.bar@x.y::IFoo/default, attempt to get
120 // android.foo.bar@x.y::IFoo/default, android.foo.bar@x.(y-1)::IFoo/default,
121 // ... android.foo.bar@x.0::IFoo/default until the passthrough HAL is retrieved.
GetPassthroughService(const FqInstance & fq_instance)122 static sp<IBase> GetPassthroughService(const FqInstance &fq_instance) {
123   for (size_t minor_version = fq_instance.getMinorVersion();; --minor_version) {
124     // String out instance name from fq_instance.
125     FqInstance interface;
126     if (!interface.setTo(fq_instance.getPackage(),
127                          fq_instance.getMajorVersion(), minor_version,
128                          fq_instance.getInterface())) {
129       ADD_FAILURE() << fq_instance.string()
130                     << " doesn't contain a valid FQName";
131       return nullptr;
132     }
133 
134     auto hal_service = VtsTrebleVintfTestBase::GetHalService(
135         interface.string(), fq_instance.getInstance(), Transport::PASSTHROUGH);
136 
137     if (hal_service != nullptr) {
138       bool interface_chain_valid = false;
139       hal_service->interfaceChain([&](const auto &chain) {
140         for (const auto &intf : chain) {
141           if (intf == interface.string()) {
142             interface_chain_valid = true;
143             return;
144           }
145         }
146       });
147       if (!interface_chain_valid) {
148         ADD_FAILURE() << "Retrieved " << interface.string() << "/"
149                       << fq_instance.getInstance() << " as "
150                       << fq_instance.string()
151                       << " but interfaceChain() doesn't contain "
152                       << fq_instance.string();
153         return nullptr;
154       }
155       cout << "Retrieved " << interface.string() << "/"
156            << fq_instance.getInstance() << " as " << fq_instance.string()
157            << endl;
158       return hal_service;
159     }
160 
161     if (minor_version == 0) {
162       return nullptr;
163     }
164   }
165   ADD_FAILURE() << "Should not reach here";
166   return nullptr;
167 }
168 
169 // Tests that no HAL outside of the allowed set is specified as passthrough in
170 // VINTF.
TEST_P(SingleManifestTest,HalsAreBinderized)171 TEST_P(SingleManifestTest, HalsAreBinderized) {
172   multimap<Transport, FqInstance> instances;
173   ForEachHidlHalInstance(GetParam(), [&instances](const FQName &fq_name,
174                                                   const string &instance_name,
175                                                   Transport transport) {
176     FqInstance fqInstance;
177     ASSERT_TRUE(fqInstance.setTo(
178         fq_name.package(), fq_name.getPackageMajorVersion(),
179         fq_name.getPackageMinorVersion(), fq_name.name(), instance_name));
180     instances.emplace(transport, std::move(fqInstance));
181   });
182 
183   for (auto it = instances.begin(); it != instances.end();
184        it = instances.upper_bound(it->first)) {
185     EXPECT_THAT(it->first, AnyOf(Transport::HWBINDER, Transport::PASSTHROUGH))
186         << "The following HALs has unknown transport specified in VINTF ("
187         << it->first << ", ordinal "
188         << static_cast<std::underlying_type_t<Transport>>(it->first) << ")"
189         << RangeInstancesToString(instances.equal_range(it->first));
190   }
191 
192   auto passthrough_declared_range =
193       instances.equal_range(Transport::PASSTHROUGH);
194   set<FqInstance> passthrough_declared;
195   std::transform(
196       passthrough_declared_range.first, passthrough_declared_range.second,
197       std::inserter(passthrough_declared, passthrough_declared.begin()),
198       [](const auto &pair) { return pair.second; });
199 
200   set<FqInstance> passthrough_allowed;
201   for (const auto &declared_instance : passthrough_declared) {
202     auto hal_service = GetPassthroughService(declared_instance);
203 
204     // For vendor extensions, hal_service may be null because we don't know
205     // its interfaceChain()[1] to call getService(). However, the base interface
206     // should be declared in the manifest, so other iterations of this for-loop
207     // verify that vendor extension.
208     if (hal_service == nullptr) {
209       cout << "Skip calling interfaceChain on " << declared_instance.string()
210            << " because it can't be retrieved directly." << endl;
211       continue;
212     }
213 
214     // For example, given the following interfaceChain when
215     // hal_service is "android.hardware.mapper@2.0::IMapper/default":
216     // ["vendor.foo.mapper@1.0::IMapper",
217     //  "android.hardware.mapper@2.1::IMapper",
218     //  "android.hardware.mapper@2.0::IMapper",
219     //  "android.hidl.base@1.0::IBase"],
220     // Allow the following:
221     // ["vendor.foo.mapper@1.0::IMapper/default",
222     //  "android.hardware.mapper@2.1::IMapper/default",
223     //  "android.hardware.mapper@2.0::IMapper/default"]
224     hal_service->interfaceChain([&](const auto &chain) {
225       vector<FqInstance> fq_instances;
226       std::transform(
227           chain.begin(), chain.end(), std::back_inserter(fq_instances),
228           [&](const auto &interface) {
229             return ToFqInstance(interface, declared_instance.getInstance());
230           });
231 
232       bool allowing = false;
233       for (auto it = fq_instances.rbegin(); it != fq_instances.rend(); ++it) {
234         if (kPassthroughHals.find(it->getPackage()) != kPassthroughHals.end()) {
235           allowing = true;
236         }
237         if (allowing) {
238           cout << it->string() << " is allowed to be passthrough" << endl;
239           passthrough_allowed.insert(*it);
240         }
241       }
242     });
243   }
244 
245   set<FqInstance> passthrough_not_allowed;
246   std::set_difference(
247       passthrough_declared.begin(), passthrough_declared.end(),
248       passthrough_allowed.begin(), passthrough_allowed.end(),
249       std::inserter(passthrough_not_allowed, passthrough_not_allowed.begin()));
250 
251   EXPECT_TRUE(passthrough_not_allowed.empty())
252       << "The following HALs can't be passthrough under Treble rules: ["
253       << InstancesToString(passthrough_not_allowed) << "].";
254 }
255 
256 // Tests that all HALs specified in the VINTF are available through service
257 // manager.
258 // This tests (HAL in manifest) => (HAL is served)
TEST_P(SingleManifestTest,HalsAreServed)259 TEST_P(SingleManifestTest, HalsAreServed) {
260   // Returns a function that verifies that HAL is available through service
261   // manager and is served from a specific set of partitions.
262   auto is_available_from =
263       [this](Partition expected_partition) -> HidlVerifyFn {
264     return [this, expected_partition](const FQName &fq_name,
265                                       const string &instance_name,
266                                       Transport transport) {
267       sp<IBase> hal_service;
268 
269       if (transport == Transport::PASSTHROUGH) {
270         using android::hardware::details::canCastInterface;
271 
272         // Passthrough services all start with minor version 0.
273         // there are only three of them listed above. They are looked
274         // up based on their binary location. For instance,
275         // V1_0::IFoo::getService() might correspond to looking up
276         // android.hardware.foo@1.0-impl for the symbol
277         // HIDL_FETCH_IFoo. For @1.1::IFoo to continue to work with
278         // 1.0 clients, it must also be present in a library that is
279         // called the 1.0 name. Clients can say:
280         //     mFoo1_0 = V1_0::IFoo::getService();
281         //     mFoo1_1 = V1_1::IFoo::castFrom(mFoo1_0);
282         // This is the standard pattern for making a service work
283         // for both versions (mFoo1_1 != nullptr => you have 1.1)
284         // and a 1.0 client still works with the 1.1 interface.
285 
286         if (!IsAndroidPlatformInterface(fq_name)) {
287           // This isn't the case for extensions of core Google interfaces.
288           return;
289         }
290 
291         const FQName lowest_name =
292             fq_name.withVersion(fq_name.getPackageMajorVersion(), 0);
293         hal_service = GetHalService(lowest_name, instance_name, transport);
294         EXPECT_TRUE(
295             canCastInterface(hal_service.get(), fq_name.string().c_str()))
296             << fq_name.string() << " is not on the device.";
297       } else {
298         hal_service = GetHalService(fq_name, instance_name, transport);
299       }
300 
301       if (hal_service == nullptr) {
302         FailureHalMissing(fq_name, instance_name);
303         return;
304       }
305 
306       EXPECT_EQ(transport == Transport::HWBINDER, hal_service->isRemote())
307           << "transport is " << transport << "but HAL service is "
308           << (hal_service->isRemote() ? "" : "not") << " remote.";
309       EXPECT_EQ(transport == Transport::PASSTHROUGH, !hal_service->isRemote())
310           << "transport is " << transport << "but HAL service is "
311           << (hal_service->isRemote() ? "" : "not") << " remote.";
312 
313       if (!hal_service->isRemote()) return;
314 
315       Partition partition = GetPartition(hal_service);
316       if (partition == Partition::UNKNOWN) return;
317       EXPECT_EQ(expected_partition, partition)
318           << fq_name.string() << "/" << instance_name << " is in partition "
319           << partition << " but is expected to be in " << expected_partition;
320     };
321   };
322 
323   auto manifest = GetParam();
324   ForEachHidlHalInstance(manifest,
325                          is_available_from(PartitionOfType(manifest->type())));
326 }
327 
328 // Tests that all HALs which are served are specified in the VINTF
329 // This tests (HAL is served) => (HAL in manifest)
TEST_P(SingleManifestTest,ServedHwbinderHalsAreInManifest)330 TEST_P(SingleManifestTest, ServedHwbinderHalsAreInManifest) {
331   auto manifest = GetParam();
332   auto expected_partition = PartitionOfType(manifest->type());
333   std::set<std::string> manifest_hwbinder_hals_ = GetHwbinderHals(manifest);
334 
335   Return<void> ret = default_manager_->list([&](const auto &list) {
336     for (const auto &name : list) {
337       if (std::string(name).find(IBase::descriptor) == 0) continue;
338 
339       FqInstance fqInstanceName;
340       EXPECT_TRUE(fqInstanceName.setTo(name));
341 
342       auto service =
343           GetHalService(toFQNameString(fqInstanceName.getPackage(),
344                                        fqInstanceName.getVersion(),
345                                        fqInstanceName.getInterface()),
346                         fqInstanceName.getInstance(), Transport::HWBINDER);
347       ASSERT_NE(service, nullptr);
348 
349       Partition partition = GetPartition(service);
350       if (partition == Partition::UNKNOWN) {
351         // Caught by SystemVendorTest.ServedHwbinderHalsAreInManifest
352         // if that test is run.
353         return;
354       }
355       if (partition == expected_partition) {
356         EXPECT_NE(manifest_hwbinder_hals_.find(name),
357                   manifest_hwbinder_hals_.end())
358             << name << " is being served, but it is not in a manifest.";
359       }
360     }
361   });
362   EXPECT_TRUE(ret.isOk());
363 }
364 
TEST_P(SingleManifestTest,ServedPassthroughHalsAreInManifest)365 TEST_P(SingleManifestTest, ServedPassthroughHalsAreInManifest) {
366   auto manifest = GetParam();
367   std::set<std::string> manifest_passthrough_hals_ =
368       GetPassthroughHals(manifest);
369 
370   auto passthrough_interfaces_declared = [&manifest_passthrough_hals_](
371                                              const FQName &fq_name,
372                                              const string &instance_name,
373                                              Transport transport) {
374     if (transport != Transport::PASSTHROUGH) return;
375 
376     // See HalsAreServed. These are always retrieved through the base interface
377     // and if it is not a google defined interface, it must be an extension of
378     // one.
379     if (!IsAndroidPlatformInterface(fq_name)) return;
380 
381     const FQName lowest_name =
382         fq_name.withVersion(fq_name.getPackageMajorVersion(), 0);
383     sp<IBase> hal_service =
384         GetHalService(lowest_name, instance_name, transport);
385     if (hal_service == nullptr) {
386       ADD_FAILURE() << "Could not get service " << fq_name.string() << "/"
387                     << instance_name;
388       return;
389     }
390 
391     Return<void> ret = hal_service->interfaceChain(
392         [&manifest_passthrough_hals_, &instance_name](const auto &interfaces) {
393           for (const auto &interface : interfaces) {
394             if (std::string(interface) == IBase::descriptor) continue;
395 
396             const std::string instance =
397                 std::string(interface) + "/" + instance_name;
398             EXPECT_NE(manifest_passthrough_hals_.find(instance),
399                       manifest_passthrough_hals_.end())
400                 << "Instance missing from manifest: " << instance;
401           }
402         });
403     EXPECT_TRUE(ret.isOk());
404   };
405   ForEachHidlHalInstance(manifest, passthrough_interfaces_declared);
406 }
407 
408 // Tests that HAL interfaces are officially released.
TEST_P(SingleManifestTest,InterfacesAreReleased)409 TEST_P(SingleManifestTest, InterfacesAreReleased) {
410   // Device support automotive features.
411   const static bool automotive_device =
412       DeviceSupportsFeature("android.hardware.type.automotive");
413   // Verifies that HAL are released by fetching the hash of the interface and
414   // comparing it to the set of known hashes of released interfaces.
415   HidlVerifyFn is_released = [](const FQName &fq_name,
416                                 const string &instance_name,
417                                 Transport transport) {
418     // See HalsAreServed. These are always retrieved through the base interface
419     // and if it is not a google defined interface, it must be an extension of
420     // one.
421     if (transport == Transport::PASSTHROUGH &&
422         (!IsAndroidPlatformInterface(fq_name) ||
423          fq_name.getPackageMinorVersion() != 0)) {
424       return;
425     }
426 
427     sp<IBase> hal_service = GetHalService(fq_name, instance_name, transport);
428 
429     if (hal_service == nullptr) {
430       FailureHalMissing(fq_name, instance_name);
431       return;
432     }
433 
434     vector<string> iface_chain = GetInterfaceChain(hal_service);
435 
436     vector<string> hash_chain{};
437     hal_service->getHashChain(
438         [&hash_chain](const hidl_vec<HashCharArray> &chain) {
439           for (const HashCharArray &hash_array : chain) {
440             vector<uint8_t> hash{hash_array.data(),
441                                  hash_array.data() + hash_array.size()};
442             hash_chain.push_back(Hash::hexString(hash));
443           }
444         });
445 
446     ASSERT_EQ(iface_chain.size(), hash_chain.size());
447     for (size_t i = 0; i < iface_chain.size(); ++i) {
448       FQName fq_iface_name;
449       if (!FQName::parse(iface_chain[i], &fq_iface_name)) {
450         ADD_FAILURE() << "Could not parse iface name " << iface_chain[i]
451                       << " from interface chain of " << fq_name.string();
452         return;
453       }
454       string hash = hash_chain[i];
455 
456       bool vehicle_hal_in_automotive_device =
457           automotive_device &&
458           fq_iface_name.string() ==
459               "android.hardware.automotive.vehicle@2.0::IVehicle";
460       if (hash == Hash::hexString(Hash::kEmptyHash)) {
461         FailureHashMissing(fq_iface_name, vehicle_hal_in_automotive_device);
462       }
463 
464       if (IsAndroidPlatformInterface(fq_iface_name) &&
465           !vehicle_hal_in_automotive_device) {
466         set<string> released_hashes = ReleasedHashes(fq_iface_name);
467         EXPECT_NE(released_hashes.find(hash), released_hashes.end())
468             << "Hash not found. This interface was not released." << endl
469             << "Interface name: " << fq_iface_name.string() << endl
470             << "Hash: " << hash << endl;
471       }
472     }
473   };
474 
475   ForEachHidlHalInstance(GetParam(), is_released);
476 }
477 
hashesForInterface(const std::string & name)478 static std::vector<std::string> hashesForInterface(const std::string &name) {
479   for (const auto &module : AidlInterfaceMetadata::all()) {
480     if (std::find(module.types.begin(), module.types.end(), name) !=
481         module.types.end()) {
482       return module.hashes;
483     }
484   }
485   return {};
486 }
487 
488 // TODO(b/150155678): using standard code to do this
getInterfaceHash(const sp<IBinder> & binder)489 static std::string getInterfaceHash(const sp<IBinder> &binder) {
490   Parcel data;
491   Parcel reply;
492   data.writeInterfaceToken(binder->getInterfaceDescriptor());
493   status_t err =
494       binder->transact(IBinder::LAST_CALL_TRANSACTION - 1, data, &reply, 0);
495   if (err == UNKNOWN_TRANSACTION) {
496     return "";
497   }
498   EXPECT_EQ(OK, err);
499   binder::Status status;
500   EXPECT_EQ(OK, status.readFromParcel(reply));
501   EXPECT_TRUE(status.isOk()) << status.toString8().c_str();
502   std::string str;
503   EXPECT_EQ(OK, reply.readUtf8FromUtf16(&str));
504   return str;
505 }
506 
507 // An AIDL HAL with VINTF stability can only be registered if it is in the
508 // manifest. However, we still must manually check that every declared HAL is
509 // actually present on the device.
TEST_P(SingleManifestTest,ManifestAidlHalsServed)510 TEST_P(SingleManifestTest, ManifestAidlHalsServed) {
511   AidlVerifyFn expect_available = [](const string &package,
512                                      const string &interface,
513                                      const string &instance) {
514     const std::string type = package + "." + interface;
515     const std::string name = type + "/" + instance;
516     sp<IBinder> binder =
517         defaultServiceManager()->waitForService(String16(name.c_str()));
518     EXPECT_NE(binder, nullptr) << "Failed to get " << name;
519 
520     const std::string hash = getInterfaceHash(binder);
521     const std::vector<std::string> hashes = hashesForInterface(type);
522 
523     const bool is_aosp = base::StartsWith(package, "android.");
524     const bool is_release =
525         base::GetProperty("ro.build.version.codename", "") == "REL";
526     const bool found_hash =
527         std::find(hashes.begin(), hashes.end(), hash) != hashes.end();
528 
529     if (is_aosp) {
530       if (!found_hash) {
531         if (is_release) {
532           ADD_FAILURE() << "Interface " << name
533                         << " has an unrecognized hash: '" << hash
534                         << "'. The following hashes are known:\n"
535                         << base::Join(hashes, '\n')
536                         << "\nHAL interfaces must be released and unchanged.";
537         } else {
538           std::cout << "INFO: using unfrozen hash '" << hash << "' for " << type
539                     << ". This will become an error upon release." << std::endl;
540         }
541       }
542     } else {
543       // is extension
544       //
545       // we only require that these are frozen, but we cannot check them for
546       // accuracy
547       if (hash.empty()) {
548         if (is_release) {
549           ADD_FAILURE() << "Interface " << name
550                         << " is used but not frozen (cannot find hash for it).";
551         } else {
552           std::cout << "INFO: missing hash for " << type
553                     << ". This will become an error upon release." << std::endl;
554         }
555       }
556     }
557 
558   };
559 
560   ForEachAidlHalInstance(GetParam(), expect_available);
561 }
562 
563 }  // namespace testing
564 }  // namespace vintf
565 }  // namespace android
566