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 "EmulatedCameraFactory.h"
     29 
     30 extern camera_module_t HAL_MODULE_INFO_SYM;
     31 
     32 /* A global instance of EmulatedCameraFactory is statically instantiated and
     33  * initialized when camera emulation HAL is loaded.
     34  */
     35 android::EmulatedCameraFactory  gEmulatedCameraFactory;
     36 
     37 namespace android {
     38 
     39 EmulatedCameraFactory::EmulatedCameraFactory()
     40         : mQemuClient(),
     41           mEmulatedCameras(NULL),
     42           mEmulatedCameraNum(0),
     43           mFakeCameraID(-1),
     44           mConstructedOK(false)
     45 
     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 (isFakeCameraEmulationOn()) {
     55         /* ID fake camera with the number of created 'qemud' cameras. */
     56         mFakeCameraID = mEmulatedCameraNum;
     57         mEmulatedCameraNum++;
     58 
     59         /* Make sure that array is allocated (in case there were no 'qemu'
     60          * cameras created. */
     61         if (mEmulatedCameras == NULL) {
     62             mEmulatedCameras = new EmulatedCamera*[mEmulatedCameraNum];
     63             if (mEmulatedCameras == NULL) {
     64                 LOGE("%s: Unable to allocate emulated camera array for %d entries",
     65                      __FUNCTION__, mEmulatedCameraNum);
     66                 return;
     67             }
     68             memset(mEmulatedCameras, 0, mEmulatedCameraNum * sizeof(EmulatedCamera*));
     69         }
     70 
     71         /* Create, and initialize the fake camera */
     72         mEmulatedCameras[mFakeCameraID] =
     73             new EmulatedFakeCamera(mFakeCameraID, &HAL_MODULE_INFO_SYM.common);
     74         if (mEmulatedCameras[mFakeCameraID] != NULL) {
     75             if (mEmulatedCameras[mFakeCameraID]->Initialize() != NO_ERROR) {
     76                 delete mEmulatedCameras[mFakeCameraID];
     77                 mEmulatedCameras--;
     78                 mFakeCameraID = -1;
     79             }
     80         } else {
     81             mEmulatedCameras--;
     82             mFakeCameraID = -1;
     83             LOGE("%s: Unable to instantiate fake camera class", __FUNCTION__);
     84         }
     85     } else {
     86         LOGD("Fake camera emulation is disabled.");
     87     }
     88 
     89     LOGV("%d cameras are being emulated. Fake camera ID is %d",
     90          mEmulatedCameraNum, mFakeCameraID);
     91 
     92     mConstructedOK = true;
     93 }
     94 
     95 EmulatedCameraFactory::~EmulatedCameraFactory()
     96 {
     97     if (mEmulatedCameras != NULL) {
     98         for (int n = 0; n < mEmulatedCameraNum; n++) {
     99             if (mEmulatedCameras[n] != NULL) {
    100                 delete mEmulatedCameras[n];
    101             }
    102         }
    103         delete[] mEmulatedCameras;
    104     }
    105 }
    106 
    107 /****************************************************************************
    108  * Camera HAL API handlers.
    109  *
    110  * Each handler simply verifies existence of an appropriate EmulatedCamera
    111  * instance, and dispatches the call to that instance.
    112  *
    113  ***************************************************************************/
    114 
    115 int EmulatedCameraFactory::cameraDeviceOpen(int camera_id, hw_device_t** device)
    116 {
    117     LOGV("%s: id = %d", __FUNCTION__, camera_id);
    118 
    119     *device = NULL;
    120 
    121     if (!isConstructedOK()) {
    122         LOGE("%s: EmulatedCameraFactory has failed to initialize", __FUNCTION__);
    123         return -EINVAL;
    124     }
    125 
    126     if (camera_id < 0 || camera_id >= getEmulatedCameraNum()) {
    127         LOGE("%s: Camera id %d is out of bounds (%d)",
    128              __FUNCTION__, camera_id, getEmulatedCameraNum());
    129         return -EINVAL;
    130     }
    131 
    132     return mEmulatedCameras[camera_id]->connectCamera(device);
    133 }
    134 
    135 int EmulatedCameraFactory::getCameraInfo(int camera_id, struct camera_info* info)
    136 {
    137     LOGV("%s: id = %d", __FUNCTION__, camera_id);
    138 
    139     if (!isConstructedOK()) {
    140         LOGE("%s: EmulatedCameraFactory has failed to initialize", __FUNCTION__);
    141         return -EINVAL;
    142     }
    143 
    144     if (camera_id < 0 || camera_id >= getEmulatedCameraNum()) {
    145         LOGE("%s: Camera id %d is out of bounds (%d)",
    146              __FUNCTION__, camera_id, getEmulatedCameraNum());
    147         return -EINVAL;
    148     }
    149 
    150     return mEmulatedCameras[camera_id]->getCameraInfo(info);
    151 }
    152 
    153 /****************************************************************************
    154  * Camera HAL API callbacks.
    155  ***************************************************************************/
    156 
    157 int EmulatedCameraFactory::device_open(const hw_module_t* module,
    158                                        const char* name,
    159                                        hw_device_t** device)
    160 {
    161     /*
    162      * Simply verify the parameters, and dispatch the call inside the
    163      * EmulatedCameraFactory instance.
    164      */
    165 
    166     if (module != &HAL_MODULE_INFO_SYM.common) {
    167         LOGE("%s: Invalid module %p expected %p",
    168              __FUNCTION__, module, &HAL_MODULE_INFO_SYM.common);
    169         return -EINVAL;
    170     }
    171     if (name == NULL) {
    172         LOGE("%s: NULL name is not expected here", __FUNCTION__);
    173         return -EINVAL;
    174     }
    175 
    176     return gEmulatedCameraFactory.cameraDeviceOpen(atoi(name), device);
    177 }
    178 
    179 int EmulatedCameraFactory::get_number_of_cameras(void)
    180 {
    181     return gEmulatedCameraFactory.getEmulatedCameraNum();
    182 }
    183 
    184 int EmulatedCameraFactory::get_camera_info(int camera_id,
    185                                            struct camera_info* info)
    186 {
    187     return gEmulatedCameraFactory.getCameraInfo(camera_id, info);
    188 }
    189 
    190 /********************************************************************************
    191  * Internal API
    192  *******************************************************************************/
    193 
    194 /*
    195  * Camera information tokens passed in response to the "list" factory query.
    196  */
    197 
    198 /* Device name token. */
    199 static const char lListNameToken[]    = "name=";
    200 /* Frame dimensions token. */
    201 static const char lListDimsToken[]    = "framedims=";
    202 /* Facing direction token. */
    203 static const char lListDirToken[]     = "dir=";
    204 
    205 void EmulatedCameraFactory::createQemuCameras()
    206 {
    207     /* Obtain camera list. */
    208     char* camera_list = NULL;
    209     status_t res = mQemuClient.listCameras(&camera_list);
    210     /* Empty list, or list containing just an EOL means that there were no
    211      * connected cameras found. */
    212     if (res != NO_ERROR || camera_list == NULL || *camera_list == '\0' ||
    213         *camera_list == '\n') {
    214         if (camera_list != NULL) {
    215             free(camera_list);
    216         }
    217         return;
    218     }
    219 
    220     /*
    221      * Calculate number of connected cameras. Number of EOLs in the camera list
    222      * is the number of the connected cameras.
    223      */
    224 
    225     int num = 0;
    226     const char* eol = strchr(camera_list, '\n');
    227     while (eol != NULL) {
    228         num++;
    229         eol = strchr(eol + 1, '\n');
    230     }
    231 
    232     /* Allocate the array for emulated camera instances. Note that we allocate
    233      * one more entry for the fake camera emulation. */
    234     mEmulatedCameras = new EmulatedCamera*[num + 1];
    235     if (mEmulatedCameras == NULL) {
    236         LOGE("%s: Unable to allocate emulated camera array for %d entries",
    237              __FUNCTION__, num + 1);
    238         free(camera_list);
    239         return;
    240     }
    241     memset(mEmulatedCameras, 0, sizeof(EmulatedCamera*) * (num + 1));
    242 
    243     /*
    244      * Iterate the list, creating, and initializin emulated qemu cameras for each
    245      * entry (line) in the list.
    246      */
    247 
    248     int index = 0;
    249     char* cur_entry = camera_list;
    250     while (cur_entry != NULL && *cur_entry != '\0' && index < num) {
    251         /* Find the end of the current camera entry, and terminate it with zero
    252          * for simpler string manipulation. */
    253         char* next_entry = strchr(cur_entry, '\n');
    254         if (next_entry != NULL) {
    255             *next_entry = '\0';
    256             next_entry++;   // Start of the next entry.
    257         }
    258 
    259         /* Find 'name', 'framedims', and 'dir' tokens that are required here. */
    260         char* name_start = strstr(cur_entry, lListNameToken);
    261         char* dim_start = strstr(cur_entry, lListDimsToken);
    262         char* dir_start = strstr(cur_entry, lListDirToken);
    263         if (name_start != NULL && dim_start != NULL && dir_start != NULL) {
    264             /* Advance to the token values. */
    265             name_start += strlen(lListNameToken);
    266             dim_start += strlen(lListDimsToken);
    267             dir_start += strlen(lListDirToken);
    268 
    269             /* Terminate token values with zero. */
    270             char* s = strchr(name_start, ' ');
    271             if (s != NULL) {
    272                 *s = '\0';
    273             }
    274             s = strchr(dim_start, ' ');
    275             if (s != NULL) {
    276                 *s = '\0';
    277             }
    278             s = strchr(dir_start, ' ');
    279             if (s != NULL) {
    280                 *s = '\0';
    281             }
    282 
    283             /* Create and initialize qemu camera. */
    284             EmulatedQemuCamera* qemu_cam =
    285                 new EmulatedQemuCamera(index, &HAL_MODULE_INFO_SYM.common);
    286             if (NULL != qemu_cam) {
    287                 res = qemu_cam->Initialize(name_start, dim_start, dir_start);
    288                 if (res == NO_ERROR) {
    289                     mEmulatedCameras[index] = qemu_cam;
    290                     index++;
    291                 } else {
    292                     delete qemu_cam;
    293                 }
    294             } else {
    295                 LOGE("%s: Unable to instantiate EmulatedQemuCamera",
    296                      __FUNCTION__);
    297             }
    298         } else {
    299             LOGW("%s: Bad camera information: %s", __FUNCTION__, cur_entry);
    300         }
    301 
    302         cur_entry = next_entry;
    303     }
    304 
    305     mEmulatedCameraNum = index;
    306 }
    307 
    308 bool EmulatedCameraFactory::isFakeCameraEmulationOn()
    309 {
    310     /* Defined by 'qemu.sf.fake_camera' boot property: If property is there
    311      * and contains 'off', fake camera emulation is disabled. */
    312     char prop[PROPERTY_VALUE_MAX];
    313     if (property_get("qemu.sf.fake_camera", prop, NULL) <= 0 ||
    314         strcmp(prop, "off")) {
    315         return true;
    316     } else {
    317         return false;
    318     }
    319 }
    320 
    321 /********************************************************************************
    322  * Initializer for the static member structure.
    323  *******************************************************************************/
    324 
    325 /* Entry point for camera HAL API. */
    326 struct hw_module_methods_t EmulatedCameraFactory::mCameraModuleMethods = {
    327     open: EmulatedCameraFactory::device_open
    328 };
    329 
    330 }; /* namespace android */
    331