X-Git-Url: https://gerrit.akraino.org/r/gitweb?a=blobdiff_plain;f=src%2Ftype3_AndroidCloud%2Fanbox-master%2Fandroid%2Fcamera%2FEmulatedCameraFactory.cpp;fp=src%2Ftype3_AndroidCloud%2Fanbox-master%2Fandroid%2Fcamera%2FEmulatedCameraFactory.cpp;h=137d8ab6e72ef5214658b6c71e11595016890bb6;hb=e26c1ec581be598521517829adba8c8dd23a768f;hp=0000000000000000000000000000000000000000;hpb=6699c1aea74eeb0eb400e6299079f0c7576f716f;p=iec.git diff --git a/src/type3_AndroidCloud/anbox-master/android/camera/EmulatedCameraFactory.cpp b/src/type3_AndroidCloud/anbox-master/android/camera/EmulatedCameraFactory.cpp new file mode 100644 index 0000000..137d8ab --- /dev/null +++ b/src/type3_AndroidCloud/anbox-master/android/camera/EmulatedCameraFactory.cpp @@ -0,0 +1,542 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Contains implementation of a class EmulatedCameraFactory that manages cameras + * available for emulation. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "EmulatedCamera_Factory" +#include +#include +#include "EmulatedQemuCamera.h" +#include "EmulatedFakeCamera.h" +#include "EmulatedFakeCamera2.h" +#include "EmulatedFakeCamera3.h" +#include "EmulatedCameraHotplugThread.h" +#include "EmulatedCameraFactory.h" + +extern camera_module_t HAL_MODULE_INFO_SYM; + +/* A global instance of EmulatedCameraFactory is statically instantiated and + * initialized when camera emulation HAL is loaded. + */ +android::EmulatedCameraFactory gEmulatedCameraFactory; + +namespace android { + +EmulatedCameraFactory::EmulatedCameraFactory() + : mQemuClient(), + mEmulatedCameras(NULL), + mEmulatedCameraNum(0), + mFakeCameraNum(0), + mConstructedOK(false), + mCallbacks(NULL) +{ + status_t res; + /* Connect to the factory service in the emulator, and create Qemu cameras. */ + if (mQemuClient.connectClient(NULL) == NO_ERROR) { + /* Connection has succeeded. Create emulated cameras for each camera + * device, reported by the service. */ + createQemuCameras(); + } + + if (isBackFakeCameraEmulationOn()) { + /* Camera ID. */ + const int camera_id = mEmulatedCameraNum; + /* Use fake camera to emulate back-facing camera. */ + mEmulatedCameraNum++; + + /* Make sure that array is allocated (in case there were no 'qemu' + * cameras created. Note that we preallocate the array so it may contain + * two fake cameras: one facing back, and another facing front. */ + if (mEmulatedCameras == NULL) { + mEmulatedCameras = new EmulatedBaseCamera*[mEmulatedCameraNum + 1]; + if (mEmulatedCameras == NULL) { + ALOGE("%s: Unable to allocate emulated camera array for %d entries", + __FUNCTION__, mEmulatedCameraNum); + return; + } + memset(mEmulatedCameras, 0, + (mEmulatedCameraNum + 1) * sizeof(EmulatedBaseCamera*)); + } + + /* Create, and initialize the fake camera */ + switch (getBackCameraHalVersion()) { + case 1: + mEmulatedCameras[camera_id] = + new EmulatedFakeCamera(camera_id, true, + &HAL_MODULE_INFO_SYM.common); + break; + case 2: + mEmulatedCameras[camera_id] = + new EmulatedFakeCamera2(camera_id, true, + &HAL_MODULE_INFO_SYM.common); + break; + case 3: + mEmulatedCameras[camera_id] = + new EmulatedFakeCamera3(camera_id, true, + &HAL_MODULE_INFO_SYM.common); + break; + default: + ALOGE("%s: Unknown back camera hal version requested: %d", __FUNCTION__, + getBackCameraHalVersion()); + } + if (mEmulatedCameras[camera_id] != NULL) { + ALOGV("%s: Back camera device version is %d", __FUNCTION__, + getBackCameraHalVersion()); + res = mEmulatedCameras[camera_id]->Initialize(); + if (res != NO_ERROR) { + ALOGE("%s: Unable to intialize back camera %d: %s (%d)", + __FUNCTION__, camera_id, strerror(-res), res); + delete mEmulatedCameras[camera_id]; + mEmulatedCameraNum--; + } + } else { + mEmulatedCameraNum--; + ALOGE("%s: Unable to instantiate fake camera class", __FUNCTION__); + } + } + + if (isFrontFakeCameraEmulationOn()) { + /* Camera ID. */ + const int camera_id = mEmulatedCameraNum; + /* Use fake camera to emulate front-facing camera. */ + mEmulatedCameraNum++; + + /* Make sure that array is allocated (in case there were no 'qemu' + * cameras created. */ + if (mEmulatedCameras == NULL) { + mEmulatedCameras = new EmulatedBaseCamera*[mEmulatedCameraNum]; + if (mEmulatedCameras == NULL) { + ALOGE("%s: Unable to allocate emulated camera array for %d entries", + __FUNCTION__, mEmulatedCameraNum); + return; + } + memset(mEmulatedCameras, 0, + mEmulatedCameraNum * sizeof(EmulatedBaseCamera*)); + } + + /* Create, and initialize the fake camera */ + switch (getFrontCameraHalVersion()) { + case 1: + mEmulatedCameras[camera_id] = + new EmulatedFakeCamera(camera_id, false, + &HAL_MODULE_INFO_SYM.common); + break; + case 2: + mEmulatedCameras[camera_id] = + new EmulatedFakeCamera2(camera_id, false, + &HAL_MODULE_INFO_SYM.common); + break; + case 3: + mEmulatedCameras[camera_id] = + new EmulatedFakeCamera3(camera_id, false, + &HAL_MODULE_INFO_SYM.common); + break; + default: + ALOGE("%s: Unknown front camera hal version requested: %d", + __FUNCTION__, + getFrontCameraHalVersion()); + } + if (mEmulatedCameras[camera_id] != NULL) { + ALOGV("%s: Front camera device version is %d", __FUNCTION__, + getFrontCameraHalVersion()); + res = mEmulatedCameras[camera_id]->Initialize(); + if (res != NO_ERROR) { + ALOGE("%s: Unable to intialize front camera %d: %s (%d)", + __FUNCTION__, camera_id, strerror(-res), res); + delete mEmulatedCameras[camera_id]; + mEmulatedCameraNum--; + } + } else { + mEmulatedCameraNum--; + ALOGE("%s: Unable to instantiate fake camera class", __FUNCTION__); + } + } + + ALOGV("%d cameras are being emulated. %d of them are fake cameras.", + mEmulatedCameraNum, mFakeCameraNum); + + /* Create hotplug thread */ + { + Vector cameraIdVector; + for (int i = 0; i < mEmulatedCameraNum; ++i) { + cameraIdVector.push_back(i); + } + mHotplugThread = new EmulatedCameraHotplugThread(&cameraIdVector[0], + mEmulatedCameraNum); + mHotplugThread->run("EmulatedCameraHotplugThread"); + } + + mConstructedOK = true; +} + +EmulatedCameraFactory::~EmulatedCameraFactory() +{ + if (mEmulatedCameras != NULL) { + for (int n = 0; n < mEmulatedCameraNum; n++) { + if (mEmulatedCameras[n] != NULL) { + delete mEmulatedCameras[n]; + } + } + delete[] mEmulatedCameras; + } + + if (mHotplugThread != NULL) { + mHotplugThread->requestExit(); + mHotplugThread->join(); + } +} + +/**************************************************************************** + * Camera HAL API handlers. + * + * Each handler simply verifies existence of an appropriate EmulatedBaseCamera + * instance, and dispatches the call to that instance. + * + ***************************************************************************/ + +int EmulatedCameraFactory::cameraDeviceOpen(int camera_id, hw_device_t** device) +{ + ALOGV("%s: id = %d", __FUNCTION__, camera_id); + + *device = NULL; + + if (!isConstructedOK()) { + ALOGE("%s: EmulatedCameraFactory has failed to initialize", __FUNCTION__); + return -EINVAL; + } + + if (camera_id < 0 || camera_id >= getEmulatedCameraNum()) { + ALOGE("%s: Camera id %d is out of bounds (%d)", + __FUNCTION__, camera_id, getEmulatedCameraNum()); + return -ENODEV; + } + + return mEmulatedCameras[camera_id]->connectCamera(device); +} + +int EmulatedCameraFactory::getCameraInfo(int camera_id, struct camera_info* info) +{ + ALOGV("%s: id = %d", __FUNCTION__, camera_id); + + if (!isConstructedOK()) { + ALOGE("%s: EmulatedCameraFactory has failed to initialize", __FUNCTION__); + return -EINVAL; + } + + if (camera_id < 0 || camera_id >= getEmulatedCameraNum()) { + ALOGE("%s: Camera id %d is out of bounds (%d)", + __FUNCTION__, camera_id, getEmulatedCameraNum()); + return -ENODEV; + } + + return mEmulatedCameras[camera_id]->getCameraInfo(info); +} + +int EmulatedCameraFactory::setCallbacks( + const camera_module_callbacks_t *callbacks) +{ + ALOGV("%s: callbacks = %p", __FUNCTION__, callbacks); + + mCallbacks = callbacks; + + return OK; +} + +void EmulatedCameraFactory::getVendorTagOps(vendor_tag_ops_t* ops) { + ALOGV("%s: ops = %p", __FUNCTION__, ops); + + // No vendor tags defined for emulator yet, so not touching ops +} + +/**************************************************************************** + * Camera HAL API callbacks. + ***************************************************************************/ + +int EmulatedCameraFactory::device_open(const hw_module_t* module, + const char* name, + hw_device_t** device) +{ + /* + * Simply verify the parameters, and dispatch the call inside the + * EmulatedCameraFactory instance. + */ + + if (module != &HAL_MODULE_INFO_SYM.common) { + ALOGE("%s: Invalid module %p expected %p", + __FUNCTION__, module, &HAL_MODULE_INFO_SYM.common); + return -EINVAL; + } + if (name == NULL) { + ALOGE("%s: NULL name is not expected here", __FUNCTION__); + return -EINVAL; + } + + return gEmulatedCameraFactory.cameraDeviceOpen(atoi(name), device); +} + +int EmulatedCameraFactory::get_number_of_cameras(void) +{ + return gEmulatedCameraFactory.getEmulatedCameraNum(); +} + +int EmulatedCameraFactory::get_camera_info(int camera_id, + struct camera_info* info) +{ + return gEmulatedCameraFactory.getCameraInfo(camera_id, info); +} + +int EmulatedCameraFactory::set_callbacks( + const camera_module_callbacks_t *callbacks) +{ + return gEmulatedCameraFactory.setCallbacks(callbacks); +} + +void EmulatedCameraFactory::get_vendor_tag_ops(vendor_tag_ops_t* ops) +{ + gEmulatedCameraFactory.getVendorTagOps(ops); +} + +int EmulatedCameraFactory::open_legacy(const struct hw_module_t* module, + const char* id, uint32_t halVersion, struct hw_device_t** device) { + // Not supporting legacy open + return -ENOSYS; +} + +/******************************************************************************** + * Internal API + *******************************************************************************/ + +/* + * Camera information tokens passed in response to the "list" factory query. + */ + +/* Device name token. */ +static const char lListNameToken[] = "name="; +/* Frame dimensions token. */ +static const char lListDimsToken[] = "framedims="; +/* Facing direction token. */ +static const char lListDirToken[] = "dir="; + +void EmulatedCameraFactory::createQemuCameras() +{ + /* Obtain camera list. */ + char* camera_list = NULL; + status_t res = mQemuClient.listCameras(&camera_list); + /* Empty list, or list containing just an EOL means that there were no + * connected cameras found. */ + if (res != NO_ERROR || camera_list == NULL || *camera_list == '\0' || + *camera_list == '\n') { + if (camera_list != NULL) { + free(camera_list); + } + return; + } + + /* + * Calculate number of connected cameras. Number of EOLs in the camera list + * is the number of the connected cameras. + */ + + int num = 0; + const char* eol = strchr(camera_list, '\n'); + while (eol != NULL) { + num++; + eol = strchr(eol + 1, '\n'); + } + + /* Allocate the array for emulated camera instances. Note that we allocate + * two more entries for back and front fake camera emulation. */ + mEmulatedCameras = new EmulatedBaseCamera*[num + 2]; + if (mEmulatedCameras == NULL) { + ALOGE("%s: Unable to allocate emulated camera array for %d entries", + __FUNCTION__, num + 1); + free(camera_list); + return; + } + memset(mEmulatedCameras, 0, sizeof(EmulatedBaseCamera*) * (num + 1)); + + /* + * Iterate the list, creating, and initializin emulated qemu cameras for each + * entry (line) in the list. + */ + + int index = 0; + char* cur_entry = camera_list; + while (cur_entry != NULL && *cur_entry != '\0' && index < num) { + /* Find the end of the current camera entry, and terminate it with zero + * for simpler string manipulation. */ + char* next_entry = strchr(cur_entry, '\n'); + if (next_entry != NULL) { + *next_entry = '\0'; + next_entry++; // Start of the next entry. + } + + /* Find 'name', 'framedims', and 'dir' tokens that are required here. */ + char* name_start = strstr(cur_entry, lListNameToken); + char* dim_start = strstr(cur_entry, lListDimsToken); + char* dir_start = strstr(cur_entry, lListDirToken); + if (name_start != NULL && dim_start != NULL && dir_start != NULL) { + /* Advance to the token values. */ + name_start += strlen(lListNameToken); + dim_start += strlen(lListDimsToken); + dir_start += strlen(lListDirToken); + + /* Terminate token values with zero. */ + char* s = strchr(name_start, ' '); + if (s != NULL) { + *s = '\0'; + } + s = strchr(dim_start, ' '); + if (s != NULL) { + *s = '\0'; + } + s = strchr(dir_start, ' '); + if (s != NULL) { + *s = '\0'; + } + + /* Create and initialize qemu camera. */ + EmulatedQemuCamera* qemu_cam = + new EmulatedQemuCamera(index, &HAL_MODULE_INFO_SYM.common); + if (NULL != qemu_cam) { + res = qemu_cam->Initialize(name_start, dim_start, dir_start); + if (res == NO_ERROR) { + mEmulatedCameras[index] = qemu_cam; + index++; + } else { + delete qemu_cam; + } + } else { + ALOGE("%s: Unable to instantiate EmulatedQemuCamera", + __FUNCTION__); + } + } else { + ALOGW("%s: Bad camera information: %s", __FUNCTION__, cur_entry); + } + + cur_entry = next_entry; + } + + mEmulatedCameraNum = index; +} + +bool EmulatedCameraFactory::isBackFakeCameraEmulationOn() +{ + /* Defined by 'qemu.sf.fake_camera' boot property: if property exist, and + * is set to 'both', or 'back', then fake camera is used to emulate back + * camera. */ + char prop[PROPERTY_VALUE_MAX]; + if ((property_get("qemu.sf.fake_camera", prop, NULL) > 0) && + (!strcmp(prop, "both") || !strcmp(prop, "back"))) { + return true; + } else { + return false; + } +} + +int EmulatedCameraFactory::getBackCameraHalVersion() +{ + /* Defined by 'qemu.sf.back_camera_hal_version' boot property: if the + * property doesn't exist, it is assumed to be 1. */ + char prop[PROPERTY_VALUE_MAX]; + if (property_get("qemu.sf.back_camera_hal", prop, NULL) > 0) { + char *prop_end = prop; + int val = strtol(prop, &prop_end, 10); + if (*prop_end == '\0') { + return val; + } + // Badly formatted property, should just be a number + ALOGE("qemu.sf.back_camera_hal is not a number: %s", prop); + } + return 1; +} + +bool EmulatedCameraFactory::isFrontFakeCameraEmulationOn() +{ + /* Defined by 'qemu.sf.fake_camera' boot property: if property exist, and + * is set to 'both', or 'front', then fake camera is used to emulate front + * camera. */ + char prop[PROPERTY_VALUE_MAX]; + if ((property_get("qemu.sf.fake_camera", prop, NULL) > 0) && + (!strcmp(prop, "both") || !strcmp(prop, "front"))) { + return true; + } else { + return false; + } +} + +int EmulatedCameraFactory::getFrontCameraHalVersion() +{ + /* Defined by 'qemu.sf.front_camera_hal_version' boot property: if the + * property doesn't exist, it is assumed to be 1. */ + char prop[PROPERTY_VALUE_MAX]; + if (property_get("qemu.sf.front_camera_hal", prop, NULL) > 0) { + char *prop_end = prop; + int val = strtol(prop, &prop_end, 10); + if (*prop_end == '\0') { + return val; + } + // Badly formatted property, should just be a number + ALOGE("qemu.sf.front_camera_hal is not a number: %s", prop); + } + return 1; +} + +void EmulatedCameraFactory::onStatusChanged(int cameraId, int newStatus) { + + EmulatedBaseCamera *cam = mEmulatedCameras[cameraId]; + if (!cam) { + ALOGE("%s: Invalid camera ID %d", __FUNCTION__, cameraId); + return; + } + + /** + * (Order is important) + * Send the callback first to framework, THEN close the camera. + */ + + if (newStatus == cam->getHotplugStatus()) { + ALOGW("%s: Ignoring transition to the same status", __FUNCTION__); + return; + } + + const camera_module_callbacks_t* cb = mCallbacks; + if (cb != NULL && cb->camera_device_status_change != NULL) { + cb->camera_device_status_change(cb, cameraId, newStatus); + } + + if (newStatus == CAMERA_DEVICE_STATUS_NOT_PRESENT) { + cam->unplugCamera(); + } else if (newStatus == CAMERA_DEVICE_STATUS_PRESENT) { + cam->plugCamera(); + } + +} + +/******************************************************************************** + * Initializer for the static member structure. + *******************************************************************************/ + +/* Entry point for camera HAL API. */ +struct hw_module_methods_t EmulatedCameraFactory::mCameraModuleMethods = { + open: EmulatedCameraFactory::device_open +}; + +}; /* namespace android */