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 "EmulatedFakeCamera3.h"
30#include "EmulatedCameraHotplugThread.h"
31#include "EmulatedCameraFactory.h"
32
33extern camera_module_t HAL_MODULE_INFO_SYM;
34
35/* A global instance of EmulatedCameraFactory is statically instantiated and
36 * initialized when camera emulation HAL is loaded.
37 */
38android::EmulatedCameraFactory  gEmulatedCameraFactory;
39
40namespace android {
41
42EmulatedCameraFactory::EmulatedCameraFactory()
43        : mQemuClient(),
44          mEmulatedCameras(NULL),
45          mEmulatedCameraNum(0),
46          mFakeCameraNum(0),
47          mConstructedOK(false),
48          mCallbacks(NULL)
49{
50    status_t res;
51    /* Connect to the factory service in the emulator, and create Qemu cameras. */
52    if (mQemuClient.connectClient(NULL) == NO_ERROR) {
53        /* Connection has succeeded. Create emulated cameras for each camera
54         * device, reported by the service. */
55        createQemuCameras();
56    }
57
58    waitForQemuSfFakeCameraPropertyAvailable();
59
60    if (isBackFakeCameraEmulationOn()) {
61        /* Camera ID. */
62        const int camera_id = mEmulatedCameraNum;
63        /* Use fake camera to emulate back-facing camera. */
64        mEmulatedCameraNum++;
65
66        /* Make sure that array is allocated (in case there were no 'qemu'
67         * cameras created. Note that we preallocate the array so it may contain
68         * two fake cameras: one facing back, and another facing front. */
69        if (mEmulatedCameras == NULL) {
70            mEmulatedCameras = new EmulatedBaseCamera*[mEmulatedCameraNum + 1];
71            if (mEmulatedCameras == NULL) {
72                ALOGE("%s: Unable to allocate emulated camera array for %d entries",
73                     __FUNCTION__, mEmulatedCameraNum);
74                return;
75            }
76            memset(mEmulatedCameras, 0,
77                    (mEmulatedCameraNum + 1) * sizeof(EmulatedBaseCamera*));
78        }
79
80        /* Create, and initialize the fake camera */
81        switch (getBackCameraHalVersion()) {
82            case 1:
83                mEmulatedCameras[camera_id] =
84                        new EmulatedFakeCamera(camera_id, true,
85                                &HAL_MODULE_INFO_SYM.common);
86                break;
87            case 2:
88                mEmulatedCameras[camera_id] =
89                        new EmulatedFakeCamera2(camera_id, true,
90                                &HAL_MODULE_INFO_SYM.common);
91                break;
92            case 3:
93                mEmulatedCameras[camera_id] =
94                        new EmulatedFakeCamera3(camera_id, true,
95                                &HAL_MODULE_INFO_SYM.common);
96                break;
97            default:
98                ALOGE("%s: Unknown back camera hal version requested: %d", __FUNCTION__,
99                        getBackCameraHalVersion());
100        }
101        if (mEmulatedCameras[camera_id] != NULL) {
102            ALOGV("%s: Back camera device version is %d", __FUNCTION__,
103                    getBackCameraHalVersion());
104            res = mEmulatedCameras[camera_id]->Initialize();
105            if (res != NO_ERROR) {
106                ALOGE("%s: Unable to intialize back camera %d: %s (%d)",
107                        __FUNCTION__, camera_id, strerror(-res), res);
108                delete mEmulatedCameras[camera_id];
109                mEmulatedCameraNum--;
110            }
111        } else {
112            mEmulatedCameraNum--;
113            ALOGE("%s: Unable to instantiate fake camera class", __FUNCTION__);
114        }
115    }
116
117    if (isFrontFakeCameraEmulationOn()) {
118        /* Camera ID. */
119        const int camera_id = mEmulatedCameraNum;
120        /* Use fake camera to emulate front-facing camera. */
121        mEmulatedCameraNum++;
122
123        /* Make sure that array is allocated (in case there were no 'qemu'
124         * cameras created. */
125        if (mEmulatedCameras == NULL) {
126            mEmulatedCameras = new EmulatedBaseCamera*[mEmulatedCameraNum];
127            if (mEmulatedCameras == NULL) {
128                ALOGE("%s: Unable to allocate emulated camera array for %d entries",
129                     __FUNCTION__, mEmulatedCameraNum);
130                return;
131            }
132            memset(mEmulatedCameras, 0,
133                    mEmulatedCameraNum * sizeof(EmulatedBaseCamera*));
134        }
135
136        /* Create, and initialize the fake camera */
137        switch (getFrontCameraHalVersion()) {
138            case 1:
139                mEmulatedCameras[camera_id] =
140                        new EmulatedFakeCamera(camera_id, false,
141                                &HAL_MODULE_INFO_SYM.common);
142                break;
143            case 2:
144                mEmulatedCameras[camera_id] =
145                        new EmulatedFakeCamera2(camera_id, false,
146                                &HAL_MODULE_INFO_SYM.common);
147                break;
148            case 3:
149                mEmulatedCameras[camera_id] =
150                        new EmulatedFakeCamera3(camera_id, false,
151                                &HAL_MODULE_INFO_SYM.common);
152                break;
153            default:
154                ALOGE("%s: Unknown front camera hal version requested: %d",
155                        __FUNCTION__,
156                        getFrontCameraHalVersion());
157        }
158        if (mEmulatedCameras[camera_id] != NULL) {
159            ALOGV("%s: Front camera device version is %d", __FUNCTION__,
160                    getFrontCameraHalVersion());
161            res = mEmulatedCameras[camera_id]->Initialize();
162            if (res != NO_ERROR) {
163                ALOGE("%s: Unable to intialize front camera %d: %s (%d)",
164                        __FUNCTION__, camera_id, strerror(-res), res);
165                delete mEmulatedCameras[camera_id];
166                mEmulatedCameraNum--;
167            }
168        } else {
169            mEmulatedCameraNum--;
170            ALOGE("%s: Unable to instantiate fake camera class", __FUNCTION__);
171        }
172    }
173
174    ALOGE("%d cameras are being emulated. %d of them are fake cameras.",
175          mEmulatedCameraNum, mFakeCameraNum);
176
177    /* Create hotplug thread */
178    {
179        Vector<int> cameraIdVector;
180        for (int i = 0; i < mEmulatedCameraNum; ++i) {
181            cameraIdVector.push_back(i);
182        }
183        mHotplugThread = new EmulatedCameraHotplugThread(&cameraIdVector[0],
184                                                         mEmulatedCameraNum);
185        mHotplugThread->run("EmulatedCameraHotplugThread");
186    }
187
188    mConstructedOK = true;
189}
190
191EmulatedCameraFactory::~EmulatedCameraFactory()
192{
193    if (mEmulatedCameras != NULL) {
194        for (int n = 0; n < mEmulatedCameraNum; n++) {
195            if (mEmulatedCameras[n] != NULL) {
196                delete mEmulatedCameras[n];
197            }
198        }
199        delete[] mEmulatedCameras;
200    }
201
202    if (mHotplugThread != NULL) {
203        mHotplugThread->requestExit();
204        mHotplugThread->join();
205    }
206}
207
208/****************************************************************************
209 * Camera HAL API handlers.
210 *
211 * Each handler simply verifies existence of an appropriate EmulatedBaseCamera
212 * instance, and dispatches the call to that instance.
213 *
214 ***************************************************************************/
215
216int EmulatedCameraFactory::cameraDeviceOpen(int camera_id, hw_device_t** device)
217{
218    ALOGV("%s: id = %d", __FUNCTION__, camera_id);
219
220    *device = NULL;
221
222    if (!isConstructedOK()) {
223        ALOGE("%s: EmulatedCameraFactory has failed to initialize", __FUNCTION__);
224        return -EINVAL;
225    }
226
227    if (camera_id < 0 || camera_id >= getEmulatedCameraNum()) {
228        ALOGE("%s: Camera id %d is out of bounds (%d)",
229             __FUNCTION__, camera_id, getEmulatedCameraNum());
230        return -ENODEV;
231    }
232
233    return mEmulatedCameras[camera_id]->connectCamera(device);
234}
235
236int EmulatedCameraFactory::getCameraInfo(int camera_id, struct camera_info* info)
237{
238    ALOGV("%s: id = %d", __FUNCTION__, camera_id);
239
240    if (!isConstructedOK()) {
241        ALOGE("%s: EmulatedCameraFactory has failed to initialize", __FUNCTION__);
242        return -EINVAL;
243    }
244
245    if (camera_id < 0 || camera_id >= getEmulatedCameraNum()) {
246        ALOGE("%s: Camera id %d is out of bounds (%d)",
247             __FUNCTION__, camera_id, getEmulatedCameraNum());
248        return -ENODEV;
249    }
250
251    return mEmulatedCameras[camera_id]->getCameraInfo(info);
252}
253
254int EmulatedCameraFactory::setCallbacks(
255        const camera_module_callbacks_t *callbacks)
256{
257    ALOGV("%s: callbacks = %p", __FUNCTION__, callbacks);
258
259    mCallbacks = callbacks;
260
261    return OK;
262}
263
264void EmulatedCameraFactory::getVendorTagOps(vendor_tag_ops_t* ops) {
265    ALOGV("%s: ops = %p", __FUNCTION__, ops);
266
267    // No vendor tags defined for emulator yet, so not touching ops
268}
269
270/****************************************************************************
271 * Camera HAL API callbacks.
272 ***************************************************************************/
273
274int EmulatedCameraFactory::device_open(const hw_module_t* module,
275                                       const char* name,
276                                       hw_device_t** device)
277{
278    /*
279     * Simply verify the parameters, and dispatch the call inside the
280     * EmulatedCameraFactory instance.
281     */
282
283    if (module != &HAL_MODULE_INFO_SYM.common) {
284        ALOGE("%s: Invalid module %p expected %p",
285             __FUNCTION__, module, &HAL_MODULE_INFO_SYM.common);
286        return -EINVAL;
287    }
288    if (name == NULL) {
289        ALOGE("%s: NULL name is not expected here", __FUNCTION__);
290        return -EINVAL;
291    }
292
293    return gEmulatedCameraFactory.cameraDeviceOpen(atoi(name), device);
294}
295
296int EmulatedCameraFactory::get_number_of_cameras(void)
297{
298    return gEmulatedCameraFactory.getEmulatedCameraNum();
299}
300
301int EmulatedCameraFactory::get_camera_info(int camera_id,
302                                           struct camera_info* info)
303{
304    return gEmulatedCameraFactory.getCameraInfo(camera_id, info);
305}
306
307int EmulatedCameraFactory::set_callbacks(
308        const camera_module_callbacks_t *callbacks)
309{
310    return gEmulatedCameraFactory.setCallbacks(callbacks);
311}
312
313void EmulatedCameraFactory::get_vendor_tag_ops(vendor_tag_ops_t* ops)
314{
315    gEmulatedCameraFactory.getVendorTagOps(ops);
316}
317
318int EmulatedCameraFactory::open_legacy(const struct hw_module_t* module,
319        const char* id, uint32_t halVersion, struct hw_device_t** device) {
320    // Not supporting legacy open
321    return -ENOSYS;
322}
323
324/********************************************************************************
325 * Internal API
326 *******************************************************************************/
327
328/*
329 * Camera information tokens passed in response to the "list" factory query.
330 */
331
332/* Device name token. */
333static const char lListNameToken[]    = "name=";
334/* Frame dimensions token. */
335static const char lListDimsToken[]    = "framedims=";
336/* Facing direction token. */
337static const char lListDirToken[]     = "dir=";
338
339void EmulatedCameraFactory::createQemuCameras()
340{
341    /* Obtain camera list. */
342    char* camera_list = NULL;
343    status_t res = mQemuClient.listCameras(&camera_list);
344    /* Empty list, or list containing just an EOL means that there were no
345     * connected cameras found. */
346    if (res != NO_ERROR || camera_list == NULL || *camera_list == '\0' ||
347        *camera_list == '\n') {
348        if (camera_list != NULL) {
349            free(camera_list);
350        }
351        return;
352    }
353
354    /*
355     * Calculate number of connected cameras. Number of EOLs in the camera list
356     * is the number of the connected cameras.
357     */
358
359    int num = 0;
360    const char* eol = strchr(camera_list, '\n');
361    while (eol != NULL) {
362        num++;
363        eol = strchr(eol + 1, '\n');
364    }
365
366    /* Allocate the array for emulated camera instances. Note that we allocate
367     * two more entries for back and front fake camera emulation. */
368    mEmulatedCameras = new EmulatedBaseCamera*[num + 2];
369    if (mEmulatedCameras == NULL) {
370        ALOGE("%s: Unable to allocate emulated camera array for %d entries",
371             __FUNCTION__, num + 1);
372        free(camera_list);
373        return;
374    }
375    memset(mEmulatedCameras, 0, sizeof(EmulatedBaseCamera*) * (num + 1));
376
377    /*
378     * Iterate the list, creating, and initializin emulated qemu cameras for each
379     * entry (line) in the list.
380     */
381
382    int index = 0;
383    char* cur_entry = camera_list;
384    while (cur_entry != NULL && *cur_entry != '\0' && index < num) {
385        /* Find the end of the current camera entry, and terminate it with zero
386         * for simpler string manipulation. */
387        char* next_entry = strchr(cur_entry, '\n');
388        if (next_entry != NULL) {
389            *next_entry = '\0';
390            next_entry++;   // Start of the next entry.
391        }
392
393        /* Find 'name', 'framedims', and 'dir' tokens that are required here. */
394        char* name_start = strstr(cur_entry, lListNameToken);
395        char* dim_start = strstr(cur_entry, lListDimsToken);
396        char* dir_start = strstr(cur_entry, lListDirToken);
397        if (name_start != NULL && dim_start != NULL && dir_start != NULL) {
398            /* Advance to the token values. */
399            name_start += strlen(lListNameToken);
400            dim_start += strlen(lListDimsToken);
401            dir_start += strlen(lListDirToken);
402
403            /* Terminate token values with zero. */
404            char* s = strchr(name_start, ' ');
405            if (s != NULL) {
406                *s = '\0';
407            }
408            s = strchr(dim_start, ' ');
409            if (s != NULL) {
410                *s = '\0';
411            }
412            s = strchr(dir_start, ' ');
413            if (s != NULL) {
414                *s = '\0';
415            }
416
417            /* Create and initialize qemu camera. */
418            EmulatedQemuCamera* qemu_cam =
419                new EmulatedQemuCamera(index, &HAL_MODULE_INFO_SYM.common);
420            if (NULL != qemu_cam) {
421                res = qemu_cam->Initialize(name_start, dim_start, dir_start);
422                if (res == NO_ERROR) {
423                    mEmulatedCameras[index] = qemu_cam;
424                    index++;
425                } else {
426                    delete qemu_cam;
427                }
428            } else {
429                ALOGE("%s: Unable to instantiate EmulatedQemuCamera",
430                     __FUNCTION__);
431            }
432        } else {
433            ALOGW("%s: Bad camera information: %s", __FUNCTION__, cur_entry);
434        }
435
436        cur_entry = next_entry;
437    }
438
439    mEmulatedCameraNum = index;
440}
441
442void EmulatedCameraFactory::waitForQemuSfFakeCameraPropertyAvailable() {
443    // Camera service may start running before qemu-props sets qemu.sf.fake_camera to
444    // any of the follwing four values: "none,front,back,both"; so we need to wait.
445    // android/camera/camera-service.c
446    // bug: 30768229
447    int numAttempts = 100;
448    char prop[PROPERTY_VALUE_MAX];
449    bool timeout = true;
450    for (int i = 0; i < numAttempts; ++i) {
451        if (property_get("qemu.sf.fake_camera", prop, NULL) != 0 ) {
452            timeout = false;
453            break;
454        }
455        usleep(5000);
456    }
457    if (timeout) {
458        ALOGE("timeout (%dms) waiting for property qemu.sf.fake_camera to be set\n", 5 * numAttempts);
459    }
460}
461
462bool EmulatedCameraFactory::isBackFakeCameraEmulationOn()
463{
464    /* Defined by 'qemu.sf.fake_camera' boot property: if property exist, and
465     * is set to 'both', or 'back', then fake camera is used to emulate back
466     * camera. */
467    char prop[PROPERTY_VALUE_MAX];
468    if ((property_get("qemu.sf.fake_camera", prop, NULL) > 0) &&
469        (!strcmp(prop, "both") || !strcmp(prop, "back"))) {
470        return true;
471    } else {
472        return false;
473    }
474}
475
476int EmulatedCameraFactory::getBackCameraHalVersion()
477{
478    /* Defined by 'qemu.sf.back_camera_hal_version' boot property: if the
479     * property doesn't exist, it is assumed to be 1. */
480    char prop[PROPERTY_VALUE_MAX];
481    if (property_get("qemu.sf.back_camera_hal", prop, NULL) > 0) {
482        char *prop_end = prop;
483        int val = strtol(prop, &prop_end, 10);
484        if (*prop_end == '\0') {
485            return val;
486        }
487        // Badly formatted property, should just be a number
488        ALOGE("qemu.sf.back_camera_hal is not a number: %s", prop);
489    }
490    return 1;
491}
492
493bool EmulatedCameraFactory::isFrontFakeCameraEmulationOn()
494{
495    /* Defined by 'qemu.sf.fake_camera' boot property: if property exist, and
496     * is set to 'both', or 'front', then fake camera is used to emulate front
497     * camera. */
498    char prop[PROPERTY_VALUE_MAX];
499    if ((property_get("qemu.sf.fake_camera", prop, NULL) > 0) &&
500        (!strcmp(prop, "both") || !strcmp(prop, "front"))) {
501        return true;
502    } else {
503        return false;
504    }
505}
506
507int EmulatedCameraFactory::getFrontCameraHalVersion()
508{
509    /* Defined by 'qemu.sf.front_camera_hal_version' boot property: if the
510     * property doesn't exist, it is assumed to be 1. */
511    char prop[PROPERTY_VALUE_MAX];
512    if (property_get("qemu.sf.front_camera_hal", prop, NULL) > 0) {
513        char *prop_end = prop;
514        int val = strtol(prop, &prop_end, 10);
515        if (*prop_end == '\0') {
516            return val;
517        }
518        // Badly formatted property, should just be a number
519        ALOGE("qemu.sf.front_camera_hal is not a number: %s", prop);
520    }
521    return 1;
522}
523
524void EmulatedCameraFactory::onStatusChanged(int cameraId, int newStatus) {
525
526    EmulatedBaseCamera *cam = mEmulatedCameras[cameraId];
527    if (!cam) {
528        ALOGE("%s: Invalid camera ID %d", __FUNCTION__, cameraId);
529        return;
530    }
531
532    /**
533     * (Order is important)
534     * Send the callback first to framework, THEN close the camera.
535     */
536
537    if (newStatus == cam->getHotplugStatus()) {
538        ALOGW("%s: Ignoring transition to the same status", __FUNCTION__);
539        return;
540    }
541
542    const camera_module_callbacks_t* cb = mCallbacks;
543    if (cb != NULL && cb->camera_device_status_change != NULL) {
544        cb->camera_device_status_change(cb, cameraId, newStatus);
545    }
546
547    if (newStatus == CAMERA_DEVICE_STATUS_NOT_PRESENT) {
548        cam->unplugCamera();
549    } else if (newStatus == CAMERA_DEVICE_STATUS_PRESENT) {
550        cam->plugCamera();
551    }
552
553}
554
555/********************************************************************************
556 * Initializer for the static member structure.
557 *******************************************************************************/
558
559/* Entry point for camera HAL API. */
560struct hw_module_methods_t EmulatedCameraFactory::mCameraModuleMethods = {
561    open: EmulatedCameraFactory::device_open
562};
563
564}; /* namespace android */
565