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 // Equality for timespec. This should be in global namespace where timespec
30 // is defined.
31 
32 inline bool operator==(const timespec& a, const timespec& b) noexcept {
33     return a.tv_sec == b.tv_sec && a.tv_nsec == b.tv_nsec;
34 }
35 
36 inline bool operator!=(const timespec& a, const timespec& b) noexcept {
37     return !(a == b);
38 }
39 
40 namespace android {
41 namespace vintf {
42 namespace details {
43 
44 template <typename T>
fetchAllInformation(const FileSystem * fileSystem,const std::string & path,T * outObject,std::string * error)45 status_t fetchAllInformation(const FileSystem* fileSystem, const std::string& path, T* outObject,
46                              std::string* error) {
47     if (outObject->fileName().empty()) {
48         outObject->setFileName(path);
49     } else {
50         outObject->setFileName(outObject->fileName() + ":" + path);
51     }
52 
53     std::string info;
54     status_t result = fileSystem->fetch(path, &info, error);
55 
56     if (result != OK) {
57         return result;
58     }
59 
60     bool success = fromXml(outObject, info, error);
61     if (!success) {
62         if (error) {
63             *error = "Illformed file: " + path + ": " + *error;
64         }
65         return BAD_VALUE;
66     }
67     return OK;
68 }
69 
70 class PropertyFetcherImpl : public PropertyFetcher {
71    public:
72     virtual std::string getProperty(const std::string& key,
73                                     const std::string& defaultValue = "") const;
74     virtual uint64_t getUintProperty(const std::string& key, uint64_t defaultValue,
75                                      uint64_t max = UINT64_MAX) const;
76     virtual bool getBoolProperty(const std::string& key, bool defaultValue) const;
77 };
78 
79 class PropertyFetcherNoOp : public PropertyFetcher {
80    public:
81     virtual std::string getProperty(const std::string& key,
82                                     const std::string& defaultValue = "") const override;
83     virtual uint64_t getUintProperty(const std::string& key, uint64_t defaultValue,
84                                      uint64_t max = UINT64_MAX) const override;
85     virtual bool getBoolProperty(const std::string& key, bool defaultValue) const override;
86 };
87 
88 // Merge src into dst.
89 // postcondition (if successful): *src == empty.
90 template <typename T>
91 static bool mergeField(T* dst, T* src, const T& empty = T{}) {
92     if (*dst == *src) {
93         *src = empty;
94         return true;  // no conflict
95     }
96     if (*src == empty) {
97         return true;
98     }
99     if (*dst == empty) {
100         *dst = std::move(*src);
101         *src = empty;
102         return true;
103     }
104     return false;
105 }
106 
107 // Check legacy instances (i.e. <version> + <interface> + <instance>) can be
108 // converted into FqInstance because forEachInstance relies on FqInstance.
109 // If error and appendedError is not null, error message is appended to appendedError.
110 // Return the corresponding value in <fqname> (i.e. @ver::Interface/instance for
111 // HIDL, Interface/instance for AIDL, @ver[::Interface]/instance for native)
112 [[nodiscard]] std::optional<FqInstance> convertLegacyInstanceIntoFqInstance(
113     const std::string& package, const Version& version, const std::string& interface,
114     const std::string& instance, HalFormat format, std::string* appendedError);
115 
116 bool isCoreHal(const std::string& halName);
117 
118 }  // namespace details
119 }  // namespace vintf
120 }  // namespace android
121 
122 
123 
124 #endif
125