blob: 42569fd2d0e2235878b235558bc82d5f705f8428
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 | DBG_LOGB("%s : cam is NULL", __FUNCTION__); |
307 | break; |
308 | } |
309 | } |
310 | return gEmulatedCameraFactory.getEmulatedCameraNum(); |
311 | } |
312 | |
313 | int EmulatedCameraFactory::get_camera_info(int camera_id, |
314 | struct camera_info* info) |
315 | { |
316 | return gEmulatedCameraFactory.getCameraInfo(camera_id, info); |
317 | } |
318 | |
319 | int EmulatedCameraFactory::set_callbacks( |
320 | const camera_module_callbacks_t *callbacks) |
321 | { |
322 | return gEmulatedCameraFactory.setCallbacks(callbacks); |
323 | } |
324 | |
325 | void 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. */ |
338 | static const char lListNameToken[] = "name="; |
339 | /* Frame dimensions token. */ |
340 | static const char lListDimsToken[] = "framedims="; |
341 | /* Facing direction token. */ |
342 | static const char lListDirToken[] = "dir="; |
343 | |
344 | void 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 | |
451 | bool EmulatedCameraFactory::isFakeCameraFacingBack(int cameraId) |
452 | { |
453 | if (cameraId%mEmulatedCameraNum == 1) |
454 | return false; |
455 | |
456 | return true; |
457 | } |
458 | |
459 | int 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 | |
481 | void 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. */ |
620 | struct hw_module_methods_t EmulatedCameraFactory::mCameraModuleMethods = { |
621 | open: EmulatedCameraFactory::device_open |
622 | }; |
623 | |
624 | }; /* namespace android */ |
625 |