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