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