Support multiple cameras in framework.

Change-Id: I081f0fbdca4b633715ea7c3b3d42f8662d27598a
diff --git a/camera/tests/CameraServiceTest/CameraServiceTest.cpp b/camera/tests/CameraServiceTest/CameraServiceTest.cpp
index 9fc795b..41670af 100644
--- a/camera/tests/CameraServiceTest/CameraServiceTest.cpp
+++ b/camera/tests/CameraServiceTest/CameraServiceTest.cpp
@@ -38,7 +38,7 @@
     INFO("assertion failed at file %s, line %d, function %s:",
             file, line, func);
     INFO("%s", expr);
-    exit(1);
+    abort();
 }
 
 void assert_eq_fail(const char *file, int line, const char *func,
@@ -46,7 +46,7 @@
     INFO("assertion failed at file %s, line %d, function %s:",
             file, line, func);
     INFO("(expected) %s != (actual) %d", expr, actual);
-    exit(1);
+    abort();
 }
 
 #define ASSERT(e) \
@@ -155,7 +155,7 @@
     virtual void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2);
     virtual void dataCallback(int32_t msgType, const sp<IMemory>& data);
     virtual void dataCallbackTimestamp(nsecs_t timestamp,
-            int32_t msgType, const sp<IMemory>& data) {}
+            int32_t msgType, const sp<IMemory>& data);
 
     // new functions
     void clearStat();
@@ -176,6 +176,7 @@
     DefaultKeyedVector<int32_t, int> mDataCount;
     DefaultKeyedVector<int32_t, int> mDataSize;
     bool test(OP op, int v1, int v2);
+    void assertTest(OP op, int v1, int v2);
 
     ICamera *mReleaser;
 };
@@ -199,22 +200,29 @@
     return false;
 }
 
+void MCameraClient::assertTest(OP op, int v1, int v2) {
+    if (!test(op, v1, v2)) {
+        LOGE("assertTest failed: op=%d, v1=%d, v2=%d", op, v1, v2);
+        ASSERT(0);
+    }
+}
+
 void MCameraClient::assertNotify(int32_t msgType, OP op, int count) {
     Mutex::Autolock _l(mLock);
     int v = mNotifyCount.valueFor(msgType);
-    ASSERT(test(op, v, count));
+    assertTest(op, v, count);
 }
 
 void MCameraClient::assertData(int32_t msgType, OP op, int count) {
     Mutex::Autolock _l(mLock);
     int v = mDataCount.valueFor(msgType);
-    ASSERT(test(op, v, count));
+    assertTest(op, v, count);
 }
 
 void MCameraClient::assertDataSize(int32_t msgType, OP op, int dataSize) {
     Mutex::Autolock _l(mLock);
     int v = mDataSize.valueFor(msgType);
-    ASSERT(test(op, v, dataSize));
+    assertTest(op, v, dataSize);
 }
 
 void MCameraClient::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) {
@@ -250,6 +258,11 @@
     }
 }
 
+void MCameraClient::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
+        const sp<IMemory>& data) {
+    dataCallback(msgType, data);
+}
+
 void MCameraClient::waitNotify(int32_t msgType, OP op, int count) {
     INFO("waitNotify: %d, %d, %d", msgType, op, count);
     Mutex::Autolock _l(mLock);
@@ -348,10 +361,9 @@
 
 sp<OverlayRef> MSurface::createOverlay(uint32_t w, uint32_t h, int32_t format,
         int32_t orientation) {
-    // We don't expect this to be called in current hardware.
+    // Not implemented.
     ASSERT(0);
-    sp<OverlayRef> dummy;
-    return dummy;
+    return NULL;
 }
 
 //
@@ -395,38 +407,43 @@
     return cs;
 }
 
+int getNumberOfCameras() {
+    sp<ICameraService> cs = getCameraService();
+    return cs->getNumberOfCameras();
+}
+
 //
 // Various Connect Tests
 //
