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