summaryrefslogtreecommitdiff
path: root/v3/EmulatedCameraFactory.cpp (plain)
blob: c5b255d14e374c081f68d4c6333ef83844b2de49
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_NDDEBUG 0
24//#define LOG_NIDEBUG 0
25#define LOG_TAG "EmulatedCamera_Factory"
26#include <cutils/log.h>
27#include <cutils/properties.h>
28#include "EmulatedQemuCamera.h"
29#include "EmulatedFakeCamera.h"
30#include "EmulatedFakeCamera2.h"
31#include "EmulatedFakeCamera3.h"
32#include "EmulatedCameraHotplugThread.h"
33#include "EmulatedCameraFactory.h"
34
35extern camera_module_t HAL_MODULE_INFO_SYM;
36volatile int32_t gCamHal_LogLevel = 4;
37
38/* A global instance of EmulatedCameraFactory is statically instantiated and
39 * initialized when camera emulation HAL is loaded.
40 */
41android::EmulatedCameraFactory gEmulatedCameraFactory;
42default_camera_hal::VendorTags gVendorTags;
43
44static const char *SENSOR_PATH[]={
45 "/dev/video0",
46 "/dev/video1",
47 "/dev/video2",
48 "/dev/video3",
49 "/dev/video4",
50 "/dev/video5",
51};
52
53int updateLogLevels()
54{
55 char levels_value[92];
56 int tmp = 4;
57 if (property_get("camera.log_levels", levels_value, NULL) > 0)
58 sscanf(levels_value, "%d", &tmp);
59 else
60 ALOGD("Can not read property camera.log_levels, using defalut value\n");
61 gCamHal_LogLevel = tmp;
62 return tmp;
63}
64
65static int getCameraNum() {
66 int iCamerasNum = 0;
67 for (int i = 0; i < (int)ARRAY_SIZE(SENSOR_PATH); i++ ) {
68 int camera_fd;
69 CAMHAL_LOGDB("try access %s\n", SENSOR_PATH[i]);
70 if (0 == access(SENSOR_PATH[i], F_OK | R_OK | W_OK)) {
71 CAMHAL_LOGDB("access %s success\n", SENSOR_PATH[i]);
72 iCamerasNum++;
73 }
74 }
75
76 return iCamerasNum;
77}
78namespace android {
79
80EmulatedCameraFactory::EmulatedCameraFactory()
81 : mQemuClient(),
82 mEmulatedCameraNum(0),
83 mFakeCameraNum(0),
84 mConstructedOK(false),
85 mCallbacks(NULL)
86{
87 status_t res;
88 /* Connect to the factory service in the emulator, and create Qemu cameras. */
89 int cameraId = 0;
90
91 memset(mEmulatedCameras, 0,(MAX_CAMERA_NUM) * sizeof(EmulatedBaseCamera*));
92 mEmulatedCameraNum = getCameraNum();
93 CAMHAL_LOGDB("Camera num = %d", mEmulatedCameraNum);
94
95 for( int i = 0; i < mEmulatedCameraNum; i++ ) {
96 cameraId = i;
97 mEmulatedCameras[i] = new EmulatedFakeCamera3(cameraId, &HAL_MODULE_INFO_SYM.common);
98 if (mEmulatedCameras[i] != NULL) {
99 ALOGV("%s: camera device version is %d", __FUNCTION__,
100 getFakeCameraHalVersion(cameraId));
101 res = mEmulatedCameras[i]->Initialize();
102 if (res != NO_ERROR) {
103 ALOGE("%s: Unable to intialize camera %d: %s (%d)",
104 __FUNCTION__, i, strerror(-res), res);
105 delete mEmulatedCameras[i];
106 }
107 }
108 }
109
110 CAMHAL_LOGDB("%d cameras are being created",
111 mEmulatedCameraNum);
112
113 /* Create hotplug thread */
114 {
115 Vector<int> cameraIdVector;
116 for (int i = 0; i < mEmulatedCameraNum; ++i) {
117 cameraIdVector.push_back(i);
118 }
119 mHotplugThread = new EmulatedCameraHotplugThread(&cameraIdVector[0],
120 mEmulatedCameraNum);
121 mHotplugThread->run("");
122 }
123
124 mConstructedOK = true;
125}
126
127EmulatedCameraFactory::~EmulatedCameraFactory()
128{
129 CAMHAL_LOGDA("Camera Factory deconstruct the BaseCamera\n");
130 for (int n = 0; n < mEmulatedCameraNum; n++) {
131 if (mEmulatedCameras[n] != NULL) {
132 delete mEmulatedCameras[n];
133 }
134 }
135
136 if (mHotplugThread != NULL) {
137 mHotplugThread->requestExit();
138 mHotplugThread->join();
139 }
140}
141
142int EmulatedCameraFactory::getValidCameraId() {
143 int iValidId = 0;
144 for (int i = 0; i < MAX_CAMERA_NUM; i++ ) {
145 if (0 == access(SENSOR_PATH[i], F_OK | R_OK | W_OK)) {
146 iValidId = i;
147 break;
148 }
149 }
150 return iValidId;
151}
152
153/****************************************************************************
154 * Camera HAL API handlers.
155 *
156 * Each handler simply verifies existence of an appropriate EmulatedBaseCamera
157 * instance, and dispatches the call to that instance.
158 *
159 ***************************************************************************/
160
161int EmulatedCameraFactory::cameraDeviceOpen(int camera_id, hw_device_t** device)
162{
163 ALOGV("%s: id = %d", __FUNCTION__, camera_id);
164 int valid_id;
165 *device = NULL;
166
167 updateLogLevels();
168
169 if (!isConstructedOK()) {
170 ALOGE("%s: EmulatedCameraFactory has failed to initialize", __FUNCTION__);
171 return -EINVAL;
172 }
173
174 if (camera_id < 0 || camera_id >= getEmulatedCameraNum()) {
175 ALOGE("%s: Camera id %d is out of bounds (%d)",
176 __FUNCTION__, camera_id, getEmulatedCameraNum());
177 return -ENODEV;
178 }
179 valid_id = getValidCameraId();
180 //return mEmulatedCameras[camera_id]->connectCamera(device);
181 return mEmulatedCameras[valid_id]->connectCamera(device);
182}
183
184int EmulatedCameraFactory::getCameraInfo(int camera_id, struct camera_info* info)
185{
186 ALOGV("%s: id = %d", __FUNCTION__, camera_id);
187 int valid_id;
188 if (!isConstructedOK()) {
189 ALOGE("%s: EmulatedCameraFactory has failed to initialize", __FUNCTION__);
190 return -EINVAL;
191 }
192
193 if (camera_id < 0 || camera_id >= getEmulatedCameraNum()) {
194 ALOGE("%s: Camera id %d is out of bounds (%d)",
195 __FUNCTION__, camera_id, getEmulatedCameraNum());
196 return -ENODEV;
197 }
198 valid_id = getValidCameraId();
199 //return mEmulatedCameras[camera_id]->getCameraInfo(info);
200 return mEmulatedCameras[valid_id]->getCameraInfo(info);
201}
202
203int EmulatedCameraFactory::setCallbacks(
204 const camera_module_callbacks_t *callbacks)
205{
206 ALOGV("%s: callbacks = %p", __FUNCTION__, callbacks);
207
208 mCallbacks = callbacks;
209
210 return OK;
211}
212
213static int get_tag_count(const vendor_tag_ops_t* ops)
214{
215 return gVendorTags.getTagCount(ops);
216}
217static void get_all_tags(const vendor_tag_ops_t* ops, uint32_t* tag_array)
218{
219 gVendorTags.getAllTags(ops, tag_array);
220}
221static const char* get_section_name(const vendor_tag_ops_t* ops, uint32_t tag)
222{
223 return gVendorTags.getSectionName(ops, tag);
224}
225static const char* get_tag_name(const vendor_tag_ops_t* ops, uint32_t tag)
226{
227 return gVendorTags.getTagName(ops, tag);
228}
229static int get_tag_type(const vendor_tag_ops_t* ops, uint32_t tag)
230{
231 return gVendorTags.getTagType(ops, tag);
232}
233void EmulatedCameraFactory::getvendortagops(vendor_tag_ops_t* ops)
234{
235 ALOGV("%s : ops=%p", __func__, ops);
236 ops->get_tag_count = get_tag_count;
237 ops->get_all_tags = get_all_tags;
238 ops->get_section_name = get_section_name;
239 ops->get_tag_name = get_tag_name;
240 ops->get_tag_type = get_tag_type;
241}
242/****************************************************************************
243 * Camera HAL API callbacks.
244 ***************************************************************************/
245
246EmulatedBaseCamera* EmulatedCameraFactory::getValidCameraOject()
247{
248 EmulatedBaseCamera* cam = NULL;
249 for (int i = 0; i < MAX_CAMERA_NUM; i++) {
250 if (mEmulatedCameras[i] != NULL) {
251 cam = mEmulatedCameras[i];
252 break;
253 }
254 }
255 return cam;
256}
257
258int EmulatedCameraFactory::getValidCameraOjectId()
259{
260 int j =0;
261 for (int i = 0; i < MAX_CAMERA_NUM; i++) {
262 if (mEmulatedCameras[i] != NULL) {
263 j = i;
264 break;
265 }
266 }
267 return j;
268}
269
270int EmulatedCameraFactory::device_open(const hw_module_t* module,
271 const char* name,
272 hw_device_t** device)
273{
274 /*
275 * Simply verify the parameters, and dispatch the call inside the
276 * EmulatedCameraFactory instance.
277 */
278
279 if (module != &HAL_MODULE_INFO_SYM.common) {
280 ALOGE("%s: Invalid module %p expected %p",
281 __FUNCTION__, module, &HAL_MODULE_INFO_SYM.common);
282 return -EINVAL;
283 }
284 if (name == NULL) {
285 ALOGE("%s: NULL name is not expected here", __FUNCTION__);
286 return -EINVAL;
287 }
288
289 return gEmulatedCameraFactory.cameraDeviceOpen(atoi(name), device);
290}
291
292int EmulatedCameraFactory::get_number_of_cameras(void)
293{
294 int i = 0;
295 EmulatedBaseCamera* cam = gEmulatedCameraFactory.getValidCameraOject();
296 while (i < 6) {
297 if (cam != NULL) {
298 if (!cam->getHotplugStatus()) {
299 DBG_LOGA("here we wait usb camera plug");
300 usleep(50000);
301 i++;
302 } else {
303 break;
304 }
305 } else {
306 DBG_LOGB("%s : cam is NULL", __FUNCTION__);
307 break;
308 }
309 }
310 return gEmulatedCameraFactory.getEmulatedCameraNum();
311}
312
313int EmulatedCameraFactory::get_camera_info(int camera_id,
314 struct camera_info* info)
315{
316 return gEmulatedCameraFactory.getCameraInfo(camera_id, info);
317}
318
319int EmulatedCameraFactory::set_callbacks(
320 const camera_module_callbacks_t *callbacks)
321{
322 return gEmulatedCameraFactory.setCallbacks(callbacks);
323}
324
325void EmulatedCameraFactory::get_vendor_tag_ops(vendor_tag_ops_t* ops)
326{
327 gEmulatedCameraFactory.getvendortagops(ops);
328}
329/********************************************************************************
330 * Internal API
331 *******************************************************************************/
332
333/*
334 * Camera information tokens passed in response to the "list" factory query.
335 */
336
337/* Device name token. */
338static const char lListNameToken[] = "name=";
339/* Frame dimensions token. */
340static const char lListDimsToken[] = "framedims=";
341/* Facing direction token. */
342static const char lListDirToken[] = "dir=";
343
344void EmulatedCameraFactory::createQemuCameras()
345{
346#if 0
347 /* Obtain camera list. */
348 char* camera_list = NULL;
349 status_t res = mQemuClient.listCameras(&camera_list);
350 /* Empty list, or list containing just an EOL means that there were no
351 * connected cameras found. */
352 if (res != NO_ERROR || camera_list == NULL || *camera_list == '\0' ||
353 *camera_list == '\n') {
354 if (camera_list != NULL) {
355 free(camera_list);
356 }
357 return;
358 }
359
360 /*
361 * Calculate number of connected cameras. Number of EOLs in the camera list
362 * is the number of the connected cameras.
363 */
364
365 int num = 0;
366 const char* eol = strchr(camera_list, '\n');
367 while (eol != NULL) {
368 num++;
369 eol = strchr(eol + 1, '\n');
370 }
371
372 /* Allocate the array for emulated camera instances. Note that we allocate
373 * two more entries for back and front fake camera emulation. */
374 mEmulatedCameras = new EmulatedBaseCamera*[num + 2];
375 if (mEmulatedCameras == NULL) {
376 ALOGE("%s: Unable to allocate emulated camera array for %d entries",
377 __FUNCTION__, num + 1);
378 free(camera_list);
379 return;
380 }
381 memset(mEmulatedCameras, 0, sizeof(EmulatedBaseCamera*) * (num + 1));
382
383 /*
384 * Iterate the list, creating, and initializin emulated qemu cameras for each
385 * entry (line) in the list.
386 */
387
388 int index = 0;
389 char* cur_entry = camera_list;
390 while (cur_entry != NULL && *cur_entry != '\0' && index < num) {
391 /* Find the end of the current camera entry, and terminate it with zero
392 * for simpler string manipulation. */
393 char* next_entry = strchr(cur_entry, '\n');
394 if (next_entry != NULL) {
395 *next_entry = '\0';
396 next_entry++; // Start of the next entry.
397 }
398
399 /* Find 'name', 'framedims', and 'dir' tokens that are required here. */
400 char* name_start = strstr(cur_entry, lListNameToken);
401 char* dim_start = strstr(cur_entry, lListDimsToken);
402 char* dir_start = strstr(cur_entry, lListDirToken);
403 if (name_start != NULL && dim_start != NULL && dir_start != NULL) {
404 /* Advance to the token values. */
405 name_start += strlen(lListNameToken);
406 dim_start += strlen(lListDimsToken);
407 dir_start += strlen(lListDirToken);
408
409 /* Terminate token values with zero. */
410 char* s = strchr(name_start, ' ');
411 if (s != NULL) {
412 *s = '\0';
413 }
414 s = strchr(dim_start, ' ');
415 if (s != NULL) {
416 *s = '\0';
417 }
418 s = strchr(dir_start, ' ');
419 if (s != NULL) {
420 *s = '\0';
421 }
422
423 /* Create and initialize qemu camera. */
424 EmulatedQemuCamera* qemu_cam =
425 new EmulatedQemuCamera(index, &HAL_MODULE_INFO_SYM.common);
426 if (NULL != qemu_cam) {
427 res = qemu_cam->Initialize(name_start, dim_start, dir_start);
428 if (res == NO_ERROR) {
429 mEmulatedCameras[index] = qemu_cam;
430 index++;
431 } else {
432 delete qemu_cam;
433 }
434 } else {
435 ALOGE("%s: Unable to instantiate EmulatedQemuCamera",
436 __FUNCTION__);
437 }
438 } else {
439 ALOGW("%s: Bad camera information: %s", __FUNCTION__, cur_entry);
440 }
441
442 cur_entry = next_entry;
443 }
444
445 mEmulatedCameraNum = index;
446#else
447 CAMHAL_LOGDA("delete this function");
448#endif
449}
450
451bool EmulatedCameraFactory::isFakeCameraFacingBack(int cameraId)
452{
453 if (cameraId%mEmulatedCameraNum == 1)
454 return false;
455
456 return true;
457}
458
459int EmulatedCameraFactory::getFakeCameraHalVersion(int cameraId)
460{
461 /* Defined by 'qemu.sf.back_camera_hal_version' boot property: if the
462 * property doesn't exist, it is assumed to be 1. */
463#if 0
464 char prop[PROPERTY_VALUE_MAX];
465 if (property_get("qemu.sf.back_camera_hal", prop, NULL) > 0) {
466 char *prop_end = prop;
467 int val = strtol(prop, &prop_end, 10);
468 if (*prop_end == '\0') {
469 return val;
470 }
471 // Badly formatted property, should just be a number
472 ALOGE("qemu.sf.back_camera_hal is not a number: %s", prop);
473 }
474 return 1;
475#else
476 cameraId = cameraId;
477 return 3;
478#endif
479}
480
481void EmulatedCameraFactory::onStatusChanged(int cameraId, int newStatus)
482{
483 status_t res;
484 char dev_name[128];
485 int i = 0 , j = 0;
486 int m = 0, n = 0;
487 int k = 0;
488 //EmulatedBaseCamera *cam = mEmulatedCameras[cameraId];
489 const camera_module_callbacks_t* cb = mCallbacks;
490 sprintf(dev_name, "%s%d", "/dev/video", cameraId);
491
492 /* ignore cameraid >= MAX_CAMERA_NUM to avoid overflow, we now have
493 * ion device with device like /dev/video13
494 */
495 if (cameraId >= MAX_CAMERA_NUM)
496 return;
497
498 CAMHAL_LOGDB("mEmulatedCameraNum =%d\n", mEmulatedCameraNum);
499 n = getValidCameraOjectId();
500 if ((n != cameraId) && (mEmulatedCameras[n] != NULL)) {
501 DBG_LOGA("device node changed");
502 mEmulatedCameras[n]->unplugCamera();
503 delete mEmulatedCameras[n];
504 mEmulatedCameras[n] = NULL;
505 }
506
507 if (mEmulatedCameras[cameraId] != NULL && (!mEmulatedCameras[cameraId]->getHotplugStatus())) {
508 DBG_LOGA("close EmulatedFakeCamera3 object for the last time");
509 while (k < 150) {
510 if (!(mEmulatedCameras[cameraId]->getCameraStatus())) {
511 usleep(10000);
512 k++;
513 } else {
514 break;
515 }
516 }
517 if (k == 150) {
518 DBG_LOGA("wait 1s, but camera still not closed , it's abnormal status.\n");
519 return;
520 }
521 delete mEmulatedCameras[cameraId];
522 mEmulatedCameras[cameraId] = NULL;
523 }
524
525 EmulatedBaseCamera *cam = mEmulatedCameras[cameraId];
526
527 if ((!cam) && (newStatus == CAMERA_DEVICE_STATUS_PRESENT)) {
528 /*suppose only usb camera produce uevent, and it is facing back*/
529 cam = new EmulatedFakeCamera3(cameraId, &HAL_MODULE_INFO_SYM.common);
530 if (cam != NULL) {
531 CAMHAL_LOGDB("%s: new camera device version is %d", __FUNCTION__,
532 getFakeCameraHalVersion(cameraId));
533 //sleep 10ms for /dev/video* create
534 usleep(50000);
535 while (i < 20) {
536 if (0 == access(dev_name, F_OK | R_OK | W_OK)) {
537 DBG_LOGB("access %s success\n", dev_name);
538 break;
539 } else {
540 CAMHAL_LOGDB("access %s fail , i = %d .\n", dev_name,i);
541 usleep(50000);
542 i++;
543 }
544 }
545 res = cam->Initialize();
546 if (res != NO_ERROR) {
547 ALOGE("%s: Unable to intialize camera %d: %s (%d)",
548 __FUNCTION__, cameraId, strerror(-res), res);
549 delete cam;
550 return ;
551 }
552
553 /* Open the camera. then send the callback to framework*/
554 mEmulatedCameras[cameraId] = cam;
555 mEmulatedCameraNum ++;
556 cam->plugCamera();
557 if (cb != NULL && cb->camera_device_status_change != NULL) {
558 cb->camera_device_status_change(cb, cameraId, newStatus);
559 }
560 }
561 return ;
562 }
563
564 CAMHAL_LOGDB("mEmulatedCameraNum =%d\n", mEmulatedCameraNum);
565
566 /**
567 * (Order is important)
568 * Send the callback first to framework, THEN close the camera.
569 */
570
571 if (newStatus == cam->getHotplugStatus()) {
572 CAMHAL_LOGDB("%s: Ignoring transition to the same status", __FUNCTION__);
573 return;
574 }
575
576/*here we don't notify cameraservice close camera, let app to close camera, or will generate crash*/
577#if 0
578 CAMHAL_LOGDB("mEmulatedCameraNum =%d\n", mEmulatedCameraNum);
579 if (cb != NULL && cb->camera_device_status_change != NULL) {
580 cb->camera_device_status_change(cb, cameraId, newStatus);
581 }
582#endif
583
584 CAMHAL_LOGDB("mEmulatedCameraNum =%d\n", mEmulatedCameraNum);
585
586 if (newStatus == CAMERA_DEVICE_STATUS_NOT_PRESENT) {
587 mEmulatedCameraNum --;
588 j = getValidCameraOjectId();
589 while (m < 200) {
590 if (mEmulatedCameras[j] != NULL) {
591 if (mEmulatedCameras[j]->getCameraStatus()) {
592 DBG_LOGA("start to delete EmulatedFakeCamera3 object");
593 cam->unplugCamera();
594 delete mEmulatedCameras[j];
595 mEmulatedCameras[j] = NULL;
596 } else {
597 usleep(5000);
598 m++;
599 }
600 } else {
601 break;
602 }
603 }
604 if (m == 200) {
605 cam->unplugCamera();
606 }
607 } else if (newStatus == CAMERA_DEVICE_STATUS_PRESENT) {
608 CAMHAL_LOGDA("camera plugged again?\n");
609 cam->plugCamera();
610 }
611 CAMHAL_LOGDB("mEmulatedCameraNum =%d\n", mEmulatedCameraNum);
612
613}
614
615/********************************************************************************
616 * Initializer for the static member structure.
617 *******************************************************************************/
618
619/* Entry point for camera HAL API. */
620struct hw_module_methods_t EmulatedCameraFactory::mCameraModuleMethods = {
621 open: EmulatedCameraFactory::device_open
622};
623
624}; /* namespace android */
625