-void testConnect() {
+void testConnect(int cameraId) {
     INFO(__func__);
     sp<ICameraService> cs = getCameraService();
     sp<MCameraClient> cc = new MCameraClient();
-    sp<ICamera> c = cs->connect(cc);
+    sp<ICamera> c = cs->connect(cc, cameraId);
     ASSERT(c != 0);
     c->disconnect();
 }
 
-void testAllowConnectOnceOnly() {
+void testAllowConnectOnceOnly(int cameraId) {
     INFO(__func__);
     sp<ICameraService> cs = getCameraService();
     // Connect the first client.
     sp<MCameraClient> cc = new MCameraClient();
-    sp<ICamera> c = cs->connect(cc);
+    sp<ICamera> c = cs->connect(cc, cameraId);
     ASSERT(c != 0);
     // Same client -- ok.
-    ASSERT(cs->connect(cc) != 0);
+    ASSERT(cs->connect(cc, cameraId) != 0);
     // Different client -- not ok.
     sp<MCameraClient> cc2 = new MCameraClient();
-    ASSERT(cs->connect(cc2) == 0);
+    ASSERT(cs->connect(cc2, cameraId) == 0);
     c->disconnect();
 }
 
 void testReconnectFailed() {
     INFO(__func__);
     sp<ICamera> c = interface_cast<ICamera>(getTempObject());
-    sp<MCameraClient> cc2 = new MCameraClient();
-    ASSERT(c->connect(cc2) != NO_ERROR);
+    sp<MCameraClient> cc = new MCameraClient();
+    ASSERT(c->connect(cc) != NO_ERROR);
 }
 
 void testReconnectSuccess() {
@@ -434,6 +451,7 @@
     sp<ICamera> c = interface_cast<ICamera>(getTempObject());
     sp<MCameraClient> cc = new MCameraClient();
     ASSERT(c->connect(cc) == NO_ERROR);
+    c->disconnect();
 }
 
 void testLockFailed() {
@@ -453,6 +471,7 @@
     INFO(__func__);
     sp<ICamera> c = interface_cast<ICamera>(getTempObject());
     ASSERT(c->lock() == NO_ERROR);
+    c->disconnect();
 }
 
 //
@@ -499,11 +518,11 @@
     }
 }
 
