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