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_TAG "EmulatedCamera_Factory"
24 #include <cutils/log.h>
25 #include <cutils/properties.h>
26 #include "EmulatedQemuCamera.h"
27 #include "EmulatedFakeCamera.h"
28 #include "EmulatedFakeCamera2.h"
29 #include "EmulatedFakeCamera3.h"
30 #include "EmulatedCameraHotplugThread.h"
31 #include "EmulatedCameraFactory.h"
32
33 extern camera_module_t HAL_MODULE_INFO_SYM;
34
35 /* A global instance of EmulatedCameraFactory is statically instantiated and
36 * initialized when camera emulation HAL is loaded.
37 */
38 android::EmulatedCameraFactory gEmulatedCameraFactory;
39
40 namespace android {
41
EmulatedCameraFactory()42 EmulatedCameraFactory::EmulatedCameraFactory()
43 : mQemuClient(),
44 mEmulatedCameras(NULL),
45 mEmulatedCameraNum(0),
46 mFakeCameraNum(0),
47 mConstructedOK(false),
48 mCallbacks(NULL)
49 {
50 status_t res;
51 /* Connect to the factory service in the emulator, and create Qemu cameras. */
52 if (mQemuClient.connectClient(NULL) == NO_ERROR) {
53 /* Connection has succeeded. Create emulated cameras for each camera
54 * device, reported by the service. */
55 createQemuCameras();
56 }
57
58 if (isBackFakeCameraEmulationOn()) {
59 /* Camera ID. */
60 const int camera_id = mEmulatedCameraNum;
61 /* Use fake camera to emulate back-facing camera. */
62 mEmulatedCameraNum++;
63
64 /* Make sure that array is allocated (in case there were no 'qemu'
65 * cameras created. Note that we preallocate the array so it may contain
66 * two fake cameras: one facing back, and another facing front. */
67 if (mEmulatedCameras == NULL) {
68 mEmulatedCameras = new EmulatedBaseCamera*[mEmulatedCameraNum + 1];
69 if (mEmulatedCameras == NULL) {
70 ALOGE("%s: Unable to allocate emulated camera array for %d entries",
71 __FUNCTION__, mEmulatedCameraNum);
72 return;
73 }
74 memset(mEmulatedCameras, 0,
75 (mEmulatedCameraNum + 1) * sizeof(EmulatedBaseCamera*));
76 }
77
78 /* Create, and initialize the fake camera */
79 switch (getBackCameraHalVersion()) {
80 case 1:
81 mEmulatedCameras[camera_id] =
82 new EmulatedFakeCamera(camera_id, true,
83 &HAL_MODULE_INFO_SYM.common);
84 break;
85 case 2:
86 mEmulatedCameras[camera_id] =
87 new EmulatedFakeCamera2(camera_id, true,
88 &HAL_MODULE_INFO_SYM.common);
89 break;
90 case 3:
91 mEmulatedCameras[camera_id] =
92 new EmulatedFakeCamera3(camera_id, true,
93 &HAL_MODULE_INFO_SYM.common);
94 break;
95 default:
96 ALOGE("%s: Unknown back camera hal version requested: %d", __FUNCTION__,
97 getBackCameraHalVersion());
98 }
99 if (mEmulatedCameras[camera_id] != NULL) {
100 ALOGV("%s: Back camera device version is %d", __FUNCTION__,
101 getBackCameraHalVersion());
102 res = mEmulatedCameras[camera_id]->Initialize();
103 if (res != NO_ERROR) {
104 ALOGE("%s: Unable to intialize back camera %d: %s (%d)",
105 __FUNCTION__, camera_id, strerror(-res), res);
106 delete mEmulatedCameras[camera_id];
107 mEmulatedCameraNum--;
108 }
109 } else {
110 mEmulatedCameraNum--;
111 ALOGE("%s: Unable to instantiate fake camera class", __FUNCTION__);
112 }
113 }
114
115 if (isFrontFakeCameraEmulationOn()) {
116 /* Camera ID. */
117 const int camera_id = mEmulatedCameraNum;
118 /* Use fake camera to emulate front-facing camera. */
119 mEmulatedCameraNum++;
120
121 /* Make sure that array is allocated (in case there were no 'qemu'
122 * cameras created. */
123 if (mEmulatedCameras == NULL) {
124 mEmulatedCameras = new EmulatedBaseCamera*[mEmulatedCameraNum];
125 if (mEmulatedCameras == NULL) {
126 ALOGE("%s: Unable to allocate emulated camera array for %d entries",
127 __FUNCTION__, mEmulatedCameraNum);
128 return;
129 }
130 memset(mEmulatedCameras, 0,
131 mEmulatedCameraNum * sizeof(EmulatedBaseCamera*));
132 }
133
134 /* Create, and initialize the fake camera */
135 switch (getFrontCameraHalVersion()) {
136 case 1:
137 mEmulatedCameras[camera_id] =
138 new EmulatedFakeCamera(camera_id, false,
139 &HAL_MODULE_INFO_SYM.common);
140 break;
141 case 2:
142 mEmulatedCameras[camera_id] =
143 new EmulatedFakeCamera2(camera_id, false,
144 &HAL_MODULE_INFO_SYM.common);
145 break;
146 case 3:
147 mEmulatedCameras[camera_id] =
148 new EmulatedFakeCamera3(camera_id, false,
149 &HAL_MODULE_INFO_SYM.common);
150 break;
151 default:
152 ALOGE("%s: Unknown front camera hal version requested: %d",
153 __FUNCTION__,
154 getFrontCameraHalVersion());
155 }
156 if (mEmulatedCameras[camera_id] != NULL) {
157 ALOGV("%s: Front camera device version is %d", __FUNCTION__,
158 getFrontCameraHalVersion());
159 res = mEmulatedCameras[camera_id]->Initialize();
160 if (res != NO_ERROR) {
161 ALOGE("%s: Unable to intialize front camera %d: %s (%d)",
162 __FUNCTION__, camera_id, strerror(-res), res);
163 delete mEmulatedCameras[camera_id];
164 mEmulatedCameraNum--;
165 }
166 } else {
167 mEmulatedCameraNum--;
168 ALOGE("%s: Unable to instantiate fake camera class", __FUNCTION__);
169 }
170 }
171
172 ALOGV("%d cameras are being emulated. %d of them are fake cameras.",
173 mEmulatedCameraNum, mFakeCameraNum);
174
175 /* Create hotplug thread */
176 {
177 Vector<int> cameraIdVector;
178 for (int i = 0; i < mEmulatedCameraNum; ++i) {
179 cameraIdVector.push_back(i);
180 }
181 mHotplugThread = new EmulatedCameraHotplugThread(&cameraIdVector[0],
182 mEmulatedCameraNum);
183 mHotplugThread->run();
184 }
185
186 mConstructedOK = true;
187 }
188
~EmulatedCameraFactory()189 EmulatedCameraFactory::~EmulatedCameraFactory()
190 {
191 if (mEmulatedCameras != NULL) {
192 for (int n = 0; n < mEmulatedCameraNum; n++) {
193 if (mEmulatedCameras[n] != NULL) {
194 delete mEmulatedCameras[n];
195 }
196 }
197 delete[] mEmulatedCameras;
198 }
199
200 if (mHotplugThread != NULL) {
201 mHotplugThread->requestExit();
202 mHotplugThread->join();
203 }
204 }
205
206 /****************************************************************************
207 * Camera HAL API handlers.
208 *
209 * Each handler simply verifies existence of an appropriate EmulatedBaseCamera
210 * instance, and dispatches the call to that instance.
211 *
212 ***************************************************************************/
213
cameraDeviceOpen(int camera_id,hw_device_t ** device)214 int EmulatedCameraFactory::cameraDeviceOpen(int camera_id, hw_device_t** device)
215 {
216 ALOGV("%s: id = %d", __FUNCTION__, camera_id);
217
218 *device = NULL;
219
220 if (!isConstructedOK()) {
221 ALOGE("%s: EmulatedCameraFactory has failed to initialize", __FUNCTION__);
222 return -EINVAL;
223 }
224
225 if (camera_id < 0 || camera_id >= getEmulatedCameraNum()) {
226 ALOGE("%s: Camera id %d is out of bounds (%d)",
227 __FUNCTION__, camera_id, getEmulatedCameraNum());
228 return -ENODEV;
229 }
230
231 return mEmulatedCameras[camera_id]->connectCamera(device);
232 }
233
getCameraInfo(int camera_id,struct camera_info * info)234 int EmulatedCameraFactory::getCameraInfo(int camera_id, struct camera_info* info)
235 {
236 ALOGV("%s: id = %d", __FUNCTION__, camera_id);
237
238 if (!isConstructedOK()) {
239 ALOGE("%s: EmulatedCameraFactory has failed to initialize", __FUNCTION__);
240 return -EINVAL;
241 }
242
243 if (camera_id < 0 || camera_id >= getEmulatedCameraNum()) {
244 ALOGE("%s: Camera id %d is out of bounds (%d)",
245 __FUNCTION__, camera_id, getEmulatedCameraNum());
246 return -ENODEV;
247 }
248
249 return mEmulatedCameras[camera_id]->getCameraInfo(info);
250 }
251
setCallbacks(const camera_module_callbacks_t * callbacks)252 int EmulatedCameraFactory::setCallbacks(
253 const camera_module_callbacks_t *callbacks)
254 {
255 ALOGV("%s: callbacks = %p", __FUNCTION__, callbacks);
256
257 mCallbacks = callbacks;
258
259 return OK;
260 }
261
262 /****************************************************************************
263 * Camera HAL API callbacks.
264 ***************************************************************************/
265
device_open(const hw_module_t * module,const char * name,hw_device_t ** device)266 int EmulatedCameraFactory::device_open(const hw_module_t* module,
267 const char* name,
268 hw_device_t** device)
269 {
270 /*
271 * Simply verify the parameters, and dispatch the call inside the
272 * EmulatedCameraFactory instance.
273 */
274
275 if (module != &HAL_MODULE_INFO_SYM.common) {
276 ALOGE("%s: Invalid module %p expected %p",
277 __FUNCTION__, module, &HAL_MODULE_INFO_SYM.common);
278 return -EINVAL;
279 }
280 if (name == NULL) {
281 ALOGE("%s: NULL name is not expected here", __FUNCTION__);
282 return -EINVAL;
283 }
284
285 return gEmulatedCameraFactory.cameraDeviceOpen(atoi(name), device);
286 }
287
get_number_of_cameras(void)288 int EmulatedCameraFactory::get_number_of_cameras(void)
289 {
290 return gEmulatedCameraFactory.getEmulatedCameraNum();
291 }
292
get_camera_info(int camera_id,struct camera_info * info)293 int EmulatedCameraFactory::get_camera_info(int camera_id,
294 struct camera_info* info)
295 {
296 return gEmulatedCameraFactory.getCameraInfo(camera_id, info);
297 }
298
set_callbacks(const camera_module_callbacks_t * callbacks)299 int EmulatedCameraFactory::set_callbacks(
300 const camera_module_callbacks_t *callbacks)
301 {
302 return gEmulatedCameraFactory.setCallbacks(callbacks);
303 }
304
305 /********************************************************************************
306 * Internal API
307 *******************************************************************************/
308
309 /*
310 * Camera information tokens passed in response to the "list" factory query.
311 */
312
313 /* Device name token. */
314 static const char lListNameToken[] = "name=";
315 /* Frame dimensions token. */
316 static const char lListDimsToken[] = "framedims=";
317 /* Facing direction token. */
318 static const char lListDirToken[] = "dir=";
319
createQemuCameras()320 void EmulatedCameraFactory::createQemuCameras()
321 {
322 /* Obtain camera list. */
323 char* camera_list = NULL;
324 status_t res = mQemuClient.listCameras(&camera_list);
325 /* Empty list, or list containing just an EOL means that there were no
326 * connected cameras found. */
327 if (res != NO_ERROR || camera_list == NULL || *camera_list == '\0' ||
328 *camera_list == '\n') {
329 if (camera_list != NULL) {
330 free(camera_list);
331 }
332 return;
333 }
334
335 /*
336 * Calculate number of connected cameras. Number of EOLs in the camera list
337 * is the number of the connected cameras.
338 */
339
340 int num = 0;
341 const char* eol = strchr(camera_list, '\n');
342 while (eol != NULL) {
343 num++;
344 eol = strchr(eol + 1, '\n');
345 }
346
347 /* Allocate the array for emulated camera instances. Note that we allocate
348 * two more entries for back and front fake camera emulation. */
349 mEmulatedCameras = new EmulatedBaseCamera*[num + 2];
350 if (mEmulatedCameras == NULL) {
351 ALOGE("%s: Unable to allocate emulated camera array for %d entries",
352 __FUNCTION__, num + 1);
353 free(camera_list);
354 return;
355 }
356 memset(mEmulatedCameras, 0, sizeof(EmulatedBaseCamera*) * (num + 1));
357
358 /*
359 * Iterate the list, creating, and initializin emulated qemu cameras for each
360 * entry (line) in the list.
361 */
362
363 int index = 0;
364 char* cur_entry = camera_list;
365 while (cur_entry != NULL && *cur_entry != '\0' && index < num) {
366 /* Find the end of the current camera entry, and terminate it with zero
367 * for simpler string manipulation. */
368 char* next_entry = strchr(cur_entry, '\n');
369 if (next_entry != NULL) {
370 *next_entry = '\0';
371 next_entry++; // Start of the next entry.
372 }
373
374 /* Find 'name', 'framedims', and 'dir' tokens that are required here. */
375 char* name_start = strstr(cur_entry, lListNameToken);
376 char* dim_start = strstr(cur_entry, lListDimsToken);
377 char* dir_start = strstr(cur_entry, lListDirToken);
378 if (name_start != NULL && dim_start != NULL && dir_start != NULL) {
379 /* Advance to the token values. */
380 name_start += strlen(lListNameToken);
381 dim_start += strlen(lListDimsToken);
382 dir_start += strlen(lListDirToken);
383
384 /* Terminate token values with zero. */
385 char* s = strchr(name_start, ' ');
386 if (s != NULL) {
387 *s = '\0';
388 }
389 s = strchr(dim_start, ' ');
390 if (s != NULL) {
391 *s = '\0';
392 }
393 s = strchr(dir_start, ' ');
394 if (s != NULL) {
395 *s = '\0';
396 }
397
398 /* Create and initialize qemu camera. */
399 EmulatedQemuCamera* qemu_cam =
400 new EmulatedQemuCamera(index, &HAL_MODULE_INFO_SYM.common);
401 if (NULL != qemu_cam) {
402 res = qemu_cam->Initialize(name_start, dim_start, dir_start);
403 if (res == NO_ERROR) {
404 mEmulatedCameras[index] = qemu_cam;
405 index++;
406 } else {
407 delete qemu_cam;
408 }
409 } else {
410 ALOGE("%s: Unable to instantiate EmulatedQemuCamera",
411 __FUNCTION__);
412 }
413 } else {
414 ALOGW("%s: Bad camera information: %s", __FUNCTION__, cur_entry);
415 }
416
417 cur_entry = next_entry;
418 }
419
420 mEmulatedCameraNum = index;
421 }
422
isBackFakeCameraEmulationOn()423 bool EmulatedCameraFactory::isBackFakeCameraEmulationOn()
424 {
425 /* Defined by 'qemu.sf.fake_camera' boot property: if property exist, and
426 * is set to 'both', or 'back', then fake camera is used to emulate back
427 * camera. */
428 char prop[PROPERTY_VALUE_MAX];
429 if ((property_get("qemu.sf.fake_camera", prop, NULL) > 0) &&
430 (!strcmp(prop, "both") || !strcmp(prop, "back"))) {
431 return true;
432 } else {
433 return false;
434 }
435 }
436
getBackCameraHalVersion()437 int EmulatedCameraFactory::getBackCameraHalVersion()
438 {
439 /* Defined by 'qemu.sf.back_camera_hal_version' boot property: if the
440 * property doesn't exist, it is assumed to be 1. */
441 char prop[PROPERTY_VALUE_MAX];
442 if (property_get("qemu.sf.back_camera_hal", prop, NULL) > 0) {
443 char *prop_end = prop;
444 int val = strtol(prop, &prop_end, 10);
445 if (*prop_end == '\0') {
446 return val;
447 }
448 // Badly formatted property, should just be a number
449 ALOGE("qemu.sf.back_camera_hal is not a number: %s", prop);
450 }
451 return 1;
452 }
453
isFrontFakeCameraEmulationOn()454 bool EmulatedCameraFactory::isFrontFakeCameraEmulationOn()
455 {
456 /* Defined by 'qemu.sf.fake_camera' boot property: if property exist, and
457 * is set to 'both', or 'front', then fake camera is used to emulate front
458 * camera. */
459 char prop[PROPERTY_VALUE_MAX];
460 if ((property_get("qemu.sf.fake_camera", prop, NULL) > 0) &&
461 (!strcmp(prop, "both") || !strcmp(prop, "front"))) {
462 return true;
463 } else {
464 return false;
465 }
466 }
467
getFrontCameraHalVersion()468 int EmulatedCameraFactory::getFrontCameraHalVersion()
469 {
470 /* Defined by 'qemu.sf.front_camera_hal_version' boot property: if the
471 * property doesn't exist, it is assumed to be 1. */
472 char prop[PROPERTY_VALUE_MAX];
473 if (property_get("qemu.sf.front_camera_hal", prop, NULL) > 0) {
474 char *prop_end = prop;
475 int val = strtol(prop, &prop_end, 10);
476 if (*prop_end == '\0') {
477 return val;
478 }
479 // Badly formatted property, should just be a number
480 ALOGE("qemu.sf.front_camera_hal is not a number: %s", prop);
481 }
482 return 1;
483 }
484
onStatusChanged(int cameraId,int newStatus)485 void EmulatedCameraFactory::onStatusChanged(int cameraId, int newStatus) {
486
487 EmulatedBaseCamera *cam = mEmulatedCameras[cameraId];
488 if (!cam) {
489 ALOGE("%s: Invalid camera ID %d", __FUNCTION__, cameraId);
490 return;
491 }
492
493 /**
494 * (Order is important)
495 * Send the callback first to framework, THEN close the camera.
496 */
497
498 if (newStatus == cam->getHotplugStatus()) {
499 ALOGW("%s: Ignoring transition to the same status", __FUNCTION__);
500 return;
501 }
502
503 const camera_module_callbacks_t* cb = mCallbacks;
504 if (cb != NULL && cb->camera_device_status_change != NULL) {
505 cb->camera_device_status_change(cb, cameraId, newStatus);
506 }
507
508 if (newStatus == CAMERA_DEVICE_STATUS_NOT_PRESENT) {
509 cam->unplugCamera();
510 } else if (newStatus == CAMERA_DEVICE_STATUS_PRESENT) {
511 cam->plugCamera();
512 }
513
514 }
515
516 /********************************************************************************
517 * Initializer for the static member structure.
518 *******************************************************************************/
519
520 /* Entry point for camera HAL API. */
521 struct hw_module_methods_t EmulatedCameraFactory::mCameraModuleMethods = {
522 open: EmulatedCameraFactory::device_open
523 };
524
525 }; /* namespace android */
526