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_UTILS_H
18 #define ANDROID_VINTF_UTILS_H
19 
20 #include <memory>
21 #include <mutex>
22 
23 #include <utils/Errors.h>
24 #include <vintf/FileSystem.h>
25 #include <vintf/PropertyFetcher.h>
26 #include <vintf/RuntimeInfo.h>
27 #include <vintf/parse_xml.h>
28 
29 namespace android {
30 namespace vintf {
31 namespace details {
32 
33 template <typename T>
fetchAllInformation(const FileSystem * fileSystem,const std::string & path,T * outObject,std::string * error)34 status_t fetchAllInformation(const FileSystem* fileSystem, const std::string& path, T* outObject,
35                              std::string* error) {
36     if (outObject->fileName().empty()) {
37         outObject->setFileName(path);
38     } else {
39         outObject->setFileName(outObject->fileName() + ":" + path);
40     }
41 
42     std::string info;
43     status_t result = fileSystem->fetch(path, &info, error);
44 
45     if (result != OK) {
46         return result;
47     }
48 
49     bool success = fromXml(outObject, info, error);
50     if (!success) {
51         if (error) {
52             *error = "Illformed file: " + path + ": " + *error;
53         }
54         return BAD_VALUE;
55     }
56     return OK;
57 }
58 
59 // TODO(b/70628538): Do not infer from Shipping API level.
convertFromApiLevel(size_t apiLevel)60 inline Level convertFromApiLevel(size_t apiLevel) {
61     if (apiLevel < 26) {
62         return Level::LEGACY;
63     } else if (apiLevel == 26) {
64         return Level::O;
65     } else if (apiLevel == 27) {
66         return Level::O_MR1;
67     } else {
68         return Level::UNSPECIFIED;
69     }
70 }
71 
72 class PropertyFetcherImpl : public PropertyFetcher {
73    public:
74     virtual std::string getProperty(const std::string& key,
75                                     const std::string& defaultValue = "") const;
76     virtual uint64_t getUintProperty(const std::string& key, uint64_t defaultValue,
77                                      uint64_t max = UINT64_MAX) const;
78     virtual bool getBoolProperty(const std::string& key, bool defaultValue) const;
79 };
80 
81 class PropertyFetcherNoOp : public PropertyFetcher {
82    public:
83     virtual std::string getProperty(const std::string& key,
84                                     const std::string& defaultValue = "") const override;
85     virtual uint64_t getUintProperty(const std::string& key, uint64_t defaultValue,
86                                      uint64_t max = UINT64_MAX) const override;
87     virtual bool getBoolProperty(const std::string& key, bool defaultValue) const override;
88 };
89 
90 // Merge src into dst.
91 // postcondition (if successful): *src == empty.
92 template <typename T>
93 static bool mergeField(T* dst, T* src, const T& empty = T{}) {
94     if (*dst == *src) {
95         *src = empty;
96         return true;  // no conflict
97     }
98     if (*src == empty) {
99         return true;
100     }
101     if (*dst == empty) {
102         *dst = std::move(*src);
103         *src = empty;
104         return true;
105     }
106     return false;
107 }
108 
109 // Check legacy instances (i.e. <version> + <interface> + <instance>) can be
110 // converted into FqInstance because forEachInstance relies on FqInstance.
111 // If error and appendedError is not null, error message is appended to appendedError.
112 [[nodiscard]] bool canConvertToFqInstance(const std::string& package, const Version& version,
113                                           const std::string& interface, const std::string& instance,
114                                           HalFormat format, std::string* appendedError);
115 
116 }  // namespace details
117 }  // namespace vintf
118 }  // namespace android
119 
120 
121 
122 #endif
123