/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <gtest/gtest.h>
#include <iostream>

#include <binder/IPCThreadState.h>
#include <utils/Thread.h>

#include "Camera.h"
#include "ProCamera.h"
#include <utils/Vector.h>
#include <utils/Mutex.h>
#include <utils/Condition.h>

#include <gui/SurfaceComposerClient.h>
#include <gui/Surface.h>

#include <system/camera_metadata.h>
#include <hardware/camera2.h> // for CAMERA2_TEMPLATE_PREVIEW only
#include <camera/CameraMetadata.h>

#include <camera/ICameraServiceListener.h>

namespace android {
namespace camera2 {
namespace tests {
namespace client {

#define CAMERA_ID 0
#define TEST_DEBUGGING 0

#define TEST_LISTENER_TIMEOUT 1000000000 // 1 second listener timeout
#define TEST_FORMAT HAL_PIXEL_FORMAT_Y16 //TODO: YUY2 instead

#define TEST_FORMAT_MAIN HAL_PIXEL_FORMAT_Y8
#define TEST_FORMAT_DEPTH HAL_PIXEL_FORMAT_Y16

// defaults for display "test"
#define TEST_DISPLAY_FORMAT HAL_PIXEL_FORMAT_Y8
#define TEST_DISPLAY_WIDTH 320
#define TEST_DISPLAY_HEIGHT 240

#define TEST_CPU_FRAME_COUNT 2
#define TEST_CPU_HEAP_COUNT 5

#define TEST_FRAME_PROCESSING_DELAY_US 200000 // 200 ms

#if TEST_DEBUGGING
#define dout std::cerr
#else
#define dout if (0) std::cerr
#endif

#define EXPECT_OK(x) EXPECT_EQ(OK, (x))
#define ASSERT_OK(x) ASSERT_EQ(OK, (x))

class ProCameraTest;

struct ServiceListener : public BnCameraServiceListener {

    ServiceListener() :
        mLatestStatus(STATUS_UNKNOWN),
        mPrevStatus(STATUS_UNKNOWN)
    {
    }

    void onStatusChanged(Status status, int32_t cameraId) {
        dout << "On status changed: 0x" << std::hex
             << (unsigned int) status << " cameraId " << cameraId
             << std::endl;

        Mutex::Autolock al(mMutex);

        mLatestStatus = status;
        mCondition.broadcast();
    }

    void onTorchStatusChanged(TorchStatus status, const String16& cameraId) {
        dout << "On torch status changed: 0x" << std::hex
             << (unsigned int) status << " cameraId " << cameraId.string()
             << std::endl;
    }

    status_t waitForStatusChange(Status& newStatus) {
        Mutex::Autolock al(mMutex);

        if (mLatestStatus != mPrevStatus) {
            newStatus = mLatestStatus;
            mPrevStatus = mLatestStatus;
            return OK;
        }

        status_t stat = mCondition.waitRelative(mMutex,
                                               TEST_LISTENER_TIMEOUT);

        if (stat == OK) {
            newStatus = mLatestStatus;
            mPrevStatus = mLatestStatus;
        }

        return stat;
    }

    Condition mCondition;
    Mutex mMutex;

    Status mLatestStatus;
    Status mPrevStatus;
};

enum ProEvent {
    UNKNOWN,
    ACQUIRED,
    RELEASED,
    STOLEN,
    FRAME_RECEIVED,
    RESULT_RECEIVED,
};

inline int ProEvent_Mask(ProEvent e) {
    return (1 << static_cast<int>(e));
}

typedef Vector<ProEvent> EventList;

class ProCameraTestThread : public Thread
{
public:
    ProCameraTestThread() {
    }

    virtual bool threadLoop() {
        mProc = ProcessState::self();
        mProc->startThreadPool();

        IPCThreadState *ptr = IPCThreadState::self();

        ptr->joinThreadPool();

        return false;
    }

    sp<ProcessState> mProc;
};

class ProCameraTestListener : public ProCameraListener {

public:
    static const int EVENT_MASK_ALL = 0xFFFFFFFF;

    ProCameraTestListener() {
        mEventMask = EVENT_MASK_ALL;
        mDropFrames = false;
    }

    status_t WaitForEvent() {
        Mutex::Autolock cal(mConditionMutex);

        {
            Mutex::Autolock al(mListenerMutex);

            if (mProEventList.size() > 0) {
                return OK;
            }
        }

        return mListenerCondition.waitRelative(mConditionMutex,
                                               TEST_LISTENER_TIMEOUT);
    }

    /* Read events into out. Existing queue is flushed */
    void ReadEvents(EventList& out) {
        Mutex::Autolock al(mListenerMutex);

        for (size_t i = 0; i < mProEventList.size(); ++i) {
            out.push(mProEventList[i]);
        }

        mProEventList.clear();
    }

    /**
      * Dequeue 1 event from the event queue.
      * Returns UNKNOWN if queue is empty
      */
    ProEvent ReadEvent() {
        Mutex::Autolock al(mListenerMutex);

        if (mProEventList.size() == 0) {
            return UNKNOWN;
        }

        ProEvent ev = mProEventList[0];
        mProEventList.removeAt(0);

        return ev;
    }

