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