1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ANDROID_VINTF_VINTF_OBJECT_H_
18 #define ANDROID_VINTF_VINTF_OBJECT_H_
19 
20 #include <map>
21 #include <memory>
22 #include <optional>
23 #include <string>
24 #include <tuple>
25 #include <vector>
26 
27 #include <aidl/metadata.h>
28 #include <android-base/result.h>
29 #include <hidl/metadata.h>
30 
31 #include <vintf/Apex.h>
32 #include <vintf/CheckFlags.h>
33 #include <vintf/CompatibilityMatrix.h>
34 #include <vintf/FileSystem.h>
35 #include <vintf/HalManifest.h>
36 #include <vintf/Level.h>
37 #include <vintf/ObjectFactory.h>
38 #include <vintf/PropertyFetcher.h>
39 #include <vintf/RuntimeInfo.h>
40 
41 namespace android {
42 namespace vintf {
43 
44 class VintfObject;
45 
46 namespace details {
47 class CheckVintfUtils;
48 class FmOnlyVintfObject;
49 class VintfObjectBuilder;
50 
51 template <typename T>
52 struct LockedSharedPtr {
53     std::shared_ptr<T> object;
54     std::mutex mutex;
55     std::optional<timespec> lastModified;
56 };
57 
58 struct LockedRuntimeInfoCache {
59     std::shared_ptr<RuntimeInfo> object;
60     std::mutex mutex;
61     RuntimeInfo::FetchFlags fetchedFlags = RuntimeInfo::FetchFlag::NONE;
62 };
63 
64 }  // namespace details
65 
66 namespace testing {
67 class VintfObjectTestBase;
68 class VintfObjectRecoveryTest;
69 class VintfObjectRuntimeInfoTest;
70 class VintfObjectCompatibleTest;
71 }  // namespace testing
72 
73 /*
74  * The top level class for libvintf.
75  * An overall diagram of the public API:
76  * VintfObject
77  *   + GetDeviceHalManfiest
78  *   |   + getHidlTransport
79  *   |   + checkCompatibility
80  *   + GetFrameworkHalManifest
81  *   |   + getHidlTransport
82  *   |   + checkCompatibility
83  *   + GetRuntimeInfo
84  *       + checkCompatibility
85  *
86  * Each of the function gathers all information and encapsulate it into the object.
87  * If no error, it return the same singleton object in the future, and the HAL manifest
88  * file won't be touched again.
89  * If any error, nullptr is returned, and Get will try to parse the HAL manifest
90  * again when it is called again.
91  * All these operations are thread-safe.
92  */
93 class VintfObject {
94    public:
95     virtual ~VintfObject() = default;
96 
97     /*
98      * Return the API that access the device-side HAL manifests built from component pieces on the
99      * vendor partition.
100      */
101     virtual std::shared_ptr<const HalManifest> getDeviceHalManifest();
102 
103     /*
104      * Return the API that access the framework-side HAL manifest built from component pieces on the
105      * system partition.
106      */
107     virtual std::shared_ptr<const HalManifest> getFrameworkHalManifest();
108 
109     /*
110      * Return the API that access the device-side compatibility matrix built from component pieces
111      * on the vendor partition.
112      */
113     virtual std::shared_ptr<const CompatibilityMatrix> getDeviceCompatibilityMatrix();
114 
115     /*
116      * Return the API that access the framework-side compatibility matrix built from component
117      * pieces on the system partition.
118      *
119      * This automatically selects the right compatibility matrix according to the target-level
120      * specified by the device.
121      */
122     virtual std::shared_ptr<const CompatibilityMatrix> getFrameworkCompatibilityMatrix();
123 
124     /*
125      * Return the API that access device runtime info.
126      *
127      * {skipCache == true, flags == ALL}: re-fetch everything
128      * {skipCache == false, flags == ALL}: fetch everything if not previously fetched
129      * {skipCache == true, flags == selected info}: re-fetch selected information
130      *                                if not previously fetched.
131      * {skipCache == false, flags == selected info}: fetch selected information
132      *                                if not previously fetched.
133      *
134      * @param skipCache do not fetch if previously fetched
135      * @param flags bitwise-or of RuntimeInfo::FetchFlag
136      */
137     std::shared_ptr<const RuntimeInfo> getRuntimeInfo(
138         RuntimeInfo::FetchFlags flags = RuntimeInfo::FetchFlag::ALL);
139 
140     /**
141      * Check compatibility on the device.
142      *
143      * @param error error message
144      * @param flags flags to disable certain checks. See CheckFlags.
145      *
146      * @return = 0 if success (compatible)
147      *         > 0 if incompatible
148      *         < 0 if any error (mount partition fails, illformed XML, etc.)
149      */
150     int32_t checkCompatibility(std::string* error = nullptr,
151                                CheckFlags::Type flags = CheckFlags::DEFAULT);
152 
153     /**
154      * Check deprecation on existing VINTF metadata. Use Device Manifest as the
155      * predicate to check if a HAL is in use.
156      *
157      * @return = 0 if success (no deprecated HALs)
158      *         > 0 if there is at least one deprecated HAL
159      *         < 0 if any error (mount partition fails, illformed XML, etc.)
160      */
161     int32_t checkDeprecation(const std::vector<HidlInterfaceMetadata>& hidlMetadata,
162                              std::string* error = nullptr);
163 
164     /**
165      * Return kernel FCM version.
166      *
167      * If any error, UNSPECIFIED is returned, and error is set to an error message.
168      */
169     Level getKernelLevel(std::string* error = nullptr);
170 
171     /**
172      * Returns true if the framework compatibility matrix has extensions. In
173      * other words, returns true if any of the following exists on the device:
174      * - device framework compatibility matrix
175      * - product framework compatibility matrix
176      * - system_ext framework compatibility matrix
177      *
178      * Return result:
179      * - true if framework compatibility matrix has extensions
180      * - false if framework compatibility
181      *     matrix does not have extensions.
182      * - !result.has_value() if any error. Check
183      *     result.error() for detailed message.
184      */
185     android::base::Result<bool> hasFrameworkCompatibilityMatrixExtensions();
186 
187     /**
188      * Check that there are no unused HALs in HAL manifests. Currently, only
189      * device manifest is checked against framework compatibility matrix.
190      *
191      * Return result:
192      * - result.ok() if no unused HALs
193      * - !result.ok() && result.error().code() == 0 if with unused HALs. Check
194      *     result.error() for detailed message.
195      * - !result.ok() && result.error().code() != 0 if any error. Check
196      *     result.error() for detailed message.
197      */
198     android::base::Result<void> checkUnusedHals(
199         const std::vector<HidlInterfaceMetadata>& hidlMetadata);
200 
201     // Check that all HALs are added to any framework compatibility matrix.
202     // If shouldCheck is set, only check if:
203     // - For HIDL, shouldCheck(packageAndVersion) (e.g. android.hardware.foo@1.0)
204     // - For AIDL and native, shouldCheck(package) (e.g. android.hardware.foo)
205     android::base::Result<void> checkMissingHalsInMatrices(
206         const std::vector<HidlInterfaceMetadata>& hidlMetadata,
207         const std::vector<AidlInterfaceMetadata>& aidlMetadata,
208         std::function<bool(const std::string&)> shouldCheckHidl,
209         std::function<bool(const std::string&)> shouldCheckAidl);
210 
211     // Check that all HALs in all framework compatibility matrices have the
212     // proper interface definition (HIDL / AIDL files).
213     android::base::Result<void> checkMatrixHalsHasDefinition(
214         const std::vector<HidlInterfaceMetadata>& hidlMetadata,
215         const std::vector<AidlInterfaceMetadata>& aidlMetadata);
216 
217     // Get the latest <kernel> minlts for compatibility matrix level |fcmVersion|.
218     android::base::Result<KernelVersion> getLatestMinLtsAtFcmVersion(Level fcmVersion);
219 
220    private:
221     std::unique_ptr<FileSystem> mFileSystem;
222     std::unique_ptr<ObjectFactory<RuntimeInfo>> mRuntimeInfoFactory;
223     std::unique_ptr<PropertyFetcher> mPropertyFetcher;
224     details::LockedSharedPtr<HalManifest> mDeviceManifest;
225     details::LockedSharedPtr<HalManifest> mFrameworkManifest;
226     details::LockedSharedPtr<CompatibilityMatrix> mDeviceMatrix;
227 
228     // Parent lock of the following fields. It should be acquired before locking the child locks.
229     std::mutex mFrameworkCompatibilityMatrixMutex;
230     details::LockedSharedPtr<CompatibilityMatrix> mFrameworkMatrix;
231     details::LockedSharedPtr<CompatibilityMatrix> mCombinedFrameworkMatrix;
232     // End of mFrameworkCompatibilityMatrixMutex
233 
234     details::LockedRuntimeInfoCache mDeviceRuntimeInfo;
235 
236     bool getCheckAidlCompatMatrix();
237     std::optional<bool> mFakeCheckAidlCompatibilityMatrix;
238 
239     // Expose functions for testing and recovery
240     friend class testing::VintfObjectTestBase;
241     friend class testing::VintfObjectRecoveryTest;
242     friend class testing::VintfObjectRuntimeInfoTest;
243     friend class testing::VintfObjectCompatibleTest;
244 
245     // Expose functions to simulate dependency injection.
246     friend class details::VintfObjectBuilder;
247     friend class details::CheckVintfUtils;
248     friend class details::FmOnlyVintfObject;
249 
250    protected:
setFakeCheckAidlCompatMatrix(bool check)251     void setFakeCheckAidlCompatMatrix(bool check) { mFakeCheckAidlCompatibilityMatrix = check; }
252     virtual const std::unique_ptr<FileSystem>& getFileSystem();
253     virtual const std::unique_ptr<PropertyFetcher>& getPropertyFetcher();
254     virtual const std::unique_ptr<ObjectFactory<RuntimeInfo>>& getRuntimeInfoFactory();
255 
256    public:
257     /*
258      * Get global instance. Results are cached.
259      */
260     static std::shared_ptr<VintfObject> GetInstance();
261 
262     // Static variants of member functions.
263 
264     /*
265      * Return the API that access the device-side HAL manifest built from component pieces on the
266      * vendor partition.
267      */
268     static std::shared_ptr<const HalManifest> GetDeviceHalManifest();
269 
270     /*
271      * Return the API that access the framework-side HAL manifest built from component pieces on the
272      * system partition.
273      */
274     static std::shared_ptr<const HalManifest> GetFrameworkHalManifest();
275 
276     /*
277      * Return the API that access the device-side compatibility matrix built from component pieces
278      * on the vendor partition.
279      */
280     static std::shared_ptr<const CompatibilityMatrix> GetDeviceCompatibilityMatrix();
281 
282     /*
283      * Return the API that access the framework-side compatibility matrix built from component
284      * pieces on the system partition.
285      */
286     static std::shared_ptr<const CompatibilityMatrix> GetFrameworkCompatibilityMatrix();
287 
288     /*
289      * Return the API that access device runtime info.
290      *
291      * @param flags bitwise-or of RuntimeInfo::FetchFlag
292      *   flags == ALL: fetch everything if not previously fetched
293      *   flags == selected info: fetch selected information if not previously fetched.
294      */
295     static std::shared_ptr<const RuntimeInfo> GetRuntimeInfo(
296         RuntimeInfo::FetchFlags flags = RuntimeInfo::FetchFlag::ALL);
297 
298    protected:
299     status_t getCombinedFrameworkMatrix(const std::shared_ptr<const HalManifest>& deviceManifest,
300                                         Level kernelLevel, CompatibilityMatrix* out,
301                                         std::string* error = nullptr);
302     status_t getAllFrameworkMatrixLevels(std::vector<CompatibilityMatrix>* out,
303                                          std::string* error = nullptr);
304     status_t getOneMatrix(const std::string& path, CompatibilityMatrix* out,
305                           std::string* error = nullptr);
306     status_t addDirectoryManifests(const std::string& directory, HalManifest* manifests,
307                                    bool ignoreSchemaType, std::string* error);
308     status_t addDirectoriesManifests(const std::vector<std::string>& directories,
309                                      HalManifest* manifests, bool ignoreSchemaType,
310                                      std::string* error);
311     status_t fetchDeviceHalManifest(HalManifest* out, std::string* error = nullptr);
312     status_t fetchDeviceHalManifestApex(HalManifest* out, std::string* error = nullptr);
313     status_t fetchDeviceMatrix(CompatibilityMatrix* out, std::string* error = nullptr);
314     status_t fetchOdmHalManifest(HalManifest* out, std::string* error = nullptr);
315     status_t fetchOneHalManifest(const std::string& path, HalManifest* out,
316                                  std::string* error = nullptr);
317     status_t fetchVendorHalManifest(HalManifest* out, std::string* error = nullptr);
318     status_t fetchFrameworkHalManifest(HalManifest* out, std::string* error = nullptr);
319     status_t fetchFrameworkHalManifestApex(HalManifest* out, std::string* error = nullptr);
320 
321     status_t fetchUnfilteredFrameworkHalManifest(HalManifest* out, std::string* error);
322     void filterHalsByDeviceManifestLevel(HalManifest* out);
323 
324     // Helper for checking matrices against lib*idlmetadata. Wrapper of the other variant of
325     // getAllFrameworkMatrixLevels. Treat empty output as an error.
326     android::base::Result<std::vector<CompatibilityMatrix>> getAllFrameworkMatrixLevels();
327 
328     using ChildrenMap = std::multimap<std::string, std::string>;
329     static bool IsHalDeprecated(const MatrixHal& oldMatrixHal,
330                                 const std::string& oldMatrixHalFileName,
331                                 const CompatibilityMatrix& targetMatrix,
332                                 const std::shared_ptr<const HalManifest>& halManifest,
333                                 const ChildrenMap& childrenMap, std::string* appendedError);
334     static bool IsInstanceDeprecated(const MatrixInstance& oldMatrixInstance,
335                                      const std::string& oldMatrixInstanceFileName,
336                                      const CompatibilityMatrix& targetMatrix,
337                                      const std::shared_ptr<const HalManifest>& halManifest,
338                                      const ChildrenMap& childrenMap, std::string* appendedError);
339 
340     static android::base::Result<std::vector<FqInstance>> GetListedInstanceInheritance(
341         HalFormat format, const std::string& package, const Version& version,
342         const std::string& interface, const std::string& instance,
343         const std::shared_ptr<const HalManifest>& halManifest, const ChildrenMap& childrenMap);
344     static bool IsInstanceListed(const std::shared_ptr<const HalManifest>& halManifest,
345                                  HalFormat format, const FqInstance& fqInstance);
346     static android::base::Result<void> IsFqInstanceDeprecated(
347         const CompatibilityMatrix& targetMatrix, HalFormat format, const FqInstance& fqInstance,
348         const std::shared_ptr<const HalManifest>& halManifest);
349 
350    public:
351     class Builder;
352 
353    protected:
354     /* Empty VintfObject without any dependencies. Used by Builder and subclasses. */
355     VintfObject() = default;
356 };
357 
358 enum : int32_t {
359     COMPATIBLE = 0,
360     INCOMPATIBLE = 1,
361 
362     NO_DEPRECATED_HALS = 0,
363     DEPRECATED = 1,
364 };
365 
366 // exposed for testing.
367 namespace details {
368 
369 /**
370  * DO NOT USE outside of libvintf. This is an implementation detail. Use VintfObject::Builder
371  * instead.
372  *
373  * A builder of VintfObject. If a dependency is not specified, the default behavior is used.
374  * - FileSystem fetch from "/" for target and fetch no files for host
375  * - ObjectFactory<RuntimeInfo> fetches default RuntimeInfo for target and nothing for host
376  * - PropertyFetcher fetches properties for target and nothing for host
377  */
378 class VintfObjectBuilder {
379    public:
VintfObjectBuilder(std::unique_ptr<VintfObject> && object)380     VintfObjectBuilder(std::unique_ptr<VintfObject>&& object) : mObject(std::move(object)) {}
381     ~VintfObjectBuilder();
382     VintfObjectBuilder& setFileSystem(std::unique_ptr<FileSystem>&&);
383     VintfObjectBuilder& setRuntimeInfoFactory(std::unique_ptr<ObjectFactory<RuntimeInfo>>&&);
384     VintfObjectBuilder& setPropertyFetcher(std::unique_ptr<PropertyFetcher>&&);
385     template <typename VintfObjectType = VintfObject>
build()386     std::unique_ptr<VintfObjectType> build() {
387         return std::unique_ptr<VintfObjectType>(
388             static_cast<VintfObjectType*>(buildInternal().release()));
389     }
390 
391    private:
392     std::unique_ptr<VintfObject> buildInternal();
393     std::unique_ptr<VintfObject> mObject;
394 };
395 
396 // Convenience function to dump all files and directories that could be read
397 // by calling Get(Framework|Device)(HalManifest|CompatibilityMatrix). The list
398 // include files that may not actually be read when the four functions are called
399 // because some files have a higher priority than others. The list does NOT
400 // include "files" (including kernel interfaces) that are read when GetRuntimeInfo
401 // is called.
402 // The sku string from ro.boot.product.hardware.sku is needed to build the ODM
403 // manifest file name for legacy devices.
404 std::vector<std::string> dumpFileList(const std::string& sku);
405 
406 }  // namespace details
407 
408 /** Builder of VintfObject. See VintfObjectBuilder for details. */
409 class VintfObject::Builder : public details::VintfObjectBuilder {
410    public:
411     Builder();
412 };
413 
414 }  // namespace vintf
415 }  // namespace android
416 
417 #endif  // ANDROID_VINTF_VINTF_OBJECT_H_
418