    void SetEventMask(int eventMask) {
        Mutex::Autolock al(mListenerMutex);
        mEventMask = eventMask;
    }

    // Automatically acquire/release frames as they are available
    void SetDropFrames(bool dropFrames) {
        Mutex::Autolock al(mListenerMutex);
        mDropFrames = dropFrames;
    }

private:
    void QueueEvent(ProEvent ev) {
        bool eventAdded = false;
        {
            Mutex::Autolock al(mListenerMutex);

            // Drop events not part of mask
            if (ProEvent_Mask(ev) & mEventMask) {
                mProEventList.push(ev);
                eventAdded = true;
            }
        }

        if (eventAdded) {
            mListenerCondition.broadcast();
        }
    }

protected:

    //////////////////////////////////////////////////
    ///////// ProCameraListener //////////////////////
    //////////////////////////////////////////////////


    // Lock has been acquired. Write operations now available.
    virtual void onLockAcquired() {
        QueueEvent(ACQUIRED);
    }
    // Lock has been released with exclusiveUnlock
    virtual void onLockReleased() {
        QueueEvent(RELEASED);
    }

    // Lock has been stolen by another client.
    virtual void onLockStolen() {
        QueueEvent(STOLEN);
    }

    // Lock free.
    virtual void onTriggerNotify(int32_t ext1, int32_t ext2, int32_t ext3) {

        dout << "Trigger notify: " << ext1 << " " << ext2
             << " " << ext3 << std::endl;
    }

    virtual void onFrameAvailable(int streamId,
                                  const sp<CpuConsumer>& consumer) {

        QueueEvent(FRAME_RECEIVED);

        Mutex::Autolock al(mListenerMutex);
        if (mDropFrames) {
            CpuConsumer::LockedBuffer buf;
            status_t ret;

            if (OK == (ret = consumer->lockNextBuffer(&buf))) {

                dout << "Frame received on streamId = " << streamId <<
                        ", dataPtr = " << (void*)buf.data <<
                        ", timestamp = " << buf.timestamp << std::endl;

                EXPECT_OK(consumer->unlockBuffer(buf));
            }
        } else {
            dout << "Frame received on streamId = " << streamId << std::endl;
        }
    }

    virtual void onResultReceived(int32_t requestId,
                                  camera_metadata* request) {
        dout << "Result received requestId = " << requestId
             << ", requestPtr = " << (void*)request << std::endl;
        QueueEvent(RESULT_RECEIVED);
        free_camera_metadata(request);
    }

    virtual void notify(int32_t msg, int32_t ext1, int32_t ext2) {
        dout << "Notify received: msg " << std::hex << msg
             << ", ext1: " << std::hex << ext1 << ", ext2: " << std::hex << ext2
             << std::endl;
    }

    Vector<ProEvent> mProEventList;
    Mutex             mListenerMutex;
    Mutex             mConditionMutex;
    Condition         mListenerCondition;
    int               mEventMask;
    bool              mDropFrames;
};

class ProCameraTest : public ::testing::Test {

public:
    ProCameraTest() {
        char* displaySecsEnv = getenv("TEST_DISPLAY_SECS");
        if (displaySecsEnv != NULL) {
            mDisplaySecs = atoi(displaySecsEnv);
            if (mDisplaySecs < 0) {
                mDisplaySecs = 0;
            }
        } else {
            mDisplaySecs = 0;
        }

        char* displayFmtEnv = getenv("TEST_DISPLAY_FORMAT");
        if (displayFmtEnv != NULL) {
            mDisplayFmt = FormatFromString(displayFmtEnv);
        } else {
            mDisplayFmt = TEST_DISPLAY_FORMAT;
        }

        char* displayWidthEnv = getenv("TEST_DISPLAY_WIDTH");
        if (displayWidthEnv != NULL) {
            mDisplayW = atoi(displayWidthEnv);
            if (mDisplayW < 0) {
                mDisplayW = 0;
            }
        } else {
            mDisplayW = TEST_DISPLAY_WIDTH;
        }

        char* displayHeightEnv = getenv("TEST_DISPLAY_HEIGHT");
        if (displayHeightEnv != NULL) {
            mDisplayH = atoi(displayHeightEnv);
            if (mDisplayH < 0) {
                mDisplayH = 0;
            }
        } else {
            mDisplayH = TEST_DISPLAY_HEIGHT;
        }
    }

    static void SetUpTestCase() {
        // Binder Thread Pool Initialization
        mTestThread = new ProCameraTestThread();
        mTestThread->run("ProCameraTestThread");
    }

    virtual void SetUp() {
        mCamera = ProCamera::connect(CAMERA_ID);
        ASSERT_NE((void*)NULL, mCamera.get());

        mListener = new ProCameraTestListener();
        mCamera->setListener(mListener);
    }

    virtual void TearDown() {
        ASSERT_NE((void*)NULL, mCamera.get());
        mCamera->disconnect();
    }

protected:
    sp<ProCamera> mCamera;
    sp<ProCameraTestListener> mListener;

    static sp<Thread> mTestThread;

    int mDisplaySecs;
    int mDisplayFmt;
    int mDisplayW;
    int mDisplayH;

    sp<SurfaceComposerClient> mComposerClient;
    sp<SurfaceControl> mSurfaceControl;

