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("EmulatedCameraHotplugThread"); 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 void EmulatedCameraFactory::getVendorTagOps(vendor_tag_ops_t* ops) { 263 ALOGV("%s: ops = %p", __FUNCTION__, ops); 264 265 // No vendor tags defined for emulator yet, so not touching ops 266 } 267 268 /**************************************************************************** 269 * Camera HAL API callbacks. 270 ***************************************************************************/ 271 272 int EmulatedCameraFactory::device_open(const hw_module_t* module, 273 const char* name, 274 hw_device_t** device) 275 { 276 /* 277 * Simply verify the parameters, and dispatch the call inside the 278 * EmulatedCameraFactory instance. 279 */ 280 281 if (module != &HAL_MODULE_INFO_SYM.common) { 282 ALOGE("%s: Invalid module %p expected %p", 283 __FUNCTION__, module, &HAL_MODULE_INFO_SYM.common); 284 return -EINVAL; 285 } 286 if (name == NULL) { 287 ALOGE("%s: NULL name is not expected here", __FUNCTION__); 288 return -EINVAL; 289 } 290 291 return gEmulatedCameraFactory.cameraDeviceOpen(atoi(name), device); 292 } 293 294 int EmulatedCameraFactory::get_number_of_cameras(void) 295 { 296 return gEmulatedCameraFactory.getEmulatedCameraNum(); 297 } 298 299 int EmulatedCameraFactory::get_camera_info(int camera_id, 300 struct camera_info* info) 301 { 302 return gEmulatedCameraFactory.getCameraInfo(camera_id, info); 303 } 304 305 int EmulatedCameraFactory::set_callbacks( 306 const camera_module_callbacks_t *callbacks) 307 { 308 return gEmulatedCameraFactory.setCallbacks(callbacks); 309 } 310 311 void EmulatedCameraFactory::get_vendor_tag_ops(vendor_tag_ops_t* ops) 312 { 313 gEmulatedCameraFactory.getVendorTagOps(ops); 314 } 315 316 int EmulatedCameraFactory::open_legacy(const struct hw_module_t* module, 317 const char* id, uint32_t halVersion, struct hw_device_t** device) { 318 // Not supporting legacy open 319 return -ENOSYS; 320 } 321 322 /******************************************************************************** 323 * Internal API 324 *******************************************************************************/ 325 326 /* 327 * Camera information tokens passed in response to the "list" factory query. 328 */ 329 330 /* Device name token. */ 331 static const char lListNameToken[] = "name="; 332 /* Frame dimensions token. */ 333 static const char lListDimsToken[] = "framedims="; 334 /* Facing direction token. */ 335 static const char lListDirToken[] = "dir="; 336 337 void EmulatedCameraFactory::createQemuCameras() 338 { 339 /* Obtain camera list. */ 340 char* camera_list = NULL; 341 status_t res = mQemuClient.listCameras(&camera_list); 342 /* Empty list, or list containing just an EOL means that there were no 343 * connected cameras found. */ 344 if (res != NO_ERROR || camera_list == NULL || *camera_list == '\0' || 345 *camera_list == '\n') { 346 if (camera_list != NULL) { 347 free(camera_list); 348 } 349 return; 350 } 351 352 /* 353 * Calculate number of connected cameras. Number of EOLs in the camera list 354 * is the number of the connected cameras. 355 */ 356 357 int num = 0; 358 const char* eol = strchr(camera_list, '\n'); 359 while (eol != NULL) { 360 num++; 361 eol = strchr(eol + 1, '\n'); 362 } 363 364 /* Allocate the array for emulated camera instances. Note that we allocate 365 * two more entries for back and front fake camera emulation. */ 366 mEmulatedCameras = new EmulatedBaseCamera*[num + 2]; 367 if (mEmulatedCameras == NULL) { 368 ALOGE("%s: Unable to allocate emulated camera array for %d entries", 369 __FUNCTION__, num + 1); 370 free(camera_list); 371 return; 372 } 373 memset(mEmulatedCameras, 0, sizeof(EmulatedBaseCamera*) * (num + 1)); 374 375 /* 376 * Iterate the list, creating, and initializin emulated qemu cameras for each 377 * entry (line) in the list. 378 */ 379 380 int index = 0; 381 char* cur_entry = camera_list; 382 while (cur_entry != NULL && *cur_entry != '\0' && index < num) { 383 /* Find the end of the current camera entry, and terminate it with zero 384 * for simpler string manipulation. */ 385 char* next_entry = strchr(cur_entry, '\n'); 386 if (next_entry != NULL) { 387 *next_entry = '\0'; 388 next_entry++; // Start of the next entry. 389 } 390 391 /* Find 'name', 'framedims', and 'dir' tokens that are required here. */ 392 char* name_start = strstr(cur_entry, lListNameToken); 393 char* dim_start = strstr(cur_entry, lListDimsToken); 394 char* dir_start = strstr(cur_entry, lListDirToken); 395 if (name_start != NULL && dim_start != NULL && dir_start != NULL) { 396 /* Advance to the token values. */ 397 name_start += strlen(lListNameToken); 398 dim_start += strlen(lListDimsToken); 399 dir_start += strlen(lListDirToken); 400 401 /* Terminate token values with zero. */ 402 char* s = strchr(name_start, ' '); 403 if (s != NULL) { 404 *s = '\0'; 405 } 406 s = strchr(dim_start, ' '); 407 if (s != NULL) { 408 *s = '\0'; 409 } 410 s = strchr(dir_start, ' '); 411 if (s != NULL) { 412 *s = '\0'; 413 } 414 415 /* Create and initialize qemu camera. */ 416 EmulatedQemuCamera* qemu_cam = 417 new EmulatedQemuCamera(index, &HAL_MODULE_INFO_SYM.common); 418 if (NULL != qemu_cam) { 419 res = qemu_cam->Initialize(name_start, dim_start, dir_start); 420 if (res == NO_ERROR) { 421 mEmulatedCameras[index] = qemu_cam; 422 index++; 423 } else { 424 delete qemu_cam; 425 } 426 } else { 427 ALOGE("%s: Unable to instantiate EmulatedQemuCamera", 428 __FUNCTION__); 429 } 430 } else { 431 ALOGW("%s: Bad camera information: %s", __FUNCTION__, cur_entry); 432 } 433 434 cur_entry = next_entry; 435 } 436 437 mEmulatedCameraNum = index; 438 } 439 440 bool EmulatedCameraFactory::isBackFakeCameraEmulationOn() 441 { 442 /* Defined by 'qemu.sf.fake_camera' boot property: if property exist, and 443 * is set to 'both', or 'back', then fake camera is used to emulate back 444 * camera. */ 445 char prop[PROPERTY_VALUE_MAX]; 446 if ((property_get("qemu.sf.fake_camera", prop, NULL) > 0) && 447 (!strcmp(prop, "both") || !strcmp(prop, "back"))) { 448 return true; 449 } else { 450 return false; 451 } 452 } 453 454 int EmulatedCameraFactory::getBackCameraHalVersion() 455 { 456 /* Defined by 'qemu.sf.back_camera_hal_version' boot property: if the 457 * property doesn't exist, it is assumed to be 1. */ 458 char prop[PROPERTY_VALUE_MAX]; 459 if (property_get("qemu.sf.back_camera_hal", prop, NULL) > 0) { 460 char *prop_end = prop; 461 int val = strtol(prop, &prop_end, 10); 462 if (*prop_end == '\0') { 463 return val; 464 } 465 // Badly formatted property, should just be a number 466 ALOGE("qemu.sf.back_camera_hal is not a number: %s", prop); 467 } 468 return 1; 469 } 470 471 bool EmulatedCameraFactory::isFrontFakeCameraEmulationOn() 472 { 473 /* Defined by 'qemu.sf.fake_camera' boot property: if property exist, and 474 * is set to 'both', or 'front', then fake camera is used to emulate front 475 * camera. */ 476 char prop[PROPERTY_VALUE_MAX]; 477 if ((property_get("qemu.sf.fake_camera", prop, NULL) > 0) && 478 (!strcmp(prop, "both") || !strcmp(prop, "front"))) { 479 return true; 480 } else { 481 return false; 482 } 483 } 484 485 int EmulatedCameraFactory::getFrontCameraHalVersion() 486 { 487 /* Defined by 'qemu.sf.front_camera_hal_version' boot property: if the 488 * property doesn't exist, it is assumed to be 1. */ 489 char prop[PROPERTY_VALUE_MAX]; 490 if (property_get("qemu.sf.front_camera_hal", prop, NULL) > 0) { 491 char *prop_end = prop; 492 int val = strtol(prop, &prop_end, 10); 493 if (*prop_end == '\0') { 494 return val; 495 } 496 // Badly formatted property, should just be a number 497 ALOGE("qemu.sf.front_camera_hal is not a number: %s", prop); 498 } 499 return 1; 500 } 501 502 void EmulatedCameraFactory::onStatusChanged(int cameraId, int newStatus) { 503 504 EmulatedBaseCamera *cam = mEmulatedCameras[cameraId]; 505 if (!cam) { 506 ALOGE("%s: Invalid camera ID %d", __FUNCTION__, cameraId); 507 return; 508 } 509 510 /** 511 * (Order is important) 512 * Send the callback first to framework, THEN close the camera. 513 */ 514 515 if (newStatus == cam->getHotplugStatus()) { 516 ALOGW("%s: Ignoring transition to the same status", __FUNCTION__); 517 return; 518 } 519 520 const camera_module_callbacks_t* cb = mCallbacks; 521 if (cb != NULL && cb->camera_device_status_change != NULL) { 522 cb->camera_device_status_change(cb, cameraId, newStatus); 523 } 524 525 if (newStatus == CAMERA_DEVICE_STATUS_NOT_PRESENT) { 526 cam->unplugCamera(); 527 } else if (newStatus == CAMERA_DEVICE_STATUS_PRESENT) { 528 cam->plugCamera(); 529 } 530 531 } 532 533 /******************************************************************************** 534 * Initializer for the static member structure. 535 *******************************************************************************/ 536 537 /* Entry point for camera HAL API. */ 538 struct hw_module_methods_t EmulatedCameraFactory::mCameraModuleMethods = { 539 open: EmulatedCameraFactory::device_open 540 }; 541 542 }; /* namespace android */ 543