• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 #pragma once
18 
19 #include <optional>
20 #include <string>
21 #include <unordered_map>
22 
23 #include <media/AidlConversionUtil.h>
24 #include <system/audio_config.h>
25 #include <utils/Errors.h>
26 
27 namespace aidl::android::hardware::audio::core::internal {
28 
29 template <typename T>
30 class XmlConverter {
31   public:
XmlConverter(const std::string & configFilePath,std::function<std::optional<T> (const char *)> readXmlConfig)32     XmlConverter(const std::string& configFilePath,
33                  std::function<std::optional<T>(const char*)> readXmlConfig)
34         : XmlConverter(configFilePath,
35                        ::android::audio_is_readable_configuration_file(configFilePath.c_str()),
36                        readXmlConfig) {}
37 
getStatus()38     const ::android::status_t& getStatus() const { return mStatus; }
39 
getError()40     const std::string& getError() const { return mErrorMessage; }
41 
getXsdcConfig()42     const std::optional<T>& getXsdcConfig() const { return mXsdcConfig; }
43 
44   private:
XmlConverter(const std::string & configFilePath,const bool & isReadableConfigFile,const std::function<std::optional<T> (const char *)> & readXmlConfig)45     XmlConverter(const std::string& configFilePath, const bool& isReadableConfigFile,
46                  const std::function<std::optional<T>(const char*)>& readXmlConfig)
47         : mXsdcConfig{isReadableConfigFile ? readXmlConfig(configFilePath.c_str()) : std::nullopt},
48           mStatus(mXsdcConfig ? ::android::OK : ::android::NO_INIT),
49           mErrorMessage(generateError(configFilePath, isReadableConfigFile, mStatus)) {}
50 
generateError(const std::string & configFilePath,const bool & isReadableConfigFile,const::android::status_t & status)51     static std::string generateError(const std::string& configFilePath,
52                                      const bool& isReadableConfigFile,
53                                      const ::android::status_t& status) {
54         std::string errorMessage;
55         if (status != ::android::OK) {
56             if (configFilePath.empty()) {
57                 errorMessage = "No audio configuration files found";
58             } else if (!isReadableConfigFile) {
59                 errorMessage = std::string("Could not read requested XML config file: \"")
60                                        .append(configFilePath)
61                                        .append("\"");
62             } else {
63                 errorMessage = std::string("Invalid XML config file: \"")
64                                        .append(configFilePath)
65                                        .append("\"");
66             }
67         }
68         return errorMessage;
69     }
70 
71     const std::optional<T> mXsdcConfig;
72     const ::android::status_t mStatus;
73     const std::string mErrorMessage;
74 };
75 
76 /**
77  * Converts a vector of an xsd wrapper type to a flat vector of the
78  * corresponding AIDL type.
79  *
80  * Wrapper types are used in order to have well-formed xIncludes. In the
81  * example below, Modules is the wrapper type for Module.
82  *     <Modules>
83  *         <Module> ... </Module>
84  *         <Module> ... </Module>
85  *     </Modules>
86  */
87 template <typename W, typename X, typename A>
convertWrappedCollectionToAidlUnchecked(const std::vector<W> & xsdcWrapperTypeVec,std::function<const std::vector<X> & (const W &)> getInnerTypeVec,std::function<A (const X &)> convertToAidl)88 std::vector<A> convertWrappedCollectionToAidlUnchecked(
89         const std::vector<W>& xsdcWrapperTypeVec,
90         std::function<const std::vector<X>&(const W&)> getInnerTypeVec,
91         std::function<A(const X&)> convertToAidl) {
92     std::vector<A> resultAidlTypeVec;
93     if (!xsdcWrapperTypeVec.empty()) {
94         /*
95          * xsdcWrapperTypeVec likely only contains one element; that is, it's
96          * likely that all the inner types that we need to convert are inside of
97          * xsdcWrapperTypeVec[0].
98          */
99         resultAidlTypeVec.reserve(getInnerTypeVec(xsdcWrapperTypeVec[0]).size());
100         for (const W& xsdcWrapperType : xsdcWrapperTypeVec) {
101             std::transform(getInnerTypeVec(xsdcWrapperType).begin(),
102                            getInnerTypeVec(xsdcWrapperType).end(),
103                            std::back_inserter(resultAidlTypeVec), convertToAidl);
104         }
105     }
106     return resultAidlTypeVec;
107 }
108 
109 template <typename X, typename A>
convertCollectionToAidlUnchecked(const std::vector<X> & xsdcTypeVec,std::function<A (const X &)> itemConversion)110 std::vector<A> convertCollectionToAidlUnchecked(const std::vector<X>& xsdcTypeVec,
111                                                 std::function<A(const X&)> itemConversion) {
112     std::vector<A> resultAidlTypeVec;
113     resultAidlTypeVec.reserve(xsdcTypeVec.size());
114     std::transform(xsdcTypeVec.begin(), xsdcTypeVec.end(), std::back_inserter(resultAidlTypeVec),
115                    itemConversion);
116     return resultAidlTypeVec;
117 }
118 
119 /**
120  * Generates a map of xsd references, keyed by reference name, given a
121  * vector of wrapper types for the reference.
122  *
123  * Wrapper types are used in order to have well-formed xIncludes. In the
124  * example below, Wrapper is the wrapper type for Reference.
125  *     <Wrapper>
126  *         <Reference> ... </Reference>
127  *         <Reference> ... </Reference>
128  *     </Wrapper>
129  */
130 template <typename W, typename R>
generateReferenceMap(const std::vector<W> & xsdcWrapperTypeVec)131 std::unordered_map<std::string, R> generateReferenceMap(const std::vector<W>& xsdcWrapperTypeVec) {
132     std::unordered_map<std::string, R> resultMap;
133     if (!xsdcWrapperTypeVec.empty()) {
134         /*
135          * xsdcWrapperTypeVec likely only contains one element; that is, it's
136          * likely that all the inner types that we need to convert are inside of
137          * xsdcWrapperTypeVec[0].
138          */
139         resultMap.reserve(xsdcWrapperTypeVec[0].getReference().size());
140         for (const W& xsdcWrapperType : xsdcWrapperTypeVec) {
141             for (const R& xsdcReference : xsdcWrapperType.getReference()) {
142                 resultMap.insert({xsdcReference.getName(), xsdcReference});
143             }
144         }
145     }
146     return resultMap;
147 }
148 }  // namespace aidl::android::hardware::audio::core::internal
149