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