Camera2: Add more dump information, connect HAL device dump

Bug: 6243944
Change-Id: I79a302f68786d815b9ab9984dbb31d237522416b
diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp
index 7f28c67..d8b8081 100644
--- a/services/camera/libcameraservice/Camera2Client.cpp
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -104,7 +104,7 @@
 
 status_t Camera2Client::dump(int fd, const Vector<String16>& args) {
     String8 result;
-    result.appendFormat("Client2[%d] (%p) PID: %d:\n",
+    result.appendFormat("Client2[%d] (%p) PID: %d, dump:\n",
             mCameraId,
             getCameraClient()->asBinder().get(),
             mClientPid);
@@ -248,19 +248,48 @@
                 mParameters.meteringAreas[i].weight);
     }
 
-    result.appendFormat("   Zoom index: %d\n", mParameters.zoom);
-    result.appendFormat("   Video size: %d x %d\n", mParameters.videoWidth,
+    result.appendFormat("    Zoom index: %d\n", mParameters.zoom);
+    result.appendFormat("    Video size: %d x %d\n", mParameters.videoWidth,
             mParameters.videoHeight);
 
-    result.appendFormat("   Recording hint is %s\n",
+    result.appendFormat("    Recording hint is %s\n",
             mParameters.recordingHint ? "set" : "not set");
 
-    result.appendFormat("   Video stabilization is %s\n",
+    result.appendFormat("    Video stabilization is %s\n",
             mParameters.videoStabilization ? "enabled" : "disabled");
 
+    result.append("  Current streams:\n");
+    result.appendFormat("    Preview stream ID: %d\n", mPreviewStreamId);
+    result.appendFormat("    Capture stream ID: %d\n", mCaptureStreamId);
+
+    result.append("  Current requests:\n");
+    if (mPreviewRequest != NULL) {
+        result.append("    Preview request:\n");
+        write(fd, result.string(), result.size());
+        dump_camera_metadata(mPreviewRequest, fd, 2);
+    } else {
+        result.append("    Preview request: undefined\n");
+        write(fd, result.string(), result.size());
+    }
+
+    if (mCaptureRequest != NULL) {
+        result = "    Capture request:\n";
+        write(fd, result.string(), result.size());
+        dump_camera_metadata(mCaptureRequest, fd, 2);
+    } else {
+        result = "    Capture request: undefined\n";
+        write(fd, result.string(), result.size());
+    }
+
+    result = "  Device dump:\n";
     write(fd, result.string(), result.size());
 
-    // TODO: Dump Camera2Device
+    status_t res = mDevice->dump(fd, args);
+    if (res != OK) {
+        result = String8::format("   Error dumping device: %s (%d)",
+                strerror(-res), res);
+        write(fd, result.string(), result.size());
+    }
 
 #undef CASE_APPEND_ENUM
     return NO_ERROR;
diff --git a/services/camera/libcameraservice/Camera2Device.cpp b/services/camera/libcameraservice/Camera2Device.cpp
index 7db04ff..08e3cc0 100644
--- a/services/camera/libcameraservice/Camera2Device.cpp
+++ b/services/camera/libcameraservice/Camera2Device.cpp
@@ -105,6 +105,39 @@
     return OK;
 }
 
+status_t Camera2Device::dump(int fd, const Vector<String16>& args) {
+
+    String8 result;
+
+    result.appendFormat("  Camera2Device[%d] dump:\n", mId);
+
+    result.appendFormat("    Static camera information metadata:\n");
+    write(fd, result.string(), result.size());
+    dump_camera_metadata(mDeviceInfo, fd, 2);
+
+    result = "    Request queue contents:\n";
+    write(fd, result.string(), result.size());
+    mRequestQueue.dump(fd, args);
+
+    result = "    Frame queue contents:\n";
+    write(fd, result.string(), result.size());
+    mFrameQueue.dump(fd, args);
+
+    result = "    Active streams:\n";
+    write(fd, result.string(), result.size());
+    for (StreamList::iterator s = mStreams.begin(); s != mStreams.end(); s++) {
+        (*s)->dump(fd, args);
+    }
+
+    result = "    HAL device dump:\n";
+    write(fd, result.string(), result.size());
+
+    status_t res;
+    res = mDevice->ops->dump(mDevice, fd);
+
+    return res;
+}
+
 camera_metadata_t *Camera2Device::info() {
     ALOGV("%s: E", __FUNCTION__);
 
@@ -406,6 +439,53 @@
     return signalConsumerLocked();
 }
 
+status_t Camera2Device::MetadataQueue::dump(int fd,
+        const Vector<String16>& args) {
+    String8 result;
+    status_t notLocked;
+    notLocked = mMutex.tryLock();
+    if (notLocked) {
+        result.append("    (Unable to lock queue mutex)\n");
+    }
+    result.appendFormat("      Current frame number: %d\n", mFrameCount);
+    if (mStreamSlotCount == 0) {
+        result.append("      Stream slot: Empty\n");
+        write(fd, result.string(), result.size());
+    } else {
+        result.appendFormat("      Stream slot: %d entries\n",
+                mStreamSlot.size());
+        int i = 0;
+        for (List<camera_metadata_t*>::iterator r = mStreamSlot.begin();
+             r != mStreamSlot.end(); r++) {
+            result = String8::format("       Stream slot buffer %d:\n", i);
+            write(fd, result.string(), result.size());
+            dump_camera_metadata(*r, fd, 2);
+            i++;
+        }
+    }
+    if (mEntries.size() == 0) {
+        result = "      Main queue is empty\n";
+        write(fd, result.string(), result.size());
+    } else {
+        result = String8::format("      Main queue has %d entries:\n",
+                mEntries.size());
+        int i = 0;
+        for (List<camera_metadata_t*>::iterator r = mEntries.begin();
+             r != mEntries.end(); r++) {
+            result = String8::format("       Queue entry %d:\n", i);
+            write(fd, result.string(), result.size());
+            dump_camera_metadata(*r, fd, 2);
+            i++;
+        }
+    }
+
+    if (notLocked == 0) {
+        mMutex.unlock();
+    }
+
+    return OK;
+}
+
 status_t Camera2Device::MetadataQueue::signalConsumerLocked() {
     status_t res = OK;
     notEmpty.signal();
@@ -510,7 +590,13 @@
         mState(DISCONNECTED),
         mDevice(d),
         mId(-1),
-        mWidth(0), mHeight(0), mFormatRequested(0)
+        mWidth(0), mHeight(0), mFormat(0), mSize(0), mUsage(0),
+        mMaxProducerBuffers(0), mMaxConsumerBuffers(0),
+        mTotalBuffers(0),
+        mFormatRequested(0),
+        mActiveBuffers(0),
+        mFrameCount(0),
+        mLastTimestamp(0)
 {
     camera2_stream_ops::dequeue_buffer = dequeue_buffer;
     camera2_stream_ops::enqueue_buffer = enqueue_buffer;
@@ -628,10 +714,13 @@
     ALOGV("%s: Producer wants %d buffers, consumer wants %d", __FUNCTION__,
             mMaxProducerBuffers, mMaxConsumerBuffers);
 
-    int totalBuffers = mMaxConsumerBuffers + mMaxProducerBuffers;
+    mTotalBuffers = mMaxConsumerBuffers + mMaxProducerBuffers;
+    mActiveBuffers = 0;
+    mFrameCount = 0;
+    mLastTimestamp = 0;
 
     res = native_window_set_buffer_count(mConsumerInterface.get(),
-            totalBuffers);
+            mTotalBuffers);
     if (res != OK) {
         ALOGE("%s: Unable to set buffer count for stream %d",
                 __FUNCTION__, mId);
@@ -639,10 +728,10 @@
     }
 
     // Register allocated buffers with HAL device
-    buffer_handle_t *buffers = new buffer_handle_t[totalBuffers];
-    ANativeWindowBuffer **anwBuffers = new ANativeWindowBuffer*[totalBuffers];
-    int bufferIdx = 0;
-    for (; bufferIdx < totalBuffers; bufferIdx++) {
+    buffer_handle_t *buffers = new buffer_handle_t[mTotalBuffers];
+    ANativeWindowBuffer **anwBuffers = new ANativeWindowBuffer*[mTotalBuffers];
+    uint32_t bufferIdx = 0;
+    for (; bufferIdx < mTotalBuffers; bufferIdx++) {
         res = mConsumerInterface->dequeueBuffer(mConsumerInterface.get(),
                 &anwBuffers[bufferIdx]);
         if (res != OK) {
@@ -665,7 +754,7 @@
 
     res = mDevice->ops->register_stream_buffers(mDevice,
             mId,
-            totalBuffers,
+            mTotalBuffers,
             buffers);
     if (res != OK) {
         ALOGE("%s: Unable to register buffers with HAL device for stream %d",
@@ -675,7 +764,7 @@
     }
 
 cleanUpBuffers:
-    for (int i = 0; i < bufferIdx; i++) {
+    for (uint32_t i = 0; i < bufferIdx; i++) {
         res = mConsumerInterface->cancelBuffer(mConsumerInterface.get(),
                 anwBuffers[i]);
         if (res != OK) {
@@ -683,8 +772,8 @@
                     __FUNCTION__, i);
         }
     }
-    delete anwBuffers;
-    delete buffers;
+    delete[] anwBuffers;
+    delete[] buffers;
 
     return res;
 }
@@ -713,6 +802,20 @@
     return OK;
 }
 
+status_t Camera2Device::StreamAdapter::dump(int fd,
+        const Vector<String16>& args) {
+    String8 result = String8::format("      Stream %d: %d x %d, format 0x%x\n",
+            mId, mWidth, mHeight, mFormat);
+    result.appendFormat("        size %d, usage 0x%x, requested format 0x%x\n",
+            mSize, mUsage, mFormatRequested);
+    result.appendFormat("        total buffers: %d, dequeued buffers: %d\n",
+            mTotalBuffers, mActiveBuffers);
+    result.appendFormat("        frame count: %d, last timestamp %lld\n",
+            mFrameCount, mLastTimestamp);
+    write(fd, result.string(), result.size());
+    return OK;
+}
+
 const camera2_stream_ops *Camera2Device::StreamAdapter::getStreamOps() {
     return static_cast<camera2_stream_ops *>(this);
 }
@@ -725,9 +828,10 @@
 int Camera2Device::StreamAdapter::dequeue_buffer(const camera2_stream_ops_t *w,
         buffer_handle_t** buffer) {
     int res;
-    int state = static_cast<const StreamAdapter*>(w)->mState;
-    if (state != ACTIVE) {
-        ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
+    StreamAdapter* stream =
+            const_cast<StreamAdapter*>(static_cast<const StreamAdapter*>(w));
+    if (stream->mState != ACTIVE) {
+        ALOGE("%s: Called when in bad state: %d", __FUNCTION__, stream->mState);
         return INVALID_OPERATION;
     }
 
@@ -739,6 +843,8 @@
     if (res != OK) return res;
 
     *buffer = &(anb->handle);
+    stream->mActiveBuffers++;
+
     ALOGV("%s: Buffer %p", __FUNCTION__, *buffer);
     return res;
 }
@@ -746,7 +852,8 @@
 int Camera2Device::StreamAdapter::enqueue_buffer(const camera2_stream_ops_t* w,
         int64_t timestamp,
         buffer_handle_t* buffer) {
-    const StreamAdapter *stream = static_cast<const StreamAdapter*>(w);
+    StreamAdapter *stream =
+            const_cast<StreamAdapter*>(static_cast<const StreamAdapter*>(w));
     ALOGV("%s: Stream %d: Buffer %p captured at %lld ns",
             __FUNCTION__, stream->mId, buffer, timestamp);
     int state = stream->mState;
@@ -768,16 +875,21 @@
         ALOGE("%s: Error queueing buffer to native window: %s (%d)",
                 __FUNCTION__, strerror(-err), err);
     }
+    stream->mActiveBuffers--;
+    stream->mFrameCount++;
+    stream->mLastTimestamp = timestamp;
     return err;
 }
 
 int Camera2Device::StreamAdapter::cancel_buffer(const camera2_stream_ops_t* w,
         buffer_handle_t* buffer) {
-    int state = static_cast<const StreamAdapter*>(w)->mState;
-    if (state != ACTIVE) {
-        ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
+    StreamAdapter *stream =
+            const_cast<StreamAdapter*>(static_cast<const StreamAdapter*>(w));
+    if (stream->mState != ACTIVE) {
+        ALOGE("%s: Called when in bad state: %d", __FUNCTION__, stream->mState);
         return INVALID_OPERATION;
     }
+    stream->mActiveBuffers--;
     ANativeWindow *a = toANW(w);
     return a->cancelBuffer(a,
             container_of(buffer, ANativeWindowBuffer, handle));
diff --git a/services/camera/libcameraservice/Camera2Device.h b/services/camera/libcameraservice/Camera2Device.h
index 7071561..569c882 100644
--- a/services/camera/libcameraservice/Camera2Device.h
+++ b/services/camera/libcameraservice/Camera2Device.h
@@ -17,12 +17,15 @@
 #ifndef ANDROID_SERVERS_CAMERA_CAMERA2DEVICE_H
 #define ANDROID_SERVERS_CAMERA_CAMERA2DEVICE_H
 
-#include <utils/RefBase.h>
-#include <utils/List.h>
-#include <utils/Vector.h>
-#include <utils/Mutex.h>
 #include <utils/Condition.h>
 #include <utils/Errors.h>
+#include <utils/List.h>
+#include <utils/Mutex.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <utils/String16.h>
+#include <utils/Vector.h>
+
 #include "hardware/camera2.h"
 
 namespace android {
@@ -35,6 +38,11 @@
 
     status_t initialize(camera_module_t *module);
 
+    status_t dump(int fd, const Vector<String16>& args);
+
+    /**
+     * Get a pointer to the device's static characteristics metadata buffer
+     */
     camera_metadata_t* info();
 
     /**
@@ -133,6 +141,8 @@
         status_t setStreamSlot(camera_metadata_t *buf);
         status_t setStreamSlot(const List<camera_metadata_t*> &bufs);
 
+        status_t dump(int fd, const Vector<String16>& args);
+
       private:
         status_t signalConsumerLocked();
         status_t freeBuffers(List<camera_metadata_t*>::iterator start,
@@ -213,6 +223,9 @@
         uint32_t getHeight() const { return mHeight; }
         uint32_t getFormat() const { return mFormat; }
 
+        // Dump stream information
+        status_t dump(int fd, const Vector<String16>& args);
+
       private:
         enum {
             ERROR = -1,
@@ -233,9 +246,14 @@
         uint32_t mUsage;
         uint32_t mMaxProducerBuffers;
         uint32_t mMaxConsumerBuffers;
-
+        uint32_t mTotalBuffers;
         int mFormatRequested;
 
+        /** Debugging information */
+        uint32_t mActiveBuffers;
+        uint32_t mFrameCount;
+        int64_t  mLastTimestamp;
+
         const camera2_stream_ops *getStreamOps();
 
         static ANativeWindow* toANW(const camera2_stream_ops_t *w);