-void testReconnect() {
+void testReconnect(int cameraId) {
     INFO(__func__);
     sp<ICameraService> cs = getCameraService();
     sp<MCameraClient> cc = new MCameraClient();
-    sp<ICamera> c = cs->connect(cc);
+    sp<ICamera> c = cs->connect(cc, cameraId);
     ASSERT(c != 0);
     // Reconnect to the same client -- ok.
     ASSERT(c->connect(cc) == NO_ERROR);
@@ -514,10 +533,10 @@
     cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
 }
 
-void testLockUnlock() {
+void testLockUnlock(int cameraId) {
     sp<ICameraService> cs = getCameraService();
     sp<MCameraClient> cc = new MCameraClient();
-    sp<ICamera> c = cs->connect(cc);
+    sp<ICamera> c = cs->connect(cc, cameraId);
     ASSERT(c != 0);
     // We can lock as many times as we want.
     ASSERT(c->lock() == NO_ERROR);
@@ -530,16 +549,15 @@
     runInAnotherProcess("testLockUnlockSuccess");
     // Unlock then lock from a different process -- ok.
     runInAnotherProcess("testLockSuccess");
-    c->disconnect();
     clearTempObject();
 }
 
-void testReconnectFromAnotherProcess() {
+void testReconnectFromAnotherProcess(int cameraId) {
     INFO(__func__);
 
     sp<ICameraService> cs = getCameraService();
     sp<MCameraClient> cc = new MCameraClient();
-    sp<ICamera> c = cs->connect(cc);
+    sp<ICamera> c = cs->connect(cc, cameraId);
     ASSERT(c != 0);
     // Reconnect from a different process -- not ok.
     putTempObject(c->asBinder());
@@ -547,7 +565,6 @@
     // Unlock then reconnect from a different process -- ok.
     ASSERT(c->unlock() == NO_ERROR);
     runInAnotherProcess("testReconnectSuccess");
-    c->disconnect();
     clearTempObject();
 }
 
@@ -560,10 +577,11 @@
 }
 
 // Run a test case
-#define RUN(class_name) do { \
+#define RUN(class_name, cameraId) do { \
     { \
         INFO(#class_name); \
         class_name instance; \
+        instance.init(cameraId); \
         instance.run(); \
     } \
     flushCommands(); \
@@ -571,19 +589,21 @@
 
 // Base test case after the the camera is connected.
 class AfterConnect {
+public:
+    void init(int cameraId) {
+        cs = getCameraService();
+        cc = new MCameraClient();
+        c = cs->connect(cc, cameraId);
+        ASSERT(c != 0);
+    }
+
 protected:
     sp<ICameraService> cs;
     sp<MCameraClient> cc;
     sp<ICamera> c;
 
-    AfterConnect() {
-        cs = getCameraService();
-        cc = new MCameraClient();
-        c = cs->connect(cc);
-        ASSERT(c != 0);
-    }
-
     ~AfterConnect() {
+        c->disconnect();
         c.clear();
         cc.clear();
         cs.clear();
@@ -612,19 +632,16 @@
         surface->waitUntil(1, 10, 0); // needs 1 registerBuffers and 10 postBuffer
         surface->clearStat();
 
-        c->disconnect();
-        // TODO: CameraService crashes for this. Fix it.
-#if 0
         sp<MSurface> another_surface = new MSurface();
         c->setPreviewDisplay(another_surface);  // just to make sure unregisterBuffers
                                                 // is called.
         surface->waitUntil(0, 0, 1);  // needs unregisterBuffers
-#endif
+
         cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
     }
 };
 
-class TestStartPreviewWithoutDisplay : AfterConnect {
+class TestStartPreviewWithoutDisplay : public AfterConnect {
 public:
     void run() {
         ASSERT(c->startPreview() == NO_ERROR);
@@ -636,15 +653,17 @@
 
 // Base test case after the the camera is connected and the preview is started.
 class AfterStartPreview : public AfterConnect {
-protected:
-    sp<MSurface> surface;
-
-    AfterStartPreview() {
+public:
+    void init(int cameraId) {
+        AfterConnect::init(cameraId);
         surface = new MSurface();
         ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
         ASSERT(c->startPreview() == NO_ERROR);
     }
 
+protected:
+    sp<MSurface> surface;
+
     ~AfterStartPreview() {
         surface.clear();
     }
@@ -680,9 +699,6 @@
         cc->waitData(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, 1);
         cc->waitData(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::EQ, 1);
         c->stopPreview();
-#if 1  // TODO: It crashes if we don't have this. Fix it.
-        usleep(100000);
-#endif
         c->disconnect();
         cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
     }
@@ -697,7 +713,6 @@
             cc->waitNotify(CAMERA_MSG_SHUTTER, MCameraClient::EQ, 1);
             cc->waitData(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, 1);
             cc->waitData(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::EQ, 1);
-            usleep(100000);  // 100ms
         }
         c->disconnect();
         cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
@@ -712,32 +727,67 @@
     }
 };
 
+static bool getNextSize(const char **ptrS, int *w, int *h) {
+    const char *s = *ptrS;
+
+    // skip over ','
+    if (*s == ',') s++;
+
+    // remember start position in p
+    const char *p = s;
+    while (*s != '\0' && *s != 'x') {
+        s++;
+    }
+    if (*s == '\0') return false;
+
+    // get the width
+    *w = atoi(p);
+
+    // skip over 'x'
+    ASSERT(*s == 'x');
+    p = s + 1;
+    while (*s != '\0' && *s != ',') {
+        s++;
+    }
+
+    // get the height
+    *h = atoi(p);
+    *ptrS = s;
+    return true;
+}
+
 class TestPictureSize : public AfterStartPreview {
 public:
     void checkOnePicture(int w, int h) {
-        const float rate = 0.5;  // byte per pixel limit
+        const float rate = 0.9;  // byte per pixel limit
         int pixels = w * h;
 
         CameraParameters param(c->getParameters());
         param.setPictureSize(w, h);
+        // disable thumbnail to get more accurate size.
+        param.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, 0);
+        param.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, 0);
         c->setParameters(param.flatten());
 
         cc->clearStat();
         ASSERT(c->takePicture() == NO_ERROR);
         cc->waitData(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, 1);
-        cc->assertDataSize(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, pixels*3/2);
+        //cc->assertDataSize(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, pixels*3/2);
         cc->waitData(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::EQ, 1);
         cc->assertDataSize(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::LT,
                 int(pixels * rate));
         cc->assertDataSize(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::GT, 0);
         cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
-        usleep(100000);  // 100ms
     }
 
     void run() {
-        checkOnePicture(2048, 1536);
-        checkOnePicture(1600, 1200);
-        checkOnePicture(1024, 768);
+        CameraParameters param(c->getParameters());
+        int w, h;
+        const char *s = param.get(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES);
+        while (getNextSize(&s, &w, &h)) {
+            LOGD("checking picture size %dx%d", w, h);
+            checkOnePicture(w, h);
+        }
     }
 };
 
@@ -749,6 +799,8 @@
 
         // Try all flag combinations.
         for (int v = 0; v < 8; v++) {
+            LOGD("TestPreviewCallbackFlag: flag=%d", v);
+            usleep(100000); // sleep a while to clear the in-flight callbacks.
             cc->clearStat();
             c->setPreviewCallbackFlag(v);
             ASSERT(c->previewEnabled() == false);
@@ -781,6 +833,7 @@
         ASSERT(c->recordingEnabled() == true);
         sleep(2);
         c->stopRecording();
+        usleep(100000); // sleep a while to clear the in-flight callbacks.
         cc->setReleaser(NULL);
         cc->assertData(CAMERA_MSG_VIDEO_FRAME, MCameraClient::GE, 10);
     }
@@ -806,9 +859,13 @@
     }
 
     void run() {
-        checkOnePicture(480, 320);
-        checkOnePicture(352, 288);
-        checkOnePicture(176, 144);
+        CameraParameters param(c->getParameters());
+        int w, h;
+        const char *s = param.get(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES);
+        while (getNextSize(&s, &w, &h)) {
+            LOGD("checking preview size %dx%d", w, h);
+            checkOnePicture(w, h);
+        }
     }
 };
 
