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