    sp<SurfaceComposerClient> mDepthComposerClient;
    sp<SurfaceControl> mDepthSurfaceControl;

    int getSurfaceWidth() {
        return 512;
    }
    int getSurfaceHeight() {
        return 512;
    }

    void createOnScreenSurface(sp<Surface>& surface) {
        mComposerClient = new SurfaceComposerClient;
        ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());

        mSurfaceControl = mComposerClient->createSurface(
                String8("ProCameraTest StreamingImage Surface"),
                getSurfaceWidth(), getSurfaceHeight(),
                PIXEL_FORMAT_RGB_888, 0);

        mSurfaceControl->setPosition(0, 0);

        ASSERT_TRUE(mSurfaceControl != NULL);
        ASSERT_TRUE(mSurfaceControl->isValid());

        SurfaceComposerClient::openGlobalTransaction();
        ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF));
        ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
        SurfaceComposerClient::closeGlobalTransaction();

        sp<ANativeWindow> window = mSurfaceControl->getSurface();
        surface = mSurfaceControl->getSurface();

        ASSERT_NE((void*)NULL, surface.get());
    }

    void createDepthOnScreenSurface(sp<Surface>& surface) {
        mDepthComposerClient = new SurfaceComposerClient;
        ASSERT_EQ(NO_ERROR, mDepthComposerClient->initCheck());

        mDepthSurfaceControl = mDepthComposerClient->createSurface(
                String8("ProCameraTest StreamingImage Surface"),
                getSurfaceWidth(), getSurfaceHeight(),
                PIXEL_FORMAT_RGB_888, 0);

        mDepthSurfaceControl->setPosition(640, 0);

        ASSERT_TRUE(mDepthSurfaceControl != NULL);
        ASSERT_TRUE(mDepthSurfaceControl->isValid());

        SurfaceComposerClient::openGlobalTransaction();
        ASSERT_EQ(NO_ERROR, mDepthSurfaceControl->setLayer(0x7FFFFFFF));
        ASSERT_EQ(NO_ERROR, mDepthSurfaceControl->show());
        SurfaceComposerClient::closeGlobalTransaction();

        sp<ANativeWindow> window = mDepthSurfaceControl->getSurface();
        surface = mDepthSurfaceControl->getSurface();

        ASSERT_NE((void*)NULL, surface.get());
    }

    template <typename T>
    static bool ExistsItem(T needle, T* array, size_t count) {
        if (!array) {
            return false;
        }

        for (size_t i = 0; i < count; ++i) {
            if (array[i] == needle) {
                return true;
            }
        }
        return false;
    }


    static int FormatFromString(const char* str) {
        std::string s(str);

#define CMP_STR(x, y)                               \
        if (s == #x) return HAL_PIXEL_FORMAT_ ## y;
#define CMP_STR_SAME(x) CMP_STR(x, x)

        CMP_STR_SAME( Y16);
        CMP_STR_SAME( Y8);
        CMP_STR_SAME( YV12);
        CMP_STR(NV16, YCbCr_422_SP);
        CMP_STR(NV21, YCrCb_420_SP);
        CMP_STR(YUY2, YCbCr_422_I);
        CMP_STR(RAW,  RAW16);
        CMP_STR(RGBA, RGBA_8888);

        std::cerr << "Unknown format string " << str << std::endl;
        return -1;

    }

    /**
     * Creating a streaming request for these output streams from a template,
     *  and submit it
     */
    void createSubmitRequestForStreams(int32_t* streamIds, size_t count, int requestCount=-1) {

        ASSERT_NE((void*)NULL, streamIds);
        ASSERT_LT(0u, count);

        camera_metadata_t *requestTmp = NULL;
        EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
                                                /*out*/&requestTmp));
        ASSERT_NE((void*)NULL, requestTmp);
        CameraMetadata request(requestTmp);

        // set the output streams. default is empty

        uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
        request.update(tag, streamIds, count);

        requestTmp = request.release();

        if (requestCount < 0) {
            EXPECT_OK(mCamera->submitRequest(requestTmp, /*streaming*/true));
        } else {
            for (int i = 0; i < requestCount; ++i) {
                EXPECT_OK(mCamera->submitRequest(requestTmp,
                                                 /*streaming*/false));
            }
        }
        request.acquire(requestTmp);
    }
};

sp<Thread> ProCameraTest::mTestThread;

TEST_F(ProCameraTest, AvailableFormats) {
    if (HasFatalFailure()) {
        return;
    }

    CameraMetadata staticInfo = mCamera->getCameraInfo(CAMERA_ID);
    ASSERT_FALSE(staticInfo.isEmpty());

    uint32_t tag = static_cast<uint32_t>(ANDROID_SCALER_AVAILABLE_FORMATS);
    EXPECT_TRUE(staticInfo.exists(tag));
    camera_metadata_entry_t entry = staticInfo.find(tag);

    EXPECT_TRUE(ExistsItem<int32_t>(HAL_PIXEL_FORMAT_YV12,
                                                  entry.data.i32, entry.count));
    EXPECT_TRUE(ExistsItem<int32_t>(HAL_PIXEL_FORMAT_YCrCb_420_SP,
                                                  entry.data.i32, entry.count));
}

