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 <cutils/log.h> 23 #include <json/json.h> 24 #include <json/reader.h> 25 #include <stdlib.h> 26 27 namespace cvd { 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. 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. 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 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. 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 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 cvd 301