Files
android_development/tools/emulator/system/camera/EmulatedCameraFactory.cpp
Vladimir Chtchetkine c9d6edeea5 Change camera HAL to catch up with changes in emulator.
Emulator now allows fake camera to emulate both, back and front cameras at the same time.
Camera HAL is changed in this CL in order to support this.

Change-Id: I4dcf2d569bb0c6a3800b4a8da5edd4777b5a078a
2012-03-19 13:34:28 -07:00

375 lines
13 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 "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)
{
/* 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 EmulatedCamera*[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(EmulatedCamera*));
}
/* Create, and initialize the fake camera */
mEmulatedCameras[camera_id] =
new EmulatedFakeCamera(camera_id, true, &HAL_MODULE_INFO_SYM.common);
if (mEmulatedCameras[camera_id] != NULL) {
if (mEmulatedCameras[camera_id]->Initialize() != NO_ERROR) {
delete mEmulatedCameras[camera_id];
mEmulatedCameras--;
}
} else {
mEmulatedCameras--;
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 EmulatedCamera*[mEmulatedCameraNum];
if (mEmulatedCameras == NULL) {
ALOGE("%s: Unable to allocate emulated camera array for %d entries",
__FUNCTION__, mEmulatedCameraNum);
return;
}
memset(mEmulatedCameras, 0, mEmulatedCameraNum * sizeof(EmulatedCamera*));
}
/* Create, and initialize the fake camera */
mEmulatedCameras[camera_id] =
new EmulatedFakeCamera(camera_id, false, &HAL_MODULE_INFO_SYM.common);
if (mEmulatedCameras[camera_id] != NULL) {
if (mEmulatedCameras[camera_id]->Initialize() != NO_ERROR) {
delete mEmulatedCameras[camera_id];
mEmulatedCameras--;
}
} else {
mEmulatedCameras--;
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 EmulatedCamera
* 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 EmulatedCamera*[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(EmulatedCamera*) * (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;
}
}
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;
}
}
/********************************************************************************
* 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 */