// test around exclusiveTryLock (immediate locking)
TEST_F(ProCameraTest, LockingImmediate) {

    if (HasFatalFailure()) {
        return;
    }

    mListener->SetEventMask(ProEvent_Mask(ACQUIRED) |
                            ProEvent_Mask(STOLEN)   |
                            ProEvent_Mask(RELEASED));

    EXPECT_FALSE(mCamera->hasExclusiveLock());
    EXPECT_EQ(OK, mCamera->exclusiveTryLock());
    // at this point we definitely have the lock

    EXPECT_EQ(OK, mListener->WaitForEvent());
    EXPECT_EQ(ACQUIRED, mListener->ReadEvent());

    EXPECT_TRUE(mCamera->hasExclusiveLock());
    EXPECT_EQ(OK, mCamera->exclusiveUnlock());

    EXPECT_EQ(OK, mListener->WaitForEvent());
    EXPECT_EQ(RELEASED, mListener->ReadEvent());

    EXPECT_FALSE(mCamera->hasExclusiveLock());
}

// test around exclusiveLock (locking at some future point in time)
TEST_F(ProCameraTest, LockingAsynchronous) {

    if (HasFatalFailure()) {
        return;
    }


    mListener->SetEventMask(ProEvent_Mask(ACQUIRED) |
                            ProEvent_Mask(STOLEN)   |
                            ProEvent_Mask(RELEASED));

    // TODO: Add another procamera that has a lock here.
    // then we can be test that the lock wont immediately be acquired

    EXPECT_FALSE(mCamera->hasExclusiveLock());
    EXPECT_EQ(OK, mCamera->exclusiveTryLock());
    // at this point we definitely have the lock

    EXPECT_EQ(OK, mListener->WaitForEvent());
    EXPECT_EQ(ACQUIRED, mListener->ReadEvent());

    EXPECT_TRUE(mCamera->hasExclusiveLock());
    EXPECT_EQ(OK, mCamera->exclusiveUnlock());

    EXPECT_EQ(OK, mListener->WaitForEvent());
    EXPECT_EQ(RELEASED, mListener->ReadEvent());

    EXPECT_FALSE(mCamera->hasExclusiveLock());
}

// Stream directly to the screen.
TEST_F(ProCameraTest, DISABLED_StreamingImageSingle) {
    if (HasFatalFailure()) {
        return;
    }

    sp<Surface> surface;
    if (mDisplaySecs > 0) {
        createOnScreenSurface(/*out*/surface);
    }
    else {
        dout << "Skipping, will not render to screen" << std::endl;
        return;
    }

    int depthStreamId = -1;

    sp<ServiceListener> listener = new ServiceListener();
    EXPECT_OK(ProCamera::addServiceListener(listener));

    ServiceListener::Status currentStatus;

    // when subscribing a new listener,
    // we immediately get a callback to the current status
    while (listener->waitForStatusChange(/*out*/currentStatus) != OK);
    EXPECT_EQ(ServiceListener::STATUS_PRESENT, currentStatus);

    dout << "Will now stream and resume infinitely..." << std::endl;
    while (true) {

        if (currentStatus == ServiceListener::STATUS_PRESENT) {

            ASSERT_OK(mCamera->createStream(mDisplayW, mDisplayH, mDisplayFmt,
                                            surface,
                                            &depthStreamId));
            EXPECT_NE(-1, depthStreamId);

            EXPECT_OK(mCamera->exclusiveTryLock());

            int32_t streams[] = { depthStreamId };
            ASSERT_NO_FATAL_FAILURE(createSubmitRequestForStreams(
                                                 streams,
                                                 /*count*/1));
        }

        ServiceListener::Status stat = ServiceListener::STATUS_UNKNOWN;

        // TODO: maybe check for getch every once in a while?
        while (listener->waitForStatusChange(/*out*/stat) != OK);

        if (currentStatus != stat) {
            if (stat == ServiceListener::STATUS_PRESENT) {
                dout << "Reconnecting to camera" << std::endl;
                mCamera = ProCamera::connect(CAMERA_ID);
            } else if (stat == ServiceListener::STATUS_NOT_AVAILABLE) {
                dout << "Disconnecting from camera" << std::endl;
                mCamera->disconnect();
            } else if (stat == ServiceListener::STATUS_NOT_PRESENT) {
                dout << "Camera unplugged" << std::endl;
                mCamera = NULL;
            } else {
                dout << "Unknown status change "
                     << std::hex << stat << std::endl;
            }

            currentStatus = stat;
        }
    }

    EXPECT_OK(ProCamera::removeServiceListener(listener));
    EXPECT_OK(mCamera->deleteStream(depthStreamId));
    EXPECT_OK(mCamera->exclusiveUnlock());
}

