summaryrefslogtreecommitdiff
path: root/v3/EmulatedCameraFactory.cpp (plain)
blob: ca77151bd45db1f8cddf9b801299fe44d5bf15e6
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 break;
307 }
308 }
309 return gEmulatedCameraFactory.getEmulatedCameraNum();
310}
311
312int EmulatedCameraFactory::get_camera_info(int camera_id,
313 struct camera_info* info)
314{
315 return gEmulatedCameraFactory.getCameraInfo(camera_id, info);
316}
317
318int EmulatedCameraFactory::set_callbacks(
319 const camera_module_callbacks_t *callbacks)
320{
321 return gEmulatedCameraFactory.setCallbacks(callbacks);
322}
323
324void EmulatedCameraFactory::get_vendor_tag_ops(vendor_tag_ops_t* ops)
325{
326 gEmulatedCameraFactory.getvendortagops(ops);
327}
328/********************************************************************************
329 * Internal API
330 *******************************************************************************/
331
332/*
333 * Camera information tokens passed in response to the "list" factory query.
334 */
335
336/* Device name token. */
337static const char lListNameToken[] = "name=";
338/* Frame dimensions token. */
339static const char lListDimsToken[] = "framedims=";
340/* Facing direction token. */
341static const char lListDirToken[] = "dir=";
342
343void EmulatedCameraFactory::createQemuCameras()
344{
345#if 0
346 /* Obtain camera list. */
347 char* camera_list = NULL;
348 status_t res = mQemuClient.listCameras(&camera_list);
349 /* Empty list, or list containing just an EOL means that there were no
350 * connected cameras found. */
351 if (res != NO_ERROR || camera_list == NULL || *camera_list == '\0' ||
352 *camera_list == '\n') {
353 if (camera_list != NULL) {
354 free(camera_list);
355 }
356 return;
357 }
358
359 /*
360 * Calculate number of connected cameras. Number of EOLs in the camera list
361 * is the number of the connected cameras.
362 */
363
364 int num = 0;
365 const char* eol = strchr(camera_list, '\n');
366 while (eol != NULL) {
367 num++;
368 eol = strchr(eol + 1, '\n');
369 }
370
371 /* Allocate the array for emulated camera instances. Note that we allocate
372 * two more entries for back and front fake camera emulation. */
373 mEmulatedCameras = new EmulatedBaseCamera*[num + 2];
374 if (mEmulatedCameras == NULL) {
375 ALOGE("%s: Unable to allocate emulated camera array for %d entries",
376 __FUNCTION__, num + 1);
377 free(camera_list);
378 return;
379 }
380 memset(mEmulatedCameras, 0, sizeof(EmulatedBaseCamera*) * (num + 1));
381
382 /*
383 * Iterate the list, creating, and initializin emulated qemu cameras for each
384 * entry (line) in the list.
385 */
386
387 int index = 0;
388 char* cur_entry = camera_list;
389 while (cur_entry != NULL && *cur_entry != '\0' && index < num) {
390 /* Find the end of the current camera entry, and terminate it with zero
391 * for simpler string manipulation. */
392 char* next_entry = strchr(cur_entry, '\n');
393 if (next_entry != NULL) {
394 *next_entry = '\0';
395 next_entry++; // Start of the next entry.
396 }
397
398 /* Find 'name', 'framedims', and 'dir' tokens that are required here. */
399 char* name_start = strstr(cur_entry, lListNameToken);
400 char* dim_start = strstr(cur_entry, lListDimsToken);
401 char* dir_start = strstr(cur_entry, lListDirToken);
402 if (name_start != NULL && dim_start != NULL && dir_start != NULL) {
403 /* Advance to the token values. */
404 name_start += strlen(lListNameToken);
405 dim_start += strlen(lListDimsToken);
406 dir_start += strlen(lListDirToken);
407
408 /* Terminate token values with zero. */
409 char* s = strchr(name_start, ' ');
410 if (s != NULL) {
411 *s = '\0';
412 }
413 s = strchr(dim_start, ' ');
414 if (s != NULL) {
415 *s = '\0';
416 }
417 s = strchr(dir_start, ' ');
418 if (s != NULL) {
419 *s = '\0';
420 }
421
422 /* Create and initialize qemu camera. */
423 EmulatedQemuCamera* qemu_cam =
424 new EmulatedQemuCamera(index, &HAL_MODULE_INFO_SYM.common);
425 if (NULL != qemu_cam) {
426 res = qemu_cam->Initialize(name_start, dim_start, dir_start);
427 if (res == NO_ERROR) {
428 mEmulatedCameras[index] = qemu_cam;
429 index++;
430 } else {
431 delete qemu_cam;
432 }
433 } else {
434 ALOGE("%s: Unable to instantiate EmulatedQemuCamera",
435 __FUNCTION__);
436 }
437 } else {
438 ALOGW("%s: Bad camera information: %s", __FUNCTION__, cur_entry);
439 }
440
441 cur_entry = next_entry;
442 }
443
444 mEmulatedCameraNum = index;
445#else
446 CAMHAL_LOGDA("delete this function");
447#endif
448}
449
450bool EmulatedCameraFactory::isFakeCameraFacingBack(int cameraId)
451{
452 if (cameraId%mEmulatedCameraNum == 1)
453 return false;
454
455 return true;
456}
457
458int EmulatedCameraFactory::getFakeCameraHalVersion(int cameraId)
459{
460 /* Defined by 'qemu.sf.back_camera_hal_version' boot property: if the
461 * property doesn't exist, it is assumed to be 1. */
462#if 0
463 char prop[PROPERTY_VALUE_MAX];
464 if (property_get("qemu.sf.back_camera_hal", prop, NULL) > 0) {
465 char *prop_end = prop;
466 int val = strtol(prop, &prop_end, 10);
467 if (*prop_end == '\0') {
468 return val;
469 }
470 // Badly formatted property, should just be a number
471 ALOGE("qemu.sf.back_camera_hal is not a number: %s", prop);
472 }
473 return 1;
474#else
475 cameraId = cameraId;
476 return 3;
477#endif
478}
479
480void EmulatedCameraFactory::onStatusChanged(int cameraId, int newStatus)
481{
482 status_t res;
483 char dev_name[128];
484 int i = 0 , j = 0;
485 int m = 0, n = 0;
486 //EmulatedBaseCamera *cam = mEmulatedCameras[cameraId];
487 const camera_module_callbacks_t* cb = mCallbacks;
488 sprintf(dev_name, "%s%d", "/dev/video", cameraId);
489
490 /* ignore cameraid >= MAX_CAMERA_NUM to avoid overflow, we now have
491 * ion device with device like /dev/video13
492 */
493 if (cameraId >= MAX_CAMERA_NUM)
494 return;
495
496 CAMHAL_LOGDB("mEmulatedCameraNum =%d\n", mEmulatedCameraNum);
497 n = getValidCameraOjectId();
498 if ((n != cameraId) && (mEmulatedCameras[n] != NULL)) {
499 DBG_LOGA("device node changed");
500 mEmulatedCameras[n]->unplugCamera();
501 delete mEmulatedCameras[n];
502 mEmulatedCameras[n] = NULL;
503 }
504
505 if (mEmulatedCameras[cameraId] != NULL && (!mEmulatedCameras[cameraId]->getHotplugStatus())) {
506 DBG_LOGA("close EmulatedFakeCamera3 object for the last time");
507 delete mEmulatedCameras[cameraId];
508 mEmulatedCameras[cameraId] = NULL;
509 }
510
511 EmulatedBaseCamera *cam = mEmulatedCameras[cameraId];
512
513 if ((!cam) && (newStatus == CAMERA_DEVICE_STATUS_PRESENT)) {
514 /*suppose only usb camera produce uevent, and it is facing back*/
515 cam = new EmulatedFakeCamera3(cameraId, &HAL_MODULE_INFO_SYM.common);
516 if (cam != NULL) {
517 CAMHAL_LOGDB("%s: new camera device version is %d", __FUNCTION__,
518 getFakeCameraHalVersion(cameraId));
519 //sleep 10ms for /dev/video* create
520 usleep(50000);
521 while (i < 20) {
522 if (0 == access(dev_name, F_OK | R_OK | W_OK)) {
523 DBG_LOGB("access %s success\n", dev_name);
524 break;
525 } else {
526 CAMHAL_LOGDB("access %s fail , i = %d .\n", dev_name,i);
527 usleep(50000);
528 i++;
529 }
530 }
531 res = cam->Initialize();
532 if (res != NO_ERROR) {
533 ALOGE("%s: Unable to intialize camera %d: %s (%d)",
534 __FUNCTION__, cameraId, strerror(-res), res);
535 delete cam;
536 return ;
537 }
538
539 /* Open the camera. then send the callback to framework*/
540 mEmulatedCameras[cameraId] = cam;
541 mEmulatedCameraNum ++;
542 cam->plugCamera();
543 if (cb != NULL && cb->camera_device_status_change != NULL) {
544 cb->camera_device_status_change(cb, cameraId, newStatus);
545 }
546 }
547 return ;
548 }
549
550 CAMHAL_LOGDB("mEmulatedCameraNum =%d\n", mEmulatedCameraNum);
551
552 /**
553 * (Order is important)
554 * Send the callback first to framework, THEN close the camera.
555 */
556
557 if (newStatus == cam->getHotplugStatus()) {
558 CAMHAL_LOGDB("%s: Ignoring transition to the same status", __FUNCTION__);
559 return;
560 }
561
562/*here we don't notify cameraservice close camera, let app to close camera, or will generate crash*/
563#if 0
564 CAMHAL_LOGDB("mEmulatedCameraNum =%d\n", mEmulatedCameraNum);
565 if (cb != NULL && cb->camera_device_status_change != NULL) {
566 cb->camera_device_status_change(cb, cameraId, newStatus);
567 }
568#endif
569
570 CAMHAL_LOGDB("mEmulatedCameraNum =%d\n", mEmulatedCameraNum);
571
572 if (newStatus == CAMERA_DEVICE_STATUS_NOT_PRESENT) {
573 mEmulatedCameraNum --;
574 j = getValidCameraOjectId();
575 while (m < 200) {
576 if (mEmulatedCameras[j] != NULL) {
577 if (mEmulatedCameras[j]->getCameraStatus()) {
578 DBG_LOGA("start to delete EmulatedFakeCamera3 object");
579 cam->unplugCamera();
580 delete mEmulatedCameras[j];
581 mEmulatedCameras[j] = NULL;
582 } else {
583 usleep(5000);
584 m++;
585 }
586 } else {
587 break;
588 }
589 }
590 if (m == 200) {
591 cam->unplugCamera();
592 }
593 } else if (newStatus == CAMERA_DEVICE_STATUS_PRESENT) {
594 CAMHAL_LOGDA("camera plugged again?\n");
595 cam->plugCamera();
596 }
597 CAMHAL_LOGDB("mEmulatedCameraNum =%d\n", mEmulatedCameraNum);
598
599}
600
601/********************************************************************************
602 * Initializer for the static member structure.
603 *******************************************************************************/
604
605/* Entry point for camera HAL API. */
606struct hw_module_methods_t EmulatedCameraFactory::mCameraModuleMethods = {
607 open: EmulatedCameraFactory::device_open
608};
609
610}; /* namespace android */
611