• 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 "EmulatedCameraFactory.h"
29 
30 extern camera_module_t HAL_MODULE_INFO_SYM;
31 
32 /* A global instance of EmulatedCameraFactory is statically instantiated and
33  * initialized when camera emulation HAL is loaded.
34  */
35 android::EmulatedCameraFactory  gEmulatedCameraFactory;
36 
37 namespace android {
38 
EmulatedCameraFactory()39 EmulatedCameraFactory::EmulatedCameraFactory()
40         : mQemuClient(),
41           mEmulatedCameras(NULL),
42           mEmulatedCameraNum(0),
43           mFakeCameraID(-1),
44           mConstructedOK(false)
45 
46 {
47     /* Connect to the factory service in the emulator, and create Qemu cameras. */
48     if (mQemuClient.connectClient(NULL) == NO_ERROR) {
49         /* Connection has succeeded. Create emulated cameras for each camera
50          * device, reported by the service. */
51         createQemuCameras();
52     }
53 
54     if (isFakeCameraEmulationOn()) {
55         /* ID fake camera with the number of created 'qemud' cameras. */
56         mFakeCameraID = mEmulatedCameraNum;
57         mEmulatedCameraNum++;
58 
59         /* Make sure that array is allocated (in case there were no 'qemu'
60          * cameras created. */
61         if (mEmulatedCameras == NULL) {
62             mEmulatedCameras = new EmulatedCamera*[mEmulatedCameraNum];
63             if (mEmulatedCameras == NULL) {
64                 LOGE("%s: Unable to allocate emulated camera array for %d entries",
65                      __FUNCTION__, mEmulatedCameraNum);
66                 return;
67             }
68             memset(mEmulatedCameras, 0, mEmulatedCameraNum * sizeof(EmulatedCamera*));
69         }
70 
71         /* Create, and initialize the fake camera */
72         mEmulatedCameras[mFakeCameraID] =
73             new EmulatedFakeCamera(mFakeCameraID, &HAL_MODULE_INFO_SYM.common);
74         if (mEmulatedCameras[mFakeCameraID] != NULL) {
75             if (mEmulatedCameras[mFakeCameraID]->Initialize() != NO_ERROR) {
76                 delete mEmulatedCameras[mFakeCameraID];
77                 mEmulatedCameras--;
78                 mFakeCameraID = -1;
79             }
80         } else {
81             mEmulatedCameras--;
82             mFakeCameraID = -1;
83             LOGE("%s: Unable to instantiate fake camera class", __FUNCTION__);
84         }
85     } else {
86         LOGD("Fake camera emulation is disabled.");
87     }
88 
89     LOGV("%d cameras are being emulated. Fake camera ID is %d",
90          mEmulatedCameraNum, mFakeCameraID);
91 
92     mConstructedOK = true;
93 }
94 
~EmulatedCameraFactory()95 EmulatedCameraFactory::~EmulatedCameraFactory()
96 {
97     if (mEmulatedCameras != NULL) {
98         for (int n = 0; n < mEmulatedCameraNum; n++) {
99             if (mEmulatedCameras[n] != NULL) {
100                 delete mEmulatedCameras[n];
101             }
102         }
103         delete[] mEmulatedCameras;
104     }
105 }
106 
107 /****************************************************************************
108  * Camera HAL API handlers.
109  *
110  * Each handler simply verifies existence of an appropriate EmulatedCamera
111  * instance, and dispatches the call to that instance.
112  *
113  ***************************************************************************/
114 
cameraDeviceOpen(int camera_id,hw_device_t ** device)115 int EmulatedCameraFactory::cameraDeviceOpen(int camera_id, hw_device_t** device)
116 {
117     LOGV("%s: id = %d", __FUNCTION__, camera_id);
118 
119     *device = NULL;
120 
121     if (!isConstructedOK()) {
122         LOGE("%s: EmulatedCameraFactory has failed to initialize", __FUNCTION__);
123         return -EINVAL;
124     }
125 
126     if (camera_id < 0 || camera_id >= getEmulatedCameraNum()) {
127         LOGE("%s: Camera id %d is out of bounds (%d)",
128              __FUNCTION__, camera_id, getEmulatedCameraNum());
129         return -EINVAL;
130     }
131 
132     return mEmulatedCameras[camera_id]->connectCamera(device);
133 }
134 
getCameraInfo(int camera_id,struct camera_info * info)135 int EmulatedCameraFactory::getCameraInfo(int camera_id, struct camera_info* info)
136 {
137     LOGV("%s: id = %d", __FUNCTION__, camera_id);
138 
139     if (!isConstructedOK()) {
140         LOGE("%s: EmulatedCameraFactory has failed to initialize", __FUNCTION__);
141         return -EINVAL;
142     }
143 
144     if (camera_id < 0 || camera_id >= getEmulatedCameraNum()) {
145         LOGE("%s: Camera id %d is out of bounds (%d)",
146              __FUNCTION__, camera_id, getEmulatedCameraNum());
147         return -EINVAL;
148     }
149 
150     return mEmulatedCameras[camera_id]->getCameraInfo(info);
151 }
152 
153 /****************************************************************************
154  * Camera HAL API callbacks.
155  ***************************************************************************/
156 
device_open(const hw_module_t * module,const char * name,hw_device_t ** device)157 int EmulatedCameraFactory::device_open(const hw_module_t* module,
158                                        const char* name,
159                                        hw_device_t** device)
160 {
161     /*
162      * Simply verify the parameters, and dispatch the call inside the
163      * EmulatedCameraFactory instance.
164      */
165 
166     if (module != &HAL_MODULE_INFO_SYM.common) {
167         LOGE("%s: Invalid module %p expected %p",
168              __FUNCTION__, module, &HAL_MODULE_INFO_SYM.common);
169         return -EINVAL;
170     }
171     if (name == NULL) {
172         LOGE("%s: NULL name is not expected here", __FUNCTION__);
173         return -EINVAL;
174     }
175 
176     return gEmulatedCameraFactory.cameraDeviceOpen(atoi(name), device);
177 }
178 
get_number_of_cameras(void)179 int EmulatedCameraFactory::get_number_of_cameras(void)
180 {
181     return gEmulatedCameraFactory.getEmulatedCameraNum();
182 }
183 
get_camera_info(int camera_id,struct camera_info * info)184 int EmulatedCameraFactory::get_camera_info(int camera_id,
185                                            struct camera_info* info)
186 {
187     return gEmulatedCameraFactory.getCameraInfo(camera_id, info);
188 }
189 
190 /********************************************************************************
191  * Internal API
192  *******************************************************************************/
193 
194 /*
195  * Camera information tokens passed in response to the "list" factory query.
196  */
197 
198 /* Device name token. */
199 static const char lListNameToken[]    = "name=";
200 /* Frame dimensions token. */
201 static const char lListDimsToken[]    = "framedims=";
202 /* Facing direction token. */
203 static const char lListDirToken[]     = "dir=";
204 
createQemuCameras()205 void EmulatedCameraFactory::createQemuCameras()
206 {
207     /* Obtain camera list. */
208     char* camera_list = NULL;
209     status_t res = mQemuClient.listCameras(&camera_list);
210     /* Empty list, or list containing just an EOL means that there were no
211      * connected cameras found. */
212     if (res != NO_ERROR || camera_list == NULL || *camera_list == '\0' ||
213         *camera_list == '\n') {
214         if (camera_list != NULL) {
215             free(camera_list);
216         }
217         return;
218     }
219 
220     /*
221      * Calculate number of connected cameras. Number of EOLs in the camera list
222      * is the number of the connected cameras.
223      */
224 
225     int num = 0;
226     const char* eol = strchr(camera_list, '\n');
227     while (eol != NULL) {
228         num++;
229         eol = strchr(eol + 1, '\n');
230     }
231 
232     /* Allocate the array for emulated camera instances. Note that we allocate
233      * one more entry for the fake camera emulation. */
234     mEmulatedCameras = new EmulatedCamera*[num + 1];
235     if (mEmulatedCameras == NULL) {
236         LOGE("%s: Unable to allocate emulated camera array for %d entries",
237              __FUNCTION__, num + 1);
238         free(camera_list);
239         return;
240     }
241     memset(mEmulatedCameras, 0, sizeof(EmulatedCamera*) * (num + 1));
242 
243     /*
244      * Iterate the list, creating, and initializin emulated qemu cameras for each
245      * entry (line) in the list.
246      */
247 
248     int index = 0;
249     char* cur_entry = camera_list;
250     while (cur_entry != NULL && *cur_entry != '\0' && index < num) {
251         /* Find the end of the current camera entry, and terminate it with zero
252          * for simpler string manipulation. */
253         char* next_entry = strchr(cur_entry, '\n');
254         if (next_entry != NULL) {
255             *next_entry = '\0';
256             next_entry++;   // Start of the next entry.
257         }
258 
259         /* Find 'name', 'framedims', and 'dir' tokens that are required here. */
260         char* name_start = strstr(cur_entry, lListNameToken);
261         char* dim_start = strstr(cur_entry, lListDimsToken);
262         char* dir_start = strstr(cur_entry, lListDirToken);
263         if (name_start != NULL && dim_start != NULL && dir_start != NULL) {
264             /* Advance to the token values. */
265             name_start += strlen(lListNameToken);
266             dim_start += strlen(lListDimsToken);
267             dir_start += strlen(lListDirToken);
268 
269             /* Terminate token values with zero. */
270             char* s = strchr(name_start, ' ');
271             if (s != NULL) {
272                 *s = '\0';
273             }
274             s = strchr(dim_start, ' ');
275             if (s != NULL) {
276                 *s = '\0';
277             }
278             s = strchr(dir_start, ' ');
279             if (s != NULL) {
280                 *s = '\0';
281             }
282 
283             /* Create and initialize qemu camera. */
284             EmulatedQemuCamera* qemu_cam =
285                 new EmulatedQemuCamera(index, &HAL_MODULE_INFO_SYM.common);
286             if (NULL != qemu_cam) {
287                 res = qemu_cam->Initialize(name_start, dim_start, dir_start);
288                 if (res == NO_ERROR) {
289                     mEmulatedCameras[index] = qemu_cam;
290                     index++;
291                 } else {
292                     delete qemu_cam;
293                 }
294             } else {
295                 LOGE("%s: Unable to instantiate EmulatedQemuCamera",
296                      __FUNCTION__);
297             }
298         } else {
299             LOGW("%s: Bad camera information: %s", __FUNCTION__, cur_entry);
300         }
301 
302         cur_entry = next_entry;
303     }
304 
305     mEmulatedCameraNum = index;
306 }
307 
isFakeCameraEmulationOn()308 bool EmulatedCameraFactory::isFakeCameraEmulationOn()
309 {
310     /* Defined by 'qemu.sf.fake_camera' boot property: If property is there
311      * and contains 'off', fake camera emulation is disabled. */
312     char prop[PROPERTY_VALUE_MAX];
313     if (property_get("qemu.sf.fake_camera", prop, NULL) <= 0 ||
314         strcmp(prop, "off")) {
315         return true;
316     } else {
317         return false;
318     }
319 }
320 
321 /********************************************************************************
322  * Initializer for the static member structure.
323  *******************************************************************************/
324 
325 /* Entry point for camera HAL API. */
326 struct hw_module_methods_t EmulatedCameraFactory::mCameraModuleMethods = {
327     open: EmulatedCameraFactory::device_open
328 };
329 
330 }; /* namespace android */
331