Loading camera/IProCameraCallbacks.cpp +25 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,8 @@ #include <camera/IProCameraCallbacks.h> #include <system/camera_metadata.h> namespace android { enum { Loading @@ -35,8 +37,12 @@ enum { DATA_CALLBACK, DATA_CALLBACK_TIMESTAMP, LOCK_STATUS_CHANGED, RESULT_RECEIVED, }; void readMetadata(const Parcel& data, camera_metadata_t** out); void writeMetadata(Parcel& data, camera_metadata_t* metadata); class BpProCameraCallbacks: public BpInterface<IProCameraCallbacks> { public: Loading Loading @@ -96,6 +102,15 @@ public: remote()->transact(LOCK_STATUS_CHANGED, data, &reply, IBinder::FLAG_ONEWAY); } void onResultReceived(int32_t frameId, camera_metadata* result) { ALOGV("onResultReceived"); Parcel data, reply; data.writeInterfaceToken(IProCameraCallbacks::getInterfaceDescriptor()); data.writeInt32(frameId); writeMetadata(data, result); remote()->transact(RESULT_RECEIVED, data, &reply, IBinder::FLAG_ONEWAY); } }; IMPLEMENT_META_INTERFACE(ProCameraCallbacks, Loading Loading @@ -152,6 +167,16 @@ status_t BnProCameraCallbacks::onTransact( onLockStatusChanged(newLockStatus); return NO_ERROR; } break; case RESULT_RECEIVED: { ALOGV("RESULT_RECEIVED"); CHECK_INTERFACE(IProCameraCallbacks, data, reply); int32_t frameId = data.readInt32(); camera_metadata_t *result = NULL; readMetadata(data, &result); onResultReceived(frameId, result); return NO_ERROR; break; } default: return BBinder::onTransact(code, data, reply, flags); } Loading camera/ProCamera.cpp +18 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,8 @@ #include <gui/IGraphicBufferProducer.h> #include <gui/Surface.h> #include <system/camera_metadata.h> namespace android { // client singleton for camera service binder interface Loading Loading @@ -198,6 +200,22 @@ void ProCamera::onLockStatusChanged( } } void ProCamera::onResultReceived(int32_t frameId, camera_metadata* result) { ALOGV("%s: frameId = %d, result = %p", __FUNCTION__, frameId, result); sp<ProCameraListener> listener; { Mutex::Autolock _l(mLock); listener = mListener; } if (listener != NULL) { listener->onResultReceived(frameId, result); } else { free_camera_metadata(result); } } status_t ProCamera::exclusiveTryLock() { sp <IProCameraUser> c = mCamera; Loading camera/tests/ProCameraTests.cpp +116 −12 Original line number Diff line number Diff line Loading @@ -66,8 +66,13 @@ enum ProEvent { RELEASED, STOLEN, BUFFER_RECEIVED, RESULT_RECEIVED, }; inline int ProEvent_Mask(ProEvent e) { return (1 << static_cast<int>(e)); } typedef Vector<ProEvent> EventList; class ProCameraTestThread : public Thread Loading @@ -93,6 +98,12 @@ public: class ProCameraTestListener : public ProCameraListener { public: static const int EVENT_MASK_ALL = 0xFFFFFFFF; ProCameraTestListener() { mEventMask = EVENT_MASK_ALL; } status_t WaitForEvent() { Mutex::Autolock cal(mConditionMutex); Loading Loading @@ -136,16 +147,27 @@ public: return ev; } void SetEventMask(int eventMask) { Mutex::Autolock al(mListenerMutex); mEventMask = eventMask; } private: void QueueEvent(ProEvent ev) { bool eventAdded = false; { Mutex::Autolock al(mListenerMutex); if (ProEvent_Mask(ev) & mEventMask) { mProEventList.push(ev); eventAdded = true; } } if (eventAdded) { mListenerCondition.broadcast(); } } protected: Loading Loading @@ -184,8 +206,11 @@ protected: QueueEvent(BUFFER_RECEIVED); } virtual void onRequestReceived( virtual void onResultReceived(int32_t frameId, camera_metadata* request) { dout << "Result received frameId = " << frameId << ", requestPtr = " << (void*)request << std::endl; QueueEvent(RESULT_RECEIVED); free_camera_metadata(request); } Loading @@ -201,6 +226,7 @@ protected: Mutex mListenerMutex; Mutex mConditionMutex; Condition mListenerCondition; int mEventMask; }; class ProCameraTest : public ::testing::Test { Loading Loading @@ -309,6 +335,10 @@ TEST_F(ProCameraTest, LockingImmediate) { 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 Loading @@ -332,13 +362,17 @@ TEST_F(ProCameraTest, LockingAsynchronous) { 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->exclusiveLock()); // at this point we may or may not have the lock // we cant be sure until we get an ACQUIRED event EXPECT_EQ(OK, mCamera->exclusiveTryLock()); // at this point we definitely have the lock EXPECT_EQ(OK, mListener->WaitForEvent()); EXPECT_EQ(ACQUIRED, mListener->ReadEvent()); Loading @@ -353,7 +387,7 @@ TEST_F(ProCameraTest, LockingAsynchronous) { } // Stream directly to the screen. TEST_F(ProCameraTest, StreamingImageSingle) { TEST_F(ProCameraTest, DISABLED_StreamingImageSingle) { if (HasFatalFailure()) { return; } Loading Loading @@ -433,7 +467,7 @@ TEST_F(ProCameraTest, StreamingImageSingle) { } // Stream directly to the screen. TEST_F(ProCameraTest, StreamingImageDual) { TEST_F(ProCameraTest, DISABLED_StreamingImageDual) { if (HasFatalFailure()) { return; } Loading Loading @@ -523,6 +557,9 @@ TEST_F(ProCameraTest, CpuConsumerSingle) { if (HasFatalFailure()) { return; } mListener->SetEventMask(ProEvent_Mask(BUFFER_RECEIVED)); int streamId = -1; EXPECT_OK(mCamera->createStreamCpu(/*width*/320, /*height*/240, TEST_FORMAT_DEPTH, TEST_CPU_HEAP_COUNT, &streamId)); Loading Loading @@ -585,6 +622,9 @@ TEST_F(ProCameraTest, CpuConsumerDual) { if (HasFatalFailure()) { return; } mListener->SetEventMask(ProEvent_Mask(BUFFER_RECEIVED)); int streamId = -1; EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960, TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &streamId)); Loading @@ -596,8 +636,6 @@ TEST_F(ProCameraTest, CpuConsumerDual) { EXPECT_NE(-1, depthStreamId); EXPECT_OK(mCamera->exclusiveTryLock()); EXPECT_EQ(OK, mListener->WaitForEvent()); EXPECT_EQ(ACQUIRED, mListener->ReadEvent()); /* */ /* iterate in a loop submitting requests every frame. Loading Loading @@ -657,6 +695,72 @@ TEST_F(ProCameraTest, CpuConsumerDual) { EXPECT_OK(mCamera->exclusiveUnlock()); } TEST_F(ProCameraTest, ResultReceiver) { if (HasFatalFailure()) { return; } mListener->SetEventMask(ProEvent_Mask(RESULT_RECEIVED)); //FIXME: if this is run right after the previous test we get BUFFER_RECEIVED // need to filter out events at read time int streamId = -1; EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960, TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &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 uint8_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()); } } } } Loading include/camera/IProCameraCallbacks.h +7 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ #include <utils/Timers.h> #include <system/camera.h> struct camera_metadata; namespace android { class IProCameraCallbacks: public IInterface Loading @@ -47,6 +49,11 @@ public: }; virtual void onLockStatusChanged(LockStatus newLockStatus) = 0; /** Missing by design: implementation is client-side in ProCamera.cpp **/ // virtual void onBufferReceived(int streamId, // const CpuConsumer::LockedBufer& buf); virtual void onResultReceived(int32_t frameId, camera_metadata* result) = 0; }; // ---------------------------------------------------------------------------- Loading include/camera/ProCamera.h +11 −6 Original line number Diff line number Diff line Loading @@ -49,17 +49,19 @@ public: // OnBufferReceived and OnRequestReceived can come in with any order, // use android.sensor.timestamp and LockedBuffer.timestamp to correlate them // TODO: implement in IProCameraCallbacks, ProCamera2Client // A new frame buffer has been received for this stream. // -- This callback only fires for createStreamCpu streams // -- Use buf.timestamp to correlate with metadata's // android.sensor.timestamp // -- The buffer must not be accessed after this function call completes virtual void onBufferReceived(int streamId, const CpuConsumer::LockedBuffer& buf) = 0; // A new metadata buffer has been received. // -- Ownership of request passes on to the callee, // free with free_camera_metadata. virtual void onRequestReceived(camera_metadata* request) = 0; /** * A new metadata buffer has been received. * -- Ownership of request passes on to the callee, free with * free_camera_metadata. */ virtual void onResultReceived(int32_t frameId, camera_metadata* result) = 0; }; class ProCamera : public BnProCameraCallbacks, public IBinder::DeathRecipient Loading Loading @@ -189,6 +191,9 @@ protected: virtual void onLockStatusChanged( IProCameraCallbacks::LockStatus newLockStatus); virtual void onResultReceived(int32_t frameId, camera_metadata* result); class DeathNotifier: public IBinder::DeathRecipient { public: Loading Loading
camera/IProCameraCallbacks.cpp +25 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,8 @@ #include <camera/IProCameraCallbacks.h> #include <system/camera_metadata.h> namespace android { enum { Loading @@ -35,8 +37,12 @@ enum { DATA_CALLBACK, DATA_CALLBACK_TIMESTAMP, LOCK_STATUS_CHANGED, RESULT_RECEIVED, }; void readMetadata(const Parcel& data, camera_metadata_t** out); void writeMetadata(Parcel& data, camera_metadata_t* metadata); class BpProCameraCallbacks: public BpInterface<IProCameraCallbacks> { public: Loading Loading @@ -96,6 +102,15 @@ public: remote()->transact(LOCK_STATUS_CHANGED, data, &reply, IBinder::FLAG_ONEWAY); } void onResultReceived(int32_t frameId, camera_metadata* result) { ALOGV("onResultReceived"); Parcel data, reply; data.writeInterfaceToken(IProCameraCallbacks::getInterfaceDescriptor()); data.writeInt32(frameId); writeMetadata(data, result); remote()->transact(RESULT_RECEIVED, data, &reply, IBinder::FLAG_ONEWAY); } }; IMPLEMENT_META_INTERFACE(ProCameraCallbacks, Loading Loading @@ -152,6 +167,16 @@ status_t BnProCameraCallbacks::onTransact( onLockStatusChanged(newLockStatus); return NO_ERROR; } break; case RESULT_RECEIVED: { ALOGV("RESULT_RECEIVED"); CHECK_INTERFACE(IProCameraCallbacks, data, reply); int32_t frameId = data.readInt32(); camera_metadata_t *result = NULL; readMetadata(data, &result); onResultReceived(frameId, result); return NO_ERROR; break; } default: return BBinder::onTransact(code, data, reply, flags); } Loading
camera/ProCamera.cpp +18 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,8 @@ #include <gui/IGraphicBufferProducer.h> #include <gui/Surface.h> #include <system/camera_metadata.h> namespace android { // client singleton for camera service binder interface Loading Loading @@ -198,6 +200,22 @@ void ProCamera::onLockStatusChanged( } } void ProCamera::onResultReceived(int32_t frameId, camera_metadata* result) { ALOGV("%s: frameId = %d, result = %p", __FUNCTION__, frameId, result); sp<ProCameraListener> listener; { Mutex::Autolock _l(mLock); listener = mListener; } if (listener != NULL) { listener->onResultReceived(frameId, result); } else { free_camera_metadata(result); } } status_t ProCamera::exclusiveTryLock() { sp <IProCameraUser> c = mCamera; Loading
camera/tests/ProCameraTests.cpp +116 −12 Original line number Diff line number Diff line Loading @@ -66,8 +66,13 @@ enum ProEvent { RELEASED, STOLEN, BUFFER_RECEIVED, RESULT_RECEIVED, }; inline int ProEvent_Mask(ProEvent e) { return (1 << static_cast<int>(e)); } typedef Vector<ProEvent> EventList; class ProCameraTestThread : public Thread Loading @@ -93,6 +98,12 @@ public: class ProCameraTestListener : public ProCameraListener { public: static const int EVENT_MASK_ALL = 0xFFFFFFFF; ProCameraTestListener() { mEventMask = EVENT_MASK_ALL; } status_t WaitForEvent() { Mutex::Autolock cal(mConditionMutex); Loading Loading @@ -136,16 +147,27 @@ public: return ev; } void SetEventMask(int eventMask) { Mutex::Autolock al(mListenerMutex); mEventMask = eventMask; } private: void QueueEvent(ProEvent ev) { bool eventAdded = false; { Mutex::Autolock al(mListenerMutex); if (ProEvent_Mask(ev) & mEventMask) { mProEventList.push(ev); eventAdded = true; } } if (eventAdded) { mListenerCondition.broadcast(); } } protected: Loading Loading @@ -184,8 +206,11 @@ protected: QueueEvent(BUFFER_RECEIVED); } virtual void onRequestReceived( virtual void onResultReceived(int32_t frameId, camera_metadata* request) { dout << "Result received frameId = " << frameId << ", requestPtr = " << (void*)request << std::endl; QueueEvent(RESULT_RECEIVED); free_camera_metadata(request); } Loading @@ -201,6 +226,7 @@ protected: Mutex mListenerMutex; Mutex mConditionMutex; Condition mListenerCondition; int mEventMask; }; class ProCameraTest : public ::testing::Test { Loading Loading @@ -309,6 +335,10 @@ TEST_F(ProCameraTest, LockingImmediate) { 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 Loading @@ -332,13 +362,17 @@ TEST_F(ProCameraTest, LockingAsynchronous) { 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->exclusiveLock()); // at this point we may or may not have the lock // we cant be sure until we get an ACQUIRED event EXPECT_EQ(OK, mCamera->exclusiveTryLock()); // at this point we definitely have the lock EXPECT_EQ(OK, mListener->WaitForEvent()); EXPECT_EQ(ACQUIRED, mListener->ReadEvent()); Loading @@ -353,7 +387,7 @@ TEST_F(ProCameraTest, LockingAsynchronous) { } // Stream directly to the screen. TEST_F(ProCameraTest, StreamingImageSingle) { TEST_F(ProCameraTest, DISABLED_StreamingImageSingle) { if (HasFatalFailure()) { return; } Loading Loading @@ -433,7 +467,7 @@ TEST_F(ProCameraTest, StreamingImageSingle) { } // Stream directly to the screen. TEST_F(ProCameraTest, StreamingImageDual) { TEST_F(ProCameraTest, DISABLED_StreamingImageDual) { if (HasFatalFailure()) { return; } Loading Loading @@ -523,6 +557,9 @@ TEST_F(ProCameraTest, CpuConsumerSingle) { if (HasFatalFailure()) { return; } mListener->SetEventMask(ProEvent_Mask(BUFFER_RECEIVED)); int streamId = -1; EXPECT_OK(mCamera->createStreamCpu(/*width*/320, /*height*/240, TEST_FORMAT_DEPTH, TEST_CPU_HEAP_COUNT, &streamId)); Loading Loading @@ -585,6 +622,9 @@ TEST_F(ProCameraTest, CpuConsumerDual) { if (HasFatalFailure()) { return; } mListener->SetEventMask(ProEvent_Mask(BUFFER_RECEIVED)); int streamId = -1; EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960, TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &streamId)); Loading @@ -596,8 +636,6 @@ TEST_F(ProCameraTest, CpuConsumerDual) { EXPECT_NE(-1, depthStreamId); EXPECT_OK(mCamera->exclusiveTryLock()); EXPECT_EQ(OK, mListener->WaitForEvent()); EXPECT_EQ(ACQUIRED, mListener->ReadEvent()); /* */ /* iterate in a loop submitting requests every frame. Loading Loading @@ -657,6 +695,72 @@ TEST_F(ProCameraTest, CpuConsumerDual) { EXPECT_OK(mCamera->exclusiveUnlock()); } TEST_F(ProCameraTest, ResultReceiver) { if (HasFatalFailure()) { return; } mListener->SetEventMask(ProEvent_Mask(RESULT_RECEIVED)); //FIXME: if this is run right after the previous test we get BUFFER_RECEIVED // need to filter out events at read time int streamId = -1; EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960, TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &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 uint8_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()); } } } } Loading
include/camera/IProCameraCallbacks.h +7 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ #include <utils/Timers.h> #include <system/camera.h> struct camera_metadata; namespace android { class IProCameraCallbacks: public IInterface Loading @@ -47,6 +49,11 @@ public: }; virtual void onLockStatusChanged(LockStatus newLockStatus) = 0; /** Missing by design: implementation is client-side in ProCamera.cpp **/ // virtual void onBufferReceived(int streamId, // const CpuConsumer::LockedBufer& buf); virtual void onResultReceived(int32_t frameId, camera_metadata* result) = 0; }; // ---------------------------------------------------------------------------- Loading
include/camera/ProCamera.h +11 −6 Original line number Diff line number Diff line Loading @@ -49,17 +49,19 @@ public: // OnBufferReceived and OnRequestReceived can come in with any order, // use android.sensor.timestamp and LockedBuffer.timestamp to correlate them // TODO: implement in IProCameraCallbacks, ProCamera2Client // A new frame buffer has been received for this stream. // -- This callback only fires for createStreamCpu streams // -- Use buf.timestamp to correlate with metadata's // android.sensor.timestamp // -- The buffer must not be accessed after this function call completes virtual void onBufferReceived(int streamId, const CpuConsumer::LockedBuffer& buf) = 0; // A new metadata buffer has been received. // -- Ownership of request passes on to the callee, // free with free_camera_metadata. virtual void onRequestReceived(camera_metadata* request) = 0; /** * A new metadata buffer has been received. * -- Ownership of request passes on to the callee, free with * free_camera_metadata. */ virtual void onResultReceived(int32_t frameId, camera_metadata* result) = 0; }; class ProCamera : public BnProCameraCallbacks, public IBinder::DeathRecipient Loading Loading @@ -189,6 +191,9 @@ protected: virtual void onLockStatusChanged( IProCameraCallbacks::LockStatus newLockStatus); virtual void onResultReceived(int32_t frameId, camera_metadata* result); class DeathNotifier: public IBinder::DeathRecipient { public: Loading