Home | History | Annotate | Download | only in camera
      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 
     33 extern 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  */
     38 android::EmulatedCameraFactory  gEmulatedCameraFactory;
     39 
     40 namespace android {
     41 
     42 EmulatedCameraFactory::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 
    191 EmulatedCameraFactory::~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 
    216 int 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 
    236 int 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 
    254 int 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 
    264 void 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 
    274 int 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 
    296 int EmulatedCameraFactory::get_number_of_cameras(void)
    297 {
    298     return gEmulatedCameraFactory.getEmulatedCameraNum();
    299 }
    300 
    301 int EmulatedCameraFactory::get_camera_info(int camera_id,
    302                                            struct camera_info* info)
    303 {
    304     return gEmulatedCameraFactory.getCameraInfo(camera_id, info);
    305 }
    306 
    307 int EmulatedCameraFactory::set_callbacks(
    308         const camera_module_callbacks_t *callbacks)
    309 {
    310     return gEmulatedCameraFactory.setCallbacks(callbacks);
    311 }
    312 
    313 void EmulatedCameraFactory::get_vendor_tag_ops(vendor_tag_ops_t* ops)
    314 {
    315     gEmulatedCameraFactory.getVendorTagOps(ops);
    316 }
    317 
    318 int 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. */
    333 static const char lListNameToken[]    = "name=";
    334 /* Frame dimensions token. */
    335 static const char lListDimsToken[]    = "framedims=";
    336 /* Facing direction token. */
    337 static const char lListDirToken[]     = "dir=";
    338 
    339 void 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 
    442 void 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 
    462 bool 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 
    476 int 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 
    493 bool 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 
    507 int 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 
    524 void 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. */
    560 struct hw_module_methods_t EmulatedCameraFactory::mCameraModuleMethods = {
    561     open: EmulatedCameraFactory::device_open
    562 };
    563 
    564 }; /* namespace android */
    565