Change camera interface to support multiple cameras.

Change-Id: Ie88fe706d2278acf762eca87780de349434778a4
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 @@
   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 @@
 LOCAL_SHARED_LIBRARIES:= libui
 
 include $(BUILD_STATIC_LIBRARY)
-endif # INCLUDE_CAMERA_STUB
+endif # USE_CAMERA_STUB
 
 #
 # libcameraservice
@@ -61,13 +57,9 @@
 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 @@
     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 @@
     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 @@
 {
     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() {
-    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 @@
 }
 
 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 @@
     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 @@
     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 @@
 }
 
 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 @@
     mCameraId = cameraId;
     mClientPid = clientPid;
 
-    mHardware = sOpenCameraTable[cameraId]();
+    mHardware = HAL_openCameraHardware(cameraId);
     mUseOverlay = mHardware->useOverlay();
     mMsgEnabled = 0;
 
@@ -1246,7 +1235,7 @@
         }
 
         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 @@
     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 @@
 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 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 @@
     }
 
     /**
+     * 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 @@
      * {@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 @@
 struct fields_t {
     jfieldID    context;
     jfieldID    surface;
+    jfieldID    facing;
+    jfieldID    orientation;
     jmethodID   post_event;
 };
 
@@ -293,6 +295,20 @@
     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 @@
   { "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 @@
 {
     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 @@
     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 @@
             // 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 @@
     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 @@
 public:
     enum {
         GET_NUMBER_OF_CAMERAS = IBinder::FIRST_CALL_TRANSACTION,
+        GET_CAMERA_INFO,
         CONNECT
     };
 
@@ -38,6 +39,8 @@
     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 @@
     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 @@
         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 @@
             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());