diff options
author | Chih-Chung Chang <chihchung@google.com> | 2010-06-10 13:32:16 +0800 |
---|---|---|
committer | Chih-Chung Chang <chihchung@google.com> | 2010-06-11 16:47:33 +0800 |
commit | b8bb78f54b48868465a9d69d65fda08524ab5ae1 (patch) | |
tree | fadbdd8dd989ce2b3b29cd780fabc91d7f98dd09 | |
parent | 2fd73a452268d2acb6e72a1d23a422085ed3c510 (diff) | |
download | frameworks_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.mk | 20 | ||||
-rw-r--r-- | camera/libcameraservice/CameraHardwareStub.cpp | 19 | ||||
-rw-r--r-- | camera/libcameraservice/CameraHardwareStub.h | 2 | ||||
-rw-r--r-- | camera/libcameraservice/CameraService.cpp | 61 | ||||
-rw-r--r-- | camera/libcameraservice/CameraService.h | 3 | ||||
-rw-r--r-- | core/java/android/hardware/Camera.java | 58 | ||||
-rw-r--r-- | core/jni/android_hardware_Camera.cpp | 23 | ||||
-rw-r--r-- | include/camera/Camera.h | 28 | ||||
-rw-r--r-- | include/camera/CameraHardwareInterface.h | 11 | ||||
-rw-r--r-- | include/camera/ICameraService.h | 3 | ||||
-rw-r--r-- | libs/camera/Camera.cpp | 7 | ||||
-rw-r--r-- | libs/camera/ICameraService.cpp | 22 |
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()); |