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