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