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/file.h>
21 #include <android-base/hex.h>
22 #include <android-base/properties.h>
23 #include <android-base/strings.h>
24 #include <android/apex/ApexInfo.h>
25 #include <android/apex/IApexService.h>
26 #include <binder/IServiceManager.h>
27 #include <binder/Parcel.h>
28 #include <binder/Stability.h>
29 #include <binder/Status.h>
30 #include <dirent.h>
31 #include <dlfcn.h>
32 #include <gmock/gmock.h>
33 #include <hidl-util/FqInstance.h>
34 #include <hidl/HidlTransportUtils.h>
35 #include <stdio.h>
36 #include <vintf/constants.h>
37 #include <vintf/parse_string.h>
38
39 #include <algorithm>
40
41 #include "utils.h"
42
43 using ::testing::AnyOf;
44 using ::testing::Contains;
45 using ::testing::StartsWith;
46
47 namespace android {
48 namespace vintf {
49 namespace testing {
50
51 namespace {
52
53 constexpr int kAndroidApi202404 = 202404;
54
55 } // namespace
56 using android::FqInstance;
57 using android::vintf::toFQNameString;
58
59 // For devices that launched <= Android O-MR1, systems/hals/implementations
60 // were delivered to companies which either don't start up on device boot.
LegacyAndExempt(const FQName & fq_name)61 bool LegacyAndExempt(const FQName &fq_name) {
62 return GetBoardApiLevel() <= 27 && !IsAndroidPlatformInterface(fq_name);
63 }
64
FailureHalMissing(const FQName & fq_name,const std::string & instance)65 void FailureHalMissing(const FQName &fq_name, const std::string &instance) {
66 if (LegacyAndExempt(fq_name)) {
67 cout << "[ WARNING ] " << fq_name.string() << "/" << instance
68 << " not available but is exempted because it is legacy. It is still "
69 "recommended to fix this."
70 << endl;
71 } else {
72 ADD_FAILURE() << fq_name.string() << "/" << instance << " not available.";
73 }
74 }
75
FailureHashMissing(const FQName & fq_name)76 void FailureHashMissing(const FQName &fq_name) {
77 if (LegacyAndExempt(fq_name)) {
78 cout << "[ WARNING ] " << fq_name.string()
79 << " has an empty hash but is exempted because it is legacy. It is "
80 "still recommended to fix this. This is because it was compiled "
81 "without being frozen in a corresponding current.txt file."
82 << endl;
83 } else if (base::GetProperty("ro.build.version.codename", "") != "REL") {
84 cout << "[ WARNING ] " << fq_name.string()
85 << " has an empty hash but is exempted because it is not a release "
86 "build"
87 << endl;
88 } else {
89 ADD_FAILURE()
90 << fq_name.string()
91 << " has an empty hash. This is because it was compiled "
92 "without being frozen in a corresponding current.txt file.";
93 }
94 }
95
ToFqInstance(const string & interface,const string & instance)96 static FqInstance ToFqInstance(const string &interface,
97 const string &instance) {
98 FqInstance fq_interface;
99 FqInstance ret;
100
101 if (!fq_interface.setTo(interface)) {
102 ADD_FAILURE() << interface << " is not a valid FQName";
103 return ret;
104 }
105 if (!ret.setTo(fq_interface.getPackage(), fq_interface.getMajorVersion(),
106 fq_interface.getMinorVersion(), fq_interface.getInterface(),
107 instance)) {
108 ADD_FAILURE() << "Cannot convert to FqInstance: " << interface << "/"
109 << instance;
110 }
111 return ret;
112 }
113
114 // Given android.foo.bar@x.y::IFoo/default, attempt to get
115 // android.foo.bar@x.y::IFoo/default, android.foo.bar@x.(y-1)::IFoo/default,
116 // ... android.foo.bar@x.0::IFoo/default until the passthrough HAL is retrieved.
GetPassthroughServiceExact(const FqInstance & fq_instance,bool expect_interface_chain_valid)117 static sp<IBase> GetPassthroughServiceExact(const FqInstance &fq_instance,
118 bool expect_interface_chain_valid) {
119 for (size_t minor_version = fq_instance.getMinorVersion();; --minor_version) {
120 // String out instance name from fq_instance.
121 FqInstance interface;
122 if (!interface.setTo(fq_instance.getPackage(),
123 fq_instance.getMajorVersion(), minor_version,
124 fq_instance.getInterface())) {
125 ADD_FAILURE() << fq_instance.string()
126 << " doesn't contain a valid FQName";
127 return nullptr;
128 }
129
130 auto hal_service = VtsTrebleVintfTestBase::GetHidlService(
131 interface.string(), fq_instance.getInstance(), Transport::PASSTHROUGH);
132
133 if (hal_service != nullptr) {
134 bool interface_chain_valid = false;
135 hal_service->interfaceChain([&](const auto &chain) {
136 for (const auto &intf : chain) {
137 if (intf == interface.string()) {
138 interface_chain_valid = true;
139 return;
140 }
141 }
142 });
143 if (!interface_chain_valid && expect_interface_chain_valid) {
144 ADD_FAILURE() << "Retrieved " << interface.string() << "/"
145 << fq_instance.getInstance() << " as "
146 << fq_instance.string()
147 << " but interfaceChain() doesn't contain "
148 << fq_instance.string();
149 return nullptr;
150 }
151 cout << "Retrieved " << interface.string() << "/"
152 << fq_instance.getInstance() << " as " << fq_instance.string()
153 << endl;
154 return hal_service;
155 }
156
157 if (minor_version == 0) {
158 return nullptr;
159 }
160 }
161 ADD_FAILURE() << "Should not reach here";
162 return nullptr;
163 }
164
165 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SingleHwbinderHalTest);
166 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SingleHidlTest);
167
168 // Given vendor.foo.bar@x.y::IFoo/default, also look up all declared passthrough
169 // HAL implementations on the device that implements this interface.
GetPassthroughService(const FqInstance & fq_instance)170 sp<IBase> SingleHidlTest::GetPassthroughService(const FqInstance &fq_instance) {
171 sp<IBase> hal_service = GetPassthroughServiceExact(
172 fq_instance, true /* expect_interface_chain_valid */);
173 if (hal_service != nullptr) {
174 return hal_service;
175 }
176
177 // For vendor extensions, hal_service may be null because we don't know
178 // its interfaceChain()[1] to call getService(). However, the base interface
179 // should be declared in the manifest. Attempt to find it.
180 cout
181 << "Can't find passthrough service " << fq_instance.string()
182 << ". It might be a vendor extension. Searching all passthrough services "
183 "on the device for a match."
184 << endl;
185
186 const auto &[_, manifest] = GetParam();
187 auto all_declared_passthrough_instances = GetHidlInstances(manifest);
188 for (const HidlInstance &other_hidl_instance :
189 all_declared_passthrough_instances) {
190 if (other_hidl_instance.transport() != Transport::PASSTHROUGH) {
191 continue;
192 }
193 if (other_hidl_instance.instance_name() != fq_instance.getInstance()) {
194 cout << "Skipping " << other_hidl_instance.fq_name().string() << "/"
195 << other_hidl_instance.instance_name()
196 << " because instance name is not " << fq_instance.getInstance();
197 continue;
198 }
199 auto other_fq_instance = FqInstance::from(
200 other_hidl_instance.fq_name(), other_hidl_instance.instance_name());
201 if (!other_fq_instance) {
202 cout << other_hidl_instance.fq_name().string() << "/"
203 << other_hidl_instance.instance_name()
204 << " is not a valid FqInstance, skipping." << endl;
205 continue;
206 }
207 auto other_service = GetPassthroughServiceExact(
208 *other_fq_instance, false /* expect_interface_chain_valid */);
209 if (other_service == nullptr) {
210 cout << "Cannot retrieve " << other_fq_instance->string() << ", skipping."
211 << endl;
212 continue;
213 }
214 bool match = false;
215 auto other_interface_chain_ret =
216 other_service->interfaceChain([&](const auto &chain) {
217 for (const auto &intf : chain) {
218 auto other_fq_instance_in_chain = FqInstance::from(
219 std::string(intf) + "/" + other_fq_instance->getInstance());
220 if (other_fq_instance_in_chain == fq_instance) {
221 match = true;
222 break;
223 }
224 }
225 });
226 if (!other_interface_chain_ret.isOk()) {
227 cout << "Cannot call interfaceChain on " << other_fq_instance->string()
228 << ", skipping." << endl;
229 continue;
230 }
231 if (match) {
232 cout << "The implementation of " << other_fq_instance->string()
233 << " also implements " << fq_instance.string()
234 << ", using it to check if passthrough is allowed for "
235 << fq_instance.string() << endl;
236 return other_service;
237 }
238 }
239 cout << "Can't find any other passthrough service implementing "
240 << fq_instance.string() << endl;
241 return nullptr;
242 }
243
244 // returns true only if the specified apex is updated
IsApexUpdated(const std::string & apex_name)245 static bool IsApexUpdated(const std::string &apex_name) {
246 using namespace ::android::apex;
247 auto binder =
248 defaultServiceManager()->waitForService(String16("apexservice"));
249 if (binder != nullptr) {
250 auto apex_service = interface_cast<IApexService>(binder);
251 std::vector<ApexInfo> list;
252 auto status = apex_service->getActivePackages(&list);
253 EXPECT_TRUE(status.isOk())
254 << "Failed to getActivePackages():" << status.exceptionMessage();
255 for (const ApexInfo &apex_info : list) {
256 if (apex_info.moduleName == apex_name) {
257 return !apex_info.isFactory;
258 }
259 }
260 }
261 return false;
262 }
263
264 // Tests that no HAL outside of the allowed set is specified as passthrough in
265 // VINTF.
266 // @VsrTest = VSR-3.2-014
TEST_P(SingleHidlTest,HalIsBinderized)267 TEST_P(SingleHidlTest, HalIsBinderized) {
268 const auto &[hidl_instance, manifest] = GetParam();
269 const FQName &fq_name = hidl_instance.fq_name();
270 auto opt_fq_instance =
271 FqInstance::from(fq_name, hidl_instance.instance_name());
272 ASSERT_TRUE(opt_fq_instance);
273 const FqInstance &fq_instance = *opt_fq_instance;
274
275 EXPECT_THAT(hidl_instance.transport(),
276 AnyOf(Transport::HWBINDER, Transport::PASSTHROUGH))
277 << "HIDL HAL has unknown transport specified in VINTF ("
278 << hidl_instance.transport() << ": " << fq_instance.string();
279
280 if (hidl_instance.transport() == Transport::HWBINDER) {
281 return;
282 }
283
284 set<FqInstance> passthrough_allowed;
285 auto hal_service = GetPassthroughService(fq_instance);
286 if (hal_service == nullptr) {
287 cout << "Skip calling interfaceChain on " << fq_instance.string()
288 << " because it can't be retrieved directly." << endl;
289 } else {
290 // For example, given the following interfaceChain when
291 // hal_service is "android.hardware.mapper@2.0::IMapper/default":
292 // ["vendor.foo.mapper@1.0::IMapper",
293 // "android.hardware.mapper@2.1::IMapper",
294 // "android.hardware.mapper@2.0::IMapper",
295 // "android.hidl.base@1.0::IBase"],
296 // Allow the following:
297 // ["vendor.foo.mapper@1.0::IMapper/default",
298 // "android.hardware.mapper@2.1::IMapper/default",
299 // "android.hardware.mapper@2.0::IMapper/default"]
300 hal_service->interfaceChain([&](const auto &chain) {
301 vector<FqInstance> fq_instances;
302 std::transform(
303 chain.begin(), chain.end(), std::back_inserter(fq_instances),
304 [&](const auto &interface) {
305 return ToFqInstance(interface, fq_instance.getInstance());
306 });
307
308 bool allowing = false;
309 for (auto it = fq_instances.rbegin(); it != fq_instances.rend(); ++it) {
310 if (kPassthroughHals.find(it->getPackage()) != kPassthroughHals.end()) {
311 allowing = true;
312 }
313 if (allowing) {
314 cout << it->string() << " is allowed to be passthrough" << endl;
315 passthrough_allowed.insert(*it);
316 }
317 }
318 });
319 }
320
321 EXPECT_THAT(passthrough_allowed, Contains(fq_instance))
322 << "HIDL HAL can't be passthrough under Treble rules (or they "
323 "can't be retrieved): "
324 << fq_instance.string();
325 }
326
327 // Tests that all HALs specified in the VINTF are available through service
328 // manager.
329 // This tests (HAL in manifest) => (HAL is served)
330 // @VsrTest = VSR-3.2-014
TEST_P(SingleHidlTest,HalIsServed)331 TEST_P(SingleHidlTest, HalIsServed) {
332 // Verifies that HAL is available through service manager and is served from a
333 // specific set of partitions.
334
335 const auto &[hidl_instance, manifest] = GetParam();
336
337 Partition expected_partition = PartitionOfType(manifest->type());
338 const FQName &fq_name = hidl_instance.fq_name();
339 const string &instance_name = hidl_instance.instance_name();
340 Transport transport = hidl_instance.transport();
341
342 sp<IBase> hal_service;
343
344 if (transport == Transport::PASSTHROUGH) {
345 using android::hardware::details::canCastInterface;
346
347 // Passthrough services all start with minor version 0.
348 // there are only three of them listed above. They are looked
349 // up based on their binary location. For instance,
350 // V1_0::IFoo::getService() might correspond to looking up
351 // android.hardware.foo@1.0-impl for the symbol
352 // HIDL_FETCH_IFoo. For @1.1::IFoo to continue to work with
353 // 1.0 clients, it must also be present in a library that is
354 // called the 1.0 name. Clients can say:
355 // mFoo1_0 = V1_0::IFoo::getService();
356 // mFoo1_1 = V1_1::IFoo::castFrom(mFoo1_0);
357 // This is the standard pattern for making a service work
358 // for both versions (mFoo1_1 != nullptr => you have 1.1)
359 // and a 1.0 client still works with the 1.1 interface.
360
361 if (!IsAndroidPlatformInterface(fq_name)) {
362 // This isn't the case for extensions of core Google interfaces.
363 return;
364 }
365
366 const FQName lowest_name =
367 fq_name.withVersion(fq_name.getPackageMajorVersion(), 0);
368 hal_service = GetHidlService(lowest_name, instance_name, transport);
369 EXPECT_TRUE(canCastInterface(hal_service.get(), fq_name.string().c_str()))
370 << fq_name.string() << " is not on the device.";
371 } else {
372 hal_service = GetHidlService(fq_name, instance_name, transport);
373 }
374
375 if (hal_service == nullptr) {
376 FailureHalMissing(fq_name, instance_name);
377 return;
378 }
379
380 EXPECT_EQ(transport == Transport::HWBINDER, hal_service->isRemote())
381 << "transport is " << transport << "but HAL service is "
382 << (hal_service->isRemote() ? "" : "not") << " remote.";
383 EXPECT_EQ(transport == Transport::PASSTHROUGH, !hal_service->isRemote())
384 << "transport is " << transport << "but HAL service is "
385 << (hal_service->isRemote() ? "" : "not") << " remote.";
386
387 if (!hal_service->isRemote()) return;
388
389 Partition partition = GetPartition(hal_service);
390 if (partition == Partition::UNKNOWN) return;
391 EXPECT_EQ(expected_partition, partition)
392 << fq_name.string() << "/" << instance_name << " is in partition "
393 << partition << " but is expected to be in " << expected_partition;
394 }
395
396 // Tests that all HALs which are served are specified in the VINTF
397 // This tests (HAL is served) => (HAL in manifest)
398 // @VsrTest = VSR-3.2-014
TEST_P(SingleHwbinderHalTest,ServedHwbinderHalIsInManifest)399 TEST_P(SingleHwbinderHalTest, ServedHwbinderHalIsInManifest) {
400 const auto &[fq_instance_name, manifest] = GetParam();
401
402 if (fq_instance_name.find(IBase::descriptor) == 0) {
403 GTEST_SKIP() << "Ignore IBase: " << fq_instance_name;
404 }
405
406 auto expected_partition = PartitionOfType(manifest->type());
407 std::set<std::string> manifest_hwbinder_hals =
408 GetDeclaredHidlHalsOfTransport(manifest, Transport::HWBINDER);
409
410 auto opt_fq_instance = FqInstance::from(fq_instance_name);
411 ASSERT_TRUE(opt_fq_instance);
412 const FqInstance &fq_instance = *opt_fq_instance;
413
414 auto service = GetHidlService(
415 toFQNameString(fq_instance.getPackage(), fq_instance.getVersion(),
416 fq_instance.getInterface()),
417 fq_instance.getInstance(), Transport::HWBINDER);
418 ASSERT_NE(service, nullptr);
419
420 Partition partition = GetPartition(service);
421 if (partition == Partition::UNKNOWN) {
422 // Caught by SystemVendorTest.ServedHwbinderHalIsInManifest
423 // if that test is run.
424 GTEST_SKIP() << "Unable to determine partition. "
425 "Refer to SystemVendorTest.ServedHwbinderHalIsInManifest "
426 "or SingleHwbinderHalTest.ServedHwbinderHalIsInManifest "
427 "for the other manifest for correct result: "
428 << fq_instance_name;
429 }
430 if (partition != expected_partition) {
431 GTEST_SKIP() << "Skipping because this test only test "
432 << expected_partition << " partition on the "
433 << manifest->type()
434 << " side of Treble boundary. "
435 "Refer to SystemVendorTest.ServedHwbinderHalIsInManifest "
436 "or SingleHwbinderHalTest.ServedHwbinderHalIsInManifest "
437 "for the other manifest for correct result: "
438 << fq_instance_name;
439 }
440 EXPECT_NE(manifest_hwbinder_hals.find(fq_instance_name),
441 manifest_hwbinder_hals.end())
442 << fq_instance_name << " is being served, but it is not in a manifest.";
443 }
444
GetTestCaseSuffix(const::testing::TestParamInfo<ParamType> & info)445 std::string SingleHwbinderHalTest::GetTestCaseSuffix(
446 const ::testing::TestParamInfo<ParamType> &info) {
447 const auto &[fq_instance_name, manifest] = info.param;
448 return SanitizeTestCaseName(fq_instance_name) + "_" +
449 std::to_string(info.index);
450 }
451
452 // Tests that all HALs which are served are specified in the VINTF
453 // This tests (HAL is served) => (HAL in manifest) for passthrough HALs
454 // @VsrTest = VSR-3.2-014
TEST_P(SingleHidlTest,ServedPassthroughHalIsInManifest)455 TEST_P(SingleHidlTest, ServedPassthroughHalIsInManifest) {
456 const auto &[hidl_instance, manifest] = GetParam();
457 const FQName &fq_name = hidl_instance.fq_name();
458 const string &instance_name = hidl_instance.instance_name();
459 Transport transport = hidl_instance.transport();
460 std::set<std::string> manifest_passthrough_hals =
461 GetDeclaredHidlHalsOfTransport(manifest, Transport::PASSTHROUGH);
462
463 if (transport != Transport::PASSTHROUGH) {
464 GTEST_SKIP() << "Not passthrough: " << fq_name.string() << "/"
465 << instance_name;
466 }
467
468 // See HalIsServed. These are always retrieved through the base interface
469 // and if it is not a google defined interface, it must be an extension of
470 // one.
471 if (!IsAndroidPlatformInterface(fq_name)) {
472 GTEST_SKIP() << "Not Android Platform Interface: " << fq_name.string()
473 << "/" << instance_name;
474 }
475
476 const FQName lowest_name =
477 fq_name.withVersion(fq_name.getPackageMajorVersion(), 0);
478 sp<IBase> hal_service = GetHidlService(lowest_name, instance_name, transport);
479 ASSERT_NE(nullptr, hal_service)
480 << "Could not get service " << fq_name.string() << "/" << instance_name;
481
482 Return<void> ret = hal_service->interfaceChain(
483 [&manifest_passthrough_hals, &instance_name](const auto &interfaces) {
484 for (const auto &interface : interfaces) {
485 if (std::string(interface) == IBase::descriptor) continue;
486
487 const std::string instance =
488 std::string(interface) + "/" + instance_name;
489 EXPECT_NE(manifest_passthrough_hals.find(instance),
490 manifest_passthrough_hals.end())
491 << "Instance missing from manifest: " << instance;
492 }
493 });
494 EXPECT_TRUE(ret.isOk());
495 }
496
497 // Tests that HAL interfaces are officially released.
498 // @VsrTest = VSR-3.2-014
TEST_P(SingleHidlTest,InterfaceIsReleased)499 TEST_P(SingleHidlTest, InterfaceIsReleased) {
500 const auto &[hidl_instance, manifest] = GetParam();
501
502 const FQName &fq_name = hidl_instance.fq_name();
503 const string &instance_name = hidl_instance.instance_name();
504 Transport transport = hidl_instance.transport();
505
506 // See HalIsServed. These are always retrieved through the base interface
507 // and if it is not a google defined interface, it must be an extension of
508 // one.
509 if (transport == Transport::PASSTHROUGH &&
510 (!IsAndroidPlatformInterface(fq_name) ||
511 fq_name.getPackageMinorVersion() != 0)) {
512 return;
513 }
514
515 sp<IBase> hal_service = GetHidlService(fq_name, instance_name, transport);
516
517 if (hal_service == nullptr) {
518 FailureHalMissing(fq_name, instance_name);
519 return;
520 }
521
522 vector<string> iface_chain = GetInterfaceChain(hal_service);
523
524 vector<string> hash_chain{};
525 hal_service->getHashChain([&hash_chain](
526 const hidl_vec<HashCharArray> &chain) {
527 for (const HashCharArray &hash : chain) {
528 hash_chain.push_back(android::base::HexString(hash.data(), hash.size()));
529 }
530 });
531
532 ASSERT_EQ(iface_chain.size(), hash_chain.size());
533 for (size_t i = 0; i < iface_chain.size(); ++i) {
534 FQName fq_iface_name;
535 if (!FQName::parse(iface_chain[i], &fq_iface_name)) {
536 ADD_FAILURE() << "Could not parse iface name " << iface_chain[i]
537 << " from interface chain of " << fq_name.string();
538 return;
539 }
540 string hash = hash_chain[i];
541 if (hash == android::base::HexString(Hash::kEmptyHash.data(),
542 Hash::kEmptyHash.size())) {
543 FailureHashMissing(fq_iface_name);
544 } else if (IsAndroidPlatformInterface(fq_iface_name)) {
545 set<string> released_hashes = ReleasedHashes(fq_iface_name);
546 EXPECT_NE(released_hashes.find(hash), released_hashes.end())
547 << "Hash not found. This interface was not released." << endl
548 << "Interface name: " << fq_iface_name.string() << endl
549 << "Hash: " << hash << endl;
550 }
551 }
552 }
553
metadataForInterface(const std::string & name)554 static std::optional<AidlInterfaceMetadata> metadataForInterface(
555 const std::string &name) {
556 for (const auto &module : AidlInterfaceMetadata::all()) {
557 if (std::find(module.types.begin(), module.types.end(), name) !=
558 module.types.end()) {
559 return module;
560 }
561 }
562 return std::nullopt;
563 }
564
565 // TODO(b/150155678): using standard code to do this
getInterfaceHash(const sp<IBinder> & binder)566 static std::string getInterfaceHash(const sp<IBinder> &binder) {
567 Parcel data;
568 Parcel reply;
569 data.writeInterfaceToken(binder->getInterfaceDescriptor());
570 status_t err =
571 binder->transact(IBinder::LAST_CALL_TRANSACTION - 1, data, &reply, 0);
572 if (err == UNKNOWN_TRANSACTION) {
573 return "";
574 }
575 EXPECT_EQ(OK, err);
576 binder::Status status;
577 EXPECT_EQ(OK, status.readFromParcel(reply));
578 EXPECT_TRUE(status.isOk()) << status.toString8().c_str();
579 std::string str;
580 EXPECT_EQ(OK, reply.readUtf8FromUtf16(&str));
581 return str;
582 }
583
584 // TODO(b/150155678): using standard code to do this
getInterfaceVersion(const sp<IBinder> & binder)585 static int32_t getInterfaceVersion(const sp<IBinder> &binder) {
586 Parcel data;
587 Parcel reply;
588 const auto &descriptor = binder->getInterfaceDescriptor();
589 data.writeInterfaceToken(descriptor);
590 status_t err = binder->transact(IBinder::LAST_CALL_TRANSACTION, data, &reply);
591 // On upgrading devices, the HAL may not implement this transaction. libvintf
592 // treats missing <version> as version 1, so we do the same here.
593 if (err == UNKNOWN_TRANSACTION) {
594 std::cout << "INFO: " << descriptor
595 << " does not have an interface version, using default value "
596 << android::vintf::kDefaultAidlMinorVersion << std::endl;
597 return android::vintf::kDefaultAidlMinorVersion;
598 }
599 EXPECT_EQ(OK, err);
600 binder::Status status;
601 EXPECT_EQ(OK, status.readFromParcel(reply));
602 EXPECT_TRUE(status.isOk()) << status.toString8().c_str();
603 auto version = reply.readInt32();
604 return version;
605 }
606
CheckAidlVersionMatchesDeclared(sp<IBinder> binder,const std::string & name,uint64_t declared_version,bool allow_upgrade)607 static bool CheckAidlVersionMatchesDeclared(sp<IBinder> binder,
608 const std::string &name,
609 uint64_t declared_version,
610 bool allow_upgrade) {
611 const int32_t actual_version = getInterfaceVersion(binder);
612 if (actual_version < 1) {
613 ADD_FAILURE() << "For " << name << ", version should be >= 1 but it is "
614 << actual_version << ".";
615 return false;
616 }
617
618 if (declared_version == actual_version) {
619 std::cout << "For " << name << ", version " << actual_version
620 << " matches declared value." << std::endl;
621 return true;
622 }
623 if (allow_upgrade && actual_version > declared_version) {
624 std::cout << "For " << name << ", upgraded version " << actual_version
625 << " is okay. (declared value = " << declared_version << ".)"
626 << std::endl;
627 return true;
628 }
629
630 // Android R VINTF did not support AIDL version in the manifest.
631 Level shipping_fcm_version = VintfObject::GetDeviceHalManifest()->level();
632 if (shipping_fcm_version != Level::UNSPECIFIED &&
633 shipping_fcm_version <= Level::R) {
634 std::cout << "For " << name << ", manifest declares version "
635 << declared_version << ", but the actual version is "
636 << actual_version << ". Exempted for shipping FCM version "
637 << shipping_fcm_version << ". (b/178458001, b/199190514)"
638 << std::endl;
639 return true;
640 }
641
642 ADD_FAILURE()
643 << "For " << name << ", manifest (targeting FCM:" << shipping_fcm_version
644 << ") declares version " << declared_version
645 << ", but the actual version is " << actual_version << std::endl
646 << "Either the VINTF manifest <hal> entry needs to be updated with a "
647 "version tag for the actual version, or the implementation should be "
648 "changed to use the declared version";
649 return false;
650 }
651
652 // This checks to make sure all vintf extensions are frozen.
653 // We do not check for known hashes because the Android framework does not
654 // support these extensions without out-of-tree changes from partners.
655 // @param binder - the parent binder to check all of its extensions
checkVintfExtensionInterfaces(const sp<IBinder> & binder,bool is_release)656 void checkVintfExtensionInterfaces(const sp<IBinder> &binder, bool is_release) {
657 // if you end up here because of a stack overflow when running this
658 // test... you have a cycle in your interface extensions. Break that
659 // cycle to continue.
660 if (!binder) return;
661 sp<IBinder> extension;
662 status_t status = binder->getExtension(&extension);
663 if (status != OK || !extension) return;
664
665 if (android::internal::Stability::requiresVintfDeclaration(extension)) {
666 const std::string hash = getInterfaceHash(extension);
667 if (hash.empty() || hash == "notfrozen") {
668 if (is_release) {
669 ADD_FAILURE() << "Interface extension "
670 << extension->getInterfaceDescriptor()
671 << " is unfrozen! It is attached to "
672 << " a binder for frozen VINTF interface ("
673 << binder->getInterfaceDescriptor()
674 << " so it must also be frozen.";
675 } else {
676 std::cout << "INFO: missing hash for vintf interface extension "
677 << binder->getInterfaceDescriptor()
678 << " which is attached to "
679 << binder->getInterfaceDescriptor()
680 << ". This will become an error upon release." << std::endl;
681 }
682 }
683 }
684 checkVintfExtensionInterfaces(extension, is_release);
685 }
686
687 // This checks if @updatable-via-apex in VINTF is correct.
checkVintfUpdatableViaApex(const sp<IBinder> & binder,const std::string & apex_name)688 void checkVintfUpdatableViaApex(const sp<IBinder> &binder,
689 const std::string &apex_name) {
690 pid_t pid;
691 ASSERT_EQ(OK, binder->getDebugPid(&pid));
692
693 std::string exe;
694 ASSERT_TRUE(base::Readlink("/proc/" + std::to_string(pid) + "/exe", &exe));
695
696 // HAL service should start from the apex
697 ASSERT_THAT(exe, StartsWith("/apex/" + apex_name + "/"));
698 }
699
700 // An AIDL HAL with VINTF stability can only be registered if it is in the
701 // manifest. However, we still must manually check that every declared HAL is
702 // actually present on the device.
703 // @VsrTest = VSR-3.2-014
TEST_P(SingleAidlTest,HalIsServed)704 TEST_P(SingleAidlTest, HalIsServed) {
705 const auto &[aidl_instance, manifest] = GetParam();
706 const string &package = aidl_instance.package();
707 uint64_t version = aidl_instance.version();
708 const string &interface = aidl_instance.interface();
709 const string &instance = aidl_instance.instance();
710 const optional<string> &updatable_via_apex =
711 aidl_instance.updatable_via_apex();
712
713 const std::string type = package + "." + interface;
714 const std::string name = type + "/" + instance;
715
716 sp<IBinder> binder = GetAidlService(name);
717
718 ASSERT_NE(binder, nullptr) << "Failed to get " << name;
719
720 // allow upgrade if updatable HAL's declared APEX is actually updated.
721 const bool allow_upgrade = updatable_via_apex.has_value() &&
722 IsApexUpdated(updatable_via_apex.value());
723 const bool reliable_version =
724 CheckAidlVersionMatchesDeclared(binder, name, version, allow_upgrade);
725
726 const std::string hash = getInterfaceHash(binder);
727 const std::optional<AidlInterfaceMetadata> metadata =
728 metadataForInterface(type);
729
730 const bool is_aosp = base::StartsWith(package, "android.");
731 ASSERT_TRUE(!is_aosp || metadata)
732 << "AOSP interface must have metadata: " << package;
733
734 if (GetBoardApiLevel() >= kAndroidApi202404 &&
735 !android::internal::Stability::requiresVintfDeclaration(binder)) {
736 ADD_FAILURE() << "Interface " << name
737 << " is declared in the VINTF manifest "
738 << "but it does not have \"vintf\" stability. "
739 << "Add 'stability: \"vintf\" to the aidl_interface module, "
740 << "or remove it from the VINTF manifest.";
741 }
742
743 const bool is_release =
744 base::GetProperty("ro.build.version.codename", "") == "REL";
745
746 const bool is_existing =
747 metadata ? std::find(metadata->versions.begin(), metadata->versions.end(),
748 version) != metadata->versions.end()
749 : false;
750
751 const std::vector<std::string> hashes =
752 metadata ? metadata->hashes : std::vector<std::string>();
753 const bool found_hash =
754 std::find(hashes.begin(), hashes.end(), hash) != hashes.end();
755
756 if (is_aosp) {
757 if (!found_hash) {
758 if (is_release || (reliable_version && is_existing)) {
759 ADD_FAILURE() << "Interface " << name << " has an unrecognized hash: '"
760 << hash << "'. The following hashes are known:\n"
761 << base::Join(hashes, '\n')
762 << "\nHAL interfaces must be released and unchanged.";
763 } else {
764 std::cout << "INFO: using unfrozen hash '" << hash << "' for " << type
765 << ". This will become an error upon release." << std::endl;
766 }
767 }
768 } else {
769 // is partner-owned
770 //
771 // we only require that these are frozen, but we cannot check them for
772 // accuracy
773 if (hash.empty() || hash == "notfrozen") {
774 if (is_release) {
775 ADD_FAILURE() << "Interface " << name
776 << " is used but not frozen (cannot find hash for it).";
777 } else {
778 std::cout << "INFO: missing hash for " << type
779 << ". This will become an error upon release." << std::endl;
780 }
781 }
782 }
783 if (GetBoardApiLevel() >= kAndroidApi202404) {
784 checkVintfExtensionInterfaces(binder, is_release);
785 }
786
787 if (updatable_via_apex.has_value()) {
788 checkVintfUpdatableViaApex(binder, updatable_via_apex.value());
789 }
790 }
791
792 // We don't want to add more same process HALs in Android. We have some 3rd
793 // party ones such as openGL and Vulkan. In the future, we should verify those
794 // here as well. However we want to strictly limit other HALs because a
795 // same-process HAL confuses the client and server SELinux permissions. In
796 // Android, we prefer upstream Linux support, then secondary to that, we prefer
797 // having hardware use in a process isolated from the Android framework.
798 struct NativePackage {
799 std::string name;
800 int32_t majorVersion;
801 };
802
operator <<(ostream & os,const NativePackage & pkg)803 ostream &operator<<(ostream &os, const NativePackage &pkg) {
804 os << pkg.name << "-v" << pkg.majorVersion;
805 return os;
806 }
807
808 static const std::array<NativePackage, 1> kKnownNativePackages = {
809 NativePackage{"mapper", 5},
810 };
811 static const std::vector<std::string> kNativeHalPaths = {
812 "/vendor/lib/hw/",
813 "/vendor/lib64/hw/",
814 };
815
findKnownNativePackage(std::string_view package)816 static std::optional<NativePackage> findKnownNativePackage(
817 std::string_view package) {
818 for (const auto &it : kKnownNativePackages) {
819 if (it.name == package) {
820 return it;
821 }
822 }
823 return std::nullopt;
824 }
825
826 // using device manifest test for access to GetNativeInstances
TEST(NativeDeclaredTest,NativeDeclaredIfExists)827 TEST(NativeDeclaredTest, NativeDeclaredIfExists) {
828 std::set<std::string> names; // e.g. 'mapper.instance_name'
829
830 // read all the native HALs installed on disk
831 bool found_a_dir = false;
832 for (const std::string &dir : kNativeHalPaths) {
833 DIR *dp = opendir(dir.c_str());
834 if (dp == nullptr) continue;
835 found_a_dir = true;
836
837 dirent *entry;
838 while ((entry = readdir(dp))) {
839 std::string name = entry->d_name;
840 size_t dot_one = name.find('.');
841 if (dot_one == std::string::npos) continue;
842 size_t dot_end = name.rfind('.');
843 if (dot_end == std::string::npos || dot_one == dot_end) continue;
844 ASSERT_LT(dot_one, dot_end);
845 if (name.substr(dot_end) != ".so") continue;
846
847 std::string package = name.substr(0, dot_one);
848 if (!findKnownNativePackage(package).has_value()) continue;
849
850 names.insert(name.substr(0, dot_end));
851 }
852 closedir(dp);
853 }
854 ASSERT_TRUE(found_a_dir);
855
856 // ignore HALs which are declared, because they'll be checked in
857 // SingleNativeTest ExistsIfDeclared
858 for (const auto &hal : VtsTrebleVintfTestBase::GetNativeInstances(
859 VintfObject::GetDeviceHalManifest())) {
860 std::string this_name = hal.package() + "." + hal.instance();
861 names.erase(this_name);
862 }
863
864 for (const std::string &name : names) {
865 ADD_FAILURE() << name
866 << " is installed on the device, but it's not declared in "
867 "the VINTF manifest";
868 }
869 }
870
871 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SingleNativeTest);
TEST_P(SingleNativeTest,ExistsIfDeclared)872 TEST_P(SingleNativeTest, ExistsIfDeclared) {
873 const auto &[native_instance, manifest] = GetParam();
874
875 // Currently only support rev'ing the major version
876 EXPECT_EQ(native_instance.minor_version(), 0);
877
878 auto knownPackageInfo = findKnownNativePackage(native_instance.package());
879 ASSERT_TRUE(knownPackageInfo.has_value())
880 << "Unsupported package: " << native_instance.package()
881 << " must be one of: " << base::Join(kKnownNativePackages, ", ");
882 EXPECT_EQ(native_instance.major_version(), knownPackageInfo->majorVersion);
883 EXPECT_TRUE(native_instance.interface() == "I" ||
884 native_instance.interface() == "")
885 << "Interface must be 'I' or '' for native HAL: "
886 << native_instance.interface();
887
888 void *so = openDeclaredPassthroughHal(
889 String16(native_instance.package().c_str()),
890 String16(native_instance.instance().c_str()), RTLD_LAZY | RTLD_LOCAL);
891 ASSERT_NE(so, nullptr) << "Failed to load " << native_instance << dlerror();
892
893 std::string upperPackage = native_instance.package();
894 std::transform(upperPackage.begin(), upperPackage.end(), upperPackage.begin(),
895 ::toupper);
896 std::string versionSymbol = "ANDROID_HAL_" + upperPackage + "_VERSION";
897 int32_t *halVersion = (int32_t *)dlsym(so, versionSymbol.c_str());
898 ASSERT_NE(halVersion, nullptr) << "Failed to find symbol " << versionSymbol;
899 EXPECT_EQ(native_instance.major_version(), *halVersion);
900
901 dlclose(so);
902 }
903
904 } // namespace testing
905 } // namespace vintf
906 } // namespace android
907