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