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
31extern 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 */
36android::EmulatedCameraFactory  gEmulatedCameraFactory;
37
38namespace android {
39
40EmulatedCameraFactory::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
165EmulatedCameraFactory::~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
185int 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
205int 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
227int 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
249int EmulatedCameraFactory::get_number_of_cameras(void)
250{
251    return gEmulatedCameraFactory.getEmulatedCameraNum();
252}
253
254int 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. */
269static const char lListNameToken[]    = "name=";
270/* Frame dimensions token. */
271static const char lListDimsToken[]    = "framedims=";
272/* Facing direction token. */
273static const char lListDirToken[]     = "dir=";
274
275void 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
378bool 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
392int 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
409bool 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
423int 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. */
445struct hw_module_methods_t EmulatedCameraFactory::mCameraModuleMethods = {
446    open: EmulatedCameraFactory::device_open
447};
448
449}; /* namespace android */
450