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