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 #include "CameraConfiguration.h"
17 
18 #define LOG_TAG "CameraConfiguration"
19 
20 #include <android-base/file.h>
21 #include <android-base/strings.h>
22 #include <log/log.h>
23 #include <json/json.h>
24 #include <json/reader.h>
25 #include <stdlib.h>
26 
27 namespace cuttlefish {
28 namespace {
29 ////////////////////// Device Personality keys //////////////////////
30 //
31 // **** Camera ****
32 //
33 // Example segment (transcribed to constants):
34 //
35 // kCameraDefinitionsKey: [
36 //   {
37 //     kCameraDefinitionOrientationKey: "front",
38 //     kCameraDefinitionHalVersionKey: "1",
39 //     kCameraDefinitionResolutionsKey: [
40 //       {
41 //         kCameraDefinitionResolutionWidthKey: "1600",
42 //         kCameraDefinitionResolutionHeightKey: "1200",
43 //       },
44 //       {
45 //         kCameraDefinitionResolutionWidthKey: "1280",
46 //         kCameraDefinitionResolutionHeightKey: "800",
47 //       }
48 //     ]
49 //   },
50 //   {
51 //     kCameraDefinitionOrientationKey: "back",
52 //     kCameraDefinitionHalVersionKey: "1",
53 //     kCameraDefinitionResolutionsKey: [
54 //       {
55 //         kCameraDefinitionResolutionWidthKey: "1024",
56 //         kCameraDefinitionResolutionHeightKey: "768",
57 //       },
58 //       {
59 //         kCameraDefinitionResolutionWidthKey: "800",
60 //         kCameraDefinitionResolutionHeightKey: "600",
61 //       }
62 //     ]
63 //   }
64 // ]
65 //
66 
67 // Location of the camera configuration files.
68 const char* const kConfigurationFileLocation = "/vendor/etc/config/camera.json";
69 
70 //
71 // Array of camera definitions for all cameras available on the device (array).
72 // Top Level Key.
73 const char* const kCameraDefinitionsKey = "camera_definitions";
74 
75 // Camera orientation of currently defined camera (string).
76 // Currently supported values:
77 // - "back",
78 // - "front".
79 const char* const kCameraDefinitionOrientationKey = "orientation";
80 
81 // Camera HAL version of currently defined camera (int).
82 // Currently supported values:
83 // - 1 (Camera HALv1)
84 // - 2 (Camera HALv2)
85 // - 3 (Camera HALv3)
86 const char* const kCameraDefinitionHalVersionKey = "hal_version";
87 
88 // Array of resolutions supported by camera (array).
89 const char* const kCameraDefinitionResolutionsKey = "resolutions";
90 
91 // Width of currently defined resolution (int).
92 // Must be divisible by 8.
93 const char* const kCameraDefinitionResolutionWidthKey = "width";
94 
95 // Height of currently defined resolution (int).
96 // Must be divisible by 8.
97 const char* const kCameraDefinitionResolutionHeightKey = "height";
98 
99 // Convert string value to camera orientation.
ValueToCameraOrientation(const std::string & value,CameraDefinition::Orientation * orientation)100 bool ValueToCameraOrientation(const std::string& value,
101                               CameraDefinition::Orientation* orientation) {
102   if (value == "back") {
103     *orientation = CameraDefinition::kBack;
104     return true;
105   } else if (value == "front") {
106     *orientation = CameraDefinition::kFront;
107     return true;
108   }
109   ALOGE("%s: Invalid camera orientation: %s.", __FUNCTION__, value.c_str());
110   return false;
111 }
112 
113 // Convert string value to camera HAL version.
ValueToCameraHalVersion(const std::string & value,CameraDefinition::HalVersion * hal_version)114 bool ValueToCameraHalVersion(const std::string& value,
115                              CameraDefinition::HalVersion* hal_version) {
116   int temp;
117   char* endptr;
118 
119   temp = strtol(value.c_str(), &endptr, 10);
120   if (endptr != value.c_str() + value.size()) {
121     ALOGE("%s: Invalid camera HAL version. Expected number, got %s.",
122           __FUNCTION__, value.c_str());
123     return false;
124   }
125 
126   switch (temp) {
127     case 1:
128       *hal_version = CameraDefinition::kHalV1;
129       break;
130 
131     case 2:
132       *hal_version = CameraDefinition::kHalV2;
133       break;
134 
135     case 3:
136       *hal_version = CameraDefinition::kHalV3;
137       break;
138 
139     default:
140       ALOGE("%s: Invalid camera HAL version. Version %d not supported.",
141             __FUNCTION__, temp);
142       return false;
143   }
144 
145   return true;
146 }
147 
ValueToCameraResolution(const std::string & width,const std::string & height,CameraDefinition::Resolution * resolution)148 bool ValueToCameraResolution(const std::string& width,
149                              const std::string& height,
150                              CameraDefinition::Resolution* resolution) {
151   char* endptr;
152 
153   resolution->width = strtol(width.c_str(), &endptr, 10);
154   if (endptr != width.c_str() + width.size()) {
155     ALOGE("%s: Invalid camera resolution width. Expected number, got %s.",
156           __FUNCTION__, width.c_str());
157     return false;
158   }
159 
160   resolution->height = strtol(height.c_str(), &endptr, 10);
161   if (endptr != height.c_str() + height.size()) {
162     ALOGE("%s: Invalid camera resolution height. Expected number, got %s.",
163           __FUNCTION__, height.c_str());
164     return false;
165   }
166 
167   // Validate width and height parameters are sane.
168   if (resolution->width <= 0 || resolution->height <= 0) {
169     ALOGE("%s: Invalid camera resolution: %dx%d", __FUNCTION__,
170           resolution->width, resolution->height);
171     return false;
172   }
173 
174   // Validate width and height divisible by 8.
175   if ((resolution->width & 7) != 0 || (resolution->height & 7) != 0) {
176     ALOGE(
177         "%s: Invalid camera resolution: width and height must be "
178         "divisible by 8, got %dx%d (%dx%d).",
179         __FUNCTION__, resolution->width, resolution->height,
180         resolution->width & 7, resolution->height & 7);
181     return false;
182   }
183 
184   return true;
185 }
186 
187 // Process camera definitions.
188 // Returns true, if definitions were sane.
ConfigureCameras(const Json::Value & value,std::vector<CameraDefinition> * cameras)189 bool ConfigureCameras(const Json::Value& value,
190                       std::vector<CameraDefinition>* cameras) {
191   if (!value.isObject()) {
192     ALOGE("%s: Configuration root is not an object", __FUNCTION__);
193     return false;
194   }
195 
196   if (!value.isMember(kCameraDefinitionsKey)) return true;
197   for (Json::ValueConstIterator iter = value[kCameraDefinitionsKey].begin();
198        iter != value[kCameraDefinitionsKey].end(); ++iter) {
199     cameras->push_back(CameraDefinition());
200     CameraDefinition& camera = cameras->back();
201 
202     if (!iter->isObject()) {
203       ALOGE("%s: Camera definition is not an object", __FUNCTION__);
204       continue;
205     }
206 
207     // Camera without orientation -> invalid setting.
208     if (!iter->isMember(kCameraDefinitionOrientationKey)) {
209       ALOGE("%s: Invalid camera definition: key %s is missing.", __FUNCTION__,
210             kCameraDefinitionOrientationKey);
211       return false;
212     }
213 
214     if (!ValueToCameraOrientation(
215             (*iter)[kCameraDefinitionOrientationKey].asString(),
216             &camera.orientation))
217       return false;
218 
219     // Camera without HAL version -> invalid setting.
220     if (!(*iter).isMember(kCameraDefinitionHalVersionKey)) {
221       ALOGE("%s: Invalid camera definition: key %s is missing.", __FUNCTION__,
222             kCameraDefinitionHalVersionKey);
223       return false;
224     }
225 
226     if (!ValueToCameraHalVersion(
227             (*iter)[kCameraDefinitionHalVersionKey].asString(),
228             &camera.hal_version))
229       return false;
230 
231     // Camera without resolutions -> invalid setting.
232     if (!iter->isMember(kCameraDefinitionResolutionsKey)) {
233       ALOGE("%s: Invalid camera definition: key %s is missing.", __FUNCTION__,
234             kCameraDefinitionResolutionsKey);
235       return false;
236     }
237 
238     const Json::Value& json_resolutions =
239         (*iter)[kCameraDefinitionResolutionsKey];
240 
241     // Resolutions not an array, or an empty array -> invalid setting.
242     if (!json_resolutions.isArray() || json_resolutions.empty()) {
243       ALOGE("%s: Invalid camera definition: %s is not an array or is empty.",
244             __FUNCTION__, kCameraDefinitionResolutionsKey);
245       return false;
246     }
247 
248     // Process all resolutions.
249     for (Json::ValueConstIterator json_res_iter = json_resolutions.begin();
250          json_res_iter != json_resolutions.end(); ++json_res_iter) {
251       // Check presence of width and height keys.
252       if (!json_res_iter->isObject()) {
253         ALOGE("%s: Camera resolution item is not an object", __FUNCTION__);
254         continue;
255       }
256       if (!json_res_iter->isMember(kCameraDefinitionResolutionWidthKey) ||
257           !json_res_iter->isMember(kCameraDefinitionResolutionHeightKey)) {
258         ALOGE(
259             "%s: Invalid camera resolution: keys %s and %s are both required.",
260             __FUNCTION__, kCameraDefinitionResolutionWidthKey,
261             kCameraDefinitionResolutionHeightKey);
262         return false;
263       }
264 
265       camera.resolutions.push_back(CameraDefinition::Resolution());
266       CameraDefinition::Resolution& resolution = camera.resolutions.back();
267 
268       if (!ValueToCameraResolution(
269               (*json_res_iter)[kCameraDefinitionResolutionWidthKey].asString(),
270               (*json_res_iter)[kCameraDefinitionResolutionHeightKey].asString(),
271               &resolution))
272         return false;
273     }
274   }
275 
276   return true;
277 }
278 }  // namespace
279 
Init()280 bool CameraConfiguration::Init() {
281   cameras_.clear();
282   std::string config;
283   if (!android::base::ReadFileToString(kConfigurationFileLocation, &config)) {
284     ALOGE("%s: Could not open configuration file: %s", __FUNCTION__,
285           kConfigurationFileLocation);
286     return false;
287   }
288 
289   Json::Reader config_reader;
290   Json::Value root;
291   if (!config_reader.parse(config, root)) {
292     ALOGE("Could not parse configuration file: %s",
293           config_reader.getFormattedErrorMessages().c_str());
294     return false;
295   }
296 
297   return ConfigureCameras(root, &cameras_);
298 }
299 
300 }  // namespace cuttlefish
301