summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChih-Chung Chang <chihchung@google.com>2010-06-10 13:32:16 +0800
committerChih-Chung Chang <chihchung@google.com>2010-06-11 16:47:33 +0800
commitb8bb78f54b48868465a9d69d65fda08524ab5ae1 (patch)
treefadbdd8dd989ce2b3b29cd780fabc91d7f98dd09
parent2fd73a452268d2acb6e72a1d23a422085ed3c510 (diff)
downloadframeworks_base-b8bb78f54b48868465a9d69d65fda08524ab5ae1.zip
frameworks_base-b8bb78f54b48868465a9d69d65fda08524ab5ae1.tar.gz
frameworks_base-b8bb78f54b48868465a9d69d65fda08524ab5ae1.tar.bz2
Change camera interface to support multiple cameras.
Change-Id: Ie88fe706d2278acf762eca87780de349434778a4
-rw-r--r--camera/libcameraservice/Android.mk20
-rw-r--r--camera/libcameraservice/CameraHardwareStub.cpp19
-rw-r--r--camera/libcameraservice/CameraHardwareStub.h2
-rw-r--r--camera/libcameraservice/CameraService.cpp61
-rw-r--r--camera/libcameraservice/CameraService.h3
-rw-r--r--core/java/android/hardware/Camera.java58
-rw-r--r--core/jni/android_hardware_Camera.cpp23
-rw-r--r--include/camera/Camera.h28
-rw-r--r--include/camera/CameraHardwareInterface.h11
-rw-r--r--include/camera/ICameraService.h3
-rw-r--r--libs/camera/Camera.cpp7
-rw-r--r--libs/camera/ICameraService.cpp22
12 files changed, 199 insertions, 58 deletions
diff --git a/camera/libcameraservice/Android.mk b/camera/libcameraservice/Android.mk
index a0d6ee1..87975af 100644
--- a/camera/libcameraservice/Android.mk
+++ b/camera/libcameraservice/Android.mk
@@ -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
diff --git a/camera/libcameraservice/CameraHardwareStub.cpp b/camera/libcameraservice/CameraHardwareStub.cpp
index fda48e8..b3e0ee6 100644
--- a/camera/libcameraservice/CameraHardwareStub.cpp
+++ b/camera/libcameraservice/CameraHardwareStub.cpp
@@ -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();
}
diff --git a/camera/libcameraservice/CameraHardwareStub.h b/camera/libcameraservice/CameraHardwareStub.h
index d194f3c..d3427ba 100644
--- a/camera/libcameraservice/CameraHardwareStub.h
+++ b/camera/libcameraservice/CameraHardwareStub.h
@@ -128,8 +128,6 @@ private:
int mCurrentPreviewFrame;
};
-extern "C" sp<CameraHardwareInterface> openCameraHardwareStub();
-
}; // namespace android
#endif
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index 690169a..75948a5 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -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;
diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h
index 86986ca..8193e77 100644
--- a/camera/libcameraservice/CameraService.h
+++ b/camera/libcameraservice/CameraService.h
@@ -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];
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 5c96a44..7640cc1 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -90,8 +90,44 @@ 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
*/
@@ -100,10 +136,16 @@ public class Camera {
}
/**
+ * 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).
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index c363156..c784974 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -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)
diff --git a/include/camera/Camera.h b/include/camera/Camera.h
index 1beac27..9974f2f 100644
--- a/include/camera/Camera.h
+++ b/include/camera/Camera.h
@@ -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();
diff --git a/include/camera/CameraHardwareInterface.h b/include/camera/CameraHardwareInterface.h
index d877c74..1529db7 100644
--- a/include/camera/CameraHardwareInterface.h
+++ b/include/camera/CameraHardwareInterface.h
@@ -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
diff --git a/include/camera/ICameraService.h b/include/camera/ICameraService.h
index dcd434f..7d70c1e 100644
--- a/include/camera/ICameraService.h
+++ b/include/camera/ICameraService.h
@@ -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;
};
diff --git a/libs/camera/Camera.cpp b/libs/camera/Camera.cpp
index 2fbddd5..0037399 100644
--- a/libs/camera/Camera.cpp
+++ b/libs/camera/Camera.cpp
@@ -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");
diff --git a/libs/camera/ICameraService.cpp b/libs/camera/ICameraService.cpp
index db1dca6..85f1a29 100644
--- a/libs/camera/ICameraService.cpp
+++ b/libs/camera/ICameraService.cpp
@@ -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());