// Stream directly to the screen.
TEST_F(ProCameraTest, DISABLED_StreamingImageDual) {
    if (HasFatalFailure()) {
        return;
    }
    sp<Surface> surface;
    sp<Surface> depthSurface;
    if (mDisplaySecs > 0) {
        createOnScreenSurface(/*out*/surface);
        createDepthOnScreenSurface(/*out*/depthSurface);
    }

    int streamId = -1;
    EXPECT_OK(mCamera->createStream(/*width*/1280, /*height*/960,
              TEST_FORMAT_MAIN, surface, &streamId));
    EXPECT_NE(-1, streamId);

    int depthStreamId = -1;
    EXPECT_OK(mCamera->createStream(/*width*/320, /*height*/240,
              TEST_FORMAT_DEPTH, depthSurface, &depthStreamId));
    EXPECT_NE(-1, depthStreamId);

    EXPECT_OK(mCamera->exclusiveTryLock());
    /*
    */
    /* iterate in a loop submitting requests every frame.
     *  what kind of requests doesnt really matter, just whatever.
     */

    // it would probably be better to use CameraMetadata from camera service.
    camera_metadata_t *request = NULL;
    EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
              /*out*/&request));
    EXPECT_NE((void*)NULL, request);

    /*FIXME: dont need this later, at which point the above should become an
             ASSERT_NE*/
    if(request == NULL) request = allocate_camera_metadata(10, 100);

    // set the output streams to just this stream ID

    // wow what a verbose API.
    int32_t allStreams[] = { streamId, depthStreamId };
    // IMPORTANT. bad things will happen if its not a uint8.
    size_t streamCount = sizeof(allStreams) / sizeof(allStreams[0]);
    camera_metadata_entry_t entry;
    uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
    int find = find_camera_metadata_entry(request, tag, &entry);
    if (find == -ENOENT) {
        if (add_camera_metadata_entry(request, tag, &allStreams,
                                      /*data_count*/streamCount) != OK) {
            camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000);
            ASSERT_OK(append_camera_metadata(tmp, request));
            free_camera_metadata(request);
            request = tmp;

            ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams,
                                                /*data_count*/streamCount));
        }
    } else {
        ASSERT_OK(update_camera_metadata_entry(request, entry.index,
                  &allStreams, /*data_count*/streamCount, &entry));
    }

    EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));

    dout << "will sleep now for " << mDisplaySecs << std::endl;
    sleep(mDisplaySecs);

    free_camera_metadata(request);

    for (size_t i = 0; i < streamCount; ++i) {
        EXPECT_OK(mCamera->deleteStream(allStreams[i]));
    }
    EXPECT_OK(mCamera->exclusiveUnlock());
}

TEST_F(ProCameraTest, CpuConsumerSingle) {
    if (HasFatalFailure()) {
        return;
    }

    mListener->SetEventMask(ProEvent_Mask(ACQUIRED) |
                            ProEvent_Mask(STOLEN)   |
                            ProEvent_Mask(RELEASED) |
                            ProEvent_Mask(FRAME_RECEIVED));
    mListener->SetDropFrames(true);

    int streamId = -1;
    sp<CpuConsumer> consumer;
    EXPECT_OK(mCamera->createStreamCpu(/*width*/320, /*height*/240,
                TEST_FORMAT_DEPTH, TEST_CPU_HEAP_COUNT, &consumer, &streamId));
    EXPECT_NE(-1, streamId);

    EXPECT_OK(mCamera->exclusiveTryLock());
    EXPECT_EQ(OK, mListener->WaitForEvent());
    EXPECT_EQ(ACQUIRED, mListener->ReadEvent());
    /* iterate in a loop submitting requests every frame.
     *  what kind of requests doesnt really matter, just whatever.
     */

    // it would probably be better to use CameraMetadata from camera service.
    camera_metadata_t *request = NULL;
    EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
        /*out*/&request));
    EXPECT_NE((void*)NULL, request);

    /*FIXME: dont need this later, at which point the above should become an
      ASSERT_NE*/
    if(request == NULL) request = allocate_camera_metadata(10, 100);

    // set the output streams to just this stream ID

    int32_t allStreams[] = { streamId };
    camera_metadata_entry_t entry;
    uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
    int find = find_camera_metadata_entry(request, tag, &entry);
    if (find == -ENOENT) {
        if (add_camera_metadata_entry(request, tag, &allStreams,
                /*data_count*/1) != OK) {
            camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000);
            ASSERT_OK(append_camera_metadata(tmp, request));
            free_camera_metadata(request);
            request = tmp;

            ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams,
                /*data_count*/1));
        }
    } else {
        ASSERT_OK(update_camera_metadata_entry(request, entry.index,
            &allStreams, /*data_count*/1, &entry));
    }

    EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));

    // Consume a couple of frames
    for (int i = 0; i < TEST_CPU_FRAME_COUNT; ++i) {
        EXPECT_EQ(OK, mListener->WaitForEvent());
        EXPECT_EQ(FRAME_RECEIVED, mListener->ReadEvent());
    }

    // Done: clean up
    free_camera_metadata(request);
    EXPECT_OK(mCamera->deleteStream(streamId));
    EXPECT_OK(mCamera->exclusiveUnlock());
}

