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