Change camera interface to support multiple cameras.
Change-Id: Ie88fe706d2278acf762eca87780de349434778a4
This commit is contained in:
@ -7,15 +7,11 @@ ifneq ($(filter sooner generic sim,$(TARGET_DEVICE)),)
|
||||
USE_CAMERA_STUB:=true
|
||||
endif
|
||||
|
||||
ifeq ($(USE_CAMERA_STUB),true)
|
||||
INCLUDE_CAMERA_STUB:=true
|
||||
INCLUDE_CAMERA_HARDWARE:=false
|
||||
else
|
||||
INCLUDE_CAMERA_STUB:=true # set this to true temporarily for testing
|
||||
INCLUDE_CAMERA_HARDWARE:=true
|
||||
ifeq ($(USE_CAMERA_STUB),)
|
||||
USE_CAMERA_STUB:=false
|
||||
endif
|
||||
|
||||
ifeq ($(INCLUDE_CAMERA_STUB),true)
|
||||
ifeq ($(USE_CAMERA_STUB),true)
|
||||
#
|
||||
# libcamerastub
|
||||
#
|
||||
@ -35,7 +31,7 @@ endif
|
||||
LOCAL_SHARED_LIBRARIES:= libui
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
endif # INCLUDE_CAMERA_STUB
|
||||
endif # USE_CAMERA_STUB
|
||||
|
||||
#
|
||||
# libcameraservice
|
||||
@ -61,13 +57,9 @@ ifeq ($(TARGET_SIMULATOR),true)
|
||||
LOCAL_CFLAGS += -DSINGLE_PROCESS
|
||||
endif
|
||||
|
||||
ifeq ($(INCLUDE_CAMERA_STUB), true)
|
||||
ifeq ($(USE_CAMERA_STUB), true)
|
||||
LOCAL_STATIC_LIBRARIES += libcamerastub
|
||||
LOCAL_CFLAGS += -DINCLUDE_CAMERA_STUB
|
||||
endif
|
||||
|
||||
ifeq ($(INCLUDE_CAMERA_HARDWARE),true)
|
||||
LOCAL_CFLAGS += -DINCLUDE_CAMERA_HARDWARE
|
||||
else
|
||||
LOCAL_SHARED_LIBRARIES += libcamera
|
||||
endif
|
||||
|
||||
|
@ -385,7 +385,24 @@ sp<CameraHardwareInterface> CameraHardwareStub::createInstance()
|
||||
return new CameraHardwareStub();
|
||||
}
|
||||
|
||||
extern "C" sp<CameraHardwareInterface> openCameraHardwareStub()
|
||||
static CameraInfo sCameraInfo[] = {
|
||||
{
|
||||
CAMERA_FACING_BACK,
|
||||
90, /* orientation */
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" int HAL_getNumberOfCameras()
|
||||
{
|
||||
return sizeof(sCameraInfo) / sizeof(sCameraInfo[0]);
|
||||
}
|
||||
|
||||
extern "C" void HAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo)
|
||||
{
|
||||
memcpy(cameraInfo, &sCameraInfo[cameraId], sizeof(CameraInfo));
|
||||
}
|
||||
|
||||
extern "C" sp<CameraHardwareInterface> HAL_openCameraHardware(int cameraId)
|
||||
{
|
||||
return CameraHardwareStub::createInstance();
|
||||
}
|
||||
|
@ -128,8 +128,6 @@ private:
|
||||
int mCurrentPreviewFrame;
|
||||
};
|
||||
|
||||
extern "C" sp<CameraHardwareInterface> openCameraHardwareStub();
|
||||
|
||||
}; // namespace android
|
||||
|
||||
#endif
|
||||
|
@ -37,37 +37,9 @@
|
||||
#include <utils/String16.h>
|
||||
|
||||
#include "CameraService.h"
|
||||
#ifdef INCLUDE_CAMERA_STUB
|
||||
#include "CameraHardwareStub.h"
|
||||
#endif
|
||||
|
||||
namespace android {
|
||||
|
||||
/* This determines the number of cameras available */
|
||||
#if defined(INCLUDE_CAMERA_HARDWARE) && defined(INCLUDE_CAMERA_STUB)
|
||||
#define NUM_CAMERAS 2
|
||||
#elif defined(INCLUDE_CAMERA_HARDWARE) || defined(INCLUDE_CAMERA_STUB)
|
||||
#define NUM_CAMERAS 1
|
||||
#else
|
||||
#error "Should have at least one camera"
|
||||
#endif
|
||||
|
||||
/* Make sure we have enough array space allocated */
|
||||
#if NUM_CAMERAS > MAX_CAMERAS
|
||||
#error "Need to increase MAX_CAMERAS"
|
||||
#endif
|
||||
|
||||
/* This defines the "open" function for each camera */
|
||||
extern "C" typedef sp<CameraHardwareInterface> (*OpenCameraHardwareFunction)();
|
||||
static OpenCameraHardwareFunction sOpenCameraTable[] = {
|
||||
#ifdef INCLUDE_CAMERA_HARDWARE
|
||||
&openCameraHardware,
|
||||
#endif
|
||||
#ifdef INCLUDE_CAMERA_STUB
|
||||
&openCameraHardwareStub,
|
||||
#endif
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Logging support -- this is for debugging only
|
||||
// Use "adb shell dumpsys media.camera -v 1" to change it.
|
||||
@ -101,7 +73,14 @@ CameraService::CameraService()
|
||||
{
|
||||
LOGI("CameraService started (pid=%d)", getpid());
|
||||
|
||||
for (int i = 0; i < NUM_CAMERAS; i++) {
|
||||
mNumberOfCameras = HAL_getNumberOfCameras();
|
||||
if (mNumberOfCameras > MAX_CAMERAS) {
|
||||
LOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",
|
||||
mNumberOfCameras, MAX_CAMERAS);
|
||||
mNumberOfCameras = MAX_CAMERAS;
|
||||
}
|
||||
|
||||
for (int i = 0; i < mNumberOfCameras; i++) {
|
||||
setCameraFree(i);
|
||||
}
|
||||
|
||||
@ -109,7 +88,7 @@ CameraService::CameraService()
|
||||
}
|
||||
|
||||
CameraService::~CameraService() {
|
||||
for (int i = 0; i < NUM_CAMERAS; i++) {
|
||||
for (int i = 0; i < mNumberOfCameras; i++) {
|
||||
if (mBusy[i]) {
|
||||
LOGE("camera %d is still in use in destructor!", i);
|
||||
}
|
||||
@ -119,7 +98,17 @@ CameraService::~CameraService() {
|
||||
}
|
||||
|
||||
int32_t CameraService::getNumberOfCameras() {
|
||||
return NUM_CAMERAS;
|
||||
return mNumberOfCameras;
|
||||
}
|
||||
|
||||
status_t CameraService::getCameraInfo(int cameraId,
|
||||
struct CameraInfo* cameraInfo) {
|
||||
if (cameraId < 0 || cameraId >= mNumberOfCameras) {
|
||||
return BAD_VALUE;
|
||||
}
|
||||
|
||||
HAL_getCameraInfo(cameraId, cameraInfo);
|
||||
return OK;
|
||||
}
|
||||
|
||||
sp<ICamera> CameraService::connect(
|
||||
@ -128,7 +117,7 @@ sp<ICamera> CameraService::connect(
|
||||
LOG1("CameraService::connect E (pid %d, id %d)", callingPid, cameraId);
|
||||
|
||||
sp<Client> client;
|
||||
if (cameraId < 0 || cameraId >= NUM_CAMERAS) {
|
||||
if (cameraId < 0 || cameraId >= mNumberOfCameras) {
|
||||
LOGE("CameraService::connect X (pid %d) rejected (invalid cameraId %d).",
|
||||
callingPid, cameraId);
|
||||
return NULL;
|
||||
@ -167,7 +156,7 @@ void CameraService::removeClient(const sp<ICameraClient>& cameraClient) {
|
||||
int callingPid = getCallingPid();
|
||||
LOG1("CameraService::removeClient E (pid %d)", callingPid);
|
||||
|
||||
for (int i = 0; i < NUM_CAMERAS; i++) {
|
||||
for (int i = 0; i < mNumberOfCameras; i++) {
|
||||
// Declare this before the lock to make absolutely sure the
|
||||
// destructor won't be called with the lock held.
|
||||
sp<Client> client;
|
||||
@ -199,7 +188,7 @@ void CameraService::removeClient(const sp<ICameraClient>& cameraClient) {
|
||||
}
|
||||
|
||||
sp<CameraService::Client> CameraService::getClientById(int cameraId) {
|
||||
if (cameraId < 0 || cameraId >= NUM_CAMERAS) return NULL;
|
||||
if (cameraId < 0 || cameraId >= mNumberOfCameras) return NULL;
|
||||
return mClient[cameraId].promote();
|
||||
}
|
||||
|
||||
@ -311,7 +300,7 @@ CameraService::Client::Client(const sp<CameraService>& cameraService,
|
||||
mCameraId = cameraId;
|
||||
mClientPid = clientPid;
|
||||
|
||||
mHardware = sOpenCameraTable[cameraId]();
|
||||
mHardware = HAL_openCameraHardware(cameraId);
|
||||
mUseOverlay = mHardware->useOverlay();
|
||||
mMsgEnabled = 0;
|
||||
|
||||
@ -1246,7 +1235,7 @@ status_t CameraService::dump(int fd, const Vector<String16>& args) {
|
||||
}
|
||||
|
||||
bool hasClient = false;
|
||||
for (int i = 0; i < NUM_CAMERAS; i++) {
|
||||
for (int i = 0; i < mNumberOfCameras; i++) {
|
||||
sp<Client> client = mClient[i].promote();
|
||||
if (client == 0) continue;
|
||||
hasClient = true;
|
||||
|
@ -40,6 +40,8 @@ public:
|
||||
virtual ~CameraService();
|
||||
|
||||
virtual int32_t getNumberOfCameras();
|
||||
virtual status_t getCameraInfo(int cameraId,
|
||||
struct CameraInfo* cameraInfo);
|
||||
virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId);
|
||||
virtual void removeClient(const sp<ICameraClient>& cameraClient);
|
||||
virtual sp<Client> getClientById(int cameraId);
|
||||
@ -61,6 +63,7 @@ public:
|
||||
private:
|
||||
Mutex mServiceLock;
|
||||
wp<Client> mClient[MAX_CAMERAS]; // protected by mServiceLock
|
||||
int mNumberOfCameras;
|
||||
|
||||
// atomics to record whether the hardware is allocated to some client.
|
||||
volatile int32_t mBusy[MAX_CAMERAS];
|
||||
|
@ -89,9 +89,45 @@ public class Camera {
|
||||
*/
|
||||
public native static int getNumberOfCameras();
|
||||
|
||||
/**
|
||||
* Returns the information about the camera.
|
||||
* If {@link #getNumberOfCameras()} returns N, the valid id is 0 to N-1.
|
||||
* @hide
|
||||
*/
|
||||
public native static void getCameraInfo(int cameraId, CameraInfo cameraInfo);
|
||||
|
||||
/**
|
||||
* Information about a camera
|
||||
* @hide
|
||||
*/
|
||||
public static class CameraInfo {
|
||||
public static final int CAMERA_FACING_BACK = 0;
|
||||
public static final int CAMERA_FACING_FRONT = 1;
|
||||
|
||||
/**
|
||||
* The direction that the camera faces to. It should be
|
||||
* CAMERA_FACING_BACK or CAMERA_FACING_FRONT.
|
||||
*/
|
||||
public int mFacing;
|
||||
|
||||
/**
|
||||
* The orientation of the camera image. The value is the angle that the
|
||||
* camera image needs to be rotated clockwise so it shows correctly on
|
||||
* the display in its natural orientation. It should be 0, 90, 180, or 270.
|
||||
*
|
||||
* For example, suppose a device has a naturally tall screen, but the camera
|
||||
* sensor is mounted in landscape. If the top side of the camera sensor is
|
||||
* aligned with the right edge of the display in natural orientation, the
|
||||
* value should be 90.
|
||||
*
|
||||
* @see #setDisplayOrientation(int)
|
||||
*/
|
||||
public int mOrientation;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a new Camera object.
|
||||
* If {@link #getNumberOfCameras()} returns N, the valid is is 0 to N-1.
|
||||
* If {@link #getNumberOfCameras()} returns N, the valid id is 0 to N-1.
|
||||
* The id 0 is the default camera.
|
||||
* @hide
|
||||
*/
|
||||
@ -99,11 +135,17 @@ public class Camera {
|
||||
return new Camera(cameraId);
|
||||
}
|
||||
|
||||
/**
|
||||
* The id for the default camera.
|
||||
* @hide
|
||||
*/
|
||||
public static int CAMERA_ID_DEFAULT = 0;
|
||||
|
||||
/**
|
||||
* Returns a new Camera object. This returns the default camera.
|
||||
*/
|
||||
public static Camera open() {
|
||||
return new Camera(0);
|
||||
return new Camera(CAMERA_ID_DEFAULT);
|
||||
}
|
||||
|
||||
Camera(int cameraId) {
|
||||
@ -581,6 +623,18 @@ public class Camera {
|
||||
* {@link PreviewCallback#onPreviewFrame}. This method is not allowed to
|
||||
* be called during preview.
|
||||
*
|
||||
* If you want to make the camera image show in the same orientation as
|
||||
* the display, you can use <p>
|
||||
* <pre>
|
||||
* android.view.Display display;
|
||||
* android.hardware.Camera.CameraInfo cameraInfo;
|
||||
*
|
||||
* int rotation = getWindowManager().getDefaultDisplay().getRotation();
|
||||
* android.hardware.Camera.getCameraInfo(id, cameraInfo);
|
||||
* int degrees = (cameraInfo.mOrientation - rotation + 360) % 360;
|
||||
*
|
||||
* setDisplayOrientation(degrees);
|
||||
* </pre>
|
||||
* @param degrees the angle that the picture will be rotated clockwise.
|
||||
* Valid values are 0, 90, 180, and 270. The starting
|
||||
* position is 0 (landscape).
|
||||
|
@ -34,6 +34,8 @@ using namespace android;
|
||||
struct fields_t {
|
||||
jfieldID context;
|
||||
jfieldID surface;
|
||||
jfieldID facing;
|
||||
jfieldID orientation;
|
||||
jmethodID post_event;
|
||||
};
|
||||
|
||||
@ -293,6 +295,20 @@ static jint android_hardware_Camera_getNumberOfCameras(JNIEnv *env, jobject thiz
|
||||
return Camera::getNumberOfCameras();
|
||||
}
|
||||
|
||||
static void android_hardware_Camera_getCameraInfo(JNIEnv *env, jobject thiz,
|
||||
jint cameraId, jobject info_obj)
|
||||
{
|
||||
CameraInfo cameraInfo;
|
||||
status_t rc = Camera::getCameraInfo(cameraId, &cameraInfo);
|
||||
if (rc != NO_ERROR) {
|
||||
jniThrowException(env, "java/lang/RuntimeException",
|
||||
"Fail to get camera info");
|
||||
return;
|
||||
}
|
||||
env->SetIntField(info_obj, fields.facing, cameraInfo.facing);
|
||||
env->SetIntField(info_obj, fields.orientation, cameraInfo.orientation);
|
||||
}
|
||||
|
||||
// connect to camera service
|
||||
static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
|
||||
jobject weak_this, jint cameraId)
|
||||
@ -575,6 +591,9 @@ static JNINativeMethod camMethods[] = {
|
||||
{ "getNumberOfCameras",
|
||||
"()I",
|
||||
(void *)android_hardware_Camera_getNumberOfCameras },
|
||||
{ "getCameraInfo",
|
||||
"(ILandroid/hardware/Camera$CameraInfo;)V",
|
||||
(void*)android_hardware_Camera_getCameraInfo },
|
||||
{ "native_setup",
|
||||
"(Ljava/lang/Object;I)V",
|
||||
(void*)android_hardware_Camera_native_setup },
|
||||
@ -668,7 +687,9 @@ int register_android_hardware_Camera(JNIEnv *env)
|
||||
{
|
||||
field fields_to_find[] = {
|
||||
{ "android/hardware/Camera", "mNativeContext", "I", &fields.context },
|
||||
{ "android/view/Surface", ANDROID_VIEW_SURFACE_JNI_ID, "I", &fields.surface }
|
||||
{ "android/view/Surface", ANDROID_VIEW_SURFACE_JNI_ID, "I", &fields.surface },
|
||||
{ "android/hardware/Camera$CameraInfo", "mFacing", "I", &fields.facing },
|
||||
{ "android/hardware/Camera$CameraInfo", "mOrientation", "I", &fields.orientation },
|
||||
};
|
||||
|
||||
if (find_fields(env, fields_to_find, NELEM(fields_to_find)) < 0)
|
||||
|
@ -93,6 +93,32 @@ enum {
|
||||
CAMERA_ERROR_SERVER_DIED = 100
|
||||
};
|
||||
|
||||
enum {
|
||||
CAMERA_FACING_BACK = 0,
|
||||
CAMERA_FACING_FRONT = 1 /* The camera faces to the user */
|
||||
};
|
||||
|
||||
struct CameraInfo {
|
||||
|
||||
/**
|
||||
* The direction that the camera faces to. It should be
|
||||
* CAMERA_FACING_BACK or CAMERA_FACING_FRONT.
|
||||
*/
|
||||
int facing;
|
||||
|
||||
/**
|
||||
* The orientation of the camera image. The value is the angle that the
|
||||
* camera image needs to be rotated clockwise so it shows correctly on
|
||||
* the display in its natural orientation. It should be 0, 90, 180, or 270.
|
||||
*
|
||||
* For example, suppose a device has a naturally tall screen, but the camera
|
||||
* sensor is mounted in landscape. If the top side of the camera sensor is
|
||||
* aligned with the right edge of the display in natural orientation, the
|
||||
* value should be 90.
|
||||
*/
|
||||
int orientation;
|
||||
};
|
||||
|
||||
class ICameraService;
|
||||
class ICamera;
|
||||
class Surface;
|
||||
@ -114,6 +140,8 @@ public:
|
||||
// construct a camera client from an existing remote
|
||||
static sp<Camera> create(const sp<ICamera>& camera);
|
||||
static int32_t getNumberOfCameras();
|
||||
static status_t getCameraInfo(int cameraId,
|
||||
struct CameraInfo* cameraInfo);
|
||||
static sp<Camera> connect(int cameraId);
|
||||
~Camera();
|
||||
void init();
|
||||
|
@ -213,8 +213,15 @@ public:
|
||||
virtual status_t dump(int fd, const Vector<String16>& args) const = 0;
|
||||
};
|
||||
|
||||
/** factory function to instantiate a camera hardware object */
|
||||
extern "C" sp<CameraHardwareInterface> openCameraHardware();
|
||||
/**
|
||||
* The functions need to be provided by the camera HAL.
|
||||
*
|
||||
* If getNumberOfCameras() returns N, the valid cameraId for getCameraInfo()
|
||||
* and openCameraHardware() is 0 to N-1.
|
||||
*/
|
||||
extern "C" int HAL_getNumberOfCameras();
|
||||
extern "C" void HAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo);
|
||||
extern "C" sp<CameraHardwareInterface> HAL_openCameraHardware(int cameraId);
|
||||
|
||||
}; // namespace android
|
||||
|
||||
|
@ -31,6 +31,7 @@ class ICameraService : public IInterface
|
||||
public:
|
||||
enum {
|
||||
GET_NUMBER_OF_CAMERAS = IBinder::FIRST_CALL_TRANSACTION,
|
||||
GET_CAMERA_INFO,
|
||||
CONNECT
|
||||
};
|
||||
|
||||
@ -38,6 +39,8 @@ public:
|
||||
DECLARE_META_INTERFACE(CameraService);
|
||||
|
||||
virtual int32_t getNumberOfCameras() = 0;
|
||||
virtual status_t getCameraInfo(int cameraId,
|
||||
struct CameraInfo* cameraInfo) = 0;
|
||||
virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient,
|
||||
int cameraId) = 0;
|
||||
};
|
||||
|
@ -107,6 +107,13 @@ int32_t Camera::getNumberOfCameras()
|
||||
return cs->getNumberOfCameras();
|
||||
}
|
||||
|
||||
status_t Camera::getCameraInfo(int cameraId,
|
||||
struct CameraInfo* cameraInfo) {
|
||||
const sp<ICameraService>& cs = getCameraService();
|
||||
if (cs == 0) return UNKNOWN_ERROR;
|
||||
return cs->getCameraInfo(cameraId, cameraInfo);
|
||||
}
|
||||
|
||||
sp<Camera> Camera::connect(int cameraId)
|
||||
{
|
||||
LOGV("connect");
|
||||
|
@ -43,6 +43,18 @@ public:
|
||||
return reply.readInt32();
|
||||
}
|
||||
|
||||
// get information about a camera
|
||||
virtual status_t getCameraInfo(int cameraId,
|
||||
struct CameraInfo* cameraInfo) {
|
||||
Parcel data, reply;
|
||||
data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
|
||||
data.writeInt32(cameraId);
|
||||
remote()->transact(BnCameraService::GET_CAMERA_INFO, data, &reply);
|
||||
cameraInfo->facing = reply.readInt32();
|
||||
cameraInfo->orientation = reply.readInt32();
|
||||
return reply.readInt32();
|
||||
}
|
||||
|
||||
// connect to camera service
|
||||
virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId)
|
||||
{
|
||||
@ -68,6 +80,16 @@ status_t BnCameraService::onTransact(
|
||||
reply->writeInt32(getNumberOfCameras());
|
||||
return NO_ERROR;
|
||||
} break;
|
||||
case GET_CAMERA_INFO: {
|
||||
CHECK_INTERFACE(ICameraService, data, reply);
|
||||
CameraInfo cameraInfo;
|
||||
memset(&cameraInfo, 0, sizeof(cameraInfo));
|
||||
status_t result = getCameraInfo(data.readInt32(), &cameraInfo);
|
||||
reply->writeInt32(cameraInfo.facing);
|
||||
reply->writeInt32(cameraInfo.orientation);
|
||||
reply->writeInt32(result);
|
||||
return NO_ERROR;
|
||||
} break;
|
||||
case CONNECT: {
|
||||
CHECK_INTERFACE(ICameraService, data, reply);
|
||||
sp<ICameraClient> cameraClient = interface_cast<ICameraClient>(data.readStrongBinder());
|
||||
|
Reference in New Issue
Block a user