TEST_F(ProCameraTest, CpuConsumerDual) {
    if (HasFatalFailure()) {
        return;
    }

    mListener->SetEventMask(ProEvent_Mask(FRAME_RECEIVED));
    mListener->SetDropFrames(true);

    int streamId = -1;
    sp<CpuConsumer> consumer;
    EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
                TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &consumer, &streamId));
    EXPECT_NE(-1, streamId);

    int depthStreamId = -1;
    EXPECT_OK(mCamera->createStreamCpu(/*width*/320, /*height*/240,
            TEST_FORMAT_DEPTH, TEST_CPU_HEAP_COUNT, &consumer, &depthStreamId));
    EXPECT_NE(-1, depthStreamId);

    EXPECT_OK(mCamera->exclusiveTryLock());
    /*
    */
    /* iterate in a loop submitting requests every frame.
     *  what kind of requests doesnt really matter, just whatever.
     */

    // it would probably be better to use CameraMetadata from camera service.
    camera_metadata_t *request = NULL;
    EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
                                            /*out*/&request));
    EXPECT_NE((void*)NULL, request);

    if(request == NULL) request = allocate_camera_metadata(10, 100);

    // set the output streams to just this stream ID

    // wow what a verbose API.
    int32_t allStreams[] = { streamId, depthStreamId };
    size_t streamCount = 2;
    camera_metadata_entry_t entry;
    uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
    int find = find_camera_metadata_entry(request, tag, &entry);
    if (find == -ENOENT) {
        if (add_camera_metadata_entry(request, tag, &allStreams,
                                      /*data_count*/streamCount) != OK) {
            camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000);
            ASSERT_OK(append_camera_metadata(tmp, request));
            free_camera_metadata(request);
            request = tmp;

            ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams,
                                                   /*data_count*/streamCount));
        }
    } else {
        ASSERT_OK(update_camera_metadata_entry(request, entry.index,
                              &allStreams, /*data_count*/streamCount, &entry));
    }

    EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));

    // Consume a couple of frames
    for (int i = 0; i < TEST_CPU_FRAME_COUNT; ++i) {
        // stream id 1
        EXPECT_EQ(OK, mListener->WaitForEvent());
        EXPECT_EQ(FRAME_RECEIVED, mListener->ReadEvent());

        // stream id 2
        EXPECT_EQ(OK, mListener->WaitForEvent());
        EXPECT_EQ(FRAME_RECEIVED, mListener->ReadEvent());

        //TODO: events should be a struct with some data like the stream id
    }

    // Done: clean up
    free_camera_metadata(request);
    EXPECT_OK(mCamera->deleteStream(streamId));
    EXPECT_OK(mCamera->exclusiveUnlock());
}

TEST_F(ProCameraTest, ResultReceiver) {
    if (HasFatalFailure()) {
        return;
    }

    mListener->SetEventMask(ProEvent_Mask(RESULT_RECEIVED));
    mListener->SetDropFrames(true);
    //FIXME: if this is run right after the previous test we get FRAME_RECEIVED
    // need to filter out events at read time

    int streamId = -1;
    sp<CpuConsumer> consumer;
    EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
                TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &consumer, &streamId));
    EXPECT_NE(-1, streamId);

    EXPECT_OK(mCamera->exclusiveTryLock());
    /*
    */
    /* iterate in a loop submitting requests every frame.
     *  what kind of requests doesnt really matter, just whatever.
     */

    camera_metadata_t *request = NULL;
    EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
                                            /*out*/&request));
    EXPECT_NE((void*)NULL, request);

    /*FIXME*/
    if(request == NULL) request = allocate_camera_metadata(10, 100);

    // set the output streams to just this stream ID

    int32_t allStreams[] = { streamId };
    size_t streamCount = 1;
    camera_metadata_entry_t entry;
    uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
    int find = find_camera_metadata_entry(request, tag, &entry);
    if (find == -ENOENT) {
        if (add_camera_metadata_entry(request, tag, &allStreams,
                                      /*data_count*/streamCount) != OK) {
            camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000);
            ASSERT_OK(append_camera_metadata(tmp, request));
            free_camera_metadata(request);
            request = tmp;

            ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams,
                                                /*data_count*/streamCount));
        }
    } else {
        ASSERT_OK(update_camera_metadata_entry(request, entry.index,
                               &allStreams, /*data_count*/streamCount, &entry));
    }

    EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));

    // Consume a couple of results
    for (int i = 0; i < TEST_CPU_FRAME_COUNT; ++i) {
        EXPECT_EQ(OK, mListener->WaitForEvent());
        EXPECT_EQ(RESULT_RECEIVED, mListener->ReadEvent());
    }

    // Done: clean up
    free_camera_metadata(request);
    EXPECT_OK(mCamera->deleteStream(streamId));
    EXPECT_OK(mCamera->exclusiveUnlock());
}

// FIXME: This is racy and sometimes fails on waitForFrameMetadata
TEST_F(ProCameraTest, DISABLED_WaitForResult) {
    if (HasFatalFailure()) {
        return;
    }

    mListener->SetDropFrames(true);

    int streamId = -1;
    sp<CpuConsumer> consumer;
    EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
                 TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &consumer, &streamId));
    EXPECT_NE(-1, streamId);

    EXPECT_OK(mCamera->exclusiveTryLock());

    int32_t streams[] = { streamId };
    ASSERT_NO_FATAL_FAILURE(createSubmitRequestForStreams(streams, /*count*/1));

    // Consume a couple of results
    for (int i = 0; i < TEST_CPU_FRAME_COUNT; ++i) {
        EXPECT_OK(mCamera->waitForFrameMetadata());
        CameraMetadata meta = mCamera->consumeFrameMetadata();
        EXPECT_FALSE(meta.isEmpty());
    }

    // Done: clean up
    EXPECT_OK(mCamera->deleteStream(streamId));
    EXPECT_OK(mCamera->exclusiveUnlock());
}