@@ -827,23 +884,30 @@
     INFO("CameraServiceTest start");
     gExecutable = argv[0];
     runHolderService();
+    int n = getNumberOfCameras();
+    INFO("%d Cameras available", n);
 
-    testConnect();                              flushCommands();
-    testAllowConnectOnceOnly();                 flushCommands();
-    testReconnect();                            flushCommands();
-    testLockUnlock();                           flushCommands();
-    testReconnectFromAnotherProcess();          flushCommands();
+    for (int id = 0; id < n; id++) {
+        INFO("Testing camera %d", id);
+        testConnect(id);                              flushCommands();
+        testAllowConnectOnceOnly(id);                 flushCommands();
+        testReconnect(id);                            flushCommands();
+        testLockUnlock(id);                           flushCommands();
+        testReconnectFromAnotherProcess(id);          flushCommands();
 
-    RUN(TestSetPreviewDisplay);
-    RUN(TestStartPreview);
-    RUN(TestStartPreviewWithoutDisplay);
-    RUN(TestAutoFocus);
-    RUN(TestStopPreview);
-    RUN(TestTakePicture);
-    RUN(TestTakeMultiplePictures);
-    RUN(TestGetParameters);
-    RUN(TestPictureSize);
-    RUN(TestPreviewCallbackFlag);
-    RUN(TestRecording);
-    RUN(TestPreviewSize);
+        RUN(TestSetPreviewDisplay, id);
+        RUN(TestStartPreview, id);
+        RUN(TestStartPreviewWithoutDisplay, id);
+        RUN(TestAutoFocus, id);
+        RUN(TestStopPreview, id);
+        RUN(TestTakePicture, id);
+        RUN(TestTakeMultiplePictures, id);
+        RUN(TestGetParameters, id);
+        RUN(TestPictureSize, id);
+        RUN(TestPreviewCallbackFlag, id);
+        RUN(TestRecording, id);
+        RUN(TestPreviewSize, id);
+    }
+
+    INFO("CameraServiceTest finished");
 }