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