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 <map>
21 #include <set>
22 #include <string>
23 #include <vector>
24 
25 #include <android-base/properties.h>
26 
27 using android::base::GetUintProperty;
28 
29 namespace android {
30 namespace vintf {
31 namespace testing {
32 
33 // Path to directory on target containing test data.
34 const string kDataDir = "/data/local/tmp/";
35 
36 // Name of file containing HAL hashes.
37 const string kHashFileName = "current.txt";
38 
39 // Map from package name to package root.
40 const map<string, string> kPackageRoot = {
41     {"android.frameworks", "frameworks/hardware/interfaces/"},
42     {"android.hardware", "hardware/interfaces/"},
43     {"android.hidl", "system/libhidl/transport/"},
44     {"android.system", "system/hardware/interfaces/"},
45 };
46 
47 // HALs that are allowed to be passthrough under Treble rules.
48 const set<string> kPassthroughHals = {
49     "android.hardware.graphics.mapper", "android.hardware.renderscript",
50     "android.hidl.memory",
51 };
52 
53 // kFcm2ApiLevelMap is associated with API level. There can be multiple
54 // Framework Compatibility Matrix Version (FCM Version) per API level, or
55 // multiple API levels per FCM version.
56 // kFcm2ApiLevelMap is defined apart from android::vintf::Level. Level is an
57 // integer designed to be irrelevant with API level; the O / O_MR1 values are
58 // historic values for convenience, and should be removed (b/70628538). Hence
59 // these values are not used here.
60 // For example:
61 //    ...
62 //    // Assume devices launch with Android X must implement FCM version >= 9
63 //    X = 9,
64 //    // Assume devices launch with Android Y and Android Z must implement
65 //    // FCM version >= 11
66 //    Y = 11,
67 //    Z = 11
68 const map<size_t /* Shipping API Level */, Level /* FCM Version */>
69     kFcm2ApiLevelMap{{
70         // N. The test runs on devices that launch with N and
71         // become a Treble device when upgrading to O.
72         {25, static_cast<Level>(1)},
73         // O
74         {26, static_cast<Level>(1)},
75         // O MR-1
76         {27, static_cast<Level>(2)},
77         // P
78         {28, static_cast<Level>(3)},
79         // Q
80         {29, static_cast<Level>(4)},
81         // R
82         {30, static_cast<Level>(5)},
83     }};
84 
85 // Returns ro.product.first_api_level if it is defined and not 0. Returns
86 // ro.build.version.sdk otherwise.
GetShippingApiLevel()87 uint64_t GetShippingApiLevel() {
88   uint64_t api_level =
89       GetUintProperty<uint64_t>("ro.product.first_api_level", 0);
90   if (api_level != 0) {
91     return api_level;
92   }
93   return GetUintProperty<uint64_t>("ro.build.version.sdk", 0);
94 }
95 
96 // For a given interface returns package root if known. Returns empty string
97 // otherwise.
PackageRoot(const FQName & fq_iface_name)98 const string PackageRoot(const FQName &fq_iface_name) {
99   for (const auto &package_root : kPackageRoot) {
100     if (fq_iface_name.inPackage(package_root.first)) {
101       return package_root.second;
102     }
103   }
104   return "";
105 }
106 
107 // Returns true iff HAL interface is Android platform.
IsAndroidPlatformInterface(const FQName & fq_iface_name)108 bool IsAndroidPlatformInterface(const FQName &fq_iface_name) {
109   // Package roots are only known for Android platform packages.
110   return !PackageRoot(fq_iface_name).empty();
111 }
112 
113 // Returns true iff the device has the specified feature.
DeviceSupportsFeature(const char * feature)114 bool DeviceSupportsFeature(const char *feature) {
115   bool device_supports_feature = false;
116   FILE *p = popen("pm list features", "re");
117   if (p) {
118     char *line = NULL;
119     size_t len = 0;
120     while (getline(&line, &len, p) > 0) {
121       if (strstr(line, feature)) {
122         device_supports_feature = true;
123         break;
124       }
125     }
126     pclose(p);
127   }
128   return device_supports_feature;
129 }
130 
131 // Returns the set of released hashes for a given HAL interface.
ReleasedHashes(const FQName & fq_iface_name)132 set<string> ReleasedHashes(const FQName &fq_iface_name) {
133   set<string> released_hashes{};
134   string err = "";
135 
136   string file_path = kDataDir + PackageRoot(fq_iface_name) + kHashFileName;
137   auto hashes = Hash::lookupHash(file_path, fq_iface_name.string(), &err);
138   released_hashes.insert(hashes.begin(), hashes.end());
139   return released_hashes;
140 }
141 
142 // Returns the partition that a HAL is associated with.
PartitionOfProcess(int32_t pid)143 Partition PartitionOfProcess(int32_t pid) {
144   auto partition = android::procpartition::getPartition(pid);
145 
146   // TODO(b/70033981): remove once ODM and Vendor manifests are distinguished
147   if (partition == Partition::ODM) {
148     partition = Partition::VENDOR;
149   }
150 
151   return partition;
152 }
153 
PartitionOfType(SchemaType type)154 Partition PartitionOfType(SchemaType type) {
155   switch (type) {
156     case SchemaType::DEVICE:
157       return Partition::VENDOR;
158     case SchemaType::FRAMEWORK:
159       return Partition::SYSTEM;
160   }
161   return Partition::UNKNOWN;
162 }
163 
164 }  // namespace testing
165 }  // namespace vintf
166 }  // namespace android
167 
168 namespace std {
PrintTo(const android::vintf::testing::HalManifestPtr & v,ostream * os)169 void PrintTo(const android::vintf::testing::HalManifestPtr &v, ostream *os) {
170   if (v == nullptr) {
171     *os << "nullptr";
172     return;
173   }
174   *os << to_string(v->type()) << " manifest";
175 }
176 }  // namespace std
177