1 
2 /*
3  * Copyright (C) 2018 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include "utils.h"
19 
20 #include <android-base/logging.h>
21 #include <android-base/properties.h>
22 
23 #include <map>
24 #include <set>
25 #include <string>
26 #include <vector>
27 
28 using android::base::GetUintProperty;
29 
30 namespace android {
31 namespace vintf {
32 namespace testing {
33 
34 // Path to directory on target containing test data.
35 const string kDataDir = "/data/local/tmp/";
36 
37 // Name of file containing HAL hashes.
38 const string kHashFileName = "current.txt";
39 
40 // Map from package name to package root.
41 const map<string, string> kPackageRoot = {
42     {"android.frameworks", "frameworks/hardware/interfaces/"},
43     {"android.hardware", "hardware/interfaces/"},
44     {"android.hidl", "system/libhidl/transport/"},
45     {"android.system", "system/hardware/interfaces/"},
46 };
47 
48 // HALs that are allowed to be passthrough under Treble rules.
49 const set<string> kPassthroughHals = {
50     "android.hardware.graphics.mapper", "android.hardware.renderscript",
51     "android.hidl.memory",
52 };
53 
SanitizeTestCaseName(std::string original)54 std::string SanitizeTestCaseName(std::string original) {
55   for (char &c : original) {
56     if (!isalnum(c)) {
57       c = '_';
58     }
59   }
60   return original;
61 }
62 
HidlInstance(const ManifestInstance & other)63 HidlInstance::HidlInstance(const ManifestInstance &other)
64     : ManifestInstance(other) {
65   CHECK_EQ(format(), HalFormat::HIDL);
66 }
67 
operator <<(ostream & os,const HidlInstance & val)68 ostream &operator<<(ostream &os, const HidlInstance& val) {
69   return os << val.transport() << " HAL " << val.fq_name().string() << "/"
70             << val.instance_name();
71 }
72 
test_case_name() const73 string HidlInstance::test_case_name() const {
74   return SanitizeTestCaseName(fq_name().string() + "/" + instance_name());
75 }
76 
AidlInstance(const ManifestInstance & other)77 AidlInstance::AidlInstance(const ManifestInstance &other)
78     : ManifestInstance(other) {
79   CHECK_EQ(format(), HalFormat::AIDL);
80 }
81 
test_case_name() const82 string AidlInstance::test_case_name() const {
83   return SanitizeTestCaseName(
84       toAidlFqnameString(package(), interface(), instance()) + "_V" +
85       to_string(version()));
86 }
87 
operator <<(ostream & os,const AidlInstance & val)88 ostream &operator<<(ostream &os, const AidlInstance& val) {
89   os << toAidlFqnameString(val.package(), val.interface(), val.instance())
90      << ", Version " << val.version();
91   if (val.updatable_via_apex()) {
92     os << ", updatable_via_apex = " << *val.updatable_via_apex();
93   }
94   return os;
95 }
96 
NativeInstance(const ManifestInstance & other)97 NativeInstance::NativeInstance(const ManifestInstance &other)
98     : ManifestInstance(other) {
99   CHECK_EQ(format(), HalFormat::NATIVE);
100 }
101 
test_case_name() const102 string NativeInstance::test_case_name() const {
103   return SanitizeTestCaseName(
104       toAidlFqnameString(package(), interface(), instance()) + "_V" +
105       to_string(version()));
106 }
107 
operator <<(ostream & os,const NativeInstance & val)108 ostream &operator<<(ostream &os, const NativeInstance &val) {
109   os << "Native HAL { package: " << val.package()
110      << " version: " << val.major_version() << "." << val.minor_version()
111      << " interface: " << val.interface() << " instance: " << val.instance()
112      << " }";
113   return os;
114 }
115 
GetBoardApiLevel()116 uint64_t GetBoardApiLevel() {
117   return GetUintProperty<uint64_t>("ro.vendor.api_level", 0);
118 }
119 
120 // For a given interface returns package root if known. Returns empty string
121 // otherwise.
PackageRoot(const FQName & fq_iface_name)122 const string PackageRoot(const FQName &fq_iface_name) {
123   for (const auto &package_root : kPackageRoot) {
124     if (fq_iface_name.inPackage(package_root.first)) {
125       return package_root.second;
126     }
127   }
128   return "";
129 }
130 
131 // Returns true iff HAL interface is Android platform.
IsAndroidPlatformInterface(const FQName & fq_iface_name)132 bool IsAndroidPlatformInterface(const FQName &fq_iface_name) {
133   // Package roots are only known for Android platform packages.
134   return !PackageRoot(fq_iface_name).empty();
135 }
136 
137 // Returns the set of released hashes for a given HAL interface.
ReleasedHashes(const FQName & fq_iface_name)138 set<string> ReleasedHashes(const FQName &fq_iface_name) {
139   set<string> released_hashes{};
140   string err = "";
141 
142   string file_path = kDataDir + PackageRoot(fq_iface_name) + kHashFileName;
143   auto hashes = Hash::lookupHash(file_path, fq_iface_name.string(), &err);
144   released_hashes.insert(hashes.begin(), hashes.end());
145   return released_hashes;
146 }
147 
148 // Returns the partition that a HAL is associated with.
PartitionOfProcess(int32_t pid)149 Partition PartitionOfProcess(int32_t pid) {
150   auto partition = android::procpartition::getPartition(pid);
151 
152   // TODO(b/70033981): remove once ODM and Vendor manifests are distinguished
153   if (partition == Partition::ODM) {
154     partition = Partition::VENDOR;
155   }
156 
157   return partition;
158 }
159 
PartitionOfType(SchemaType type)160 Partition PartitionOfType(SchemaType type) {
161   switch (type) {
162     case SchemaType::DEVICE:
163       return Partition::VENDOR;
164     case SchemaType::FRAMEWORK:
165       return Partition::SYSTEM;
166   }
167   return Partition::UNKNOWN;
168 }
169 
170 }  // namespace testing
171 }  // namespace vintf
172 }  // namespace android
173 
174 namespace std {
PrintTo(const android::vintf::testing::HalManifestPtr & v,ostream * os)175 void PrintTo(const android::vintf::testing::HalManifestPtr &v, ostream *os) {
176   if (v == nullptr) {
177     *os << "nullptr";
178     return;
179   }
180   *os << to_string(v->type()) << " manifest";
181 }
182 }  // namespace std
183