1/* 2 * Copyright (C) 2011 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/* 18 * Contains implementation of a class EmulatedCameraFactory that manages cameras 19 * available for emulation. 20 */ 21 22//#define LOG_NDEBUG 0 23#define LOG_TAG "EmulatedCamera_Factory" 24#include <cutils/log.h> 25#include <cutils/properties.h> 26#include "EmulatedQemuCamera.h" 27#include "EmulatedFakeCamera.h" 28#include "EmulatedFakeCamera2.h" 29#include "EmulatedCameraFactory.h" 30 31extern camera_module_t HAL_MODULE_INFO_SYM; 32 33/* A global instance of EmulatedCameraFactory is statically instantiated and 34 * initialized when camera emulation HAL is loaded. 35 */ 36android::EmulatedCameraFactory gEmulatedCameraFactory; 37 38namespace android { 39 40EmulatedCameraFactory::EmulatedCameraFactory() 41 : mQemuClient(), 42 mEmulatedCameras(NULL), 43 mEmulatedCameraNum(0), 44 mFakeCameraNum(0), 45 mConstructedOK(false) 46{ 47 status_t res; 48 /* Connect to the factory service in the emulator, and create Qemu cameras. */ 49 if (mQemuClient.connectClient(NULL) == NO_ERROR) { 50 /* Connection has succeeded. Create emulated cameras for each camera 51 * device, reported by the service. */ 52 createQemuCameras(); 53 } 54 55 if (isBackFakeCameraEmulationOn()) { 56 /* Camera ID. */ 57 const int camera_id = mEmulatedCameraNum; 58 /* Use fake camera to emulate back-facing camera. */ 59 mEmulatedCameraNum++; 60 61 /* Make sure that array is allocated (in case there were no 'qemu' 62 * cameras created. Note that we preallocate the array so it may contain 63 * two fake cameras: one facing back, and another facing front. */ 64 if (mEmulatedCameras == NULL) { 65 mEmulatedCameras = new EmulatedBaseCamera*[mEmulatedCameraNum + 1]; 66 if (mEmulatedCameras == NULL) { 67 ALOGE("%s: Unable to allocate emulated camera array for %d entries", 68 __FUNCTION__, mEmulatedCameraNum); 69 return; 70 } 71 memset(mEmulatedCameras, 0, 72 (mEmulatedCameraNum + 1) * sizeof(EmulatedBaseCamera*)); 73 } 74 75 /* Create, and initialize the fake camera */ 76 switch (getBackCameraHalVersion()) { 77 case 1: 78 mEmulatedCameras[camera_id] = 79 new EmulatedFakeCamera(camera_id, true, 80 &HAL_MODULE_INFO_SYM.common); 81 break; 82 case 2: 83 mEmulatedCameras[camera_id] = 84 new EmulatedFakeCamera2(camera_id, true, 85 &HAL_MODULE_INFO_SYM.common); 86 break; 87 default: 88 ALOGE("%s: Unknown back camera hal version requested: %d", __FUNCTION__, 89 getBackCameraHalVersion()); 90 } 91 if (mEmulatedCameras[camera_id] != NULL) { 92 ALOGV("%s: Back camera device version is %d", __FUNCTION__, 93 getBackCameraHalVersion()); 94 res = mEmulatedCameras[camera_id]->Initialize(); 95 if (res != NO_ERROR) { 96 ALOGE("%s: Unable to intialize back camera %d: %s (%d)", 97 __FUNCTION__, camera_id, strerror(-res), res); 98 delete mEmulatedCameras[camera_id]; 99 mEmulatedCameraNum--; 100 } 101 } else { 102 mEmulatedCameraNum--; 103 ALOGE("%s: Unable to instantiate fake camera class", __FUNCTION__); 104 } 105 } 106 107 if (isFrontFakeCameraEmulationOn()) { 108 /* Camera ID. */ 109 const int camera_id = mEmulatedCameraNum; 110 /* Use fake camera to emulate front-facing camera. */ 111 mEmulatedCameraNum++; 112 113 /* Make sure that array is allocated (in case there were no 'qemu' 114 * cameras created. */ 115 if (mEmulatedCameras == NULL) { 116 mEmulatedCameras = new EmulatedBaseCamera*[mEmulatedCameraNum]; 117 if (mEmulatedCameras == NULL) { 118 ALOGE("%s: Unable to allocate emulated camera array for %d entries", 119 __FUNCTION__, mEmulatedCameraNum); 120 return; 121 } 122 memset(mEmulatedCameras, 0, 123 mEmulatedCameraNum * sizeof(EmulatedBaseCamera*)); 124 } 125 126 /* Create, and initialize the fake camera */ 127 switch (getFrontCameraHalVersion()) { 128 case 1: 129 mEmulatedCameras[camera_id] = 130 new EmulatedFakeCamera(camera_id, false, 131 &HAL_MODULE_INFO_SYM.common); 132 break; 133 case 2: 134 mEmulatedCameras[camera_id] = 135 new EmulatedFakeCamera2(camera_id, false, 136 &HAL_MODULE_INFO_SYM.common); 137 break; 138 default: 139 ALOGE("%s: Unknown front camera hal version requested: %d", 140 __FUNCTION__, 141 getFrontCameraHalVersion()); 142 } 143 if (mEmulatedCameras[camera_id] != NULL) { 144 ALOGV("%s: Front camera device version is %d", __FUNCTION__, 145 getFrontCameraHalVersion()); 146 res = mEmulatedCameras[camera_id]->Initialize(); 147 if (res != NO_ERROR) { 148 ALOGE("%s: Unable to intialize front camera %d: %s (%d)", 149 __FUNCTION__, camera_id, strerror(-res), res); 150 delete mEmulatedCameras[camera_id]; 151 mEmulatedCameraNum--; 152 } 153 } else { 154 mEmulatedCameraNum--; 155 ALOGE("%s: Unable to instantiate fake camera class", __FUNCTION__); 156 } 157 } 158 159 ALOGV("%d cameras are being emulated. %d of them are fake cameras.", 160 mEmulatedCameraNum, mFakeCameraNum); 161 162 mConstructedOK = true; 163} 164 165EmulatedCameraFactory::~EmulatedCameraFactory() 166{ 167 if (mEmulatedCameras != NULL) { 168 for (int n = 0; n < mEmulatedCameraNum; n++) { 169 if (mEmulatedCameras[n] != NULL) { 170 delete mEmulatedCameras[n]; 171 } 172 } 173 delete[] mEmulatedCameras; 174 } 175} 176 177/**************************************************************************** 178 * Camera HAL API handlers. 179 * 180 * Each handler simply verifies existence of an appropriate EmulatedBaseCamera 181 * instance, and dispatches the call to that instance. 182 * 183 ***************************************************************************/ 184 185int EmulatedCameraFactory::cameraDeviceOpen(int camera_id, hw_device_t** device) 186{ 187 ALOGV("%s: id = %d", __FUNCTION__, camera_id); 188 189 *device = NULL; 190 191 if (!isConstructedOK()) { 192 ALOGE("%s: EmulatedCameraFactory has failed to initialize", __FUNCTION__); 193 return -EINVAL; 194 } 195 196 if (camera_id < 0 || camera_id >= getEmulatedCameraNum()) { 197 ALOGE("%s: Camera id %d is out of bounds (%d)", 198 __FUNCTION__, camera_id, getEmulatedCameraNum()); 199 return -EINVAL; 200 } 201 202 return mEmulatedCameras[camera_id]->connectCamera(device); 203} 204 205int EmulatedCameraFactory::getCameraInfo(int camera_id, struct camera_info* info) 206{ 207 ALOGV("%s: id = %d", __FUNCTION__, camera_id); 208 209 if (!isConstructedOK()) { 210 ALOGE("%s: EmulatedCameraFactory has failed to initialize", __FUNCTION__); 211 return -EINVAL; 212 } 213 214 if (camera_id < 0 || camera_id >= getEmulatedCameraNum()) { 215 ALOGE("%s: Camera id %d is out of bounds (%d)", 216 __FUNCTION__, camera_id, getEmulatedCameraNum()); 217 return -EINVAL; 218 } 219 220 return mEmulatedCameras[camera_id]->getCameraInfo(info); 221} 222 223/**************************************************************************** 224 * Camera HAL API callbacks. 225 ***************************************************************************/ 226 227int EmulatedCameraFactory::device_open(const hw_module_t* module, 228 const char* name, 229 hw_device_t** device) 230{ 231 /* 232 * Simply verify the parameters, and dispatch the call inside the 233 * EmulatedCameraFactory instance. 234 */ 235 236 if (module != &HAL_MODULE_INFO_SYM.common) { 237 ALOGE("%s: Invalid module %p expected %p", 238 __FUNCTION__, module, &HAL_MODULE_INFO_SYM.common); 239 return -EINVAL; 240 } 241 if (name == NULL) { 242 ALOGE("%s: NULL name is not expected here", __FUNCTION__); 243 return -EINVAL; 244 } 245 246 return gEmulatedCameraFactory.cameraDeviceOpen(atoi(name), device); 247} 248 249int EmulatedCameraFactory::get_number_of_cameras(void) 250{ 251 return gEmulatedCameraFactory.getEmulatedCameraNum(); 252} 253 254int EmulatedCameraFactory::get_camera_info(int camera_id, 255 struct camera_info* info) 256{ 257 return gEmulatedCameraFactory.getCameraInfo(camera_id, info); 258} 259 260/******************************************************************************** 261 * Internal API 262 *******************************************************************************/ 263 264/* 265 * Camera information tokens passed in response to the "list" factory query. 266 */ 267 268/* Device name token. */ 269static const char lListNameToken[] = "name="; 270/* Frame dimensions token. */ 271static const char lListDimsToken[] = "framedims="; 272/* Facing direction token. */ 273static const char lListDirToken[] = "dir="; 274 275void EmulatedCameraFactory::createQemuCameras() 276{ 277 /* Obtain camera list. */ 278 char* camera_list = NULL; 279 status_t res = mQemuClient.listCameras(&camera_list); 280 /* Empty list, or list containing just an EOL means that there were no 281 * connected cameras found. */ 282 if (res != NO_ERROR || camera_list == NULL || *camera_list == '\0' || 283 *camera_list == '\n') { 284 if (camera_list != NULL) { 285 free(camera_list); 286 } 287 return; 288 } 289 290 /* 291 * Calculate number of connected cameras. Number of EOLs in the camera list 292 * is the number of the connected cameras. 293 */ 294 295 int num = 0; 296 const char* eol = strchr(camera_list, '\n'); 297 while (eol != NULL) { 298 num++; 299 eol = strchr(eol + 1, '\n'); 300 } 301 302 /* Allocate the array for emulated camera instances. Note that we allocate 303 * two more entries for back and front fake camera emulation. */ 304 mEmulatedCameras = new EmulatedBaseCamera*[num + 2]; 305 if (mEmulatedCameras == NULL) { 306 ALOGE("%s: Unable to allocate emulated camera array for %d entries", 307 __FUNCTION__, num + 1); 308 free(camera_list); 309 return; 310 } 311 memset(mEmulatedCameras, 0, sizeof(EmulatedBaseCamera*) * (num + 1)); 312 313 /* 314 * Iterate the list, creating, and initializin emulated qemu cameras for each 315 * entry (line) in the list. 316 */ 317 318 int index = 0; 319 char* cur_entry = camera_list; 320 while (cur_entry != NULL && *cur_entry != '\0' && index < num) { 321 /* Find the end of the current camera entry, and terminate it with zero 322 * for simpler string manipulation. */ 323 char* next_entry = strchr(cur_entry, '\n'); 324 if (next_entry != NULL) { 325 *next_entry = '\0'; 326 next_entry++; // Start of the next entry. 327 } 328 329 /* Find 'name', 'framedims', and 'dir' tokens that are required here. */ 330 char* name_start = strstr(cur_entry, lListNameToken); 331 char* dim_start = strstr(cur_entry, lListDimsToken); 332 char* dir_start = strstr(cur_entry, lListDirToken); 333 if (name_start != NULL && dim_start != NULL && dir_start != NULL) { 334 /* Advance to the token values. */ 335 name_start += strlen(lListNameToken); 336 dim_start += strlen(lListDimsToken); 337 dir_start += strlen(lListDirToken); 338 339 /* Terminate token values with zero. */ 340 char* s = strchr(name_start, ' '); 341 if (s != NULL) { 342 *s = '\0'; 343 } 344 s = strchr(dim_start, ' '); 345 if (s != NULL) { 346 *s = '\0'; 347 } 348 s = strchr(dir_start, ' '); 349 if (s != NULL) { 350 *s = '\0'; 351 } 352 353 /* Create and initialize qemu camera. */ 354 EmulatedQemuCamera* qemu_cam = 355 new EmulatedQemuCamera(index, &HAL_MODULE_INFO_SYM.common); 356 if (NULL != qemu_cam) { 357 res = qemu_cam->Initialize(name_start, dim_start, dir_start); 358 if (res == NO_ERROR) { 359 mEmulatedCameras[index] = qemu_cam; 360 index++; 361 } else { 362 delete qemu_cam; 363 } 364 } else { 365 ALOGE("%s: Unable to instantiate EmulatedQemuCamera", 366 __FUNCTION__); 367 } 368 } else { 369 ALOGW("%s: Bad camera information: %s", __FUNCTION__, cur_entry); 370 } 371 372 cur_entry = next_entry; 373 } 374 375 mEmulatedCameraNum = index; 376} 377 378bool EmulatedCameraFactory::isBackFakeCameraEmulationOn() 379{ 380 /* Defined by 'qemu.sf.fake_camera' boot property: if property exist, and 381 * is set to 'both', or 'back', then fake camera is used to emulate back 382 * camera. */ 383 char prop[PROPERTY_VALUE_MAX]; 384 if ((property_get("qemu.sf.fake_camera", prop, NULL) > 0) && 385 (!strcmp(prop, "both") || !strcmp(prop, "back"))) { 386 return true; 387 } else { 388 return false; 389 } 390} 391 392int EmulatedCameraFactory::getBackCameraHalVersion() 393{ 394 /* Defined by 'qemu.sf.back_camera_hal_version' boot property: if the 395 * property doesn't exist, it is assumed to be 1. */ 396 char prop[PROPERTY_VALUE_MAX]; 397 if (property_get("qemu.sf.back_camera_hal", prop, NULL) > 0) { 398 char *prop_end = prop; 399 int val = strtol(prop, &prop_end, 10); 400 if (*prop_end == '\0') { 401 return val; 402 } 403 // Badly formatted property, should just be a number 404 ALOGE("qemu.sf.back_camera_hal is not a number: %s", prop); 405 } 406 return 1; 407} 408 409bool EmulatedCameraFactory::isFrontFakeCameraEmulationOn() 410{ 411 /* Defined by 'qemu.sf.fake_camera' boot property: if property exist, and 412 * is set to 'both', or 'front', then fake camera is used to emulate front 413 * camera. */ 414 char prop[PROPERTY_VALUE_MAX]; 415 if ((property_get("qemu.sf.fake_camera", prop, NULL) > 0) && 416 (!strcmp(prop, "both") || !strcmp(prop, "front"))) { 417 return true; 418 } else { 419 return false; 420 } 421} 422 423int EmulatedCameraFactory::getFrontCameraHalVersion() 424{ 425 /* Defined by 'qemu.sf.front_camera_hal_version' boot property: if the 426 * property doesn't exist, it is assumed to be 1. */ 427 char prop[PROPERTY_VALUE_MAX]; 428 if (property_get("qemu.sf.front_camera_hal", prop, NULL) > 0) { 429 char *prop_end = prop; 430 int val = strtol(prop, &prop_end, 10); 431 if (*prop_end == '\0') { 432 return val; 433 } 434 // Badly formatted property, should just be a number 435 ALOGE("qemu.sf.front_camera_hal is not a number: %s", prop); 436 } 437 return 1; 438} 439 440/******************************************************************************** 441 * Initializer for the static member structure. 442 *******************************************************************************/ 443 444/* Entry point for camera HAL API. */ 445struct hw_module_methods_t EmulatedCameraFactory::mCameraModuleMethods = { 446 open: EmulatedCameraFactory::device_open 447}; 448 449}; /* namespace android */ 450