- Add entries for all metadata - Use better idiom for static metadata construction - Revise dynamic and static metadata - New resolution reporting - Minor revision to some enums - Quiet excess logging Bug: 6243944 Change-Id: I0558d7d60ae97d2df9e209f24c1e04330737c220
450 lines
16 KiB
C++
Executable File
450 lines
16 KiB
C++
Executable File
/*
|
|
* 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 <cutils/log.h>
|
|
#include <cutils/properties.h>
|
|
#include "EmulatedQemuCamera.h"
|
|
#include "EmulatedFakeCamera.h"
|
|
#include "EmulatedFakeCamera2.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)
|
|
{
|
|
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;
|
|
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;
|
|
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);
|
|
|
|
mConstructedOK = true;
|
|
}
|
|
|
|
EmulatedCameraFactory::~EmulatedCameraFactory()
|
|
{
|
|
if (mEmulatedCameras != NULL) {
|
|
for (int n = 0; n < mEmulatedCameraNum; n++) {
|
|
if (mEmulatedCameras[n] != NULL) {
|
|
delete mEmulatedCameras[n];
|
|
}
|
|
}
|
|
delete[] mEmulatedCameras;
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
* 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 -EINVAL;
|
|
}
|
|
|
|
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 -EINVAL;
|
|
}
|
|
|
|
return mEmulatedCameras[camera_id]->getCameraInfo(info);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* 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);
|
|
}
|
|
|
|
/********************************************************************************
|
|
* 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;
|
|
}
|
|
|
|
/********************************************************************************
|
|
* 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 */
|