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 | |
35 | extern camera_module_t HAL_MODULE_INFO_SYM; |
36 | volatile 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 | */ |
41 | android::EmulatedCameraFactory gEmulatedCameraFactory; |
42 | default_camera_hal::VendorTags gVendorTags; |
43 | |
44 | static const char *SENSOR_PATH[]={ |
45 | "/dev/video0", |
46 | "/dev/video1", |
47 | "/dev/video2", |
48 | "/dev/video3", |
49 | "/dev/video4", |
50 | "/dev/video5", |
51 | }; |
52 | |
53 | int 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 | |
65 | static 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 | } |
78 | namespace android { |
79 | |
80 | EmulatedCameraFactory::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 | |
127 | EmulatedCameraFactory::~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 | |
142 | int 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 | |
161 | int 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 | |
184 | int 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 | |
203 | int 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 | |
213 | static int get_tag_count(const vendor_tag_ops_t* ops) |
214 | { |
215 | return gVendorTags.getTagCount(ops); |
216 | } |
217 | static void get_all_tags(const vendor_tag_ops_t* ops, uint32_t* tag_array) |
218 | { |
219 | gVendorTags.getAllTags(ops, tag_array); |
220 | } |
221 | static const char* get_section_name(const vendor_tag_ops_t* ops, uint32_t tag) |
222 | { |
223 | return gVendorTags.getSectionName(ops, tag); |
224 | } |
225 | static const char* get_tag_name(const vendor_tag_ops_t* ops, uint32_t tag) |
226 | { |
227 | return gVendorTags.getTagName(ops, tag); |
228 | } |
229 | static int get_tag_type(const vendor_tag_ops_t* ops, uint32_t tag) |
230 | { |
231 | return gVendorTags.getTagType(ops, tag); |
232 | } |
233 | void 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 | |
246 | EmulatedBaseCamera* 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 | |
258 | int 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 | |
270 | int 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 | |
292 | int 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 | |
312 | int EmulatedCameraFactory::get_camera_info(int camera_id, |
313 | struct camera_info* info) |
314 | { |
315 | return gEmulatedCameraFactory.getCameraInfo(camera_id, info); |
316 | } |
317 | |
318 | int EmulatedCameraFactory::set_callbacks( |
319 | const camera_module_callbacks_t *callbacks) |
320 | { |
321 | return gEmulatedCameraFactory.setCallbacks(callbacks); |
322 | } |
323 | |
324 | void 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. */ |
337 | static const char lListNameToken[] = "name="; |
338 | /* Frame dimensions token. */ |
339 | static const char lListDimsToken[] = "framedims="; |
340 | /* Facing direction token. */ |
341 | static const char lListDirToken[] = "dir="; |
342 | |
343 | void 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 | |
450 | bool EmulatedCameraFactory::isFakeCameraFacingBack(int cameraId) |
451 | { |
452 | if (cameraId%mEmulatedCameraNum == 1) |
453 | return false; |
454 | |
455 | return true; |
456 | } |
457 | |
458 | int 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 | |
480 | void 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. */ |
606 | struct hw_module_methods_t EmulatedCameraFactory::mCameraModuleMethods = { |
607 | open: EmulatedCameraFactory::device_open |
608 | }; |
609 | |
610 | }; /* namespace android */ |
611 |