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 #ifndef CPP_EVS_SAMPLEDRIVER_AIDL_INCLUDE_CONFIGMANAGER_H
17 #define CPP_EVS_SAMPLEDRIVER_AIDL_INCLUDE_CONFIGMANAGER_H
18 
19 #include "ConfigManagerUtil.h"
20 
21 #include <aidl/android/hardware/automotive/evs/CameraParam.h>
22 #include <aidl/android/hardware/graphics/common/PixelFormat.h>
23 #include <android-base/logging.h>
24 #include <system/camera_metadata.h>
25 
26 #include <tinyxml2.h>
27 
28 #include <string>
29 #include <string_view>
30 #include <unordered_map>
31 #include <unordered_set>
32 #include <vector>
33 
34 namespace {
35 /*
36  * Please note that this is different from what is defined in
37  * libhardware/modules/camera/3_4/metadata/types.h; this has one additional
38  * field to store a framerate.
39  */
40 typedef struct {
41     int id;
42     int width;
43     int height;
44     ::aidl::android::hardware::graphics::common::PixelFormat format;
45     int type;
46     int framerate;
47 } StreamConfiguration;
48 
49 }  // namespace
50 
51 class ConfigManager final {
52 public:
53     static std::unique_ptr<ConfigManager> Create();
54     ConfigManager(const ConfigManager&) = delete;
55     ConfigManager& operator=(const ConfigManager&) = delete;
56 
57     /* Camera device's capabilities and metadata */
58     class CameraInfo {
59     public:
CameraInfo()60         CameraInfo() : characteristics(nullptr) {}
61 
62         virtual ~CameraInfo();
63 
64         /* Allocate memory for camera_metadata_t */
allocate(size_t entry_cap,size_t data_cap)65         bool allocate(size_t entry_cap, size_t data_cap) {
66             if (characteristics != nullptr) {
67                 LOG(ERROR) << "Camera metadata is already allocated";
68                 return false;
69             }
70 
71             characteristics = allocate_camera_metadata(entry_cap, data_cap);
72             return characteristics != nullptr;
73         }
74 
75         /*
76          * List of supported controls that the primary client can program.
77          * Paraemters are stored with its valid range
78          */
79         std::unordered_map<::aidl::android::hardware::automotive::evs::CameraParam,
80                            std::tuple<int32_t, int32_t, int32_t>>
81                 controls;
82 
83         /*
84          * List of supported output stream configurations.
85          */
86         std::unordered_map<int32_t, StreamConfiguration> streamConfigurations;
87 
88         /*
89          * Internal storage for camera metadata.  Each entry holds a pointer to
90          * data and number of elements
91          */
92         std::unordered_map<camera_metadata_tag_t, std::pair<void*, size_t>> cameraMetadata;
93 
94         /* Camera module characteristics */
95         camera_metadata_t* characteristics;
96     };
97 
98     class CameraGroupInfo : public CameraInfo {
99     public:
CameraGroupInfo()100         CameraGroupInfo() {}
101 
102         /* ID of member camera devices */
103         std::unordered_set<std::string> devices;
104 
105         /* The capture operation of member camera devices are synchronized */
106         int32_t synchronized = 0;
107     };
108 
109     class SystemInfo {
110     public:
111         /* number of available cameras */
112         int32_t numCameras = 0;
113     };
114 
115     class DisplayInfo {
116     public:
117         /*
118          * List of supported input stream configurations.
119          */
120         std::unordered_map<int32_t, StreamConfiguration> streamConfigurations;
121     };
122 
123     /*
124      * Return system information
125      *
126      * @return SystemInfo
127      *         Constant reference of SystemInfo.
128      */
getSystemInfo()129     const SystemInfo& getSystemInfo() {
130         std::unique_lock<std::mutex> lock(mConfigLock);
131         mConfigCond.wait(lock, [this] { return mIsReady; });
132         return mSystemInfo;
133     }
134 
135     /*
136      * Return a list of camera identifiers
137      *
138      * This function assumes that it is not being called frequently.
139      *
140      * @return std::vector<std::string>
141      *         A vector that contains unique camera device identifiers.
142      */
getCameraIdList()143     std::vector<std::string> getCameraIdList() {
144         std::unique_lock<std::mutex> lock(mConfigLock);
145         mConfigCond.wait(lock, [this] { return mIsReady; });
146 
147         std::vector<std::string> aList;
148         for (auto&& v : mCameraInfo) {
149             aList.push_back(v.first);
150         }
151 
152         return aList;
153     }
154 
155     /*
156      * Return a list of camera group identifiers
157      *
158      * This function assumes that it is not being called frequently.
159      *
160      * @return std::vector<std::string>
161      *         A vector that contains unique camera device identifiers.
162      */
getCameraGroupIdList()163     std::vector<std::string> getCameraGroupIdList() {
164         std::unique_lock<std::mutex> lock(mConfigLock);
165         mConfigCond.wait(lock, [this] { return mIsReady; });
166 
167         std::vector<std::string> aList;
168         for (auto&& v : mCameraGroups) {
169             aList.push_back(v.first);
170         }
171 
172         return aList;
173     }
174 
175     /*
176      * Return a pointer to the camera group
177      *
178      * @return CameraGroup
179      *         A pointer to a camera group identified by a given id.
180      */
getCameraGroupInfo(const std::string & gid)181     std::unique_ptr<CameraGroupInfo>& getCameraGroupInfo(const std::string& gid) {
182         std::unique_lock<std::mutex> lock(mConfigLock);
183         mConfigCond.wait(lock, [this] { return mIsReady; });
184 
185         return mCameraGroups[gid];
186     }
187 
188     /*
189      * Return a camera metadata
190      *
191      * @param  cameraId
192      *         Unique camera node identifier in string
193      *
194      * @return unique_ptr<CameraInfo>
195      *         A pointer to CameraInfo that is associated with a given camera
196      *         ID.  This returns a null pointer if this does not recognize a
197      *         given camera identifier.
198      */
getCameraInfo(const std::string cameraId)199     std::unique_ptr<CameraInfo>& getCameraInfo(const std::string cameraId) noexcept {
200         std::unique_lock<std::mutex> lock(mConfigLock);
201         mConfigCond.wait(lock, [this] { return mIsReady; });
202 
203         return mCameraInfo[cameraId];
204     }
205 
206     /*
207      * Tell whether the configuration data is ready to be used
208      *
209      * @return bool
210      *         True if configuration data is ready to be consumed.
211      */
isReady()212     bool isReady() const { return mIsReady; }
213 
214 private:
215     /* Constructors */
ConfigManager()216     ConfigManager() : mBinaryFilePath("") {}
217 
218     static std::string_view sConfigDefaultPath;
219     static std::string_view sConfigOverridePath;
220 
221     /* System configuration */
222     SystemInfo mSystemInfo;
223 
224     /* Internal data structure for camera device information */
225     std::unordered_map<std::string, std::unique_ptr<CameraInfo>> mCameraInfo;
226 
227     /* Internal data structure for camera device information */
228     std::unordered_map<std::string, std::unique_ptr<DisplayInfo>> mDisplayInfo;
229 
230     /* Camera groups are stored in <groud id, CameraGroup> hash map */
231     std::unordered_map<std::string, std::unique_ptr<CameraGroupInfo>> mCameraGroups;
232 
233     /*
234      * Camera positions are stored in <position, camera id set> hash map.
235      * The position must be one of front, rear, left, and right.
236      */
237     std::unordered_map<std::string, std::unordered_set<std::string>> mCameraPosition;
238 
239     /* Configuration data lock */
240     mutable std::mutex mConfigLock;
241 
242     /*
243      * This condition is signalled when it completes a configuration data
244      * preparation.
245      */
246     std::condition_variable mConfigCond;
247 
248     /* A path to a binary configuration file */
249     const char* mBinaryFilePath;
250 
251     /* Configuration data readiness */
252     bool mIsReady = false;
253 
254     /*
255      * Parse a given EVS configuration file and store the information
256      * internally.
257      *
258      * @return bool
259      *         True if it completes parsing a file successfully.
260      */
261     bool readConfigDataFromXML() noexcept;
262 
263     /*
264      * read the information of the vehicle
265      *
266      * @param  aSysElem
267      *         A pointer to "system" XML element.
268      */
269     void readSystemInfo(const tinyxml2::XMLElement* const aSysElem);
270 
271     /*
272      * read the information of camera devices
273      *
274      * @param  aCameraElem
275      *         A pointer to "camera" XML element that may contain multiple
276      *         "device" elements.
277      */
278     void readCameraInfo(const tinyxml2::XMLElement* const aCameraElem);
279 
280     /*
281      * read display device information
282      *
283      * @param  aDisplayElem
284      *         A pointer to "display" XML element that may contain multiple
285      *         "device" elements.
286      */
287     void readDisplayInfo(const tinyxml2::XMLElement* const aDisplayElem);
288 
289     /*
290      * read camera device information
291      *
292      * @param  aCamera
293      *         A pointer to CameraInfo that will be completed by this
294      *         method.
295      *         aDeviceElem
296      *         A pointer to "device" XML element that contains camera module
297      *         capability info and its characteristics.
298      *
299      * @return bool
300      *         Return false upon any failure in reading and processing camera
301      *         device information.
302      */
303     bool readCameraDeviceInfo(CameraInfo* aCamera, const tinyxml2::XMLElement* aDeviceElem);
304 
305     /*
306      * read camera metadata
307      *
308      * @param  aCapElem
309      *         A pointer to "cap" XML element.
310      * @param  aCamera
311      *         A pointer to CameraInfo that is being filled by this method.
312      * @param  dataSize
313      *         Required size of memory to store camera metadata found in this
314      *         method.  This is calculated in this method and returned to the
315      *         caller for camera_metadata allocation.
316      *
317      * @return size_t
318      *         Number of camera metadata entries
319      */
320     size_t readCameraCapabilities(const tinyxml2::XMLElement* const aCapElem, CameraInfo* aCamera,
321                                   size_t& dataSize);
322 
323     /*
324      * read camera metadata
325      *
326      * @param  aParamElem
327      *         A pointer to "characteristics" XML element.
328      * @param  aCamera
329      *         A pointer to CameraInfo that is being filled by this method.
330      * @param  dataSize
331      *         Required size of memory to store camera metadata found in this
332      *         method.
333      *
334      * @return size_t
335      *         Number of camera metadata entries
336      */
337     size_t readCameraMetadata(const tinyxml2::XMLElement* const aParamElem, CameraInfo* aCamera,
338                               size_t& dataSize);
339 
340     /*
341      * construct camera_metadata_t from camera capabilities and metadata
342      *
343      * @param  aCamera
344      *         A pointer to CameraInfo that is being filled by this method.
345      * @param  totalEntries
346      *         Number of camera metadata entries to be added.
347      * @param  totalDataSize
348      *         Sum of sizes of camera metadata entries to be added.
349      *
350      * @return bool
351      *         False if either it fails to allocate memory for camera metadata
352      *         or its size is not large enough to add all found camera metadata
353      *         entries.
354      */
355     bool constructCameraMetadata(CameraInfo* aCamera, const size_t totalEntries,
356                                  const size_t totalDataSize);
357 
358     /*
359      * Read configuration data from the binary file
360      *
361      * @return bool
362      *         True if it succeeds to read configuration data from a binary
363      *         file.
364      */
365     bool readConfigDataFromBinary();
366 
367     /*
368      * Store configuration data to the file
369      *
370      * @return bool
371      *         True if it succeeds to serialize mCameraInfo to the file.
372      */
373     bool writeConfigDataToBinary();
374 
375     /*
376      * debugging method to print out all XML elements and their attributes in
377      * logcat message.
378      *
379      * @param  aNode
380      *         A pointer to the root XML element to navigate.
381      * @param  prefix
382      *         A prefix to XML string.
383      */
384     void printElementNames(const tinyxml2::XMLElement* aNode, std::string prefix = "") const;
385 };
386 #endif  // CPP_EVS_SAMPLEDRIVER_AIDL_INCLUDE_CONFIGMANAGER_H
387