summaryrefslogtreecommitdiffstats
path: root/camera
diff options
context:
space:
mode:
authorIgor Murashkin <iam@google.com>2013-02-20 17:41:57 -0800
committerIgor Murashkin <iam@google.com>2013-02-22 10:50:14 -0800
commit5376573eff55f370f041889618c9a7a9e1894615 (patch)
treeb90f41af6bb5a6952c7e7deb6812626c3035d927 /camera
parent634a51509ee50475f3e9f8ccf897e90fc72ded31 (diff)
downloadframeworks_av-5376573eff55f370f041889618c9a7a9e1894615.zip
frameworks_av-5376573eff55f370f041889618c9a7a9e1894615.tar.gz
frameworks_av-5376573eff55f370f041889618c9a7a9e1894615.tar.bz2
Camera: ProClient add asynchronous locks and such
Change-Id: I551e5e5e76d9be733fab5224beaa7309268c0f38
Diffstat (limited to 'camera')
-rw-r--r--camera/IProCameraCallbacks.cpp19
-rw-r--r--camera/ProCamera.cpp34
-rw-r--r--camera/tests/Android.mk3
-rw-r--r--camera/tests/ProCameraTests.cpp169
4 files changed, 221 insertions, 4 deletions
diff --git a/camera/IProCameraCallbacks.cpp b/camera/IProCameraCallbacks.cpp
index c2ad74f..756fba2 100644
--- a/camera/IProCameraCallbacks.cpp
+++ b/camera/IProCameraCallbacks.cpp
@@ -34,6 +34,7 @@ enum {
NOTIFY_CALLBACK = IBinder::FIRST_CALL_TRANSACTION,
DATA_CALLBACK,
DATA_CALLBACK_TIMESTAMP,
+ LOCK_STATUS_CHANGED,
};
class BpProCameraCallbacks: public BpInterface<IProCameraCallbacks>
@@ -86,6 +87,15 @@ public:
remote()->transact(DATA_CALLBACK_TIMESTAMP, data, &reply,
IBinder::FLAG_ONEWAY);
}
+
+ void onLockStatusChanged(LockStatus newLockStatus) {
+ ALOGV("onLockStatusChanged");
+ Parcel data, reply;
+ data.writeInterfaceToken(IProCameraCallbacks::getInterfaceDescriptor());
+ data.writeInt32(newLockStatus);
+ remote()->transact(LOCK_STATUS_CHANGED, data, &reply,
+ IBinder::FLAG_ONEWAY);
+ }
};
IMPLEMENT_META_INTERFACE(ProCameraCallbacks,
@@ -96,6 +106,7 @@ IMPLEMENT_META_INTERFACE(ProCameraCallbacks,
status_t BnProCameraCallbacks::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
+ ALOGV("onTransact - code = %d", code);
switch(code) {
case NOTIFY_CALLBACK: {
ALOGV("NOTIFY_CALLBACK");
@@ -133,6 +144,14 @@ status_t BnProCameraCallbacks::onTransact(
dataCallbackTimestamp(timestamp, msgType, imageData);
return NO_ERROR;
} break;
+ case LOCK_STATUS_CHANGED: {
+ ALOGV("LOCK_STATUS_CHANGED");
+ CHECK_INTERFACE(IProCameraCallbacks, data, reply);
+ LockStatus newLockStatus
+ = static_cast<LockStatus>(data.readInt32());
+ onLockStatusChanged(newLockStatus);
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/camera/ProCamera.cpp b/camera/ProCamera.cpp
index 134a4a3..8164188 100644
--- a/camera/ProCamera.cpp
+++ b/camera/ProCamera.cpp
@@ -118,6 +118,12 @@ void ProCamera::DeathNotifier::binderDied(const wp<IBinder>& who) {
ALOGW("Camera service died!");
}
+void ProCamera::setListener(const sp<ProCameraListener>& listener)
+{
+ Mutex::Autolock _l(mLock);
+ mListener = listener;
+}
+
// callback from camera service
void ProCamera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
@@ -164,6 +170,34 @@ void ProCamera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
/* IProCameraUser's implementation */
+void ProCamera::onLockStatusChanged(
+ IProCameraCallbacks::LockStatus newLockStatus)
+{
+ ALOGV("%s: newLockStatus = %d", __FUNCTION__, newLockStatus);
+
+ sp<ProCameraListener> listener;
+ {
+ Mutex::Autolock _l(mLock);
+ listener = mListener;
+ }
+ if (listener != NULL) {
+ switch (newLockStatus) {
+ case IProCameraCallbacks::LOCK_ACQUIRED:
+ listener->onLockAcquired();
+ break;
+ case IProCameraCallbacks::LOCK_RELEASED:
+ listener->onLockReleased();
+ break;
+ case IProCameraCallbacks::LOCK_STOLEN:
+ listener->onLockStolen();
+ break;
+ default:
+ ALOGE("%s: Unknown lock status: %d",
+ __FUNCTION__, newLockStatus);
+ }
+ }
+}
+
status_t ProCamera::exclusiveTryLock()
{
sp <IProCameraUser> c = mCamera;
diff --git a/camera/tests/Android.mk b/camera/tests/Android.mk
index 5d386c4..e455943 100644
--- a/camera/tests/Android.mk
+++ b/camera/tests/Android.mk
@@ -14,7 +14,8 @@ LOCAL_SHARED_LIBRARIES := \
libgui \
libsync \
libui \
- libdl
+ libdl \
+ libbinder
LOCAL_STATIC_LIBRARIES := \
libgtest
diff --git a/camera/tests/ProCameraTests.cpp b/camera/tests/ProCameraTests.cpp
index 4de9c10..ca9e224 100644
--- a/camera/tests/ProCameraTests.cpp
+++ b/camera/tests/ProCameraTests.cpp
@@ -17,8 +17,14 @@
#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>
namespace android {
namespace camera2 {
@@ -28,17 +34,159 @@ namespace client {
#define CAMERA_ID 0
#define TEST_DEBUGGING 0
+#define TEST_LISTENER_TIMEOUT 2000000000 // 2 second listener timeout
+
#if TEST_DEBUGGING
#define dout std::cerr
#else
#define dout if (0) std::cerr
#endif
+enum LockEvent {
+ UNKNOWN,
+ ACQUIRED,
+ RELEASED,
+ STOLEN
+};
+
+typedef Vector<LockEvent> EventList;
+
+class ProCameraTestThread : public Thread
+{
+public:
+ ProCameraTestThread() {
+ }
+
+ virtual bool threadLoop() {
+ mProc = ProcessState::self();
+ mProc->startThreadPool();
+
+ IPCThreadState *ptr = IPCThreadState::self();
+
+ dout << "will join thread pool" << std::endl;
+ ptr->joinThreadPool();
+ dout << "joined thread pool (done)" << std::endl;
+
+ return false;
+ }
+
+ sp<ProcessState> mProc;
+};
+
+class ProCameraTestListener : public ProCameraListener {
+
+public:
+ status_t WaitForEvent() {
+ Mutex::Autolock cal(mConditionMutex);
+
+ {
+ Mutex::Autolock al(mListenerMutex);
+
+ if (mLockEventList.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 < mLockEventList.size(); ++i) {
+ out.push(mLockEventList[i]);
+ }
+
+ mLockEventList.clear();
+ }
+
+ /**
+ * Dequeue 1 event from the event queue.
+ * Returns UNKNOWN if queue is empty
+ */
+ LockEvent ReadEvent() {
+ Mutex::Autolock al(mListenerMutex);
+
+ if (mLockEventList.size() == 0) {
+ return UNKNOWN;
+ }
+
+ LockEvent ev = mLockEventList[0];
+ mLockEventList.removeAt(0);
+
+ return ev;
+ }
+
+private:
+ void QueueEvent(LockEvent ev) {
+ {
+ Mutex::Autolock al(mListenerMutex);
+ mLockEventList.push(ev);
+ }
+
+
+ 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;
+ }
+
+ // TODO: remove
+
+ virtual void notify(int32_t , int32_t , int32_t ) {}
+ virtual void postData(int32_t , const sp<IMemory>& ,
+ camera_frame_metadata_t *) {}
+ virtual void postDataTimestamp(nsecs_t , int32_t , const sp<IMemory>& ) {}
+
+
+ Vector<LockEvent> mLockEventList;
+ Mutex mListenerMutex;
+ Mutex mConditionMutex;
+ Condition mListenerCondition;
+};
+
class ProCameraTest : public ::testing::Test {
+public:
+ ProCameraTest() {
+ }
+
virtual void SetUp() {
+ mTestThread = new ProCameraTestThread();
+ mTestThread->run("ProCameraTestThread");
+
mCamera = ProCamera::connect(CAMERA_ID);
ASSERT_NE((void*)NULL, mCamera.get());
+
+ mListener = new ProCameraTestListener();
+ mCamera->setListener(mListener);
}
virtual void TearDown() {
@@ -48,17 +196,32 @@ class ProCameraTest : public ::testing::Test {
protected:
sp<ProCamera> mCamera;
+ sp<ProCameraTestListener> mListener;
+
+ sp<Thread> mTestThread;
+
};
-TEST_F(ProCameraTest, Locking) {
+TEST_F(ProCameraTest, LockingImmediate) {
if (HasFatalFailure()) {
return;
}
- status_t res = mCamera->exclusiveTryLock();
- EXPECT_EQ(OK, res);
+ EXPECT_FALSE(mCamera->hasExclusiveLock());
+ EXPECT_EQ(OK, mCamera->exclusiveTryLock());
+
+ 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());
}
}