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