TEST_F(ProCameraTest, WaitForSingleStreamBuffer) {
    if (HasFatalFailure()) {
        return;
    }

    int streamId = -1;
    sp<CpuConsumer> consumer;
    EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
                  TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &consumer, &streamId));
    EXPECT_NE(-1, streamId);

    EXPECT_OK(mCamera->exclusiveTryLock());

    int32_t streams[] = { streamId };
    ASSERT_NO_FATAL_FAILURE(createSubmitRequestForStreams(streams, /*count*/1,
                                            /*requests*/TEST_CPU_FRAME_COUNT));

    // Consume a couple of results
    for (int i = 0; i < TEST_CPU_FRAME_COUNT; ++i) {
        EXPECT_EQ(1, mCamera->waitForFrameBuffer(streamId));

        CpuConsumer::LockedBuffer buf;
        EXPECT_OK(consumer->lockNextBuffer(&buf));

        dout << "Buffer synchronously received on streamId = " << streamId <<
                ", dataPtr = " << (void*)buf.data <<
                ", timestamp = " << buf.timestamp << std::endl;

        EXPECT_OK(consumer->unlockBuffer(buf));
    }

    // Done: clean up
    EXPECT_OK(mCamera->deleteStream(streamId));
    EXPECT_OK(mCamera->exclusiveUnlock());
}

// FIXME: This is racy and sometimes fails on waitForFrameMetadata
TEST_F(ProCameraTest, DISABLED_WaitForDualStreamBuffer) {
    if (HasFatalFailure()) {
        return;
    }

    const int REQUEST_COUNT = TEST_CPU_FRAME_COUNT * 10;

    // 15 fps
    int streamId = -1;
    sp<CpuConsumer> consumer;
    EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
                 TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &consumer, &streamId));
    EXPECT_NE(-1, streamId);

    // 30 fps
    int depthStreamId = -1;
    sp<CpuConsumer> depthConsumer;
    EXPECT_OK(mCamera->createStreamCpu(/*width*/320, /*height*/240,
       TEST_FORMAT_DEPTH, TEST_CPU_HEAP_COUNT, &depthConsumer, &depthStreamId));
    EXPECT_NE(-1, depthStreamId);

    EXPECT_OK(mCamera->exclusiveTryLock());

    int32_t streams[] = { streamId, depthStreamId };
    ASSERT_NO_FATAL_FAILURE(createSubmitRequestForStreams(streams, /*count*/2,
                                                    /*requests*/REQUEST_COUNT));

    int depthFrames = 0;
    int greyFrames = 0;

    // Consume two frames simultaneously. Unsynchronized by timestamps.
    for (int i = 0; i < REQUEST_COUNT; ++i) {

        // Exhaust event queue so it doesn't keep growing
        while (mListener->ReadEvent() != UNKNOWN);

        // Get the metadata
        EXPECT_OK(mCamera->waitForFrameMetadata());
        CameraMetadata meta = mCamera->consumeFrameMetadata();
        EXPECT_FALSE(meta.isEmpty());

        // Get the buffers

        EXPECT_EQ(1, mCamera->waitForFrameBuffer(depthStreamId));

        /**
          * Guaranteed to be able to consume the depth frame,
          * since we waited on it.
          */
        CpuConsumer::LockedBuffer depthBuffer;
        EXPECT_OK(depthConsumer->lockNextBuffer(&depthBuffer));

        dout << "Depth Buffer synchronously received on streamId = " <<
                streamId <<
                ", dataPtr = " << (void*)depthBuffer.data <<
                ", timestamp = " << depthBuffer.timestamp << std::endl;

        EXPECT_OK(depthConsumer->unlockBuffer(depthBuffer));

        depthFrames++;


        /** Consume Greyscale frames if there are any.
          * There may not be since it runs at half FPS */
        CpuConsumer::LockedBuffer greyBuffer;
        while (consumer->lockNextBuffer(&greyBuffer) == OK) {

            dout << "GRAY Buffer synchronously received on streamId = " <<
                streamId <<
                ", dataPtr = " << (void*)greyBuffer.data <<
                ", timestamp = " << greyBuffer.timestamp << std::endl;

            EXPECT_OK(consumer->unlockBuffer(greyBuffer));

            greyFrames++;
        }
    }

    dout << "Done, summary: depth frames " << std::dec << depthFrames
         << ", grey frames " << std::dec << greyFrames << std::endl;

    // Done: clean up
    EXPECT_OK(mCamera->deleteStream(streamId));
    EXPECT_OK(mCamera->exclusiveUnlock());
}

