• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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