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