TEST_F(ProCameraTest, WaitForSingleStreamBufferAndDropFramesSync) {
    if (HasFatalFailure()) {
        return;
    }

    const int NUM_REQUESTS = 20 * TEST_CPU_FRAME_COUNT;

    int streamId = -1;
    sp<CpuConsumer> consumer;
    EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
                  TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT,
                  /*synchronousMode*/true, &consumer, &streamId));
    EXPECT_NE(-1, streamId);

    EXPECT_OK(mCamera->exclusiveTryLock());

    int32_t streams[] = { streamId };
    ASSERT_NO_FATAL_FAILURE(createSubmitRequestForStreams(streams, /*count*/1,
                                                     /*requests*/NUM_REQUESTS));

    // Consume a couple of results
    for (int i = 0; i < NUM_REQUESTS; ++i) {
        int numFrames;
        EXPECT_TRUE((numFrames = mCamera->waitForFrameBuffer(streamId)) > 0);

        // Drop all but the newest framebuffer
        EXPECT_EQ(numFrames-1, mCamera->dropFrameBuffer(streamId, numFrames-1));

        dout << "Dropped " << (numFrames - 1) << " frames" << std::endl;

        // Skip the counter ahead, don't try to consume these frames again
        i += numFrames-1;

        // "Consume" the buffer
        CpuConsumer::LockedBuffer buf;
        EXPECT_OK(consumer->lockNextBuffer(&buf));

        dout << "Buffer synchronously received on streamId = " << streamId <<
                ", dataPtr = " << (void*)buf.data <<
                ", timestamp = " << buf.timestamp << std::endl;

        // Process at 10fps, stream is at 15fps.
        // This means we will definitely fill up the buffer queue with
        // extra buffers and need to drop them.
        usleep(TEST_FRAME_PROCESSING_DELAY_US);

        EXPECT_OK(consumer->unlockBuffer(buf));
    }

    // Done: clean up
    EXPECT_OK(mCamera->deleteStream(streamId));
    EXPECT_OK(mCamera->exclusiveUnlock());
}

TEST_F(ProCameraTest, WaitForSingleStreamBufferAndDropFramesAsync) {
    if (HasFatalFailure()) {
        return;
    }

    const int NUM_REQUESTS = 20 * TEST_CPU_FRAME_COUNT;

    int streamId = -1;
    sp<CpuConsumer> consumer;
    EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
                  TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT,
                  /*synchronousMode*/false, &consumer, &streamId));
    EXPECT_NE(-1, streamId);

    EXPECT_OK(mCamera->exclusiveTryLock());

    int32_t streams[] = { streamId };
    ASSERT_NO_FATAL_FAILURE(createSubmitRequestForStreams(streams, /*count*/1,
                                                     /*requests*/NUM_REQUESTS));

    uint64_t lastFrameNumber = 0;
    int numFrames;

    // Consume a couple of results
    int i;
    for (i = 0; i < NUM_REQUESTS && lastFrameNumber < NUM_REQUESTS; ++i) {
        EXPECT_LT(0, (numFrames = mCamera->waitForFrameBuffer(streamId)));

        dout << "Dropped " << (numFrames - 1) << " frames" << std::endl;

        // Skip the counter ahead, don't try to consume these frames again
        i += numFrames-1;

        // "Consume" the buffer
        CpuConsumer::LockedBuffer buf;

        EXPECT_EQ(OK, consumer->lockNextBuffer(&buf));

        lastFrameNumber = buf.frameNumber;

        dout << "Buffer asynchronously received on streamId = " << streamId <<
                ", dataPtr = " << (void*)buf.data <<
                ", timestamp = " << buf.timestamp <<
                ", framenumber = " << buf.frameNumber << std::endl;

        // Process at 10fps, stream is at 15fps.
        // This means we will definitely fill up the buffer queue with
        // extra buffers and need to drop them.
        usleep(TEST_FRAME_PROCESSING_DELAY_US);

        EXPECT_OK(consumer->unlockBuffer(buf));
    }

    dout << "Done after " << i << " iterations " << std::endl;

    // Done: clean up
    EXPECT_OK(mCamera->deleteStream(streamId));
    EXPECT_OK(mCamera->exclusiveUnlock());
}



//TODO: refactor into separate file
TEST_F(ProCameraTest, ServiceListenersSubscribe) {

    ASSERT_EQ(4u, sizeof(ServiceListener::Status));

    sp<ServiceListener> listener = new ServiceListener();

    EXPECT_EQ(BAD_VALUE, ProCamera::removeServiceListener(listener));
    EXPECT_OK(ProCamera::addServiceListener(listener));

    EXPECT_EQ(ALREADY_EXISTS, ProCamera::addServiceListener(listener));
    EXPECT_OK(ProCamera::removeServiceListener(listener));

    EXPECT_EQ(BAD_VALUE, ProCamera::removeServiceListener(listener));
}

//TODO: refactor into separate file
TEST_F(ProCameraTest, ServiceListenersFunctional) {

    sp<ServiceListener> listener = new ServiceListener();

    EXPECT_OK(ProCamera::addServiceListener(listener));

    sp<Camera> cam = Camera::connect(CAMERA_ID,
                                     /*clientPackageName*/String16(),
                                     -1);
    EXPECT_NE((void*)NULL, cam.get());

    ServiceListener::Status stat = ServiceListener::STATUS_UNKNOWN;
    EXPECT_OK(listener->waitForStatusChange(/*out*/stat));

    EXPECT_EQ(ServiceListener::STATUS_NOT_AVAILABLE, stat);

    if (cam.get()) {
        cam->disconnect();
    }

    EXPECT_OK(listener->waitForStatusChange(/*out*/stat));
    EXPECT_EQ(ServiceListener::STATUS_PRESENT, stat);

    EXPECT_OK(ProCamera::removeServiceListener(listener));
}



}
}
}
}
