xref: /aosp_15_r20/system/libvintf/VintfObject.cpp (revision 70a7ec852fcefd15a4fb57f8f183a8b1c3aacb08)
1*70a7ec85SAndroid Build Coastguard Worker /*
2*70a7ec85SAndroid Build Coastguard Worker  * Copyright (C) 2017 The Android Open Source Project
3*70a7ec85SAndroid Build Coastguard Worker  *
4*70a7ec85SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*70a7ec85SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*70a7ec85SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*70a7ec85SAndroid Build Coastguard Worker  *
8*70a7ec85SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*70a7ec85SAndroid Build Coastguard Worker  *
10*70a7ec85SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*70a7ec85SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*70a7ec85SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*70a7ec85SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*70a7ec85SAndroid Build Coastguard Worker  * limitations under the License.
15*70a7ec85SAndroid Build Coastguard Worker  */
16*70a7ec85SAndroid Build Coastguard Worker #include "VintfObject.h"
17*70a7ec85SAndroid Build Coastguard Worker 
18*70a7ec85SAndroid Build Coastguard Worker #include <dirent.h>
19*70a7ec85SAndroid Build Coastguard Worker 
20*70a7ec85SAndroid Build Coastguard Worker #include <algorithm>
21*70a7ec85SAndroid Build Coastguard Worker #include <functional>
22*70a7ec85SAndroid Build Coastguard Worker #include <memory>
23*70a7ec85SAndroid Build Coastguard Worker #include <mutex>
24*70a7ec85SAndroid Build Coastguard Worker #include <vector>
25*70a7ec85SAndroid Build Coastguard Worker 
26*70a7ec85SAndroid Build Coastguard Worker #include <aidl/metadata.h>
27*70a7ec85SAndroid Build Coastguard Worker #include <android-base/file.h>
28*70a7ec85SAndroid Build Coastguard Worker #include <android-base/logging.h>
29*70a7ec85SAndroid Build Coastguard Worker #include <android-base/result.h>
30*70a7ec85SAndroid Build Coastguard Worker #include <android-base/strings.h>
31*70a7ec85SAndroid Build Coastguard Worker #include <hidl/metadata.h>
32*70a7ec85SAndroid Build Coastguard Worker 
33*70a7ec85SAndroid Build Coastguard Worker #include "Apex.h"
34*70a7ec85SAndroid Build Coastguard Worker #include "CompatibilityMatrix.h"
35*70a7ec85SAndroid Build Coastguard Worker #include "VintfObjectUtils.h"
36*70a7ec85SAndroid Build Coastguard Worker #include "constants-private.h"
37*70a7ec85SAndroid Build Coastguard Worker #include "include/vintf/FqInstance.h"
38*70a7ec85SAndroid Build Coastguard Worker #include "parse_string.h"
39*70a7ec85SAndroid Build Coastguard Worker #include "parse_xml.h"
40*70a7ec85SAndroid Build Coastguard Worker #include "utils.h"
41*70a7ec85SAndroid Build Coastguard Worker 
42*70a7ec85SAndroid Build Coastguard Worker using std::placeholders::_1;
43*70a7ec85SAndroid Build Coastguard Worker using std::placeholders::_2;
44*70a7ec85SAndroid Build Coastguard Worker using std::string_literals::operator""s;
45*70a7ec85SAndroid Build Coastguard Worker 
46*70a7ec85SAndroid Build Coastguard Worker namespace android {
47*70a7ec85SAndroid Build Coastguard Worker namespace vintf {
48*70a7ec85SAndroid Build Coastguard Worker 
49*70a7ec85SAndroid Build Coastguard Worker using namespace details;
50*70a7ec85SAndroid Build Coastguard Worker 
51*70a7ec85SAndroid Build Coastguard Worker #ifdef LIBVINTF_TARGET
52*70a7ec85SAndroid Build Coastguard Worker static constexpr bool kIsTarget = true;
53*70a7ec85SAndroid Build Coastguard Worker #else
54*70a7ec85SAndroid Build Coastguard Worker static constexpr bool kIsTarget = false;
55*70a7ec85SAndroid Build Coastguard Worker #endif
56*70a7ec85SAndroid Build Coastguard Worker 
createDefaultFileSystem()57*70a7ec85SAndroid Build Coastguard Worker static std::unique_ptr<FileSystem> createDefaultFileSystem() {
58*70a7ec85SAndroid Build Coastguard Worker     std::unique_ptr<FileSystem> fileSystem;
59*70a7ec85SAndroid Build Coastguard Worker     if (kIsTarget) {
60*70a7ec85SAndroid Build Coastguard Worker         fileSystem = std::make_unique<details::FileSystemImpl>();
61*70a7ec85SAndroid Build Coastguard Worker     } else {
62*70a7ec85SAndroid Build Coastguard Worker         fileSystem = std::make_unique<details::FileSystemNoOp>();
63*70a7ec85SAndroid Build Coastguard Worker     }
64*70a7ec85SAndroid Build Coastguard Worker     return fileSystem;
65*70a7ec85SAndroid Build Coastguard Worker }
66*70a7ec85SAndroid Build Coastguard Worker 
createDefaultPropertyFetcher()67*70a7ec85SAndroid Build Coastguard Worker static std::unique_ptr<PropertyFetcher> createDefaultPropertyFetcher() {
68*70a7ec85SAndroid Build Coastguard Worker     std::unique_ptr<PropertyFetcher> propertyFetcher;
69*70a7ec85SAndroid Build Coastguard Worker     if (kIsTarget) {
70*70a7ec85SAndroid Build Coastguard Worker         propertyFetcher = std::make_unique<details::PropertyFetcherImpl>();
71*70a7ec85SAndroid Build Coastguard Worker     } else {
72*70a7ec85SAndroid Build Coastguard Worker         propertyFetcher = std::make_unique<details::PropertyFetcherNoOp>();
73*70a7ec85SAndroid Build Coastguard Worker     }
74*70a7ec85SAndroid Build Coastguard Worker     return propertyFetcher;
75*70a7ec85SAndroid Build Coastguard Worker }
76*70a7ec85SAndroid Build Coastguard Worker 
77*70a7ec85SAndroid Build Coastguard Worker // Check whether the current executable is allowed to use libvintf.
78*70a7ec85SAndroid Build Coastguard Worker // Allowed binaries:
79*70a7ec85SAndroid Build Coastguard Worker // - host binaries
80*70a7ec85SAndroid Build Coastguard Worker // - tests
81*70a7ec85SAndroid Build Coastguard Worker // - {hw,}servicemanager
isAllowedToUseLibvintf()82*70a7ec85SAndroid Build Coastguard Worker static bool isAllowedToUseLibvintf() {
83*70a7ec85SAndroid Build Coastguard Worker     if constexpr (!kIsTarget) {
84*70a7ec85SAndroid Build Coastguard Worker         return true;
85*70a7ec85SAndroid Build Coastguard Worker     }
86*70a7ec85SAndroid Build Coastguard Worker 
87*70a7ec85SAndroid Build Coastguard Worker     auto execPath = android::base::GetExecutablePath();
88*70a7ec85SAndroid Build Coastguard Worker     if (android::base::StartsWith(execPath, "/data/")) {
89*70a7ec85SAndroid Build Coastguard Worker         return true;
90*70a7ec85SAndroid Build Coastguard Worker     }
91*70a7ec85SAndroid Build Coastguard Worker 
92*70a7ec85SAndroid Build Coastguard Worker     std::vector<std::string> allowedBinaries{
93*70a7ec85SAndroid Build Coastguard Worker         "/system/bin/servicemanager",
94*70a7ec85SAndroid Build Coastguard Worker         "/system/bin/hwservicemanager",
95*70a7ec85SAndroid Build Coastguard Worker         "/system_ext/bin/hwservicemanager",
96*70a7ec85SAndroid Build Coastguard Worker         // Java: boot time VINTF check
97*70a7ec85SAndroid Build Coastguard Worker         "/system/bin/app_process32",
98*70a7ec85SAndroid Build Coastguard Worker         "/system/bin/app_process64",
99*70a7ec85SAndroid Build Coastguard Worker         // These aren't daemons so the memory impact is less concerning.
100*70a7ec85SAndroid Build Coastguard Worker         "/system/bin/lshal",
101*70a7ec85SAndroid Build Coastguard Worker         "/system/bin/vintf",
102*70a7ec85SAndroid Build Coastguard Worker     };
103*70a7ec85SAndroid Build Coastguard Worker 
104*70a7ec85SAndroid Build Coastguard Worker     return std::find(allowedBinaries.begin(), allowedBinaries.end(), execPath) !=
105*70a7ec85SAndroid Build Coastguard Worker            allowedBinaries.end();
106*70a7ec85SAndroid Build Coastguard Worker }
107*70a7ec85SAndroid Build Coastguard Worker 
GetInstance()108*70a7ec85SAndroid Build Coastguard Worker std::shared_ptr<VintfObject> VintfObject::GetInstance() {
109*70a7ec85SAndroid Build Coastguard Worker     static details::LockedSharedPtr<VintfObject> sInstance{};
110*70a7ec85SAndroid Build Coastguard Worker     std::unique_lock<std::mutex> lock(sInstance.mutex);
111*70a7ec85SAndroid Build Coastguard Worker     if (sInstance.object == nullptr) {
112*70a7ec85SAndroid Build Coastguard Worker         if (!isAllowedToUseLibvintf()) {
113*70a7ec85SAndroid Build Coastguard Worker             LOG(ERROR) << "libvintf-usage-violation: Executable "
114*70a7ec85SAndroid Build Coastguard Worker                        << android::base::GetExecutablePath()
115*70a7ec85SAndroid Build Coastguard Worker                        << " should not use libvintf. It should query VINTF "
116*70a7ec85SAndroid Build Coastguard Worker                        << "metadata via servicemanager";
117*70a7ec85SAndroid Build Coastguard Worker         }
118*70a7ec85SAndroid Build Coastguard Worker 
119*70a7ec85SAndroid Build Coastguard Worker         sInstance.object = std::shared_ptr<VintfObject>(VintfObject::Builder().build().release());
120*70a7ec85SAndroid Build Coastguard Worker     }
121*70a7ec85SAndroid Build Coastguard Worker     return sInstance.object;
122*70a7ec85SAndroid Build Coastguard Worker }
123*70a7ec85SAndroid Build Coastguard Worker 
GetDeviceHalManifest()124*70a7ec85SAndroid Build Coastguard Worker std::shared_ptr<const HalManifest> VintfObject::GetDeviceHalManifest() {
125*70a7ec85SAndroid Build Coastguard Worker     return GetInstance()->getDeviceHalManifest();
126*70a7ec85SAndroid Build Coastguard Worker }
127*70a7ec85SAndroid Build Coastguard Worker 
getDeviceHalManifest()128*70a7ec85SAndroid Build Coastguard Worker std::shared_ptr<const HalManifest> VintfObject::getDeviceHalManifest() {
129*70a7ec85SAndroid Build Coastguard Worker     // TODO(b/242070736): only APEX data needs to be updated
130*70a7ec85SAndroid Build Coastguard Worker     return Get(__func__, &mDeviceManifest,
131*70a7ec85SAndroid Build Coastguard Worker                std::bind(&VintfObject::fetchDeviceHalManifest, this, _1, _2),
132*70a7ec85SAndroid Build Coastguard Worker                apex::GetModifiedTime(getFileSystem().get(), getPropertyFetcher().get()));
133*70a7ec85SAndroid Build Coastguard Worker }
134*70a7ec85SAndroid Build Coastguard Worker 
GetFrameworkHalManifest()135*70a7ec85SAndroid Build Coastguard Worker std::shared_ptr<const HalManifest> VintfObject::GetFrameworkHalManifest() {
136*70a7ec85SAndroid Build Coastguard Worker     return GetInstance()->getFrameworkHalManifest();
137*70a7ec85SAndroid Build Coastguard Worker }
138*70a7ec85SAndroid Build Coastguard Worker 
getFrameworkHalManifest()139*70a7ec85SAndroid Build Coastguard Worker std::shared_ptr<const HalManifest> VintfObject::getFrameworkHalManifest() {
140*70a7ec85SAndroid Build Coastguard Worker     // TODO(b/242070736): only APEX data needs to be updated
141*70a7ec85SAndroid Build Coastguard Worker     return Get(__func__, &mFrameworkManifest,
142*70a7ec85SAndroid Build Coastguard Worker                std::bind(&VintfObject::fetchFrameworkHalManifest, this, _1, _2),
143*70a7ec85SAndroid Build Coastguard Worker                apex::GetModifiedTime(getFileSystem().get(), getPropertyFetcher().get()));
144*70a7ec85SAndroid Build Coastguard Worker }
145*70a7ec85SAndroid Build Coastguard Worker 
GetDeviceCompatibilityMatrix()146*70a7ec85SAndroid Build Coastguard Worker std::shared_ptr<const CompatibilityMatrix> VintfObject::GetDeviceCompatibilityMatrix() {
147*70a7ec85SAndroid Build Coastguard Worker     return GetInstance()->getDeviceCompatibilityMatrix();
148*70a7ec85SAndroid Build Coastguard Worker }
149*70a7ec85SAndroid Build Coastguard Worker 
getDeviceCompatibilityMatrix()150*70a7ec85SAndroid Build Coastguard Worker std::shared_ptr<const CompatibilityMatrix> VintfObject::getDeviceCompatibilityMatrix() {
151*70a7ec85SAndroid Build Coastguard Worker     return Get(__func__, &mDeviceMatrix, std::bind(&VintfObject::fetchDeviceMatrix, this, _1, _2));
152*70a7ec85SAndroid Build Coastguard Worker }
153*70a7ec85SAndroid Build Coastguard Worker 
GetFrameworkCompatibilityMatrix()154*70a7ec85SAndroid Build Coastguard Worker std::shared_ptr<const CompatibilityMatrix> VintfObject::GetFrameworkCompatibilityMatrix() {
155*70a7ec85SAndroid Build Coastguard Worker     return GetInstance()->getFrameworkCompatibilityMatrix();
156*70a7ec85SAndroid Build Coastguard Worker }
157*70a7ec85SAndroid Build Coastguard Worker 
getFrameworkCompatibilityMatrix()158*70a7ec85SAndroid Build Coastguard Worker std::shared_ptr<const CompatibilityMatrix> VintfObject::getFrameworkCompatibilityMatrix() {
159*70a7ec85SAndroid Build Coastguard Worker     // To avoid deadlock, get device manifest before any locks.
160*70a7ec85SAndroid Build Coastguard Worker     auto deviceManifest = getDeviceHalManifest();
161*70a7ec85SAndroid Build Coastguard Worker 
162*70a7ec85SAndroid Build Coastguard Worker     std::string error;
163*70a7ec85SAndroid Build Coastguard Worker     auto kernelLevel = getKernelLevel(&error);
164*70a7ec85SAndroid Build Coastguard Worker     if (kernelLevel == Level::UNSPECIFIED) {
165*70a7ec85SAndroid Build Coastguard Worker         LOG(WARNING) << "getKernelLevel: " << error;
166*70a7ec85SAndroid Build Coastguard Worker     }
167*70a7ec85SAndroid Build Coastguard Worker 
168*70a7ec85SAndroid Build Coastguard Worker     std::unique_lock<std::mutex> _lock(mFrameworkCompatibilityMatrixMutex);
169*70a7ec85SAndroid Build Coastguard Worker 
170*70a7ec85SAndroid Build Coastguard Worker     auto combined = Get(__func__, &mCombinedFrameworkMatrix,
171*70a7ec85SAndroid Build Coastguard Worker                         std::bind(&VintfObject::getCombinedFrameworkMatrix, this, deviceManifest,
172*70a7ec85SAndroid Build Coastguard Worker                                   kernelLevel, _1, _2));
173*70a7ec85SAndroid Build Coastguard Worker     if (combined != nullptr) {
174*70a7ec85SAndroid Build Coastguard Worker         return combined;
175*70a7ec85SAndroid Build Coastguard Worker     }
176*70a7ec85SAndroid Build Coastguard Worker 
177*70a7ec85SAndroid Build Coastguard Worker     return Get(__func__, &mFrameworkMatrix,
178*70a7ec85SAndroid Build Coastguard Worker                std::bind(&CompatibilityMatrix::fetchAllInformation, _1, getFileSystem().get(),
179*70a7ec85SAndroid Build Coastguard Worker                          kSystemLegacyMatrix, _2));
180*70a7ec85SAndroid Build Coastguard Worker }
181*70a7ec85SAndroid Build Coastguard Worker 
getCombinedFrameworkMatrix(const std::shared_ptr<const HalManifest> & deviceManifest,Level kernelLevel,CompatibilityMatrix * out,std::string * error)182*70a7ec85SAndroid Build Coastguard Worker status_t VintfObject::getCombinedFrameworkMatrix(
183*70a7ec85SAndroid Build Coastguard Worker     const std::shared_ptr<const HalManifest>& deviceManifest, Level kernelLevel,
184*70a7ec85SAndroid Build Coastguard Worker     CompatibilityMatrix* out, std::string* error) {
185*70a7ec85SAndroid Build Coastguard Worker     std::vector<CompatibilityMatrix> matrixFragments;
186*70a7ec85SAndroid Build Coastguard Worker     auto matrixFragmentsStatus = getAllFrameworkMatrixLevels(&matrixFragments, error);
187*70a7ec85SAndroid Build Coastguard Worker     if (matrixFragmentsStatus != OK) {
188*70a7ec85SAndroid Build Coastguard Worker         return matrixFragmentsStatus;
189*70a7ec85SAndroid Build Coastguard Worker     }
190*70a7ec85SAndroid Build Coastguard Worker     if (matrixFragments.empty()) {
191*70a7ec85SAndroid Build Coastguard Worker         if (error && error->empty()) {
192*70a7ec85SAndroid Build Coastguard Worker             *error = "Cannot get framework matrix for each FCM version for unknown error.";
193*70a7ec85SAndroid Build Coastguard Worker         }
194*70a7ec85SAndroid Build Coastguard Worker         return NAME_NOT_FOUND;
195*70a7ec85SAndroid Build Coastguard Worker     }
196*70a7ec85SAndroid Build Coastguard Worker 
197*70a7ec85SAndroid Build Coastguard Worker     Level deviceLevel = Level::UNSPECIFIED;
198*70a7ec85SAndroid Build Coastguard Worker 
199*70a7ec85SAndroid Build Coastguard Worker     if (deviceManifest != nullptr) {
200*70a7ec85SAndroid Build Coastguard Worker         deviceLevel = deviceManifest->level();
201*70a7ec85SAndroid Build Coastguard Worker     }
202*70a7ec85SAndroid Build Coastguard Worker 
203*70a7ec85SAndroid Build Coastguard Worker     if (deviceLevel == Level::UNSPECIFIED) {
204*70a7ec85SAndroid Build Coastguard Worker         // Cannot infer FCM version. Combine all matrices by assuming
205*70a7ec85SAndroid Build Coastguard Worker         // Shipping FCM Version == min(all supported FCM Versions in the framework)
206*70a7ec85SAndroid Build Coastguard Worker         for (auto&& fragment : matrixFragments) {
207*70a7ec85SAndroid Build Coastguard Worker             Level fragmentLevel = fragment.level();
208*70a7ec85SAndroid Build Coastguard Worker             if (fragmentLevel != Level::UNSPECIFIED && deviceLevel > fragmentLevel) {
209*70a7ec85SAndroid Build Coastguard Worker                 deviceLevel = fragmentLevel;
210*70a7ec85SAndroid Build Coastguard Worker             }
211*70a7ec85SAndroid Build Coastguard Worker         }
212*70a7ec85SAndroid Build Coastguard Worker     }
213*70a7ec85SAndroid Build Coastguard Worker 
214*70a7ec85SAndroid Build Coastguard Worker     if (deviceLevel == Level::UNSPECIFIED) {
215*70a7ec85SAndroid Build Coastguard Worker         // None of the fragments specify any FCM version. Should never happen except
216*70a7ec85SAndroid Build Coastguard Worker         // for inconsistent builds.
217*70a7ec85SAndroid Build Coastguard Worker         if (error) {
218*70a7ec85SAndroid Build Coastguard Worker             *error = "No framework compatibility matrix files under "s + kSystemVintfDir +
219*70a7ec85SAndroid Build Coastguard Worker                      " declare FCM version.";
220*70a7ec85SAndroid Build Coastguard Worker         }
221*70a7ec85SAndroid Build Coastguard Worker         return NAME_NOT_FOUND;
222*70a7ec85SAndroid Build Coastguard Worker     }
223*70a7ec85SAndroid Build Coastguard Worker 
224*70a7ec85SAndroid Build Coastguard Worker     auto combined = CompatibilityMatrix::combine(deviceLevel, kernelLevel, &matrixFragments, error);
225*70a7ec85SAndroid Build Coastguard Worker     if (combined == nullptr) {
226*70a7ec85SAndroid Build Coastguard Worker         return BAD_VALUE;
227*70a7ec85SAndroid Build Coastguard Worker     }
228*70a7ec85SAndroid Build Coastguard Worker     *out = std::move(*combined);
229*70a7ec85SAndroid Build Coastguard Worker     return OK;
230*70a7ec85SAndroid Build Coastguard Worker }
231*70a7ec85SAndroid Build Coastguard Worker 
232*70a7ec85SAndroid Build Coastguard Worker // Load and combine all of the manifests in a directory
233*70a7ec85SAndroid Build Coastguard Worker // If forceSchemaType, all fragment manifests are coerced into manifest->type().
addDirectoryManifests(const std::string & directory,HalManifest * manifest,bool forceSchemaType,std::string * error)234*70a7ec85SAndroid Build Coastguard Worker status_t VintfObject::addDirectoryManifests(const std::string& directory, HalManifest* manifest,
235*70a7ec85SAndroid Build Coastguard Worker                                             bool forceSchemaType, std::string* error) {
236*70a7ec85SAndroid Build Coastguard Worker     std::vector<std::string> fileNames;
237*70a7ec85SAndroid Build Coastguard Worker     status_t err = getFileSystem()->listFiles(directory, &fileNames, error);
238*70a7ec85SAndroid Build Coastguard Worker     // if the directory isn't there, that's okay
239*70a7ec85SAndroid Build Coastguard Worker     if (err == NAME_NOT_FOUND) {
240*70a7ec85SAndroid Build Coastguard Worker         if (error) {
241*70a7ec85SAndroid Build Coastguard Worker             error->clear();
242*70a7ec85SAndroid Build Coastguard Worker         }
243*70a7ec85SAndroid Build Coastguard Worker         return OK;
244*70a7ec85SAndroid Build Coastguard Worker     }
245*70a7ec85SAndroid Build Coastguard Worker     if (err != OK) return err;
246*70a7ec85SAndroid Build Coastguard Worker 
247*70a7ec85SAndroid Build Coastguard Worker     for (const std::string& file : fileNames) {
248*70a7ec85SAndroid Build Coastguard Worker         // Only adds HALs because all other things are added by libvintf
249*70a7ec85SAndroid Build Coastguard Worker         // itself for now.
250*70a7ec85SAndroid Build Coastguard Worker         HalManifest fragmentManifest;
251*70a7ec85SAndroid Build Coastguard Worker         err = fetchOneHalManifest(directory + file, &fragmentManifest, error);
252*70a7ec85SAndroid Build Coastguard Worker         if (err != OK) return err;
253*70a7ec85SAndroid Build Coastguard Worker 
254*70a7ec85SAndroid Build Coastguard Worker         if (forceSchemaType) {
255*70a7ec85SAndroid Build Coastguard Worker             fragmentManifest.setType(manifest->type());
256*70a7ec85SAndroid Build Coastguard Worker         }
257*70a7ec85SAndroid Build Coastguard Worker 
258*70a7ec85SAndroid Build Coastguard Worker         if (!manifest->addAll(&fragmentManifest, error)) {
259*70a7ec85SAndroid Build Coastguard Worker             if (error) {
260*70a7ec85SAndroid Build Coastguard Worker                 error->insert(0, "Cannot add manifest fragment " + directory + file + ": ");
261*70a7ec85SAndroid Build Coastguard Worker             }
262*70a7ec85SAndroid Build Coastguard Worker             return UNKNOWN_ERROR;
263*70a7ec85SAndroid Build Coastguard Worker         }
264*70a7ec85SAndroid Build Coastguard Worker     }
265*70a7ec85SAndroid Build Coastguard Worker 
266*70a7ec85SAndroid Build Coastguard Worker     return OK;
267*70a7ec85SAndroid Build Coastguard Worker }
268*70a7ec85SAndroid Build Coastguard Worker 
269*70a7ec85SAndroid Build Coastguard Worker // addDirectoryManifests for multiple directories
addDirectoriesManifests(const std::vector<std::string> & directories,HalManifest * manifest,bool forceSchemaType,std::string * error)270*70a7ec85SAndroid Build Coastguard Worker status_t VintfObject::addDirectoriesManifests(const std::vector<std::string>& directories,
271*70a7ec85SAndroid Build Coastguard Worker                                               HalManifest* manifest, bool forceSchemaType,
272*70a7ec85SAndroid Build Coastguard Worker                                               std::string* error) {
273*70a7ec85SAndroid Build Coastguard Worker     for (const auto& dir : directories) {
274*70a7ec85SAndroid Build Coastguard Worker         auto status = addDirectoryManifests(dir, manifest, forceSchemaType, error);
275*70a7ec85SAndroid Build Coastguard Worker         if (status != OK) {
276*70a7ec85SAndroid Build Coastguard Worker             return status;
277*70a7ec85SAndroid Build Coastguard Worker         }
278*70a7ec85SAndroid Build Coastguard Worker     }
279*70a7ec85SAndroid Build Coastguard Worker     return OK;
280*70a7ec85SAndroid Build Coastguard Worker }
281*70a7ec85SAndroid Build Coastguard Worker 
282*70a7ec85SAndroid Build Coastguard Worker // Fetch fragments from apexes originated from /vendor.
283*70a7ec85SAndroid Build Coastguard Worker // For now, we don't have /odm apexes.
fetchDeviceHalManifestApex(HalManifest * out,std::string * error)284*70a7ec85SAndroid Build Coastguard Worker status_t VintfObject::fetchDeviceHalManifestApex(HalManifest* out, std::string* error) {
285*70a7ec85SAndroid Build Coastguard Worker     std::vector<std::string> dirs;
286*70a7ec85SAndroid Build Coastguard Worker     status_t status =
287*70a7ec85SAndroid Build Coastguard Worker         apex::GetDeviceVintfDirs(getFileSystem().get(), getPropertyFetcher().get(), &dirs, error);
288*70a7ec85SAndroid Build Coastguard Worker     if (status != OK) {
289*70a7ec85SAndroid Build Coastguard Worker         return status;
290*70a7ec85SAndroid Build Coastguard Worker     }
291*70a7ec85SAndroid Build Coastguard Worker     return addDirectoriesManifests(dirs, out, /*forceSchemaType=*/false, error);
292*70a7ec85SAndroid Build Coastguard Worker }
293*70a7ec85SAndroid Build Coastguard Worker 
294*70a7ec85SAndroid Build Coastguard Worker // Priority for loading vendor manifest:
295*70a7ec85SAndroid Build Coastguard Worker // 1. Vendor manifest + device fragments (including vapex) + ODM manifest (optional) + odm fragments
296*70a7ec85SAndroid Build Coastguard Worker // 2. Vendor manifest + device fragments (including vapex)
297*70a7ec85SAndroid Build Coastguard Worker // 3. ODM manifest (optional) + odm fragments
298*70a7ec85SAndroid Build Coastguard Worker // 4. /vendor/manifest.xml (legacy, no fragments)
299*70a7ec85SAndroid Build Coastguard Worker // where:
300*70a7ec85SAndroid Build Coastguard Worker // A + B means unioning <hal> tags from A and B. If B declares an override, then this takes priority
301*70a7ec85SAndroid Build Coastguard Worker // over A.
fetchDeviceHalManifest(HalManifest * out,std::string * error)302*70a7ec85SAndroid Build Coastguard Worker status_t VintfObject::fetchDeviceHalManifest(HalManifest* out, std::string* error) {
303*70a7ec85SAndroid Build Coastguard Worker     HalManifest vendorManifest;
304*70a7ec85SAndroid Build Coastguard Worker     status_t vendorStatus = fetchVendorHalManifest(&vendorManifest, error);
305*70a7ec85SAndroid Build Coastguard Worker     if (vendorStatus != OK && vendorStatus != NAME_NOT_FOUND) {
306*70a7ec85SAndroid Build Coastguard Worker         return vendorStatus;
307*70a7ec85SAndroid Build Coastguard Worker     }
308*70a7ec85SAndroid Build Coastguard Worker 
309*70a7ec85SAndroid Build Coastguard Worker     if (vendorStatus == OK) {
310*70a7ec85SAndroid Build Coastguard Worker         *out = std::move(vendorManifest);
311*70a7ec85SAndroid Build Coastguard Worker         status_t fragmentStatus = addDirectoryManifests(kVendorManifestFragmentDir, out,
312*70a7ec85SAndroid Build Coastguard Worker                                                         false /* forceSchemaType*/, error);
313*70a7ec85SAndroid Build Coastguard Worker         if (fragmentStatus != OK) {
314*70a7ec85SAndroid Build Coastguard Worker             return fragmentStatus;
315*70a7ec85SAndroid Build Coastguard Worker         }
316*70a7ec85SAndroid Build Coastguard Worker 
317*70a7ec85SAndroid Build Coastguard Worker         status_t apexStatus = fetchDeviceHalManifestApex(out, error);
318*70a7ec85SAndroid Build Coastguard Worker         if (apexStatus != OK) {
319*70a7ec85SAndroid Build Coastguard Worker             return apexStatus;
320*70a7ec85SAndroid Build Coastguard Worker         }
321*70a7ec85SAndroid Build Coastguard Worker     }
322*70a7ec85SAndroid Build Coastguard Worker 
323*70a7ec85SAndroid Build Coastguard Worker     HalManifest odmManifest;
324*70a7ec85SAndroid Build Coastguard Worker     status_t odmStatus = fetchOdmHalManifest(&odmManifest, error);
325*70a7ec85SAndroid Build Coastguard Worker     if (odmStatus != OK && odmStatus != NAME_NOT_FOUND) {
326*70a7ec85SAndroid Build Coastguard Worker         return odmStatus;
327*70a7ec85SAndroid Build Coastguard Worker     }
328*70a7ec85SAndroid Build Coastguard Worker 
329*70a7ec85SAndroid Build Coastguard Worker     if (vendorStatus == OK) {
330*70a7ec85SAndroid Build Coastguard Worker         if (odmStatus == OK) {
331*70a7ec85SAndroid Build Coastguard Worker             if (!out->addAll(&odmManifest, error)) {
332*70a7ec85SAndroid Build Coastguard Worker                 if (error) {
333*70a7ec85SAndroid Build Coastguard Worker                     error->insert(0, "Cannot add ODM manifest :");
334*70a7ec85SAndroid Build Coastguard Worker                 }
335*70a7ec85SAndroid Build Coastguard Worker                 return UNKNOWN_ERROR;
336*70a7ec85SAndroid Build Coastguard Worker             }
337*70a7ec85SAndroid Build Coastguard Worker         }
338*70a7ec85SAndroid Build Coastguard Worker         return addDirectoryManifests(kOdmManifestFragmentDir, out, false /* forceSchemaType */,
339*70a7ec85SAndroid Build Coastguard Worker                                      error);
340*70a7ec85SAndroid Build Coastguard Worker     }
341*70a7ec85SAndroid Build Coastguard Worker 
342*70a7ec85SAndroid Build Coastguard Worker     // vendorStatus != OK, "out" is not changed.
343*70a7ec85SAndroid Build Coastguard Worker     if (odmStatus == OK) {
344*70a7ec85SAndroid Build Coastguard Worker         *out = std::move(odmManifest);
345*70a7ec85SAndroid Build Coastguard Worker         return addDirectoryManifests(kOdmManifestFragmentDir, out, false /* forceSchemaType */,
346*70a7ec85SAndroid Build Coastguard Worker                                      error);
347*70a7ec85SAndroid Build Coastguard Worker     }
348*70a7ec85SAndroid Build Coastguard Worker 
349*70a7ec85SAndroid Build Coastguard Worker     // Use legacy /vendor/manifest.xml
350*70a7ec85SAndroid Build Coastguard Worker     return out->fetchAllInformation(getFileSystem().get(), kVendorLegacyManifest, error);
351*70a7ec85SAndroid Build Coastguard Worker }
352*70a7ec85SAndroid Build Coastguard Worker 
353*70a7ec85SAndroid Build Coastguard Worker // Priority:
354*70a7ec85SAndroid Build Coastguard Worker // 1. if {vendorSku} is defined, /vendor/etc/vintf/manifest_{vendorSku}.xml
355*70a7ec85SAndroid Build Coastguard Worker // 2. /vendor/etc/vintf/manifest.xml
356*70a7ec85SAndroid Build Coastguard Worker // where:
357*70a7ec85SAndroid Build Coastguard Worker // {vendorSku} is the value of ro.boot.product.vendor.sku
fetchVendorHalManifest(HalManifest * out,std::string * error)358*70a7ec85SAndroid Build Coastguard Worker status_t VintfObject::fetchVendorHalManifest(HalManifest* out, std::string* error) {
359*70a7ec85SAndroid Build Coastguard Worker     status_t status;
360*70a7ec85SAndroid Build Coastguard Worker 
361*70a7ec85SAndroid Build Coastguard Worker     std::string vendorSku;
362*70a7ec85SAndroid Build Coastguard Worker     vendorSku = getPropertyFetcher()->getProperty("ro.boot.product.vendor.sku", "");
363*70a7ec85SAndroid Build Coastguard Worker 
364*70a7ec85SAndroid Build Coastguard Worker     if (!vendorSku.empty()) {
365*70a7ec85SAndroid Build Coastguard Worker         status =
366*70a7ec85SAndroid Build Coastguard Worker             fetchOneHalManifest(kVendorVintfDir + "manifest_"s + vendorSku + ".xml", out, error);
367*70a7ec85SAndroid Build Coastguard Worker         if (status == OK || status != NAME_NOT_FOUND) {
368*70a7ec85SAndroid Build Coastguard Worker             return status;
369*70a7ec85SAndroid Build Coastguard Worker         }
370*70a7ec85SAndroid Build Coastguard Worker     }
371*70a7ec85SAndroid Build Coastguard Worker 
372*70a7ec85SAndroid Build Coastguard Worker     status = fetchOneHalManifest(kVendorManifest, out, error);
373*70a7ec85SAndroid Build Coastguard Worker     if (status == OK || status != NAME_NOT_FOUND) {
374*70a7ec85SAndroid Build Coastguard Worker         return status;
375*70a7ec85SAndroid Build Coastguard Worker     }
376*70a7ec85SAndroid Build Coastguard Worker 
377*70a7ec85SAndroid Build Coastguard Worker     return NAME_NOT_FOUND;
378*70a7ec85SAndroid Build Coastguard Worker }
379*70a7ec85SAndroid Build Coastguard Worker 
getOdmProductManifestFile(const std::string & dir,const::std::string & sku)380*70a7ec85SAndroid Build Coastguard Worker std::string getOdmProductManifestFile(const std::string& dir, const ::std::string& sku) {
381*70a7ec85SAndroid Build Coastguard Worker     return sku.empty() ? "" : dir + "manifest_"s + sku + ".xml";
382*70a7ec85SAndroid Build Coastguard Worker }
383*70a7ec85SAndroid Build Coastguard Worker 
384*70a7ec85SAndroid Build Coastguard Worker // "out" is written to iff return status is OK.
385*70a7ec85SAndroid Build Coastguard Worker // Priority:
386*70a7ec85SAndroid Build Coastguard Worker // 1. if {sku} is defined, /odm/etc/vintf/manifest_{sku}.xml
387*70a7ec85SAndroid Build Coastguard Worker // 2. /odm/etc/vintf/manifest.xml
388*70a7ec85SAndroid Build Coastguard Worker // 3. if {sku} is defined, /odm/etc/manifest_{sku}.xml
389*70a7ec85SAndroid Build Coastguard Worker // 4. /odm/etc/manifest.xml
390*70a7ec85SAndroid Build Coastguard Worker // where:
391*70a7ec85SAndroid Build Coastguard Worker // {sku} is the value of ro.boot.product.hardware.sku
fetchOdmHalManifest(HalManifest * out,std::string * error)392*70a7ec85SAndroid Build Coastguard Worker status_t VintfObject::fetchOdmHalManifest(HalManifest* out, std::string* error) {
393*70a7ec85SAndroid Build Coastguard Worker     status_t status;
394*70a7ec85SAndroid Build Coastguard Worker     std::string productModel;
395*70a7ec85SAndroid Build Coastguard Worker     productModel = getPropertyFetcher()->getProperty("ro.boot.product.hardware.sku", "");
396*70a7ec85SAndroid Build Coastguard Worker 
397*70a7ec85SAndroid Build Coastguard Worker     const std::string productFile = getOdmProductManifestFile(kOdmVintfDir, productModel);
398*70a7ec85SAndroid Build Coastguard Worker     if (!productFile.empty()) {
399*70a7ec85SAndroid Build Coastguard Worker         status = fetchOneHalManifest(productFile, out, error);
400*70a7ec85SAndroid Build Coastguard Worker         if (status == OK || status != NAME_NOT_FOUND) {
401*70a7ec85SAndroid Build Coastguard Worker             return status;
402*70a7ec85SAndroid Build Coastguard Worker         }
403*70a7ec85SAndroid Build Coastguard Worker     }
404*70a7ec85SAndroid Build Coastguard Worker 
405*70a7ec85SAndroid Build Coastguard Worker     status = fetchOneHalManifest(kOdmManifest, out, error);
406*70a7ec85SAndroid Build Coastguard Worker     if (status == OK || status != NAME_NOT_FOUND) {
407*70a7ec85SAndroid Build Coastguard Worker         return status;
408*70a7ec85SAndroid Build Coastguard Worker     }
409*70a7ec85SAndroid Build Coastguard Worker 
410*70a7ec85SAndroid Build Coastguard Worker     const std::string productLegacyFile =
411*70a7ec85SAndroid Build Coastguard Worker         getOdmProductManifestFile(kOdmLegacyVintfDir, productModel);
412*70a7ec85SAndroid Build Coastguard Worker     if (!productLegacyFile.empty()) {
413*70a7ec85SAndroid Build Coastguard Worker         status = fetchOneHalManifest(productLegacyFile, out, error);
414*70a7ec85SAndroid Build Coastguard Worker         if (status == OK || status != NAME_NOT_FOUND) {
415*70a7ec85SAndroid Build Coastguard Worker             return status;
416*70a7ec85SAndroid Build Coastguard Worker         }
417*70a7ec85SAndroid Build Coastguard Worker     }
418*70a7ec85SAndroid Build Coastguard Worker 
419*70a7ec85SAndroid Build Coastguard Worker     status = fetchOneHalManifest(kOdmLegacyManifest, out, error);
420*70a7ec85SAndroid Build Coastguard Worker     if (status == OK || status != NAME_NOT_FOUND) {
421*70a7ec85SAndroid Build Coastguard Worker         return status;
422*70a7ec85SAndroid Build Coastguard Worker     }
423*70a7ec85SAndroid Build Coastguard Worker 
424*70a7ec85SAndroid Build Coastguard Worker     return NAME_NOT_FOUND;
425*70a7ec85SAndroid Build Coastguard Worker }
426*70a7ec85SAndroid Build Coastguard Worker 
427*70a7ec85SAndroid Build Coastguard Worker // Fetch one manifest.xml file. "out" is written to iff return status is OK.
428*70a7ec85SAndroid Build Coastguard Worker // Returns NAME_NOT_FOUND if file is missing.
fetchOneHalManifest(const std::string & path,HalManifest * out,std::string * error)429*70a7ec85SAndroid Build Coastguard Worker status_t VintfObject::fetchOneHalManifest(const std::string& path, HalManifest* out,
430*70a7ec85SAndroid Build Coastguard Worker                                           std::string* error) {
431*70a7ec85SAndroid Build Coastguard Worker     HalManifest ret;
432*70a7ec85SAndroid Build Coastguard Worker     status_t status = ret.fetchAllInformation(getFileSystem().get(), path, error);
433*70a7ec85SAndroid Build Coastguard Worker     if (status == OK) {
434*70a7ec85SAndroid Build Coastguard Worker         *out = std::move(ret);
435*70a7ec85SAndroid Build Coastguard Worker     }
436*70a7ec85SAndroid Build Coastguard Worker     return status;
437*70a7ec85SAndroid Build Coastguard Worker }
438*70a7ec85SAndroid Build Coastguard Worker 
fetchDeviceMatrix(CompatibilityMatrix * out,std::string * error)439*70a7ec85SAndroid Build Coastguard Worker status_t VintfObject::fetchDeviceMatrix(CompatibilityMatrix* out, std::string* error) {
440*70a7ec85SAndroid Build Coastguard Worker     CompatibilityMatrix etcMatrix;
441*70a7ec85SAndroid Build Coastguard Worker     if (etcMatrix.fetchAllInformation(getFileSystem().get(), kVendorMatrix, error) == OK) {
442*70a7ec85SAndroid Build Coastguard Worker         *out = std::move(etcMatrix);
443*70a7ec85SAndroid Build Coastguard Worker         return OK;
444*70a7ec85SAndroid Build Coastguard Worker     }
445*70a7ec85SAndroid Build Coastguard Worker     return out->fetchAllInformation(getFileSystem().get(), kVendorLegacyMatrix, error);
446*70a7ec85SAndroid Build Coastguard Worker }
447*70a7ec85SAndroid Build Coastguard Worker 
448*70a7ec85SAndroid Build Coastguard Worker // Priority:
449*70a7ec85SAndroid Build Coastguard Worker // 1. /system/etc/vintf/manifest.xml
450*70a7ec85SAndroid Build Coastguard Worker //    + /system/etc/vintf/manifest/*.xml if they exist
451*70a7ec85SAndroid Build Coastguard Worker //    + /product/etc/vintf/manifest.xml if it exists
452*70a7ec85SAndroid Build Coastguard Worker //    + /product/etc/vintf/manifest/*.xml if they exist
453*70a7ec85SAndroid Build Coastguard Worker // 2. (deprecated) /system/manifest.xml
fetchUnfilteredFrameworkHalManifest(HalManifest * out,std::string * error)454*70a7ec85SAndroid Build Coastguard Worker status_t VintfObject::fetchUnfilteredFrameworkHalManifest(HalManifest* out, std::string* error) {
455*70a7ec85SAndroid Build Coastguard Worker     auto systemEtcStatus = fetchOneHalManifest(kSystemManifest, out, error);
456*70a7ec85SAndroid Build Coastguard Worker     if (systemEtcStatus == OK) {
457*70a7ec85SAndroid Build Coastguard Worker         auto dirStatus = addDirectoryManifests(kSystemManifestFragmentDir, out,
458*70a7ec85SAndroid Build Coastguard Worker                                                false /* forceSchemaType */, error);
459*70a7ec85SAndroid Build Coastguard Worker         if (dirStatus != OK) {
460*70a7ec85SAndroid Build Coastguard Worker             return dirStatus;
461*70a7ec85SAndroid Build Coastguard Worker         }
462*70a7ec85SAndroid Build Coastguard Worker 
463*70a7ec85SAndroid Build Coastguard Worker         std::vector<std::pair<const char*, const char*>> extensions{
464*70a7ec85SAndroid Build Coastguard Worker             {kProductManifest, kProductManifestFragmentDir},
465*70a7ec85SAndroid Build Coastguard Worker             {kSystemExtManifest, kSystemExtManifestFragmentDir},
466*70a7ec85SAndroid Build Coastguard Worker         };
467*70a7ec85SAndroid Build Coastguard Worker         for (auto&& [manifestPath, frags] : extensions) {
468*70a7ec85SAndroid Build Coastguard Worker             HalManifest halManifest;
469*70a7ec85SAndroid Build Coastguard Worker             auto status = fetchOneHalManifest(manifestPath, &halManifest, error);
470*70a7ec85SAndroid Build Coastguard Worker             if (status != OK && status != NAME_NOT_FOUND) {
471*70a7ec85SAndroid Build Coastguard Worker                 return status;
472*70a7ec85SAndroid Build Coastguard Worker             }
473*70a7ec85SAndroid Build Coastguard Worker             if (status == OK) {
474*70a7ec85SAndroid Build Coastguard Worker                 if (!out->addAll(&halManifest, error)) {
475*70a7ec85SAndroid Build Coastguard Worker                     if (error) {
476*70a7ec85SAndroid Build Coastguard Worker                         error->insert(0, "Cannot add "s + manifestPath + ":");
477*70a7ec85SAndroid Build Coastguard Worker                     }
478*70a7ec85SAndroid Build Coastguard Worker                     return UNKNOWN_ERROR;
479*70a7ec85SAndroid Build Coastguard Worker                 }
480*70a7ec85SAndroid Build Coastguard Worker             }
481*70a7ec85SAndroid Build Coastguard Worker 
482*70a7ec85SAndroid Build Coastguard Worker             auto fragmentStatus =
483*70a7ec85SAndroid Build Coastguard Worker                 addDirectoryManifests(frags, out, false /* forceSchemaType */, error);
484*70a7ec85SAndroid Build Coastguard Worker             if (fragmentStatus != OK) {
485*70a7ec85SAndroid Build Coastguard Worker                 return fragmentStatus;
486*70a7ec85SAndroid Build Coastguard Worker             }
487*70a7ec85SAndroid Build Coastguard Worker         }
488*70a7ec85SAndroid Build Coastguard Worker 
489*70a7ec85SAndroid Build Coastguard Worker         return OK;
490*70a7ec85SAndroid Build Coastguard Worker     } else {
491*70a7ec85SAndroid Build Coastguard Worker         LOG(WARNING) << "Cannot fetch " << kSystemManifest << ": "
492*70a7ec85SAndroid Build Coastguard Worker                      << (error ? *error : strerror(-systemEtcStatus));
493*70a7ec85SAndroid Build Coastguard Worker     }
494*70a7ec85SAndroid Build Coastguard Worker 
495*70a7ec85SAndroid Build Coastguard Worker     return out->fetchAllInformation(getFileSystem().get(), kSystemLegacyManifest, error);
496*70a7ec85SAndroid Build Coastguard Worker }
497*70a7ec85SAndroid Build Coastguard Worker 
fetchFrameworkHalManifest(HalManifest * out,std::string * error)498*70a7ec85SAndroid Build Coastguard Worker status_t VintfObject::fetchFrameworkHalManifest(HalManifest* out, std::string* error) {
499*70a7ec85SAndroid Build Coastguard Worker     status_t status = fetchUnfilteredFrameworkHalManifest(out, error);
500*70a7ec85SAndroid Build Coastguard Worker     if (status != OK) {
501*70a7ec85SAndroid Build Coastguard Worker         return status;
502*70a7ec85SAndroid Build Coastguard Worker     }
503*70a7ec85SAndroid Build Coastguard Worker     status = fetchFrameworkHalManifestApex(out, error);
504*70a7ec85SAndroid Build Coastguard Worker     if (status != OK) {
505*70a7ec85SAndroid Build Coastguard Worker         return status;
506*70a7ec85SAndroid Build Coastguard Worker     }
507*70a7ec85SAndroid Build Coastguard Worker     filterHalsByDeviceManifestLevel(out);
508*70a7ec85SAndroid Build Coastguard Worker     return OK;
509*70a7ec85SAndroid Build Coastguard Worker }
510*70a7ec85SAndroid Build Coastguard Worker 
511*70a7ec85SAndroid Build Coastguard Worker // Fetch fragments from apexes originated from /system.
fetchFrameworkHalManifestApex(HalManifest * out,std::string * error)512*70a7ec85SAndroid Build Coastguard Worker status_t VintfObject::fetchFrameworkHalManifestApex(HalManifest* out, std::string* error) {
513*70a7ec85SAndroid Build Coastguard Worker     std::vector<std::string> dirs;
514*70a7ec85SAndroid Build Coastguard Worker     status_t status = apex::GetFrameworkVintfDirs(getFileSystem().get(), getPropertyFetcher().get(),
515*70a7ec85SAndroid Build Coastguard Worker                                                   &dirs, error);
516*70a7ec85SAndroid Build Coastguard Worker     if (status != OK) {
517*70a7ec85SAndroid Build Coastguard Worker         return status;
518*70a7ec85SAndroid Build Coastguard Worker     }
519*70a7ec85SAndroid Build Coastguard Worker     return addDirectoriesManifests(dirs, out, /*forceSchemaType=*/false, error);
520*70a7ec85SAndroid Build Coastguard Worker }
521*70a7ec85SAndroid Build Coastguard Worker 
522*70a7ec85SAndroid Build Coastguard Worker // If deviceManifestLevel is not in the range [minLevel, maxLevel] of a HAL, remove the HAL,
523*70a7ec85SAndroid Build Coastguard Worker // where:
524*70a7ec85SAndroid Build Coastguard Worker //    minLevel = hal.getMinLevel(); if unspecified, -infinity
525*70a7ec85SAndroid Build Coastguard Worker //    maxLevel = hal.getMaxLevel(); if unspecified, +infinity
526*70a7ec85SAndroid Build Coastguard Worker //    deviceManifestLevel = deviceManifest->level(); if unspecified, -infinity
527*70a7ec85SAndroid Build Coastguard Worker // That is, if device manifest has no level, it is treated as an infinitely old device.
filterHalsByDeviceManifestLevel(HalManifest * out)528*70a7ec85SAndroid Build Coastguard Worker void VintfObject::filterHalsByDeviceManifestLevel(HalManifest* out) {
529*70a7ec85SAndroid Build Coastguard Worker     auto deviceManifest = getDeviceHalManifest();
530*70a7ec85SAndroid Build Coastguard Worker     Level deviceManifestLevel =
531*70a7ec85SAndroid Build Coastguard Worker         deviceManifest != nullptr ? deviceManifest->level() : Level::UNSPECIFIED;
532*70a7ec85SAndroid Build Coastguard Worker 
533*70a7ec85SAndroid Build Coastguard Worker     if (deviceManifest == nullptr) {
534*70a7ec85SAndroid Build Coastguard Worker         LOG(WARNING) << "Cannot fetch device manifest to determine target FCM version to "
535*70a7ec85SAndroid Build Coastguard Worker                         "filter framework manifest HALs properly. Treating as infinitely old "
536*70a7ec85SAndroid Build Coastguard Worker                         "device.";
537*70a7ec85SAndroid Build Coastguard Worker     } else if (deviceManifestLevel == Level::UNSPECIFIED) {
538*70a7ec85SAndroid Build Coastguard Worker         LOG(WARNING)
539*70a7ec85SAndroid Build Coastguard Worker             << "Cannot filter framework manifest HALs properly because target FCM version is "
540*70a7ec85SAndroid Build Coastguard Worker                "unspecified in the device manifest. Treating as infinitely old device.";
541*70a7ec85SAndroid Build Coastguard Worker     }
542*70a7ec85SAndroid Build Coastguard Worker 
543*70a7ec85SAndroid Build Coastguard Worker     out->removeHalsIf([deviceManifestLevel](const ManifestHal& hal) {
544*70a7ec85SAndroid Build Coastguard Worker         if (hal.getMaxLevel() != Level::UNSPECIFIED) {
545*70a7ec85SAndroid Build Coastguard Worker             if (deviceManifestLevel != Level::UNSPECIFIED &&
546*70a7ec85SAndroid Build Coastguard Worker                 hal.getMaxLevel() < deviceManifestLevel) {
547*70a7ec85SAndroid Build Coastguard Worker                 return true;
548*70a7ec85SAndroid Build Coastguard Worker             }
549*70a7ec85SAndroid Build Coastguard Worker         }
550*70a7ec85SAndroid Build Coastguard Worker         if (hal.getMinLevel() != Level::UNSPECIFIED) {
551*70a7ec85SAndroid Build Coastguard Worker             if (deviceManifestLevel == Level::UNSPECIFIED ||
552*70a7ec85SAndroid Build Coastguard Worker                 hal.getMinLevel() > deviceManifestLevel) {
553*70a7ec85SAndroid Build Coastguard Worker                 return true;
554*70a7ec85SAndroid Build Coastguard Worker             }
555*70a7ec85SAndroid Build Coastguard Worker         }
556*70a7ec85SAndroid Build Coastguard Worker         return false;
557*70a7ec85SAndroid Build Coastguard Worker     });
558*70a7ec85SAndroid Build Coastguard Worker }
559*70a7ec85SAndroid Build Coastguard Worker 
appendLine(std::string * error,const std::string & message)560*70a7ec85SAndroid Build Coastguard Worker static void appendLine(std::string* error, const std::string& message) {
561*70a7ec85SAndroid Build Coastguard Worker     if (error != nullptr) {
562*70a7ec85SAndroid Build Coastguard Worker         if (!error->empty()) *error += "\n";
563*70a7ec85SAndroid Build Coastguard Worker         *error += message;
564*70a7ec85SAndroid Build Coastguard Worker     }
565*70a7ec85SAndroid Build Coastguard Worker }
566*70a7ec85SAndroid Build Coastguard Worker 
getOneMatrix(const std::string & path,CompatibilityMatrix * out,std::string * error)567*70a7ec85SAndroid Build Coastguard Worker status_t VintfObject::getOneMatrix(const std::string& path, CompatibilityMatrix* out,
568*70a7ec85SAndroid Build Coastguard Worker                                    std::string* error) {
569*70a7ec85SAndroid Build Coastguard Worker     std::string content;
570*70a7ec85SAndroid Build Coastguard Worker     status_t status = getFileSystem()->fetch(path, &content, error);
571*70a7ec85SAndroid Build Coastguard Worker     if (status != OK) {
572*70a7ec85SAndroid Build Coastguard Worker         return status;
573*70a7ec85SAndroid Build Coastguard Worker     }
574*70a7ec85SAndroid Build Coastguard Worker     if (!fromXml(out, content, error)) {
575*70a7ec85SAndroid Build Coastguard Worker         if (error) {
576*70a7ec85SAndroid Build Coastguard Worker             error->insert(0, "Cannot parse " + path + ": ");
577*70a7ec85SAndroid Build Coastguard Worker         }
578*70a7ec85SAndroid Build Coastguard Worker         return BAD_VALUE;
579*70a7ec85SAndroid Build Coastguard Worker     }
580*70a7ec85SAndroid Build Coastguard Worker     out->setFileName(path);
581*70a7ec85SAndroid Build Coastguard Worker     return OK;
582*70a7ec85SAndroid Build Coastguard Worker }
583*70a7ec85SAndroid Build Coastguard Worker 
getAllFrameworkMatrixLevels(std::vector<CompatibilityMatrix> * results,std::string * error)584*70a7ec85SAndroid Build Coastguard Worker status_t VintfObject::getAllFrameworkMatrixLevels(std::vector<CompatibilityMatrix>* results,
585*70a7ec85SAndroid Build Coastguard Worker                                                   std::string* error) {
586*70a7ec85SAndroid Build Coastguard Worker     std::vector<std::string> dirs = {
587*70a7ec85SAndroid Build Coastguard Worker         kSystemVintfDir,
588*70a7ec85SAndroid Build Coastguard Worker         kSystemExtVintfDir,
589*70a7ec85SAndroid Build Coastguard Worker         kProductVintfDir,
590*70a7ec85SAndroid Build Coastguard Worker     };
591*70a7ec85SAndroid Build Coastguard Worker     for (const auto& dir : dirs) {
592*70a7ec85SAndroid Build Coastguard Worker         std::vector<std::string> fileNames;
593*70a7ec85SAndroid Build Coastguard Worker         status_t listStatus = getFileSystem()->listFiles(dir, &fileNames, error);
594*70a7ec85SAndroid Build Coastguard Worker         if (listStatus == NAME_NOT_FOUND) {
595*70a7ec85SAndroid Build Coastguard Worker             if (error) {
596*70a7ec85SAndroid Build Coastguard Worker                 error->clear();
597*70a7ec85SAndroid Build Coastguard Worker             }
598*70a7ec85SAndroid Build Coastguard Worker             continue;
599*70a7ec85SAndroid Build Coastguard Worker         }
600*70a7ec85SAndroid Build Coastguard Worker         if (listStatus != OK) {
601*70a7ec85SAndroid Build Coastguard Worker             return listStatus;
602*70a7ec85SAndroid Build Coastguard Worker         }
603*70a7ec85SAndroid Build Coastguard Worker         for (const std::string& fileName : fileNames) {
604*70a7ec85SAndroid Build Coastguard Worker             std::string path = dir + fileName;
605*70a7ec85SAndroid Build Coastguard Worker             CompatibilityMatrix namedMatrix;
606*70a7ec85SAndroid Build Coastguard Worker             std::string matrixError;
607*70a7ec85SAndroid Build Coastguard Worker             status_t matrixStatus = getOneMatrix(path, &namedMatrix, &matrixError);
608*70a7ec85SAndroid Build Coastguard Worker             if (matrixStatus != OK) {
609*70a7ec85SAndroid Build Coastguard Worker                 // Manifests and matrices share the same dir. Client may not have enough
610*70a7ec85SAndroid Build Coastguard Worker                 // permissions to read system manifests, or may not be able to parse it.
611*70a7ec85SAndroid Build Coastguard Worker                 auto logLevel = matrixStatus == BAD_VALUE ? base::DEBUG : base::ERROR;
612*70a7ec85SAndroid Build Coastguard Worker                 LOG(logLevel) << "Framework Matrix: Ignore file " << path << ": " << matrixError;
613*70a7ec85SAndroid Build Coastguard Worker                 continue;
614*70a7ec85SAndroid Build Coastguard Worker             }
615*70a7ec85SAndroid Build Coastguard Worker             results->emplace_back(std::move(namedMatrix));
616*70a7ec85SAndroid Build Coastguard Worker         }
617*70a7ec85SAndroid Build Coastguard Worker 
618*70a7ec85SAndroid Build Coastguard Worker         if (dir == kSystemVintfDir && results->empty()) {
619*70a7ec85SAndroid Build Coastguard Worker             if (error) {
620*70a7ec85SAndroid Build Coastguard Worker                 *error = "No framework matrices under " + dir + " can be fetched or parsed.\n";
621*70a7ec85SAndroid Build Coastguard Worker             }
622*70a7ec85SAndroid Build Coastguard Worker             return NAME_NOT_FOUND;
623*70a7ec85SAndroid Build Coastguard Worker         }
624*70a7ec85SAndroid Build Coastguard Worker     }
625*70a7ec85SAndroid Build Coastguard Worker 
626*70a7ec85SAndroid Build Coastguard Worker     if (results->empty()) {
627*70a7ec85SAndroid Build Coastguard Worker         if (error) {
628*70a7ec85SAndroid Build Coastguard Worker             *error =
629*70a7ec85SAndroid Build Coastguard Worker                 "No framework matrices can be fetched or parsed. "
630*70a7ec85SAndroid Build Coastguard Worker                 "The following directories are searched:\n  " +
631*70a7ec85SAndroid Build Coastguard Worker                 android::base::Join(dirs, "\n  ");
632*70a7ec85SAndroid Build Coastguard Worker         }
633*70a7ec85SAndroid Build Coastguard Worker         return NAME_NOT_FOUND;
634*70a7ec85SAndroid Build Coastguard Worker     }
635*70a7ec85SAndroid Build Coastguard Worker     return OK;
636*70a7ec85SAndroid Build Coastguard Worker }
637*70a7ec85SAndroid Build Coastguard Worker 
GetRuntimeInfo(RuntimeInfo::FetchFlags flags)638*70a7ec85SAndroid Build Coastguard Worker std::shared_ptr<const RuntimeInfo> VintfObject::GetRuntimeInfo(RuntimeInfo::FetchFlags flags) {
639*70a7ec85SAndroid Build Coastguard Worker     return GetInstance()->getRuntimeInfo(flags);
640*70a7ec85SAndroid Build Coastguard Worker }
getRuntimeInfo(RuntimeInfo::FetchFlags flags)641*70a7ec85SAndroid Build Coastguard Worker std::shared_ptr<const RuntimeInfo> VintfObject::getRuntimeInfo(RuntimeInfo::FetchFlags flags) {
642*70a7ec85SAndroid Build Coastguard Worker     std::unique_lock<std::mutex> _lock(mDeviceRuntimeInfo.mutex);
643*70a7ec85SAndroid Build Coastguard Worker 
644*70a7ec85SAndroid Build Coastguard Worker     // Skip fetching information that has already been fetched previously.
645*70a7ec85SAndroid Build Coastguard Worker     flags &= (~mDeviceRuntimeInfo.fetchedFlags);
646*70a7ec85SAndroid Build Coastguard Worker 
647*70a7ec85SAndroid Build Coastguard Worker     if (mDeviceRuntimeInfo.object == nullptr) {
648*70a7ec85SAndroid Build Coastguard Worker         mDeviceRuntimeInfo.object = getRuntimeInfoFactory()->make_shared();
649*70a7ec85SAndroid Build Coastguard Worker     }
650*70a7ec85SAndroid Build Coastguard Worker 
651*70a7ec85SAndroid Build Coastguard Worker     status_t status = mDeviceRuntimeInfo.object->fetchAllInformation(flags);
652*70a7ec85SAndroid Build Coastguard Worker     if (status != OK) {
653*70a7ec85SAndroid Build Coastguard Worker         // If only kernel FCM is needed, ignore errors when fetching RuntimeInfo because RuntimeInfo
654*70a7ec85SAndroid Build Coastguard Worker         // is not available on host. On host, the kernel level can still be inferred from device
655*70a7ec85SAndroid Build Coastguard Worker         // manifest.
656*70a7ec85SAndroid Build Coastguard Worker         // If other information is needed, flag the error by returning nullptr.
657*70a7ec85SAndroid Build Coastguard Worker         auto allExceptKernelFcm = RuntimeInfo::FetchFlag::ALL & ~RuntimeInfo::FetchFlag::KERNEL_FCM;
658*70a7ec85SAndroid Build Coastguard Worker         bool needDeviceRuntimeInfo = flags & allExceptKernelFcm;
659*70a7ec85SAndroid Build Coastguard Worker         if (needDeviceRuntimeInfo) {
660*70a7ec85SAndroid Build Coastguard Worker             mDeviceRuntimeInfo.fetchedFlags &= (~flags);  // mark the fields as "not fetched"
661*70a7ec85SAndroid Build Coastguard Worker             return nullptr;
662*70a7ec85SAndroid Build Coastguard Worker         }
663*70a7ec85SAndroid Build Coastguard Worker     }
664*70a7ec85SAndroid Build Coastguard Worker 
665*70a7ec85SAndroid Build Coastguard Worker     // To support devices without GKI, RuntimeInfo::fetchAllInformation does not report errors
666*70a7ec85SAndroid Build Coastguard Worker     // if kernel level cannot be retrieved. If so, fetch kernel FCM version from device HAL
667*70a7ec85SAndroid Build Coastguard Worker     // manifest and store it in RuntimeInfo too.
668*70a7ec85SAndroid Build Coastguard Worker     if (flags & RuntimeInfo::FetchFlag::KERNEL_FCM) {
669*70a7ec85SAndroid Build Coastguard Worker         Level deviceManifestKernelLevel = Level::UNSPECIFIED;
670*70a7ec85SAndroid Build Coastguard Worker         auto manifest = getDeviceHalManifest();
671*70a7ec85SAndroid Build Coastguard Worker         if (manifest) {
672*70a7ec85SAndroid Build Coastguard Worker             deviceManifestKernelLevel = manifest->inferredKernelLevel();
673*70a7ec85SAndroid Build Coastguard Worker         }
674*70a7ec85SAndroid Build Coastguard Worker         if (deviceManifestKernelLevel != Level::UNSPECIFIED) {
675*70a7ec85SAndroid Build Coastguard Worker             Level kernelLevel = mDeviceRuntimeInfo.object->kernelLevel();
676*70a7ec85SAndroid Build Coastguard Worker             if (kernelLevel == Level::UNSPECIFIED) {
677*70a7ec85SAndroid Build Coastguard Worker                 mDeviceRuntimeInfo.object->setKernelLevel(deviceManifestKernelLevel);
678*70a7ec85SAndroid Build Coastguard Worker             } else if (kernelLevel != deviceManifestKernelLevel) {
679*70a7ec85SAndroid Build Coastguard Worker                 LOG(WARNING) << "uname() reports kernel level " << kernelLevel
680*70a7ec85SAndroid Build Coastguard Worker                              << " but device manifest sets kernel level "
681*70a7ec85SAndroid Build Coastguard Worker                              << deviceManifestKernelLevel << ". Using kernel level " << kernelLevel;
682*70a7ec85SAndroid Build Coastguard Worker             }
683*70a7ec85SAndroid Build Coastguard Worker         }
684*70a7ec85SAndroid Build Coastguard Worker     }
685*70a7ec85SAndroid Build Coastguard Worker 
686*70a7ec85SAndroid Build Coastguard Worker     mDeviceRuntimeInfo.fetchedFlags |= flags;
687*70a7ec85SAndroid Build Coastguard Worker     return mDeviceRuntimeInfo.object;
688*70a7ec85SAndroid Build Coastguard Worker }
689*70a7ec85SAndroid Build Coastguard Worker 
checkCompatibility(std::string * error,CheckFlags::Type flags)690*70a7ec85SAndroid Build Coastguard Worker int32_t VintfObject::checkCompatibility(std::string* error, CheckFlags::Type flags) {
691*70a7ec85SAndroid Build Coastguard Worker     status_t status = OK;
692*70a7ec85SAndroid Build Coastguard Worker     // null checks for files and runtime info
693*70a7ec85SAndroid Build Coastguard Worker     if (getFrameworkHalManifest() == nullptr) {
694*70a7ec85SAndroid Build Coastguard Worker         appendLine(error, "No framework manifest file from device or from update package");
695*70a7ec85SAndroid Build Coastguard Worker         status = NO_INIT;
696*70a7ec85SAndroid Build Coastguard Worker     }
697*70a7ec85SAndroid Build Coastguard Worker     if (getDeviceHalManifest() == nullptr) {
698*70a7ec85SAndroid Build Coastguard Worker         appendLine(error, "No device manifest file from device or from update package");
699*70a7ec85SAndroid Build Coastguard Worker         status = NO_INIT;
700*70a7ec85SAndroid Build Coastguard Worker     }
701*70a7ec85SAndroid Build Coastguard Worker     if (getFrameworkCompatibilityMatrix() == nullptr) {
702*70a7ec85SAndroid Build Coastguard Worker         appendLine(error, "No framework matrix file from device or from update package");
703*70a7ec85SAndroid Build Coastguard Worker         status = NO_INIT;
704*70a7ec85SAndroid Build Coastguard Worker     }
705*70a7ec85SAndroid Build Coastguard Worker     if (getDeviceCompatibilityMatrix() == nullptr) {
706*70a7ec85SAndroid Build Coastguard Worker         appendLine(error, "No device matrix file from device or from update package");
707*70a7ec85SAndroid Build Coastguard Worker         status = NO_INIT;
708*70a7ec85SAndroid Build Coastguard Worker     }
709*70a7ec85SAndroid Build Coastguard Worker 
710*70a7ec85SAndroid Build Coastguard Worker     if (flags.isRuntimeInfoEnabled()) {
711*70a7ec85SAndroid Build Coastguard Worker         if (getRuntimeInfo() == nullptr) {
712*70a7ec85SAndroid Build Coastguard Worker             appendLine(error, "No runtime info from device");
713*70a7ec85SAndroid Build Coastguard Worker             status = NO_INIT;
714*70a7ec85SAndroid Build Coastguard Worker         }
715*70a7ec85SAndroid Build Coastguard Worker     }
716*70a7ec85SAndroid Build Coastguard Worker     if (status != OK) return status;
717*70a7ec85SAndroid Build Coastguard Worker 
718*70a7ec85SAndroid Build Coastguard Worker     // compatiblity check.
719*70a7ec85SAndroid Build Coastguard Worker     if (!getDeviceHalManifest()->checkCompatibility(*getFrameworkCompatibilityMatrix(), error)) {
720*70a7ec85SAndroid Build Coastguard Worker         if (error) {
721*70a7ec85SAndroid Build Coastguard Worker             error->insert(0,
722*70a7ec85SAndroid Build Coastguard Worker                           "Device manifest and framework compatibility matrix are incompatible: ");
723*70a7ec85SAndroid Build Coastguard Worker         }
724*70a7ec85SAndroid Build Coastguard Worker         return INCOMPATIBLE;
725*70a7ec85SAndroid Build Coastguard Worker     }
726*70a7ec85SAndroid Build Coastguard Worker     if (!getFrameworkHalManifest()->checkCompatibility(*getDeviceCompatibilityMatrix(), error)) {
727*70a7ec85SAndroid Build Coastguard Worker         if (error) {
728*70a7ec85SAndroid Build Coastguard Worker             error->insert(0,
729*70a7ec85SAndroid Build Coastguard Worker                           "Framework manifest and device compatibility matrix are incompatible: ");
730*70a7ec85SAndroid Build Coastguard Worker         }
731*70a7ec85SAndroid Build Coastguard Worker         return INCOMPATIBLE;
732*70a7ec85SAndroid Build Coastguard Worker     }
733*70a7ec85SAndroid Build Coastguard Worker 
734*70a7ec85SAndroid Build Coastguard Worker     if (flags.isRuntimeInfoEnabled()) {
735*70a7ec85SAndroid Build Coastguard Worker         if (!getRuntimeInfo()->checkCompatibility(*getFrameworkCompatibilityMatrix(), error,
736*70a7ec85SAndroid Build Coastguard Worker                                                   flags)) {
737*70a7ec85SAndroid Build Coastguard Worker             if (error) {
738*70a7ec85SAndroid Build Coastguard Worker                 error->insert(0,
739*70a7ec85SAndroid Build Coastguard Worker                               "Runtime info and framework compatibility matrix are incompatible: ");
740*70a7ec85SAndroid Build Coastguard Worker             }
741*70a7ec85SAndroid Build Coastguard Worker             return INCOMPATIBLE;
742*70a7ec85SAndroid Build Coastguard Worker         }
743*70a7ec85SAndroid Build Coastguard Worker     }
744*70a7ec85SAndroid Build Coastguard Worker 
745*70a7ec85SAndroid Build Coastguard Worker     return COMPATIBLE;
746*70a7ec85SAndroid Build Coastguard Worker }
747*70a7ec85SAndroid Build Coastguard Worker 
748*70a7ec85SAndroid Build Coastguard Worker namespace details {
749*70a7ec85SAndroid Build Coastguard Worker 
dumpFileList(const std::string & sku)750*70a7ec85SAndroid Build Coastguard Worker std::vector<std::string> dumpFileList(const std::string& sku) {
751*70a7ec85SAndroid Build Coastguard Worker     std::vector<std::string> list = {
752*70a7ec85SAndroid Build Coastguard Worker         // clang-format off
753*70a7ec85SAndroid Build Coastguard Worker         kSystemVintfDir,
754*70a7ec85SAndroid Build Coastguard Worker         kVendorVintfDir,
755*70a7ec85SAndroid Build Coastguard Worker         kOdmVintfDir,
756*70a7ec85SAndroid Build Coastguard Worker         kProductVintfDir,
757*70a7ec85SAndroid Build Coastguard Worker         kSystemExtVintfDir,
758*70a7ec85SAndroid Build Coastguard Worker         kOdmLegacyManifest,
759*70a7ec85SAndroid Build Coastguard Worker         kVendorLegacyManifest,
760*70a7ec85SAndroid Build Coastguard Worker         kVendorLegacyMatrix,
761*70a7ec85SAndroid Build Coastguard Worker         kSystemLegacyManifest,
762*70a7ec85SAndroid Build Coastguard Worker         kSystemLegacyMatrix,
763*70a7ec85SAndroid Build Coastguard Worker         // clang-format on
764*70a7ec85SAndroid Build Coastguard Worker     };
765*70a7ec85SAndroid Build Coastguard Worker     if (!sku.empty()) {
766*70a7ec85SAndroid Build Coastguard Worker         list.push_back(getOdmProductManifestFile(kOdmLegacyVintfDir, sku));
767*70a7ec85SAndroid Build Coastguard Worker     }
768*70a7ec85SAndroid Build Coastguard Worker     return list;
769*70a7ec85SAndroid Build Coastguard Worker }
770*70a7ec85SAndroid Build Coastguard Worker 
771*70a7ec85SAndroid Build Coastguard Worker }  // namespace details
772*70a7ec85SAndroid Build Coastguard Worker 
IsHalDeprecated(const MatrixHal & oldMatrixHal,const std::string & oldMatrixHalFileName,const CompatibilityMatrix & targetMatrix,const std::shared_ptr<const HalManifest> & deviceManifest,const ChildrenMap & childrenMap,std::string * appendedError)773*70a7ec85SAndroid Build Coastguard Worker bool VintfObject::IsHalDeprecated(const MatrixHal& oldMatrixHal,
774*70a7ec85SAndroid Build Coastguard Worker                                   const std::string& oldMatrixHalFileName,
775*70a7ec85SAndroid Build Coastguard Worker                                   const CompatibilityMatrix& targetMatrix,
776*70a7ec85SAndroid Build Coastguard Worker                                   const std::shared_ptr<const HalManifest>& deviceManifest,
777*70a7ec85SAndroid Build Coastguard Worker                                   const ChildrenMap& childrenMap, std::string* appendedError) {
778*70a7ec85SAndroid Build Coastguard Worker     bool isDeprecated = false;
779*70a7ec85SAndroid Build Coastguard Worker     oldMatrixHal.forEachInstance([&](const MatrixInstance& oldMatrixInstance) {
780*70a7ec85SAndroid Build Coastguard Worker         if (IsInstanceDeprecated(oldMatrixInstance, oldMatrixHalFileName, targetMatrix,
781*70a7ec85SAndroid Build Coastguard Worker                                  deviceManifest, childrenMap, appendedError)) {
782*70a7ec85SAndroid Build Coastguard Worker             isDeprecated = true;
783*70a7ec85SAndroid Build Coastguard Worker         }
784*70a7ec85SAndroid Build Coastguard Worker         return true;  // continue to check next instance
785*70a7ec85SAndroid Build Coastguard Worker     });
786*70a7ec85SAndroid Build Coastguard Worker     return isDeprecated;
787*70a7ec85SAndroid Build Coastguard Worker }
788*70a7ec85SAndroid Build Coastguard Worker 
789*70a7ec85SAndroid Build Coastguard Worker // Let oldMatrixInstance = [email protected]::interface/instancePattern.
790*70a7ec85SAndroid Build Coastguard Worker // If any "@servedVersion::interface/servedInstance" in deviceManifest([email protected]::interface)
791*70a7ec85SAndroid Build Coastguard Worker // matches instancePattern, return true iff for all child interfaces (from
792*70a7ec85SAndroid Build Coastguard Worker // GetListedInstanceInheritance), IsFqInstanceDeprecated returns false.
IsInstanceDeprecated(const MatrixInstance & oldMatrixInstance,const std::string & oldMatrixInstanceFileName,const CompatibilityMatrix & targetMatrix,const std::shared_ptr<const HalManifest> & deviceManifest,const ChildrenMap & childrenMap,std::string * appendedError)793*70a7ec85SAndroid Build Coastguard Worker bool VintfObject::IsInstanceDeprecated(const MatrixInstance& oldMatrixInstance,
794*70a7ec85SAndroid Build Coastguard Worker                                        const std::string& oldMatrixInstanceFileName,
795*70a7ec85SAndroid Build Coastguard Worker                                        const CompatibilityMatrix& targetMatrix,
796*70a7ec85SAndroid Build Coastguard Worker                                        const std::shared_ptr<const HalManifest>& deviceManifest,
797*70a7ec85SAndroid Build Coastguard Worker                                        const ChildrenMap& childrenMap, std::string* appendedError) {
798*70a7ec85SAndroid Build Coastguard Worker     const std::string& package = oldMatrixInstance.package();
799*70a7ec85SAndroid Build Coastguard Worker     const Version& version = oldMatrixInstance.versionRange().minVer();
800*70a7ec85SAndroid Build Coastguard Worker     const std::string& interface = oldMatrixInstance.interface();
801*70a7ec85SAndroid Build Coastguard Worker 
802*70a7ec85SAndroid Build Coastguard Worker     std::vector<std::string> accumulatedErrors;
803*70a7ec85SAndroid Build Coastguard Worker 
804*70a7ec85SAndroid Build Coastguard Worker     auto addErrorForInstance = [&](const ManifestInstance& manifestInstance) {
805*70a7ec85SAndroid Build Coastguard Worker         const std::string& servedInstance = manifestInstance.instance();
806*70a7ec85SAndroid Build Coastguard Worker         Version servedVersion = manifestInstance.version();
807*70a7ec85SAndroid Build Coastguard Worker         if (!oldMatrixInstance.matchInstance(servedInstance)) {
808*70a7ec85SAndroid Build Coastguard Worker             // ignore unrelated instance
809*70a7ec85SAndroid Build Coastguard Worker             return true;  // continue
810*70a7ec85SAndroid Build Coastguard Worker         }
811*70a7ec85SAndroid Build Coastguard Worker 
812*70a7ec85SAndroid Build Coastguard Worker         auto inheritance = GetListedInstanceInheritance(
813*70a7ec85SAndroid Build Coastguard Worker             oldMatrixInstance.format(), oldMatrixInstance.exclusiveTo(), package, servedVersion,
814*70a7ec85SAndroid Build Coastguard Worker             interface, servedInstance, deviceManifest, childrenMap);
815*70a7ec85SAndroid Build Coastguard Worker         if (!inheritance.has_value()) {
816*70a7ec85SAndroid Build Coastguard Worker             accumulatedErrors.push_back(inheritance.error().message());
817*70a7ec85SAndroid Build Coastguard Worker             return true;  // continue
818*70a7ec85SAndroid Build Coastguard Worker         }
819*70a7ec85SAndroid Build Coastguard Worker 
820*70a7ec85SAndroid Build Coastguard Worker         std::vector<std::string> errors;
821*70a7ec85SAndroid Build Coastguard Worker         for (const auto& fqInstance : *inheritance) {
822*70a7ec85SAndroid Build Coastguard Worker             auto result =
823*70a7ec85SAndroid Build Coastguard Worker                 IsFqInstanceDeprecated(targetMatrix, oldMatrixInstance.format(),
824*70a7ec85SAndroid Build Coastguard Worker                                        oldMatrixInstance.exclusiveTo(), fqInstance, deviceManifest);
825*70a7ec85SAndroid Build Coastguard Worker             if (result.ok()) {
826*70a7ec85SAndroid Build Coastguard Worker                 errors.clear();
827*70a7ec85SAndroid Build Coastguard Worker                 break;
828*70a7ec85SAndroid Build Coastguard Worker             }
829*70a7ec85SAndroid Build Coastguard Worker             std::string error = result.error().message() + "\n    ";
830*70a7ec85SAndroid Build Coastguard Worker             std::string servedFqInstanceString =
831*70a7ec85SAndroid Build Coastguard Worker                 toFQNameString(package, servedVersion, interface, servedInstance);
832*70a7ec85SAndroid Build Coastguard Worker             if (fqInstance.string() == servedFqInstanceString) {
833*70a7ec85SAndroid Build Coastguard Worker                 error += "because it matches ";
834*70a7ec85SAndroid Build Coastguard Worker             } else {
835*70a7ec85SAndroid Build Coastguard Worker                 error += "because it inherits from " + fqInstance.string() + " that matches ";
836*70a7ec85SAndroid Build Coastguard Worker             }
837*70a7ec85SAndroid Build Coastguard Worker             error += oldMatrixInstance.description(oldMatrixInstance.versionRange().minVer()) +
838*70a7ec85SAndroid Build Coastguard Worker                      " from " + oldMatrixInstanceFileName;
839*70a7ec85SAndroid Build Coastguard Worker             errors.push_back(error);
840*70a7ec85SAndroid Build Coastguard Worker             // Do not immediately think (package, servedVersion, interface, servedInstance)
841*70a7ec85SAndroid Build Coastguard Worker             // is deprecated; check parents too.
842*70a7ec85SAndroid Build Coastguard Worker         }
843*70a7ec85SAndroid Build Coastguard Worker 
844*70a7ec85SAndroid Build Coastguard Worker         if (errors.empty()) {
845*70a7ec85SAndroid Build Coastguard Worker             return true;  // continue
846*70a7ec85SAndroid Build Coastguard Worker         }
847*70a7ec85SAndroid Build Coastguard Worker         accumulatedErrors.insert(accumulatedErrors.end(), errors.begin(), errors.end());
848*70a7ec85SAndroid Build Coastguard Worker         return true;  // continue to next instance
849*70a7ec85SAndroid Build Coastguard Worker     };
850*70a7ec85SAndroid Build Coastguard Worker     (void)deviceManifest->forEachInstanceOfInterface(oldMatrixInstance.format(),
851*70a7ec85SAndroid Build Coastguard Worker                                                      oldMatrixInstance.exclusiveTo(), package,
852*70a7ec85SAndroid Build Coastguard Worker                                                      version, interface, addErrorForInstance);
853*70a7ec85SAndroid Build Coastguard Worker 
854*70a7ec85SAndroid Build Coastguard Worker     if (accumulatedErrors.empty()) {
855*70a7ec85SAndroid Build Coastguard Worker         return false;
856*70a7ec85SAndroid Build Coastguard Worker     }
857*70a7ec85SAndroid Build Coastguard Worker     appendLine(appendedError, android::base::Join(accumulatedErrors, "\n"));
858*70a7ec85SAndroid Build Coastguard Worker     return true;
859*70a7ec85SAndroid Build Coastguard Worker }
860*70a7ec85SAndroid Build Coastguard Worker 
861*70a7ec85SAndroid Build Coastguard Worker // Check if fqInstance is listed in |deviceManifest|.
IsInstanceListed(const std::shared_ptr<const HalManifest> & deviceManifest,HalFormat format,ExclusiveTo exclusiveTo,const FqInstance & fqInstance)862*70a7ec85SAndroid Build Coastguard Worker bool VintfObject::IsInstanceListed(const std::shared_ptr<const HalManifest>& deviceManifest,
863*70a7ec85SAndroid Build Coastguard Worker                                    HalFormat format, ExclusiveTo exclusiveTo,
864*70a7ec85SAndroid Build Coastguard Worker                                    const FqInstance& fqInstance) {
865*70a7ec85SAndroid Build Coastguard Worker     bool found = false;
866*70a7ec85SAndroid Build Coastguard Worker     (void)deviceManifest->forEachInstanceOfInterface(
867*70a7ec85SAndroid Build Coastguard Worker         format, exclusiveTo, fqInstance.getPackage(), fqInstance.getVersion(),
868*70a7ec85SAndroid Build Coastguard Worker         fqInstance.getInterface(), [&](const ManifestInstance& manifestInstance) {
869*70a7ec85SAndroid Build Coastguard Worker             if (manifestInstance.instance() == fqInstance.getInstance()) {
870*70a7ec85SAndroid Build Coastguard Worker                 found = true;
871*70a7ec85SAndroid Build Coastguard Worker             }
872*70a7ec85SAndroid Build Coastguard Worker             return !found;  // continue to next instance if not found
873*70a7ec85SAndroid Build Coastguard Worker         });
874*70a7ec85SAndroid Build Coastguard Worker     return found;
875*70a7ec85SAndroid Build Coastguard Worker }
876*70a7ec85SAndroid Build Coastguard Worker 
877*70a7ec85SAndroid Build Coastguard Worker // Return a list of FqInstance, where each element:
878*70a7ec85SAndroid Build Coastguard Worker // - is listed in |deviceManifest|; AND
879*70a7ec85SAndroid Build Coastguard Worker // - is, or inherits from, package@version::interface/instance (as specified by |childrenMap|)
GetListedInstanceInheritance(HalFormat format,ExclusiveTo exclusiveTo,const std::string & package,const Version & version,const std::string & interface,const std::string & instance,const std::shared_ptr<const HalManifest> & deviceManifest,const ChildrenMap & childrenMap)880*70a7ec85SAndroid Build Coastguard Worker android::base::Result<std::vector<FqInstance>> VintfObject::GetListedInstanceInheritance(
881*70a7ec85SAndroid Build Coastguard Worker     HalFormat format, ExclusiveTo exclusiveTo, const std::string& package, const Version& version,
882*70a7ec85SAndroid Build Coastguard Worker     const std::string& interface, const std::string& instance,
883*70a7ec85SAndroid Build Coastguard Worker     const std::shared_ptr<const HalManifest>& deviceManifest, const ChildrenMap& childrenMap) {
884*70a7ec85SAndroid Build Coastguard Worker     FqInstance fqInstance;
885*70a7ec85SAndroid Build Coastguard Worker     if (!fqInstance.setTo(package, version.majorVer, version.minorVer, interface, instance)) {
886*70a7ec85SAndroid Build Coastguard Worker         return android::base::Error() << toFQNameString(package, version, interface, instance)
887*70a7ec85SAndroid Build Coastguard Worker                                       << " is not a valid FqInstance";
888*70a7ec85SAndroid Build Coastguard Worker     }
889*70a7ec85SAndroid Build Coastguard Worker 
890*70a7ec85SAndroid Build Coastguard Worker     if (!IsInstanceListed(deviceManifest, format, exclusiveTo, fqInstance)) {
891*70a7ec85SAndroid Build Coastguard Worker         return {};
892*70a7ec85SAndroid Build Coastguard Worker     }
893*70a7ec85SAndroid Build Coastguard Worker 
894*70a7ec85SAndroid Build Coastguard Worker     const auto& fqName = fqInstance.getFqNameString();
895*70a7ec85SAndroid Build Coastguard Worker 
896*70a7ec85SAndroid Build Coastguard Worker     std::vector<FqInstance> ret;
897*70a7ec85SAndroid Build Coastguard Worker     ret.push_back(fqInstance);
898*70a7ec85SAndroid Build Coastguard Worker 
899*70a7ec85SAndroid Build Coastguard Worker     auto childRange = childrenMap.equal_range(fqName);
900*70a7ec85SAndroid Build Coastguard Worker     for (auto it = childRange.first; it != childRange.second; ++it) {
901*70a7ec85SAndroid Build Coastguard Worker         const auto& childFqNameString = it->second;
902*70a7ec85SAndroid Build Coastguard Worker         FQName childFqName;
903*70a7ec85SAndroid Build Coastguard Worker         if (!childFqName.setTo(childFqNameString)) {
904*70a7ec85SAndroid Build Coastguard Worker             return android::base::Error() << "Cannot parse " << childFqNameString << " as FQName";
905*70a7ec85SAndroid Build Coastguard Worker         }
906*70a7ec85SAndroid Build Coastguard Worker         FqInstance childFqInstance;
907*70a7ec85SAndroid Build Coastguard Worker         if (!childFqInstance.setTo(childFqName.package(), childFqName.getPackageMajorVersion(),
908*70a7ec85SAndroid Build Coastguard Worker                                    childFqName.getPackageMinorVersion(),
909*70a7ec85SAndroid Build Coastguard Worker                                    childFqName.getInterfaceName(), fqInstance.getInstance())) {
910*70a7ec85SAndroid Build Coastguard Worker             return android::base::Error() << "Cannot merge " << childFqName.string() << "/"
911*70a7ec85SAndroid Build Coastguard Worker                                           << fqInstance.getInstance() << " as FqInstance";
912*70a7ec85SAndroid Build Coastguard Worker             continue;
913*70a7ec85SAndroid Build Coastguard Worker         }
914*70a7ec85SAndroid Build Coastguard Worker         if (!IsInstanceListed(deviceManifest, format, exclusiveTo, childFqInstance)) {
915*70a7ec85SAndroid Build Coastguard Worker             continue;
916*70a7ec85SAndroid Build Coastguard Worker         }
917*70a7ec85SAndroid Build Coastguard Worker         ret.push_back(childFqInstance);
918*70a7ec85SAndroid Build Coastguard Worker     }
919*70a7ec85SAndroid Build Coastguard Worker     return ret;
920*70a7ec85SAndroid Build Coastguard Worker }
921*70a7ec85SAndroid Build Coastguard Worker 
922*70a7ec85SAndroid Build Coastguard Worker // Check if |fqInstance| is in |targetMatrix|; essentially equal to
923*70a7ec85SAndroid Build Coastguard Worker // targetMatrix.matchInstance(fqInstance), but provides richer error message. In details:
924*70a7ec85SAndroid Build Coastguard Worker // 1. package@x.?::interface/servedInstance is not in targetMatrix; OR
925*70a7ec85SAndroid Build Coastguard Worker // 2. [email protected]::interface/servedInstance is in targetMatrix but
926*70a7ec85SAndroid Build Coastguard Worker //    servedInstance is not in deviceManifest([email protected]::interface)
IsFqInstanceDeprecated(const CompatibilityMatrix & targetMatrix,HalFormat format,ExclusiveTo exclusiveTo,const FqInstance & fqInstance,const std::shared_ptr<const HalManifest> & deviceManifest)927*70a7ec85SAndroid Build Coastguard Worker android::base::Result<void> VintfObject::IsFqInstanceDeprecated(
928*70a7ec85SAndroid Build Coastguard Worker     const CompatibilityMatrix& targetMatrix, HalFormat format, ExclusiveTo exclusiveTo,
929*70a7ec85SAndroid Build Coastguard Worker     const FqInstance& fqInstance, const std::shared_ptr<const HalManifest>& deviceManifest) {
930*70a7ec85SAndroid Build Coastguard Worker     // Find minimum package@x.? in target matrix, and check if instance is in target matrix.
931*70a7ec85SAndroid Build Coastguard Worker     bool foundInstance = false;
932*70a7ec85SAndroid Build Coastguard Worker     Version targetMatrixMinVer{SIZE_MAX, SIZE_MAX};
933*70a7ec85SAndroid Build Coastguard Worker     targetMatrix.forEachInstanceOfPackage(
934*70a7ec85SAndroid Build Coastguard Worker         format, exclusiveTo, fqInstance.getPackage(), [&](const auto& targetMatrixInstance) {
935*70a7ec85SAndroid Build Coastguard Worker             if (targetMatrixInstance.versionRange().majorVer == fqInstance.getMajorVersion() &&
936*70a7ec85SAndroid Build Coastguard Worker                 targetMatrixInstance.interface() == fqInstance.getInterface() &&
937*70a7ec85SAndroid Build Coastguard Worker                 targetMatrixInstance.matchInstance(fqInstance.getInstance())) {
938*70a7ec85SAndroid Build Coastguard Worker                 targetMatrixMinVer =
939*70a7ec85SAndroid Build Coastguard Worker                     std::min(targetMatrixMinVer, targetMatrixInstance.versionRange().minVer());
940*70a7ec85SAndroid Build Coastguard Worker                 foundInstance = true;
941*70a7ec85SAndroid Build Coastguard Worker             }
942*70a7ec85SAndroid Build Coastguard Worker             return true;
943*70a7ec85SAndroid Build Coastguard Worker         });
944*70a7ec85SAndroid Build Coastguard Worker     if (!foundInstance) {
945*70a7ec85SAndroid Build Coastguard Worker         return android::base::Error()
946*70a7ec85SAndroid Build Coastguard Worker                << fqInstance.string() << " is deprecated in compatibility matrix at FCM Version "
947*70a7ec85SAndroid Build Coastguard Worker                << targetMatrix.level() << "; it should not be served.";
948*70a7ec85SAndroid Build Coastguard Worker     }
949*70a7ec85SAndroid Build Coastguard Worker 
950*70a7ec85SAndroid Build Coastguard Worker     // Assuming that targetMatrix requires @x.u-v, require that at least @x.u is served.
951*70a7ec85SAndroid Build Coastguard Worker     bool targetVersionServed = false;
952*70a7ec85SAndroid Build Coastguard Worker 
953*70a7ec85SAndroid Build Coastguard Worker     (void)deviceManifest->forEachInstanceOfInterface(
954*70a7ec85SAndroid Build Coastguard Worker         format, exclusiveTo, fqInstance.getPackage(), targetMatrixMinVer, fqInstance.getInterface(),
955*70a7ec85SAndroid Build Coastguard Worker         [&](const ManifestInstance& manifestInstance) {
956*70a7ec85SAndroid Build Coastguard Worker             if (manifestInstance.instance() == fqInstance.getInstance()) {
957*70a7ec85SAndroid Build Coastguard Worker                 targetVersionServed = true;
958*70a7ec85SAndroid Build Coastguard Worker                 return false;  // break
959*70a7ec85SAndroid Build Coastguard Worker             }
960*70a7ec85SAndroid Build Coastguard Worker             return true;  // continue
961*70a7ec85SAndroid Build Coastguard Worker         });
962*70a7ec85SAndroid Build Coastguard Worker 
963*70a7ec85SAndroid Build Coastguard Worker     if (!targetVersionServed) {
964*70a7ec85SAndroid Build Coastguard Worker         return android::base::Error()
965*70a7ec85SAndroid Build Coastguard Worker                << fqInstance.string() << " is deprecated; requires at least " << targetMatrixMinVer;
966*70a7ec85SAndroid Build Coastguard Worker     }
967*70a7ec85SAndroid Build Coastguard Worker     return {};
968*70a7ec85SAndroid Build Coastguard Worker }
969*70a7ec85SAndroid Build Coastguard Worker 
checkDeprecation(const std::vector<HidlInterfaceMetadata> & hidlMetadata,std::string * error)970*70a7ec85SAndroid Build Coastguard Worker int32_t VintfObject::checkDeprecation(const std::vector<HidlInterfaceMetadata>& hidlMetadata,
971*70a7ec85SAndroid Build Coastguard Worker                                       std::string* error) {
972*70a7ec85SAndroid Build Coastguard Worker     std::vector<CompatibilityMatrix> matrixFragments;
973*70a7ec85SAndroid Build Coastguard Worker     auto matrixFragmentsStatus = getAllFrameworkMatrixLevels(&matrixFragments, error);
974*70a7ec85SAndroid Build Coastguard Worker     if (matrixFragmentsStatus != OK) {
975*70a7ec85SAndroid Build Coastguard Worker         return matrixFragmentsStatus;
976*70a7ec85SAndroid Build Coastguard Worker     }
977*70a7ec85SAndroid Build Coastguard Worker     if (matrixFragments.empty()) {
978*70a7ec85SAndroid Build Coastguard Worker         if (error && error->empty()) {
979*70a7ec85SAndroid Build Coastguard Worker             *error = "Cannot get framework matrix for each FCM version for unknown error.";
980*70a7ec85SAndroid Build Coastguard Worker         }
981*70a7ec85SAndroid Build Coastguard Worker         return NAME_NOT_FOUND;
982*70a7ec85SAndroid Build Coastguard Worker     }
983*70a7ec85SAndroid Build Coastguard Worker     auto deviceManifest = getDeviceHalManifest();
984*70a7ec85SAndroid Build Coastguard Worker     if (deviceManifest == nullptr) {
985*70a7ec85SAndroid Build Coastguard Worker         if (error) *error = "No device manifest.";
986*70a7ec85SAndroid Build Coastguard Worker         return NAME_NOT_FOUND;
987*70a7ec85SAndroid Build Coastguard Worker     }
988*70a7ec85SAndroid Build Coastguard Worker     Level deviceLevel = deviceManifest->level();
989*70a7ec85SAndroid Build Coastguard Worker     if (deviceLevel == Level::UNSPECIFIED) {
990*70a7ec85SAndroid Build Coastguard Worker         if (error) *error = "Device manifest does not specify Shipping FCM Version.";
991*70a7ec85SAndroid Build Coastguard Worker         return BAD_VALUE;
992*70a7ec85SAndroid Build Coastguard Worker     }
993*70a7ec85SAndroid Build Coastguard Worker     std::string kernelLevelError;
994*70a7ec85SAndroid Build Coastguard Worker     Level kernelLevel = getKernelLevel(&kernelLevelError);
995*70a7ec85SAndroid Build Coastguard Worker     if (kernelLevel == Level::UNSPECIFIED) {
996*70a7ec85SAndroid Build Coastguard Worker         LOG(WARNING) << kernelLevelError;
997*70a7ec85SAndroid Build Coastguard Worker     }
998*70a7ec85SAndroid Build Coastguard Worker 
999*70a7ec85SAndroid Build Coastguard Worker     std::vector<CompatibilityMatrix> targetMatrices;
1000*70a7ec85SAndroid Build Coastguard Worker     // Partition matrixFragments into two groups, where the second group
1001*70a7ec85SAndroid Build Coastguard Worker     // contains all matrices whose level == deviceLevel.
1002*70a7ec85SAndroid Build Coastguard Worker     auto targetMatricesPartition = std::partition(
1003*70a7ec85SAndroid Build Coastguard Worker         matrixFragments.begin(), matrixFragments.end(),
1004*70a7ec85SAndroid Build Coastguard Worker         [&](const CompatibilityMatrix& matrix) { return matrix.level() != deviceLevel; });
1005*70a7ec85SAndroid Build Coastguard Worker     // Move these matrices into the targetMatrices vector...
1006*70a7ec85SAndroid Build Coastguard Worker     std::move(targetMatricesPartition, matrixFragments.end(), std::back_inserter(targetMatrices));
1007*70a7ec85SAndroid Build Coastguard Worker     if (targetMatrices.empty()) {
1008*70a7ec85SAndroid Build Coastguard Worker         if (error)
1009*70a7ec85SAndroid Build Coastguard Worker             *error = "Cannot find framework matrix at FCM version " + to_string(deviceLevel) + ".";
1010*70a7ec85SAndroid Build Coastguard Worker         return NAME_NOT_FOUND;
1011*70a7ec85SAndroid Build Coastguard Worker     }
1012*70a7ec85SAndroid Build Coastguard Worker     // so that they can be combined into one matrix for deprecation checking.
1013*70a7ec85SAndroid Build Coastguard Worker     auto targetMatrix =
1014*70a7ec85SAndroid Build Coastguard Worker         CompatibilityMatrix::combine(deviceLevel, kernelLevel, &targetMatrices, error);
1015*70a7ec85SAndroid Build Coastguard Worker     if (targetMatrix == nullptr) {
1016*70a7ec85SAndroid Build Coastguard Worker         return BAD_VALUE;
1017*70a7ec85SAndroid Build Coastguard Worker     }
1018*70a7ec85SAndroid Build Coastguard Worker 
1019*70a7ec85SAndroid Build Coastguard Worker     std::multimap<std::string, std::string> childrenMap;
1020*70a7ec85SAndroid Build Coastguard Worker     for (const auto& child : hidlMetadata) {
1021*70a7ec85SAndroid Build Coastguard Worker         for (const auto& parent : child.inherited) {
1022*70a7ec85SAndroid Build Coastguard Worker             childrenMap.emplace(parent, child.name);
1023*70a7ec85SAndroid Build Coastguard Worker         }
1024*70a7ec85SAndroid Build Coastguard Worker     }
1025*70a7ec85SAndroid Build Coastguard Worker     // AIDL does not have inheritance.
1026*70a7ec85SAndroid Build Coastguard Worker 
1027*70a7ec85SAndroid Build Coastguard Worker     // Find a list of possibly deprecated HALs by comparing |deviceManifest| with older matrices.
1028*70a7ec85SAndroid Build Coastguard Worker     // Matrices with unspecified level are considered "current".
1029*70a7ec85SAndroid Build Coastguard Worker     bool isDeprecated = false;
1030*70a7ec85SAndroid Build Coastguard Worker     for (auto it = matrixFragments.begin(); it < targetMatricesPartition; ++it) {
1031*70a7ec85SAndroid Build Coastguard Worker         const auto& namedMatrix = *it;
1032*70a7ec85SAndroid Build Coastguard Worker         if (namedMatrix.level() == Level::UNSPECIFIED) continue;
1033*70a7ec85SAndroid Build Coastguard Worker         if (namedMatrix.level() > deviceLevel) continue;
1034*70a7ec85SAndroid Build Coastguard Worker         for (const MatrixHal& hal : namedMatrix.getHals()) {
1035*70a7ec85SAndroid Build Coastguard Worker             if (IsHalDeprecated(hal, namedMatrix.fileName(), *targetMatrix, deviceManifest,
1036*70a7ec85SAndroid Build Coastguard Worker                                 childrenMap, error)) {
1037*70a7ec85SAndroid Build Coastguard Worker                 isDeprecated = true;
1038*70a7ec85SAndroid Build Coastguard Worker             }
1039*70a7ec85SAndroid Build Coastguard Worker         }
1040*70a7ec85SAndroid Build Coastguard Worker     }
1041*70a7ec85SAndroid Build Coastguard Worker 
1042*70a7ec85SAndroid Build Coastguard Worker     return isDeprecated ? DEPRECATED : NO_DEPRECATED_HALS;
1043*70a7ec85SAndroid Build Coastguard Worker }
1044*70a7ec85SAndroid Build Coastguard Worker 
getKernelLevel(std::string * error)1045*70a7ec85SAndroid Build Coastguard Worker Level VintfObject::getKernelLevel(std::string* error) {
1046*70a7ec85SAndroid Build Coastguard Worker     auto runtimeInfo = getRuntimeInfo(RuntimeInfo::FetchFlag::KERNEL_FCM);
1047*70a7ec85SAndroid Build Coastguard Worker     if (!runtimeInfo) {
1048*70a7ec85SAndroid Build Coastguard Worker         if (error) *error = "Cannot retrieve runtime info with kernel level.";
1049*70a7ec85SAndroid Build Coastguard Worker         return Level::UNSPECIFIED;
1050*70a7ec85SAndroid Build Coastguard Worker     }
1051*70a7ec85SAndroid Build Coastguard Worker     if (runtimeInfo->kernelLevel() != Level::UNSPECIFIED) {
1052*70a7ec85SAndroid Build Coastguard Worker         return runtimeInfo->kernelLevel();
1053*70a7ec85SAndroid Build Coastguard Worker     }
1054*70a7ec85SAndroid Build Coastguard Worker     if (error) {
1055*70a7ec85SAndroid Build Coastguard Worker         *error = "Both device manifest and kernel release do not specify kernel FCM version.";
1056*70a7ec85SAndroid Build Coastguard Worker     }
1057*70a7ec85SAndroid Build Coastguard Worker     return Level::UNSPECIFIED;
1058*70a7ec85SAndroid Build Coastguard Worker }
1059*70a7ec85SAndroid Build Coastguard Worker 
getFileSystem()1060*70a7ec85SAndroid Build Coastguard Worker const std::unique_ptr<FileSystem>& VintfObject::getFileSystem() {
1061*70a7ec85SAndroid Build Coastguard Worker     return mFileSystem;
1062*70a7ec85SAndroid Build Coastguard Worker }
1063*70a7ec85SAndroid Build Coastguard Worker 
getPropertyFetcher()1064*70a7ec85SAndroid Build Coastguard Worker const std::unique_ptr<PropertyFetcher>& VintfObject::getPropertyFetcher() {
1065*70a7ec85SAndroid Build Coastguard Worker     return mPropertyFetcher;
1066*70a7ec85SAndroid Build Coastguard Worker }
1067*70a7ec85SAndroid Build Coastguard Worker 
getRuntimeInfoFactory()1068*70a7ec85SAndroid Build Coastguard Worker const std::unique_ptr<ObjectFactory<RuntimeInfo>>& VintfObject::getRuntimeInfoFactory() {
1069*70a7ec85SAndroid Build Coastguard Worker     return mRuntimeInfoFactory;
1070*70a7ec85SAndroid Build Coastguard Worker }
1071*70a7ec85SAndroid Build Coastguard Worker 
hasFrameworkCompatibilityMatrixExtensions()1072*70a7ec85SAndroid Build Coastguard Worker android::base::Result<bool> VintfObject::hasFrameworkCompatibilityMatrixExtensions() {
1073*70a7ec85SAndroid Build Coastguard Worker     std::vector<CompatibilityMatrix> matrixFragments;
1074*70a7ec85SAndroid Build Coastguard Worker     std::string error;
1075*70a7ec85SAndroid Build Coastguard Worker     status_t status = getAllFrameworkMatrixLevels(&matrixFragments, &error);
1076*70a7ec85SAndroid Build Coastguard Worker     if (status != OK) {
1077*70a7ec85SAndroid Build Coastguard Worker         return android::base::Error(-status)
1078*70a7ec85SAndroid Build Coastguard Worker                << "Cannot get all framework matrix fragments: " << error;
1079*70a7ec85SAndroid Build Coastguard Worker     }
1080*70a7ec85SAndroid Build Coastguard Worker     for (const auto& namedMatrix : matrixFragments) {
1081*70a7ec85SAndroid Build Coastguard Worker         // Returns true if product matrix exists.
1082*70a7ec85SAndroid Build Coastguard Worker         if (android::base::StartsWith(namedMatrix.fileName(), kProductVintfDir)) {
1083*70a7ec85SAndroid Build Coastguard Worker             return true;
1084*70a7ec85SAndroid Build Coastguard Worker         }
1085*70a7ec85SAndroid Build Coastguard Worker         // Returns true if system_ext matrix exists.
1086*70a7ec85SAndroid Build Coastguard Worker         if (android::base::StartsWith(namedMatrix.fileName(), kSystemExtVintfDir)) {
1087*70a7ec85SAndroid Build Coastguard Worker             return true;
1088*70a7ec85SAndroid Build Coastguard Worker         }
1089*70a7ec85SAndroid Build Coastguard Worker         // Returns true if device system matrix exists.
1090*70a7ec85SAndroid Build Coastguard Worker         if (android::base::StartsWith(namedMatrix.fileName(), kSystemVintfDir) &&
1091*70a7ec85SAndroid Build Coastguard Worker             namedMatrix.level() == Level::UNSPECIFIED && !namedMatrix.getHals().empty()) {
1092*70a7ec85SAndroid Build Coastguard Worker             return true;
1093*70a7ec85SAndroid Build Coastguard Worker         }
1094*70a7ec85SAndroid Build Coastguard Worker     }
1095*70a7ec85SAndroid Build Coastguard Worker     return false;
1096*70a7ec85SAndroid Build Coastguard Worker }
1097*70a7ec85SAndroid Build Coastguard Worker 
checkUnusedHals(const std::vector<HidlInterfaceMetadata> & hidlMetadata)1098*70a7ec85SAndroid Build Coastguard Worker android::base::Result<void> VintfObject::checkUnusedHals(
1099*70a7ec85SAndroid Build Coastguard Worker     const std::vector<HidlInterfaceMetadata>& hidlMetadata) {
1100*70a7ec85SAndroid Build Coastguard Worker     auto matrix = getFrameworkCompatibilityMatrix();
1101*70a7ec85SAndroid Build Coastguard Worker     if (matrix == nullptr) {
1102*70a7ec85SAndroid Build Coastguard Worker         return android::base::Error(-NAME_NOT_FOUND) << "Missing framework matrix.";
1103*70a7ec85SAndroid Build Coastguard Worker     }
1104*70a7ec85SAndroid Build Coastguard Worker     auto manifest = getDeviceHalManifest();
1105*70a7ec85SAndroid Build Coastguard Worker     if (manifest == nullptr) {
1106*70a7ec85SAndroid Build Coastguard Worker         return android::base::Error(-NAME_NOT_FOUND) << "Missing device manifest.";
1107*70a7ec85SAndroid Build Coastguard Worker     }
1108*70a7ec85SAndroid Build Coastguard Worker     auto unused = manifest->checkUnusedHals(*matrix, hidlMetadata);
1109*70a7ec85SAndroid Build Coastguard Worker     if (!unused.empty()) {
1110*70a7ec85SAndroid Build Coastguard Worker         return android::base::Error()
1111*70a7ec85SAndroid Build Coastguard Worker                << "The following instances are in the device manifest but "
1112*70a7ec85SAndroid Build Coastguard Worker                << "not specified in framework compatibility matrix: \n"
1113*70a7ec85SAndroid Build Coastguard Worker                << "    " << android::base::Join(unused, "\n    ") << "\n"
1114*70a7ec85SAndroid Build Coastguard Worker                << "Suggested fix:\n"
1115*70a7ec85SAndroid Build Coastguard Worker                << "1. Update deprecated HALs to the latest version.\n"
1116*70a7ec85SAndroid Build Coastguard Worker                << "2. Check for any typos in device manifest or framework compatibility "
1117*70a7ec85SAndroid Build Coastguard Worker                << "matrices with FCM version >= " << matrix->level() << ".\n"
1118*70a7ec85SAndroid Build Coastguard Worker                << "3. For new platform HALs, add them to any framework compatibility matrix "
1119*70a7ec85SAndroid Build Coastguard Worker                << "with FCM version >= " << matrix->level() << " where applicable.\n"
1120*70a7ec85SAndroid Build Coastguard Worker                << "4. For device-specific HALs, add to DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE "
1121*70a7ec85SAndroid Build Coastguard Worker                << "or DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE.";
1122*70a7ec85SAndroid Build Coastguard Worker     }
1123*70a7ec85SAndroid Build Coastguard Worker     return {};
1124*70a7ec85SAndroid Build Coastguard Worker }
1125*70a7ec85SAndroid Build Coastguard Worker 
1126*70a7ec85SAndroid Build Coastguard Worker namespace {
1127*70a7ec85SAndroid Build Coastguard Worker 
1128*70a7ec85SAndroid Build Coastguard Worker // Insert |name| into |ret| if shouldCheck(name).
InsertIf(const std::string & name,const std::function<bool (const std::string &)> & shouldCheck,std::set<std::string> * ret)1129*70a7ec85SAndroid Build Coastguard Worker void InsertIf(const std::string& name, const std::function<bool(const std::string&)>& shouldCheck,
1130*70a7ec85SAndroid Build Coastguard Worker               std::set<std::string>* ret) {
1131*70a7ec85SAndroid Build Coastguard Worker     if (shouldCheck(name)) ret->insert(name);
1132*70a7ec85SAndroid Build Coastguard Worker }
1133*70a7ec85SAndroid Build Coastguard Worker 
StripHidlInterface(const std::string & fqNameString)1134*70a7ec85SAndroid Build Coastguard Worker std::string StripHidlInterface(const std::string& fqNameString) {
1135*70a7ec85SAndroid Build Coastguard Worker     FQName fqName;
1136*70a7ec85SAndroid Build Coastguard Worker     if (!fqName.setTo(fqNameString)) {
1137*70a7ec85SAndroid Build Coastguard Worker         return "";
1138*70a7ec85SAndroid Build Coastguard Worker     }
1139*70a7ec85SAndroid Build Coastguard Worker     return fqName.getPackageAndVersion().string();
1140*70a7ec85SAndroid Build Coastguard Worker }
1141*70a7ec85SAndroid Build Coastguard Worker 
1142*70a7ec85SAndroid Build Coastguard Worker // StripAidlType(android.hardware.foo.IFoo)
1143*70a7ec85SAndroid Build Coastguard Worker // -> android.hardware.foo
StripAidlType(const std::string & type)1144*70a7ec85SAndroid Build Coastguard Worker std::string StripAidlType(const std::string& type) {
1145*70a7ec85SAndroid Build Coastguard Worker     auto items = android::base::Split(type, ".");
1146*70a7ec85SAndroid Build Coastguard Worker     if (items.empty()) {
1147*70a7ec85SAndroid Build Coastguard Worker         return "";
1148*70a7ec85SAndroid Build Coastguard Worker     }
1149*70a7ec85SAndroid Build Coastguard Worker     items.erase(items.end() - 1);
1150*70a7ec85SAndroid Build Coastguard Worker     return android::base::Join(items, ".");
1151*70a7ec85SAndroid Build Coastguard Worker }
1152*70a7ec85SAndroid Build Coastguard Worker 
1153*70a7ec85SAndroid Build Coastguard Worker // GetAidlPackageAndVersion(android.hardware.foo.IFoo, 1)
1154*70a7ec85SAndroid Build Coastguard Worker // -> android.hardware.foo@1
GetAidlPackageAndVersion(const std::string & package,size_t version)1155*70a7ec85SAndroid Build Coastguard Worker std::string GetAidlPackageAndVersion(const std::string& package, size_t version) {
1156*70a7ec85SAndroid Build Coastguard Worker     return package + "@" + std::to_string(version);
1157*70a7ec85SAndroid Build Coastguard Worker }
1158*70a7ec85SAndroid Build Coastguard Worker 
1159*70a7ec85SAndroid Build Coastguard Worker // [email protected]
HidlMetadataToPackagesAndVersions(const std::vector<HidlInterfaceMetadata> & hidlMetadata,const std::function<bool (const std::string &)> & shouldCheck)1160*70a7ec85SAndroid Build Coastguard Worker std::set<std::string> HidlMetadataToPackagesAndVersions(
1161*70a7ec85SAndroid Build Coastguard Worker     const std::vector<HidlInterfaceMetadata>& hidlMetadata,
1162*70a7ec85SAndroid Build Coastguard Worker     const std::function<bool(const std::string&)>& shouldCheck) {
1163*70a7ec85SAndroid Build Coastguard Worker     std::set<std::string> ret;
1164*70a7ec85SAndroid Build Coastguard Worker     for (const auto& item : hidlMetadata) {
1165*70a7ec85SAndroid Build Coastguard Worker         InsertIf(StripHidlInterface(item.name), shouldCheck, &ret);
1166*70a7ec85SAndroid Build Coastguard Worker     }
1167*70a7ec85SAndroid Build Coastguard Worker     return ret;
1168*70a7ec85SAndroid Build Coastguard Worker }
1169*70a7ec85SAndroid Build Coastguard Worker 
1170*70a7ec85SAndroid Build Coastguard Worker // android.hardware.foo@1
1171*70a7ec85SAndroid Build Coastguard Worker // All non-vintf stable interfaces are filtered out.
AidlMetadataToVintfPackagesAndVersions(const std::vector<AidlInterfaceMetadata> & aidlMetadata,const std::function<bool (const std::string &)> & shouldCheck)1172*70a7ec85SAndroid Build Coastguard Worker android::base::Result<std::set<std::string>> AidlMetadataToVintfPackagesAndVersions(
1173*70a7ec85SAndroid Build Coastguard Worker     const std::vector<AidlInterfaceMetadata>& aidlMetadata,
1174*70a7ec85SAndroid Build Coastguard Worker     const std::function<bool(const std::string&)>& shouldCheck) {
1175*70a7ec85SAndroid Build Coastguard Worker     std::set<std::string> ret;
1176*70a7ec85SAndroid Build Coastguard Worker     for (const auto& item : aidlMetadata) {
1177*70a7ec85SAndroid Build Coastguard Worker         if (item.stability != "vintf") {
1178*70a7ec85SAndroid Build Coastguard Worker             continue;
1179*70a7ec85SAndroid Build Coastguard Worker         }
1180*70a7ec85SAndroid Build Coastguard Worker         for (const auto& type : item.types) {
1181*70a7ec85SAndroid Build Coastguard Worker             auto package = StripAidlType(type);
1182*70a7ec85SAndroid Build Coastguard Worker             for (const auto& version : item.versions) {
1183*70a7ec85SAndroid Build Coastguard Worker                 InsertIf(GetAidlPackageAndVersion(package, version), shouldCheck, &ret);
1184*70a7ec85SAndroid Build Coastguard Worker             }
1185*70a7ec85SAndroid Build Coastguard Worker             if (item.has_development) {
1186*70a7ec85SAndroid Build Coastguard Worker                 auto maxVerIt = std::max_element(item.versions.begin(), item.versions.end());
1187*70a7ec85SAndroid Build Coastguard Worker                 // If no frozen versions, the in-development version is 1.
1188*70a7ec85SAndroid Build Coastguard Worker                 size_t maxVer = maxVerIt == item.versions.end() ? 0 : *maxVerIt;
1189*70a7ec85SAndroid Build Coastguard Worker                 auto nextVer = maxVer + 1;
1190*70a7ec85SAndroid Build Coastguard Worker                 if (nextVer < maxVer) {
1191*70a7ec85SAndroid Build Coastguard Worker                     return android::base::Error()
1192*70a7ec85SAndroid Build Coastguard Worker                            << "Bad version " << maxVer << " for AIDL type " << type
1193*70a7ec85SAndroid Build Coastguard Worker                            << "; integer overflow when inferring in-development version";
1194*70a7ec85SAndroid Build Coastguard Worker                 }
1195*70a7ec85SAndroid Build Coastguard Worker                 InsertIf(GetAidlPackageAndVersion(package, nextVer), shouldCheck, &ret);
1196*70a7ec85SAndroid Build Coastguard Worker             }
1197*70a7ec85SAndroid Build Coastguard Worker         }
1198*70a7ec85SAndroid Build Coastguard Worker     }
1199*70a7ec85SAndroid Build Coastguard Worker     return ret;
1200*70a7ec85SAndroid Build Coastguard Worker }
1201*70a7ec85SAndroid Build Coastguard Worker 
1202*70a7ec85SAndroid Build Coastguard Worker // [email protected]::IFoo.
1203*70a7ec85SAndroid Build Coastguard Worker // Note that UDTs are not filtered out, so there might be non-interface types.
HidlMetadataToNames(const std::vector<HidlInterfaceMetadata> & hidlMetadata)1204*70a7ec85SAndroid Build Coastguard Worker std::set<std::string> HidlMetadataToNames(const std::vector<HidlInterfaceMetadata>& hidlMetadata) {
1205*70a7ec85SAndroid Build Coastguard Worker     std::set<std::string> ret;
1206*70a7ec85SAndroid Build Coastguard Worker     for (const auto& item : hidlMetadata) {
1207*70a7ec85SAndroid Build Coastguard Worker         ret.insert(item.name);
1208*70a7ec85SAndroid Build Coastguard Worker     }
1209*70a7ec85SAndroid Build Coastguard Worker     return ret;
1210*70a7ec85SAndroid Build Coastguard Worker }
1211*70a7ec85SAndroid Build Coastguard Worker 
1212*70a7ec85SAndroid Build Coastguard Worker // android.hardware.foo.IFoo
1213*70a7ec85SAndroid Build Coastguard Worker // Note that UDTs are not filtered out, so there might be non-interface types.
1214*70a7ec85SAndroid Build Coastguard Worker // All non-vintf stable interfaces are filtered out.
AidlMetadataToVintfNames(const std::vector<AidlInterfaceMetadata> & aidlMetadata)1215*70a7ec85SAndroid Build Coastguard Worker std::set<std::string> AidlMetadataToVintfNames(
1216*70a7ec85SAndroid Build Coastguard Worker     const std::vector<AidlInterfaceMetadata>& aidlMetadata) {
1217*70a7ec85SAndroid Build Coastguard Worker     std::set<std::string> ret;
1218*70a7ec85SAndroid Build Coastguard Worker     for (const auto& item : aidlMetadata) {
1219*70a7ec85SAndroid Build Coastguard Worker         if (item.stability == "vintf") {
1220*70a7ec85SAndroid Build Coastguard Worker             for (const auto& type : item.types) {
1221*70a7ec85SAndroid Build Coastguard Worker                 ret.insert(type);
1222*70a7ec85SAndroid Build Coastguard Worker             }
1223*70a7ec85SAndroid Build Coastguard Worker         }
1224*70a7ec85SAndroid Build Coastguard Worker     }
1225*70a7ec85SAndroid Build Coastguard Worker     return ret;
1226*70a7ec85SAndroid Build Coastguard Worker }
1227*70a7ec85SAndroid Build Coastguard Worker 
1228*70a7ec85SAndroid Build Coastguard Worker }  // anonymous namespace
1229*70a7ec85SAndroid Build Coastguard Worker 
getAllFrameworkMatrixLevels()1230*70a7ec85SAndroid Build Coastguard Worker android::base::Result<std::vector<CompatibilityMatrix>> VintfObject::getAllFrameworkMatrixLevels() {
1231*70a7ec85SAndroid Build Coastguard Worker     // Get all framework matrix fragments instead of the combined framework compatibility matrix
1232*70a7ec85SAndroid Build Coastguard Worker     // because the latter may omit interfaces from the latest FCM if device target-level is not
1233*70a7ec85SAndroid Build Coastguard Worker     // the latest.
1234*70a7ec85SAndroid Build Coastguard Worker     std::vector<CompatibilityMatrix> matrixFragments;
1235*70a7ec85SAndroid Build Coastguard Worker     std::string error;
1236*70a7ec85SAndroid Build Coastguard Worker     auto matrixFragmentsStatus = getAllFrameworkMatrixLevels(&matrixFragments, &error);
1237*70a7ec85SAndroid Build Coastguard Worker     if (matrixFragmentsStatus != OK) {
1238*70a7ec85SAndroid Build Coastguard Worker         return android::base::Error(-matrixFragmentsStatus)
1239*70a7ec85SAndroid Build Coastguard Worker                << "Unable to get all framework matrix fragments: " << error;
1240*70a7ec85SAndroid Build Coastguard Worker     }
1241*70a7ec85SAndroid Build Coastguard Worker     if (matrixFragments.empty()) {
1242*70a7ec85SAndroid Build Coastguard Worker         if (error.empty()) {
1243*70a7ec85SAndroid Build Coastguard Worker             error = "Cannot get framework matrix for each FCM version for unknown error.";
1244*70a7ec85SAndroid Build Coastguard Worker         }
1245*70a7ec85SAndroid Build Coastguard Worker         return android::base::Error(-NAME_NOT_FOUND) << error;
1246*70a7ec85SAndroid Build Coastguard Worker     }
1247*70a7ec85SAndroid Build Coastguard Worker     return matrixFragments;
1248*70a7ec85SAndroid Build Coastguard Worker }
1249*70a7ec85SAndroid Build Coastguard Worker 
1250*70a7ec85SAndroid Build Coastguard Worker // Check the compatibility matrix for the latest available AIDL interfaces only
1251*70a7ec85SAndroid Build Coastguard Worker // when AIDL_USE_UNFROZEN is defined
getCheckAidlCompatMatrix()1252*70a7ec85SAndroid Build Coastguard Worker bool VintfObject::getCheckAidlCompatMatrix() {
1253*70a7ec85SAndroid Build Coastguard Worker #ifdef AIDL_USE_UNFROZEN
1254*70a7ec85SAndroid Build Coastguard Worker     constexpr bool kAidlUseUnfrozen = true;
1255*70a7ec85SAndroid Build Coastguard Worker #else
1256*70a7ec85SAndroid Build Coastguard Worker     constexpr bool kAidlUseUnfrozen = false;
1257*70a7ec85SAndroid Build Coastguard Worker #endif
1258*70a7ec85SAndroid Build Coastguard Worker     return mFakeCheckAidlCompatibilityMatrix.value_or(kAidlUseUnfrozen);
1259*70a7ec85SAndroid Build Coastguard Worker }
1260*70a7ec85SAndroid Build Coastguard Worker 
checkMissingHalsInMatrices(const std::vector<HidlInterfaceMetadata> & hidlMetadata,const std::vector<AidlInterfaceMetadata> & aidlMetadata,std::function<bool (const std::string &)> shouldCheckHidl,std::function<bool (const std::string &)> shouldCheckAidl)1261*70a7ec85SAndroid Build Coastguard Worker android::base::Result<void> VintfObject::checkMissingHalsInMatrices(
1262*70a7ec85SAndroid Build Coastguard Worker     const std::vector<HidlInterfaceMetadata>& hidlMetadata,
1263*70a7ec85SAndroid Build Coastguard Worker     const std::vector<AidlInterfaceMetadata>& aidlMetadata,
1264*70a7ec85SAndroid Build Coastguard Worker     std::function<bool(const std::string&)> shouldCheckHidl,
1265*70a7ec85SAndroid Build Coastguard Worker     std::function<bool(const std::string&)> shouldCheckAidl) {
1266*70a7ec85SAndroid Build Coastguard Worker     auto matrixFragments = getAllFrameworkMatrixLevels();
1267*70a7ec85SAndroid Build Coastguard Worker     if (!matrixFragments.ok()) return matrixFragments.error();
1268*70a7ec85SAndroid Build Coastguard Worker 
1269*70a7ec85SAndroid Build Coastguard Worker     // Filter aidlMetadata and hidlMetadata with shouldCheck.
1270*70a7ec85SAndroid Build Coastguard Worker     auto allAidlPackagesAndVersions =
1271*70a7ec85SAndroid Build Coastguard Worker         AidlMetadataToVintfPackagesAndVersions(aidlMetadata, shouldCheckAidl);
1272*70a7ec85SAndroid Build Coastguard Worker     if (!allAidlPackagesAndVersions.ok()) return allAidlPackagesAndVersions.error();
1273*70a7ec85SAndroid Build Coastguard Worker     auto allHidlPackagesAndVersions =
1274*70a7ec85SAndroid Build Coastguard Worker         HidlMetadataToPackagesAndVersions(hidlMetadata, shouldCheckHidl);
1275*70a7ec85SAndroid Build Coastguard Worker 
1276*70a7ec85SAndroid Build Coastguard Worker     // Filter out instances in allAidlVintfPackages and allHidlPackagesAndVersions that are
1277*70a7ec85SAndroid Build Coastguard Worker     // in the matrices.
1278*70a7ec85SAndroid Build Coastguard Worker     std::vector<std::string> errors;
1279*70a7ec85SAndroid Build Coastguard Worker     for (const auto& matrix : matrixFragments.value()) {
1280*70a7ec85SAndroid Build Coastguard Worker         matrix.forEachInstance([&](const MatrixInstance& matrixInstance) {
1281*70a7ec85SAndroid Build Coastguard Worker             switch (matrixInstance.format()) {
1282*70a7ec85SAndroid Build Coastguard Worker                 case HalFormat::AIDL: {
1283*70a7ec85SAndroid Build Coastguard Worker                     for (Version v = matrixInstance.versionRange().minVer();
1284*70a7ec85SAndroid Build Coastguard Worker                          v <= matrixInstance.versionRange().maxVer(); ++v.minorVer) {
1285*70a7ec85SAndroid Build Coastguard Worker                         allAidlPackagesAndVersions->erase(
1286*70a7ec85SAndroid Build Coastguard Worker                             GetAidlPackageAndVersion(matrixInstance.package(), v.minorVer));
1287*70a7ec85SAndroid Build Coastguard Worker                     }
1288*70a7ec85SAndroid Build Coastguard Worker                     return true;  // continue to next instance
1289*70a7ec85SAndroid Build Coastguard Worker                 }
1290*70a7ec85SAndroid Build Coastguard Worker                 case HalFormat::HIDL: {
1291*70a7ec85SAndroid Build Coastguard Worker                     for (Version v = matrixInstance.versionRange().minVer();
1292*70a7ec85SAndroid Build Coastguard Worker                          v <= matrixInstance.versionRange().maxVer(); ++v.minorVer) {
1293*70a7ec85SAndroid Build Coastguard Worker                         allHidlPackagesAndVersions.erase(
1294*70a7ec85SAndroid Build Coastguard Worker                             toFQNameString(matrixInstance.package(), v));
1295*70a7ec85SAndroid Build Coastguard Worker                     }
1296*70a7ec85SAndroid Build Coastguard Worker                     return true;  // continue to next instance
1297*70a7ec85SAndroid Build Coastguard Worker                 }
1298*70a7ec85SAndroid Build Coastguard Worker                 default: {
1299*70a7ec85SAndroid Build Coastguard Worker                     for (Version v = matrixInstance.versionRange().minVer();
1300*70a7ec85SAndroid Build Coastguard Worker                          v <= matrixInstance.versionRange().maxVer(); ++v.minorVer) {
1301*70a7ec85SAndroid Build Coastguard Worker                         if (shouldCheckHidl(toFQNameString(matrixInstance.package(), v))) {
1302*70a7ec85SAndroid Build Coastguard Worker                             errors.push_back("HAL package " + matrixInstance.package() +
1303*70a7ec85SAndroid Build Coastguard Worker                                              " is not allowed to have format " +
1304*70a7ec85SAndroid Build Coastguard Worker                                              to_string(matrixInstance.format()) + ".");
1305*70a7ec85SAndroid Build Coastguard Worker                         }
1306*70a7ec85SAndroid Build Coastguard Worker                     }
1307*70a7ec85SAndroid Build Coastguard Worker                     return true;  // continue to next instance
1308*70a7ec85SAndroid Build Coastguard Worker                 }
1309*70a7ec85SAndroid Build Coastguard Worker             }
1310*70a7ec85SAndroid Build Coastguard Worker         });
1311*70a7ec85SAndroid Build Coastguard Worker     }
1312*70a7ec85SAndroid Build Coastguard Worker 
1313*70a7ec85SAndroid Build Coastguard Worker     if (!allHidlPackagesAndVersions.empty()) {
1314*70a7ec85SAndroid Build Coastguard Worker         errors.push_back(
1315*70a7ec85SAndroid Build Coastguard Worker             "The following HIDL packages are not found in any compatibility matrix fragments:\t\n" +
1316*70a7ec85SAndroid Build Coastguard Worker             android::base::Join(allHidlPackagesAndVersions, "\t\n"));
1317*70a7ec85SAndroid Build Coastguard Worker     }
1318*70a7ec85SAndroid Build Coastguard Worker     if (!allAidlPackagesAndVersions->empty() && getCheckAidlCompatMatrix()) {
1319*70a7ec85SAndroid Build Coastguard Worker         errors.push_back(
1320*70a7ec85SAndroid Build Coastguard Worker             "The following AIDL packages are not found in any compatibility matrix fragments:\t\n" +
1321*70a7ec85SAndroid Build Coastguard Worker             android::base::Join(*allAidlPackagesAndVersions, "\t\n"));
1322*70a7ec85SAndroid Build Coastguard Worker     }
1323*70a7ec85SAndroid Build Coastguard Worker 
1324*70a7ec85SAndroid Build Coastguard Worker     if (!errors.empty()) {
1325*70a7ec85SAndroid Build Coastguard Worker         return android::base::Error() << android::base::Join(errors, "\n");
1326*70a7ec85SAndroid Build Coastguard Worker     }
1327*70a7ec85SAndroid Build Coastguard Worker 
1328*70a7ec85SAndroid Build Coastguard Worker     return {};
1329*70a7ec85SAndroid Build Coastguard Worker }
1330*70a7ec85SAndroid Build Coastguard Worker 
checkMatrixHalsHasDefinition(const std::vector<HidlInterfaceMetadata> & hidlMetadata,const std::vector<AidlInterfaceMetadata> & aidlMetadata)1331*70a7ec85SAndroid Build Coastguard Worker android::base::Result<void> VintfObject::checkMatrixHalsHasDefinition(
1332*70a7ec85SAndroid Build Coastguard Worker     const std::vector<HidlInterfaceMetadata>& hidlMetadata,
1333*70a7ec85SAndroid Build Coastguard Worker     const std::vector<AidlInterfaceMetadata>& aidlMetadata) {
1334*70a7ec85SAndroid Build Coastguard Worker     auto matrixFragments = getAllFrameworkMatrixLevels();
1335*70a7ec85SAndroid Build Coastguard Worker     if (!matrixFragments.ok()) return matrixFragments.error();
1336*70a7ec85SAndroid Build Coastguard Worker 
1337*70a7ec85SAndroid Build Coastguard Worker     auto allAidlVintfNames = AidlMetadataToVintfNames(aidlMetadata);
1338*70a7ec85SAndroid Build Coastguard Worker     auto allHidlNames = HidlMetadataToNames(hidlMetadata);
1339*70a7ec85SAndroid Build Coastguard Worker     std::set<std::string> badAidlInterfaces;
1340*70a7ec85SAndroid Build Coastguard Worker     std::set<std::string> badHidlInterfaces;
1341*70a7ec85SAndroid Build Coastguard Worker 
1342*70a7ec85SAndroid Build Coastguard Worker     std::vector<std::string> errors;
1343*70a7ec85SAndroid Build Coastguard Worker     for (const auto& matrix : matrixFragments.value()) {
1344*70a7ec85SAndroid Build Coastguard Worker         if (matrix.level() == Level::UNSPECIFIED) {
1345*70a7ec85SAndroid Build Coastguard Worker             LOG(INFO) << "Skip checkMatrixHalsHasDefinition() on " << matrix.fileName()
1346*70a7ec85SAndroid Build Coastguard Worker                       << " with no level.";
1347*70a7ec85SAndroid Build Coastguard Worker             continue;
1348*70a7ec85SAndroid Build Coastguard Worker         }
1349*70a7ec85SAndroid Build Coastguard Worker 
1350*70a7ec85SAndroid Build Coastguard Worker         matrix.forEachInstance([&](const MatrixInstance& matrixInstance) {
1351*70a7ec85SAndroid Build Coastguard Worker             switch (matrixInstance.format()) {
1352*70a7ec85SAndroid Build Coastguard Worker                 case HalFormat::AIDL: {
1353*70a7ec85SAndroid Build Coastguard Worker                     auto matrixInterface =
1354*70a7ec85SAndroid Build Coastguard Worker                         toAidlFqnameString(matrixInstance.package(), matrixInstance.interface());
1355*70a7ec85SAndroid Build Coastguard Worker                     if (allAidlVintfNames.find(matrixInterface) == allAidlVintfNames.end()) {
1356*70a7ec85SAndroid Build Coastguard Worker                         errors.push_back(
1357*70a7ec85SAndroid Build Coastguard Worker                             "AIDL interface " + matrixInterface + " is referenced in " +
1358*70a7ec85SAndroid Build Coastguard Worker                             matrix.fileName() +
1359*70a7ec85SAndroid Build Coastguard Worker                             ", but there is no corresponding .aidl definition associated with an "
1360*70a7ec85SAndroid Build Coastguard Worker                             "aidl_interface module in this build. Typo?");
1361*70a7ec85SAndroid Build Coastguard Worker                     }
1362*70a7ec85SAndroid Build Coastguard Worker                     return true;  // continue to next instance
1363*70a7ec85SAndroid Build Coastguard Worker                 }
1364*70a7ec85SAndroid Build Coastguard Worker                 case HalFormat::HIDL: {
1365*70a7ec85SAndroid Build Coastguard Worker                     for (Version v = matrixInstance.versionRange().minVer();
1366*70a7ec85SAndroid Build Coastguard Worker                          v <= matrixInstance.versionRange().maxVer(); ++v.minorVer) {
1367*70a7ec85SAndroid Build Coastguard Worker                         auto matrixInterface = matrixInstance.interfaceDescription(v);
1368*70a7ec85SAndroid Build Coastguard Worker                         if (allHidlNames.find(matrixInterface) == allHidlNames.end()) {
1369*70a7ec85SAndroid Build Coastguard Worker                             errors.push_back(
1370*70a7ec85SAndroid Build Coastguard Worker                                 "HIDL interface " + matrixInterface + " is referenced in " +
1371*70a7ec85SAndroid Build Coastguard Worker                                 matrix.fileName() +
1372*70a7ec85SAndroid Build Coastguard Worker                                 ", but there is no corresponding .hal definition associated with "
1373*70a7ec85SAndroid Build Coastguard Worker                                 "a hidl_interface module in this build. Typo?");
1374*70a7ec85SAndroid Build Coastguard Worker                         }
1375*70a7ec85SAndroid Build Coastguard Worker                     }
1376*70a7ec85SAndroid Build Coastguard Worker                     return true;  // continue to next instance
1377*70a7ec85SAndroid Build Coastguard Worker                 }
1378*70a7ec85SAndroid Build Coastguard Worker                 default: {
1379*70a7ec85SAndroid Build Coastguard Worker                     // We do not have data for native HALs.
1380*70a7ec85SAndroid Build Coastguard Worker                     return true;  // continue to next instance
1381*70a7ec85SAndroid Build Coastguard Worker                 }
1382*70a7ec85SAndroid Build Coastguard Worker             }
1383*70a7ec85SAndroid Build Coastguard Worker         });
1384*70a7ec85SAndroid Build Coastguard Worker     }
1385*70a7ec85SAndroid Build Coastguard Worker 
1386*70a7ec85SAndroid Build Coastguard Worker     if (!errors.empty()) {
1387*70a7ec85SAndroid Build Coastguard Worker         return android::base::Error() << android::base::Join(errors, "\n");
1388*70a7ec85SAndroid Build Coastguard Worker     }
1389*70a7ec85SAndroid Build Coastguard Worker 
1390*70a7ec85SAndroid Build Coastguard Worker     return {};
1391*70a7ec85SAndroid Build Coastguard Worker }
1392*70a7ec85SAndroid Build Coastguard Worker 
getLatestMinLtsAtFcmVersion(Level fcmVersion)1393*70a7ec85SAndroid Build Coastguard Worker android::base::Result<KernelVersion> VintfObject::getLatestMinLtsAtFcmVersion(Level fcmVersion) {
1394*70a7ec85SAndroid Build Coastguard Worker     auto allFcms = getAllFrameworkMatrixLevels();
1395*70a7ec85SAndroid Build Coastguard Worker     if (!allFcms.ok()) return allFcms.error();
1396*70a7ec85SAndroid Build Coastguard Worker 
1397*70a7ec85SAndroid Build Coastguard Worker     // Get the max of latestKernelMinLts for all FCM fragments at |fcmVersion|.
1398*70a7ec85SAndroid Build Coastguard Worker     // Usually there's only one such fragment.
1399*70a7ec85SAndroid Build Coastguard Worker     KernelVersion foundLatestMinLts;
1400*70a7ec85SAndroid Build Coastguard Worker     for (const auto& fcm : *allFcms) {
1401*70a7ec85SAndroid Build Coastguard Worker         if (fcm.level() != fcmVersion) {
1402*70a7ec85SAndroid Build Coastguard Worker             continue;
1403*70a7ec85SAndroid Build Coastguard Worker         }
1404*70a7ec85SAndroid Build Coastguard Worker         // Note: this says "minLts", but "Latest" indicates that it is a max value.
1405*70a7ec85SAndroid Build Coastguard Worker         auto thisLatestMinLts = fcm.getLatestKernelMinLts();
1406*70a7ec85SAndroid Build Coastguard Worker         if (foundLatestMinLts < thisLatestMinLts) foundLatestMinLts = thisLatestMinLts;
1407*70a7ec85SAndroid Build Coastguard Worker     }
1408*70a7ec85SAndroid Build Coastguard Worker     if (foundLatestMinLts != KernelVersion{}) {
1409*70a7ec85SAndroid Build Coastguard Worker         return foundLatestMinLts;
1410*70a7ec85SAndroid Build Coastguard Worker     }
1411*70a7ec85SAndroid Build Coastguard Worker     return android::base::Error(-NAME_NOT_FOUND)
1412*70a7ec85SAndroid Build Coastguard Worker            << "Can't find compatibility matrix fragment for level " << fcmVersion;
1413*70a7ec85SAndroid Build Coastguard Worker }
1414*70a7ec85SAndroid Build Coastguard Worker 
1415*70a7ec85SAndroid Build Coastguard Worker // make_unique does not work because VintfObject constructor is private.
Builder()1416*70a7ec85SAndroid Build Coastguard Worker VintfObject::Builder::Builder()
1417*70a7ec85SAndroid Build Coastguard Worker     : VintfObjectBuilder(std::unique_ptr<VintfObject>(new VintfObject())) {}
1418*70a7ec85SAndroid Build Coastguard Worker 
1419*70a7ec85SAndroid Build Coastguard Worker namespace details {
1420*70a7ec85SAndroid Build Coastguard Worker 
~VintfObjectBuilder()1421*70a7ec85SAndroid Build Coastguard Worker VintfObjectBuilder::~VintfObjectBuilder() {}
1422*70a7ec85SAndroid Build Coastguard Worker 
setFileSystem(std::unique_ptr<FileSystem> && e)1423*70a7ec85SAndroid Build Coastguard Worker VintfObjectBuilder& VintfObjectBuilder::setFileSystem(std::unique_ptr<FileSystem>&& e) {
1424*70a7ec85SAndroid Build Coastguard Worker     mObject->mFileSystem = std::move(e);
1425*70a7ec85SAndroid Build Coastguard Worker     return *this;
1426*70a7ec85SAndroid Build Coastguard Worker }
1427*70a7ec85SAndroid Build Coastguard Worker 
setRuntimeInfoFactory(std::unique_ptr<ObjectFactory<RuntimeInfo>> && e)1428*70a7ec85SAndroid Build Coastguard Worker VintfObjectBuilder& VintfObjectBuilder::setRuntimeInfoFactory(
1429*70a7ec85SAndroid Build Coastguard Worker     std::unique_ptr<ObjectFactory<RuntimeInfo>>&& e) {
1430*70a7ec85SAndroid Build Coastguard Worker     mObject->mRuntimeInfoFactory = std::move(e);
1431*70a7ec85SAndroid Build Coastguard Worker     return *this;
1432*70a7ec85SAndroid Build Coastguard Worker }
1433*70a7ec85SAndroid Build Coastguard Worker 
setPropertyFetcher(std::unique_ptr<PropertyFetcher> && e)1434*70a7ec85SAndroid Build Coastguard Worker VintfObjectBuilder& VintfObjectBuilder::setPropertyFetcher(std::unique_ptr<PropertyFetcher>&& e) {
1435*70a7ec85SAndroid Build Coastguard Worker     mObject->mPropertyFetcher = std::move(e);
1436*70a7ec85SAndroid Build Coastguard Worker     return *this;
1437*70a7ec85SAndroid Build Coastguard Worker }
1438*70a7ec85SAndroid Build Coastguard Worker 
buildInternal()1439*70a7ec85SAndroid Build Coastguard Worker std::unique_ptr<VintfObject> VintfObjectBuilder::buildInternal() {
1440*70a7ec85SAndroid Build Coastguard Worker     if (!mObject->mFileSystem) mObject->mFileSystem = createDefaultFileSystem();
1441*70a7ec85SAndroid Build Coastguard Worker     if (!mObject->mRuntimeInfoFactory)
1442*70a7ec85SAndroid Build Coastguard Worker         mObject->mRuntimeInfoFactory = std::make_unique<ObjectFactory<RuntimeInfo>>();
1443*70a7ec85SAndroid Build Coastguard Worker     if (!mObject->mPropertyFetcher) mObject->mPropertyFetcher = createDefaultPropertyFetcher();
1444*70a7ec85SAndroid Build Coastguard Worker     return std::move(mObject);
1445*70a7ec85SAndroid Build Coastguard Worker }
1446*70a7ec85SAndroid Build Coastguard Worker 
1447*70a7ec85SAndroid Build Coastguard Worker }  // namespace details
1448*70a7ec85SAndroid Build Coastguard Worker 
1449*70a7ec85SAndroid Build Coastguard Worker }  // namespace vintf
1450*70a7ec85SAndroid Build Coastguard Worker }  // namespace android
1451