summaryrefslogtreecommitdiff
path: root/v3/EmulatedCameraFactory.cpp (plain)
blob: eea5127cfe6250f1f2c035e95aca029cca9fc60c
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
130/****************************************************************************
131 * Camera HAL API handlers.
132 *
133 * Each handler simply verifies existence of an appropriate EmulatedBaseCamera
134 * instance, and dispatches the call to that instance.
135 *
136 ***************************************************************************/
137
138int EmulatedCameraFactory::cameraDeviceOpen(int camera_id, hw_device_t** device)
139{
140 ALOGV("%s: id = %d", __FUNCTION__, camera_id);
141
142 *device = NULL;
143
144 if (!isConstructedOK()) {
145 ALOGE("%s: EmulatedCameraFactory has failed to initialize", __FUNCTION__);
146 return -EINVAL;
147 }
148
149 if (camera_id < 0 || camera_id >= getEmulatedCameraNum()) {
150 ALOGE("%s: Camera id %d is out of bounds (%d)",
151 __FUNCTION__, camera_id, getEmulatedCameraNum());
152 return -ENODEV;
153 }
154
155 return mEmulatedCameras[camera_id]->connectCamera(device);
156}
157
158int EmulatedCameraFactory::getCameraInfo(int camera_id, struct camera_info* info)
159{
160 ALOGV("%s: id = %d", __FUNCTION__, camera_id);
161
162 if (!isConstructedOK()) {
163 ALOGE("%s: EmulatedCameraFactory has failed to initialize", __FUNCTION__);
164 return -EINVAL;
165 }
166
167 if (camera_id < 0 || camera_id >= getEmulatedCameraNum()) {
168 ALOGE("%s: Camera id %d is out of bounds (%d)",
169 __FUNCTION__, camera_id, getEmulatedCameraNum());
170 return -ENODEV;
171 }
172
173 return mEmulatedCameras[camera_id]->getCameraInfo(info);
174}
175
176int EmulatedCameraFactory::setCallbacks(
177 const camera_module_callbacks_t *callbacks)
178{
179 ALOGV("%s: callbacks = %p", __FUNCTION__, callbacks);
180
181 mCallbacks = callbacks;
182
183 return OK;
184}
185
186static int get_tag_count(const vendor_tag_ops_t* ops)
187{
188 return gVendorTags.getTagCount(ops);
189}
190static void get_all_tags(const vendor_tag_ops_t* ops, uint32_t* tag_array)
191{
192 gVendorTags.getAllTags(ops, tag_array);
193}
194static const char* get_section_name(const vendor_tag_ops_t* ops, uint32_t tag)
195{
196 return gVendorTags.getSectionName(ops, tag);
197}
198static const char* get_tag_name(const vendor_tag_ops_t* ops, uint32_t tag)
199{
200 return gVendorTags.getTagName(ops, tag);
201}
202static int get_tag_type(const vendor_tag_ops_t* ops, uint32_t tag)
203{
204 return gVendorTags.getTagType(ops, tag);
205}
206void EmulatedCameraFactory::getvendortagops(vendor_tag_ops_t* ops)
207{
208 ALOGV("%s : ops=%p", __func__, ops);
209 ops->get_tag_count = get_tag_count;
210 ops->get_all_tags = get_all_tags;
211 ops->get_section_name = get_section_name;
212 ops->get_tag_name = get_tag_name;
213 ops->get_tag_type = get_tag_type;
214}
215/****************************************************************************
216 * Camera HAL API callbacks.
217 ***************************************************************************/
218
219int EmulatedCameraFactory::device_open(const hw_module_t* module,
220 const char* name,
221 hw_device_t** device)
222{
223 /*
224 * Simply verify the parameters, and dispatch the call inside the
225 * EmulatedCameraFactory instance.
226 */
227
228 if (module != &HAL_MODULE_INFO_SYM.common) {
229 ALOGE("%s: Invalid module %p expected %p",
230 __FUNCTION__, module, &HAL_MODULE_INFO_SYM.common);
231 return -EINVAL;
232 }
233 if (name == NULL) {
234 ALOGE("%s: NULL name is not expected here", __FUNCTION__);
235 return -EINVAL;
236 }
237
238 return gEmulatedCameraFactory.cameraDeviceOpen(atoi(name), device);
239}
240
241int EmulatedCameraFactory::get_number_of_cameras(void)
242{
243 return gEmulatedCameraFactory.getEmulatedCameraNum();
244}
245
246int EmulatedCameraFactory::get_camera_info(int camera_id,
247 struct camera_info* info)
248{
249 return gEmulatedCameraFactory.getCameraInfo(camera_id, info);
250}
251
252int EmulatedCameraFactory::set_callbacks(
253 const camera_module_callbacks_t *callbacks)
254{
255 return gEmulatedCameraFactory.setCallbacks(callbacks);
256}
257
258void EmulatedCameraFactory::get_vendor_tag_ops(vendor_tag_ops_t* ops)
259{
260 gEmulatedCameraFactory.getvendortagops(ops);
261}
262/********************************************************************************
263 * Internal API
264 *******************************************************************************/
265
266/*
267 * Camera information tokens passed in response to the "list" factory query.
268 */
269
270/* Device name token. */
271static const char lListNameToken[] = "name=";
272/* Frame dimensions token. */
273static const char lListDimsToken[] = "framedims=";
274/* Facing direction token. */
275static const char lListDirToken[] = "dir=";
276
277void EmulatedCameraFactory::createQemuCameras()
278{
279#if 0
280 /* Obtain camera list. */
281 char* camera_list = NULL;
282 status_t res = mQemuClient.listCameras(&camera_list);
283 /* Empty list, or list containing just an EOL means that there were no
284 * connected cameras found. */
285 if (res != NO_ERROR || camera_list == NULL || *camera_list == '\0' ||
286 *camera_list == '\n') {
287 if (camera_list != NULL) {
288 free(camera_list);
289 }
290 return;
291 }
292
293 /*
294 * Calculate number of connected cameras. Number of EOLs in the camera list
295 * is the number of the connected cameras.
296 */
297
298 int num = 0;
299 const char* eol = strchr(camera_list, '\n');
300 while (eol != NULL) {
301 num++;
302 eol = strchr(eol + 1, '\n');
303 }
304
305 /* Allocate the array for emulated camera instances. Note that we allocate
306 * two more entries for back and front fake camera emulation. */
307 mEmulatedCameras = new EmulatedBaseCamera*[num + 2];
308 if (mEmulatedCameras == NULL) {
309 ALOGE("%s: Unable to allocate emulated camera array for %d entries",
310 __FUNCTION__, num + 1);
311 free(camera_list);
312 return;
313 }
314 memset(mEmulatedCameras, 0, sizeof(EmulatedBaseCamera*) * (num + 1));
315
316 /*
317 * Iterate the list, creating, and initializin emulated qemu cameras for each
318 * entry (line) in the list.
319 */
320
321 int index = 0;
322 char* cur_entry = camera_list;
323 while (cur_entry != NULL && *cur_entry != '\0' && index < num) {
324 /* Find the end of the current camera entry, and terminate it with zero
325 * for simpler string manipulation. */
326 char* next_entry = strchr(cur_entry, '\n');
327 if (next_entry != NULL) {
328 *next_entry = '\0';
329 next_entry++; // Start of the next entry.
330 }
331
332 /* Find 'name', 'framedims', and 'dir' tokens that are required here. */
333 char* name_start = strstr(cur_entry, lListNameToken);
334 char* dim_start = strstr(cur_entry, lListDimsToken);
335 char* dir_start = strstr(cur_entry, lListDirToken);
336 if (name_start != NULL && dim_start != NULL && dir_start != NULL) {
337 /* Advance to the token values. */
338 name_start += strlen(lListNameToken);
339 dim_start += strlen(lListDimsToken);
340 dir_start += strlen(lListDirToken);
341
342 /* Terminate token values with zero. */
343 char* s = strchr(name_start, ' ');
344 if (s != NULL) {
345 *s = '\0';
346 }
347 s = strchr(dim_start, ' ');
348 if (s != NULL) {
349 *s = '\0';
350 }
351 s = strchr(dir_start, ' ');
352 if (s != NULL) {
353 *s = '\0';
354 }
355
356 /* Create and initialize qemu camera. */
357 EmulatedQemuCamera* qemu_cam =
358 new EmulatedQemuCamera(index, &HAL_MODULE_INFO_SYM.common);
359 if (NULL != qemu_cam) {
360 res = qemu_cam->Initialize(name_start, dim_start, dir_start);
361 if (res == NO_ERROR) {
362 mEmulatedCameras[index] = qemu_cam;
363 index++;
364 } else {
365 delete qemu_cam;
366 }
367 } else {
368 ALOGE("%s: Unable to instantiate EmulatedQemuCamera",
369 __FUNCTION__);
370 }
371 } else {
372 ALOGW("%s: Bad camera information: %s", __FUNCTION__, cur_entry);
373 }
374
375 cur_entry = next_entry;
376 }
377
378 mEmulatedCameraNum = index;
379#else
380 CAMHAL_LOGDA("delete this function");
381#endif
382}
383
384bool EmulatedCameraFactory::isFakeCameraFacingBack(int cameraId)
385{
386 if (cameraId%mEmulatedCameraNum == 1)
387 return false;
388
389 return true;
390}
391
392int EmulatedCameraFactory::getFakeCameraHalVersion(int cameraId)
393{
394 /* Defined by 'qemu.sf.back_camera_hal_version' boot property: if the
395 * property doesn't exist, it is assumed to be 1. */
396#if 0
397 char prop[PROPERTY_VALUE_MAX];
398 if (property_get("qemu.sf.back_camera_hal", prop, NULL) > 0) {
399 char *prop_end = prop;
400 int val = strtol(prop, &prop_end, 10);
401 if (*prop_end == '\0') {
402 return val;
403 }
404 // Badly formatted property, should just be a number
405 ALOGE("qemu.sf.back_camera_hal is not a number: %s", prop);
406 }
407 return 1;
408#else
409 cameraId = cameraId;
410 return 3;
411#endif
412}
413
414void EmulatedCameraFactory::onStatusChanged(int cameraId, int newStatus)
415{
416 status_t res;
417
418 EmulatedBaseCamera *cam = mEmulatedCameras[cameraId];
419 const camera_module_callbacks_t* cb = mCallbacks;
420
421 CAMHAL_LOGDB("mEmulatedCameraNum =%d\n", mEmulatedCameraNum);
422
423 if (!cam) {
424 /*suppose only usb camera produce uevent, and it is facing back*/
425 cam = new EmulatedFakeCamera3(cameraId, &HAL_MODULE_INFO_SYM.common);
426 if (cam != NULL) {
427 CAMHAL_LOGDB("%s: new camera device version is %d", __FUNCTION__,
428 getFakeCameraHalVersion(cameraId));
429 //sleep 10ms for /dev/video* create
430 usleep(10000);
431 res = cam->Initialize();
432 if (res != NO_ERROR) {
433 ALOGE("%s: Unable to intialize camera %d: %s (%d)",
434 __FUNCTION__, cameraId, strerror(-res), res);
435 delete cam;
436 }
437 }
438
439 /* Open the camera. then send the callback to framework*/
440 mEmulatedCameras[cameraId] = cam;
441 mEmulatedCameraNum ++;
442 cam->plugCamera();
443 if (cb != NULL && cb->camera_device_status_change != NULL) {
444 cb->camera_device_status_change(cb, cameraId, newStatus);
445 }
446
447 return ;
448 }
449
450 CAMHAL_LOGDB("mEmulatedCameraNum =%d\n", mEmulatedCameraNum);
451
452 /**
453 * (Order is important)
454 * Send the callback first to framework, THEN close the camera.
455 */
456
457 if (newStatus == cam->getHotplugStatus()) {
458 CAMHAL_LOGDB("%s: Ignoring transition to the same status", __FUNCTION__);
459 return;
460 }
461
462 CAMHAL_LOGDB("mEmulatedCameraNum =%d\n", mEmulatedCameraNum);
463 if (cb != NULL && cb->camera_device_status_change != NULL) {
464 cb->camera_device_status_change(cb, cameraId, newStatus);
465 }
466
467 CAMHAL_LOGDB("mEmulatedCameraNum =%d\n", mEmulatedCameraNum);
468 if (newStatus == CAMERA_DEVICE_STATUS_NOT_PRESENT) {
469 cam->unplugCamera();
470////
471 delete mEmulatedCameras[cameraId];
472 mEmulatedCameras[cameraId] = NULL;
473 mEmulatedCameraNum --;
474////
475 } else if (newStatus == CAMERA_DEVICE_STATUS_PRESENT) {
476 CAMHAL_LOGDA("camera plugged again?\n");
477 cam->plugCamera();
478 }
479 CAMHAL_LOGDB("mEmulatedCameraNum =%d\n", mEmulatedCameraNum);
480
481}
482
483/********************************************************************************
484 * Initializer for the static member structure.
485 *******************************************************************************/
486
487/* Entry point for camera HAL API. */
488struct hw_module_methods_t EmulatedCameraFactory::mCameraModuleMethods = {
489 open: EmulatedCameraFactory::device_open
490};
491
492}; /* namespace android */
493