Merge "GraphicBufferSource fixes" into jb-mr2-dev
diff --git a/camera/Camera.cpp b/camera/Camera.cpp
index f417c90..e8908d2 100644
--- a/camera/Camera.cpp
+++ b/camera/Camera.cpp
@@ -283,7 +283,14 @@
void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,
camera_frame_metadata_t *metadata)
{
- return CameraBaseT::dataCallback(msgType, dataPtr, metadata);
+ sp<CameraListener> listener;
+ {
+ Mutex::Autolock _l(mLock);
+ listener = mListener;
+ }
+ if (listener != NULL) {
+ listener->postData(msgType, dataPtr, metadata);
+ }
}
// callback from camera service when timestamped frame is ready
@@ -302,7 +309,15 @@
return;
}
- if (!CameraBaseT::dataCallbackTimestamp(timestamp, msgType, dataPtr)) {
+ sp<CameraListener> listener;
+ {
+ Mutex::Autolock _l(mLock);
+ listener = mListener;
+ }
+
+ if (listener != NULL) {
+ listener->postDataTimestamp(timestamp, msgType, dataPtr);
+ } else {
ALOGW("No listener was set. Drop a recording frame.");
releaseRecordingFrame(dataPtr);
}
diff --git a/camera/CameraBase.cpp b/camera/CameraBase.cpp
index 29096da..c25c5fd 100644
--- a/camera/CameraBase.cpp
+++ b/camera/CameraBase.cpp
@@ -176,41 +176,6 @@
}
}
-// callback from camera service when frame or image is ready
-template <typename TCam, typename TCamTraits>
-void CameraBase<TCam, TCamTraits>::dataCallback(int32_t msgType,
- const sp<IMemory>& dataPtr,
- camera_frame_metadata *metadata)
-{
- sp<TCamListener> listener;
- {
- Mutex::Autolock _l(mLock);
- listener = mListener;
- }
- if (listener != NULL) {
- listener->postData(msgType, dataPtr, metadata);
- }
-}
-
-// callback from camera service when timestamped frame is ready
-template <typename TCam, typename TCamTraits>
-bool CameraBase<TCam, TCamTraits>::dataCallbackTimestamp(nsecs_t timestamp,
- int32_t msgType,
- const sp<IMemory>& dataPtr)
-{
- sp<TCamListener> listener;
- {
- Mutex::Autolock _l(mLock);
- listener = mListener;
- }
- if (listener != NULL) {
- listener->postDataTimestamp(timestamp, msgType, dataPtr);
- return true;
- }
-
- return false;
-}
-
template <typename TCam, typename TCamTraits>
int CameraBase<TCam, TCamTraits>::getNumberOfCameras() {
const sp<ICameraService> cs = getCameraService();
diff --git a/camera/IProCameraCallbacks.cpp b/camera/IProCameraCallbacks.cpp
index 6cd36bf..b9cd14d 100644
--- a/camera/IProCameraCallbacks.cpp
+++ b/camera/IProCameraCallbacks.cpp
@@ -34,8 +34,6 @@
enum {
NOTIFY_CALLBACK = IBinder::FIRST_CALL_TRANSACTION,
- DATA_CALLBACK,
- DATA_CALLBACK_TIMESTAMP,
LOCK_STATUS_CHANGED,
RESULT_RECEIVED,
};
@@ -63,37 +61,6 @@
remote()->transact(NOTIFY_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY);
}
- // generic data callback from camera service to app with image data
- void dataCallback(int32_t msgType, const sp<IMemory>& imageData,
- camera_frame_metadata_t *metadata)
- {
- ALOGV("dataCallback");
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraCallbacks::getInterfaceDescriptor());
- data.writeInt32(msgType);
- data.writeStrongBinder(imageData->asBinder());
- if (metadata) {
- data.writeInt32(metadata->number_of_faces);
- data.write(metadata->faces,
- sizeof(camera_face_t) * metadata->number_of_faces);
- }
- remote()->transact(DATA_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY);
- }
-
- // generic data callback from camera service to app with image data
- void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
- const sp<IMemory>& imageData)
- {
- ALOGV("dataCallback");
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraCallbacks::getInterfaceDescriptor());
- data.writeInt64(timestamp);
- data.writeInt32(msgType);
- data.writeStrongBinder(imageData->asBinder());
- remote()->transact(DATA_CALLBACK_TIMESTAMP, data, &reply,
- IBinder::FLAG_ONEWAY);
- }
-
void onLockStatusChanged(LockStatus newLockStatus) {
ALOGV("onLockStatusChanged");
Parcel data, reply;
@@ -132,33 +99,6 @@
notifyCallback(msgType, ext1, ext2);
return NO_ERROR;
} break;
- case DATA_CALLBACK: {
- ALOGV("DATA_CALLBACK");
- CHECK_INTERFACE(IProCameraCallbacks, data, reply);
- int32_t msgType = data.readInt32();
- sp<IMemory> imageData = interface_cast<IMemory>(
- data.readStrongBinder());
- camera_frame_metadata_t *metadata = NULL;
- if (data.dataAvail() > 0) {
- metadata = new camera_frame_metadata_t;
- metadata->number_of_faces = data.readInt32();
- metadata->faces = (camera_face_t *) data.readInplace(
- sizeof(camera_face_t) * metadata->number_of_faces);
- }
- dataCallback(msgType, imageData, metadata);
- if (metadata) delete metadata;
- return NO_ERROR;
- } break;
- case DATA_CALLBACK_TIMESTAMP: {
- ALOGV("DATA_CALLBACK_TIMESTAMP");
- CHECK_INTERFACE(IProCameraCallbacks, data, reply);
- nsecs_t timestamp = data.readInt64();
- int32_t msgType = data.readInt32();
- sp<IMemory> imageData = interface_cast<IMemory>(
- data.readStrongBinder());
- dataCallbackTimestamp(timestamp, msgType, imageData);
- return NO_ERROR;
- } break;
case LOCK_STATUS_CHANGED: {
ALOGV("LOCK_STATUS_CHANGED");
CHECK_INTERFACE(IProCameraCallbacks, data, reply);
diff --git a/camera/IProCameraUser.cpp b/camera/IProCameraUser.cpp
index c9d98aa..0c94bd4 100644
--- a/camera/IProCameraUser.cpp
+++ b/camera/IProCameraUser.cpp
@@ -40,8 +40,7 @@
HAS_EXCLUSIVE_LOCK,
SUBMIT_REQUEST,
CANCEL_REQUEST,
- REQUEST_STREAM,
- CANCEL_STREAM,
+ DELETE_STREAM,
CREATE_STREAM,
CREATE_DEFAULT_REQUEST,
GET_CAMERA_INFO,
@@ -200,22 +199,13 @@
return reply.readInt32();
}
- virtual status_t requestStream(int streamId)
+ virtual status_t deleteStream(int streamId)
{
Parcel data, reply;
data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
data.writeInt32(streamId);
- remote()->transact(REQUEST_STREAM, data, &reply);
- return reply.readInt32();
- }
- virtual status_t cancelStream(int streamId)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
- data.writeInt32(streamId);
-
- remote()->transact(CANCEL_STREAM, data, &reply);
+ remote()->transact(DELETE_STREAM, data, &reply);
return reply.readInt32();
}
@@ -334,16 +324,10 @@
reply->writeInt32(cancelRequest(requestId));
return NO_ERROR;
} break;
- case REQUEST_STREAM: {
+ case DELETE_STREAM: {
CHECK_INTERFACE(IProCameraUser, data, reply);
int streamId = data.readInt32();
- reply->writeInt32(requestStream(streamId));
- return NO_ERROR;
- } break;
- case CANCEL_STREAM: {
- CHECK_INTERFACE(IProCameraUser, data, reply);
- int streamId = data.readInt32();
- reply->writeInt32(cancelStream(streamId));
+ reply->writeInt32(deleteStream(streamId));
return NO_ERROR;
} break;
case CREATE_STREAM: {
diff --git a/camera/ProCamera.cpp b/camera/ProCamera.cpp
index 3cfabf6..396b009 100644
--- a/camera/ProCamera.cpp
+++ b/camera/ProCamera.cpp
@@ -60,21 +60,6 @@
return CameraBaseT::notifyCallback(msgType, ext1, ext2);
}
-// callback from camera service when frame or image is ready
-void ProCamera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,
- camera_frame_metadata_t *metadata)
-{
- return CameraBaseT::dataCallback(msgType, dataPtr, metadata);
-}
-
-// callback from camera service when timestamped frame is ready
-void ProCamera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
- const sp<IMemory>& dataPtr)
-{
- CameraBaseT::dataCallbackTimestamp(timestamp, msgType, dataPtr);
-}
-
-
void ProCamera::onLockStatusChanged(
IProCameraCallbacks::LockStatus newLockStatus)
{
@@ -185,7 +170,7 @@
sp <IProCameraUser> c = mCamera;
if (c == 0) return NO_INIT;
- status_t s = c->cancelStream(streamId);
+ status_t s = c->deleteStream(streamId);
mStreams.removeItem(streamId);
@@ -330,10 +315,7 @@
CpuConsumer::LockedBuffer buf;
if (listener.get() != NULL) {
- if (listener->useOnFrameAvailable()) {
- listener->onFrameAvailable(streamId, stream.cpuConsumer);
- return;
- }
+ listener->onFrameAvailable(streamId, stream.cpuConsumer);
}
// Unblock waitForFrame(id) callers
diff --git a/camera/tests/ProCameraTests.cpp b/camera/tests/ProCameraTests.cpp
index 1a8564e..71813ae 100644
--- a/camera/tests/ProCameraTests.cpp
+++ b/camera/tests/ProCameraTests.cpp
@@ -271,13 +271,11 @@
free_camera_metadata(request);
}
- // 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>& ) {}
-
+ 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;
@@ -717,6 +715,7 @@
return;
}
+ // FIXME: Note this test is broken because onBufferReceived was removed
mListener->SetEventMask(ProEvent_Mask(BUFFER_RECEIVED));
int streamId = -1;
@@ -783,6 +782,7 @@
return;
}
+ // FIXME: Note this test is broken because onBufferReceived was removed
mListener->SetEventMask(ProEvent_Mask(BUFFER_RECEIVED));
int streamId = -1;
diff --git a/include/camera/CameraBase.h b/include/camera/CameraBase.h
index 2735a86..9b08c0f 100644
--- a/include/camera/CameraBase.h
+++ b/include/camera/CameraBase.h
@@ -91,12 +91,6 @@
////////////////////////////////////////////////////////
virtual void notifyCallback(int32_t msgType, int32_t ext,
int32_t ext2);
- virtual void dataCallback(int32_t msgType,
- const sp<IMemory>& dataPtr,
- camera_frame_metadata *metadata);
- bool dataCallbackTimestamp(nsecs_t timestamp,
- int32_t msgType,
- const sp<IMemory>& dataPtr);
////////////////////////////////////////////////////////
// Common instance variables
@@ -115,7 +109,7 @@
const int mCameraId;
- typedef CameraBase<TCam> CameraBaseT;
+ typedef CameraBase<TCam> CameraBaseT;
};
}; // namespace android
diff --git a/include/camera/IProCameraCallbacks.h b/include/camera/IProCameraCallbacks.h
index fc24026..563ec17 100644
--- a/include/camera/IProCameraCallbacks.h
+++ b/include/camera/IProCameraCallbacks.h
@@ -28,19 +28,14 @@
namespace android {
-class IProCameraCallbacks: public IInterface
+class IProCameraCallbacks : public IInterface
{
public:
DECLARE_META_INTERFACE(ProCameraCallbacks);
- virtual void notifyCallback(int32_t msgType, int32_t ext1,
- int32_t ext2) = 0;
- virtual void dataCallback(int32_t msgType,
- const sp<IMemory>& data,
- camera_frame_metadata_t *metadata) = 0;
- virtual void dataCallbackTimestamp(nsecs_t timestamp,
- int32_t msgType,
- const sp<IMemory>& data) = 0;
+ virtual void notifyCallback(int32_t msgType,
+ int32_t ext1,
+ int32_t ext2) = 0;
enum LockStatus {
LOCK_ACQUIRED,
@@ -53,12 +48,13 @@
/** 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;
+ virtual void onResultReceived(int32_t frameId,
+ camera_metadata* result) = 0;
};
// ----------------------------------------------------------------------------
-class BnProCameraCallbacks: public BnInterface<IProCameraCallbacks>
+class BnProCameraCallbacks : public BnInterface<IProCameraCallbacks>
{
public:
virtual status_t onTransact( uint32_t code,
diff --git a/include/camera/IProCameraUser.h b/include/camera/IProCameraUser.h
index 7bddb0c..45b818c 100644
--- a/include/camera/IProCameraUser.h
+++ b/include/camera/IProCameraUser.h
@@ -61,8 +61,7 @@
bool streaming = false) = 0;
virtual status_t cancelRequest(int requestId) = 0;
- virtual status_t requestStream(int streamId) = 0;
- virtual status_t cancelStream(int streamId) = 0;
+ virtual status_t deleteStream(int streamId) = 0;
virtual status_t createStream(
int width, int height, int format,
const sp<IGraphicBufferProducer>& bufferProducer,
diff --git a/include/camera/ProCamera.h b/include/camera/ProCamera.h
index 5d6cfaa..3d1652f 100644
--- a/include/camera/ProCamera.h
+++ b/include/camera/ProCamera.h
@@ -40,9 +40,11 @@
// All callbacks on this class are concurrent
// (they come from separate threads)
-class ProCameraListener : public CameraListener
+class ProCameraListener : virtual public RefBase
{
public:
+ virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2) = 0;
+
// Lock has been acquired. Write operations now available.
virtual void onLockAcquired() = 0;
// Lock has been released with exclusiveUnlock.
@@ -53,19 +55,9 @@
// Lock free.
virtual void onTriggerNotify(int32_t msgType, int32_t ext1, int32_t ext2)
= 0;
-
- // OnBufferReceived and OnRequestReceived can come in with any order,
+ // onFrameAvailable and OnResultReceived can come in with any order,
// use android.sensor.timestamp and LockedBuffer.timestamp to correlate them
- // TODO: remove onBufferReceived
-
- // 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
@@ -77,17 +69,14 @@
// 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
+ // -- A buffer may be obtained by calling cpuConsumer->lockNextBuffer
+ // -- Use buf.timestamp to correlate with result's android.sensor.timestamp
// -- The buffer should be accessed with CpuConsumer::lockNextBuffer
// and CpuConsumer::unlockBuffer
virtual void onFrameAvailable(int /*streamId*/,
const sp<CpuConsumer>& /*cpuConsumer*/) {
}
- // TODO: Remove useOnFrameAvailable
- virtual bool useOnFrameAvailable() {
- return false;
- }
};
class ProCamera;
@@ -249,14 +238,10 @@
////////////////////////////////////////////////////////
// IProCameraCallbacks implementation
////////////////////////////////////////////////////////
- virtual void notifyCallback(int32_t msgType, int32_t ext,
+ virtual void notifyCallback(int32_t msgType,
+ int32_t ext,
int32_t ext2);
- virtual void dataCallback(int32_t msgType,
- const sp<IMemory>& dataPtr,
- camera_frame_metadata_t *metadata);
- virtual void dataCallbackTimestamp(nsecs_t timestamp,
- int32_t msgType,
- const sp<IMemory>& dataPtr);
+
virtual void onLockStatusChanged(
IProCameraCallbacks::LockStatus newLockStatus);
diff --git a/services/audioflinger/FastMixer.h b/services/audioflinger/FastMixer.h
index 462739b..2ab1d04 100644
--- a/services/audioflinger/FastMixer.h
+++ b/services/audioflinger/FastMixer.h
@@ -107,7 +107,7 @@
#ifdef FAST_MIXER_STATISTICS
// Recently collected samples of per-cycle monotonic time, thread CPU time, and CPU frequency.
// kSamplingN is the size of the sampling frame, and must be a power of 2 <= 0x8000.
- static const uint32_t kSamplingN = 0x1000;
+ static const uint32_t kSamplingN = 0x8000;
// The bounds define the interval of valid samples, and are represented as follows:
// newest open (excluded) endpoint = lower 16 bits of bounds, modulo N
// oldest closed (included) endpoint = upper 16 bits of bounds, modulo N
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index d6ad889..8600735 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -11,6 +11,7 @@
CameraClient.cpp \
Camera2Client.cpp \
ProCamera2Client.cpp \
+ Camera2ClientBase.cpp \
CameraDeviceBase.cpp \
Camera2Device.cpp \
Camera3Device.cpp \
diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp
index 8295905..056271d 100644
--- a/services/camera/libcameraservice/Camera2Client.cpp
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -49,9 +49,8 @@
uid_t clientUid,
int servicePid,
int deviceVersion):
- Client(cameraService, cameraClient, clientPackageName,
+ Camera2ClientBase(cameraService, cameraClient, clientPackageName,
cameraId, cameraFacing, clientPid, clientUid, servicePid),
- mSharedCameraClient(cameraClient),
mParameters(cameraId, cameraFacing)
{
ATRACE_CALL();
@@ -76,42 +75,17 @@
l.mParameters.state = Parameters::DISCONNECTED;
}
-status_t Camera2Client::checkPid(const char* checkLocation) const {
- int callingPid = getCallingPid();
- if (callingPid == mClientPid) return NO_ERROR;
-
- ALOGE("%s: attempt to use a locked camera from a different process"
- " (old pid %d, new pid %d)", checkLocation, mClientPid, callingPid);
- return PERMISSION_DENIED;
-}
-
status_t Camera2Client::initialize(camera_module_t *module)
{
ATRACE_CALL();
ALOGV("%s: Initializing client for camera %d", __FUNCTION__, mCameraId);
status_t res;
- // Verify ops permissions
- res = startCameraOps();
+ res = Camera2ClientBase::initialize(module);
if (res != OK) {
return res;
}
- if (mDevice == NULL) {
- ALOGE("%s: Camera %d: No device connected",
- __FUNCTION__, mCameraId);
- return NO_INIT;
- }
-
- res = mDevice->initialize(module);
- if (res != OK) {
- ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
- __FUNCTION__, mCameraId, strerror(-res), res);
- return NO_INIT;
- }
-
- res = mDevice->setNotifyCallback(this);
-
SharedParameters::Lock l(mParameters);
res = l.mParameters.initialize(&(mDevice->info()));
@@ -125,7 +99,7 @@
mStreamingProcessor = new StreamingProcessor(this);
- mFrameProcessor = new FrameProcessor(this);
+ mFrameProcessor = new FrameProcessor(mDevice, this);
threadName = String8::format("C2-%d-FrameProc",
mCameraId);
mFrameProcessor->run(threadName.string());
@@ -173,7 +147,7 @@
String8 result;
result.appendFormat("Client2[%d] (%p) PID: %d, dump:\n",
mCameraId,
- getCameraClient()->asBinder().get(),
+ getRemoteCallback()->asBinder().get(),
mClientPid);
result.append(" State: ");
#define CASE_APPEND_ENUM(x) case x: result.append(#x "\n"); break;
@@ -376,25 +350,15 @@
mZslProcessor->dump(fd, args);
- result = " Device dump:\n";
- write(fd, result.string(), result.size());
-
- 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());
- }
-
+ return dumpDevice(fd, args);
#undef CASE_APPEND_ENUM
- return NO_ERROR;
}
// ICamera interface
void Camera2Client::disconnect() {
ATRACE_CALL();
- Mutex::Autolock icl(mICameraLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
// Allow both client and the media server to disconnect at all times
int callingPid = getCallingPid();
@@ -444,7 +408,7 @@
status_t Camera2Client::connect(const sp<ICameraClient>& client) {
ATRACE_CALL();
ALOGV("%s: E", __FUNCTION__);
- Mutex::Autolock icl(mICameraLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
if (mClientPid != 0 && getCallingPid() != mClientPid) {
ALOGE("%s: Camera %d: Connection attempt from pid %d; "
@@ -455,8 +419,8 @@
mClientPid = getCallingPid();
- mCameraClient = client;
- mSharedCameraClient = client;
+ mRemoteCallback = client;
+ mSharedCameraCallbacks = client;
return OK;
}
@@ -464,7 +428,7 @@
status_t Camera2Client::lock() {
ATRACE_CALL();
ALOGV("%s: E", __FUNCTION__);
- Mutex::Autolock icl(mICameraLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
ALOGV("%s: Camera %d: Lock call from pid %d; current client pid %d",
__FUNCTION__, mCameraId, getCallingPid(), mClientPid);
@@ -485,7 +449,7 @@
status_t Camera2Client::unlock() {
ATRACE_CALL();
ALOGV("%s: E", __FUNCTION__);
- Mutex::Autolock icl(mICameraLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
ALOGV("%s: Camera %d: Unlock call from pid %d; current client pid %d",
__FUNCTION__, mCameraId, getCallingPid(), mClientPid);
@@ -497,8 +461,8 @@
return INVALID_OPERATION;
}
mClientPid = 0;
- mCameraClient.clear();
- mSharedCameraClient.clear();
+ mRemoteCallback.clear();
+ mSharedCameraCallbacks.clear();
return OK;
}
@@ -511,7 +475,7 @@
const sp<Surface>& surface) {
ATRACE_CALL();
ALOGV("%s: E", __FUNCTION__);
- Mutex::Autolock icl(mICameraLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
status_t res;
if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
@@ -529,7 +493,7 @@
const sp<IGraphicBufferProducer>& bufferProducer) {
ATRACE_CALL();
ALOGV("%s: E", __FUNCTION__);
- Mutex::Autolock icl(mICameraLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
status_t res;
if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
@@ -598,7 +562,7 @@
void Camera2Client::setPreviewCallbackFlag(int flag) {
ATRACE_CALL();
ALOGV("%s: Camera %d: Flag 0x%x", __FUNCTION__, mCameraId, flag);
- Mutex::Autolock icl(mICameraLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
if ( checkPid(__FUNCTION__) != OK) return;
@@ -637,7 +601,7 @@
status_t Camera2Client::startPreview() {
ATRACE_CALL();
ALOGV("%s: E", __FUNCTION__);
- Mutex::Autolock icl(mICameraLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
status_t res;
if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
SharedParameters::Lock l(mParameters);
@@ -753,7 +717,7 @@
void Camera2Client::stopPreview() {
ATRACE_CALL();
ALOGV("%s: E", __FUNCTION__);
- Mutex::Autolock icl(mICameraLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
status_t res;
if ( (res = checkPid(__FUNCTION__) ) != OK) return;
stopPreviewL();
@@ -801,7 +765,7 @@
bool Camera2Client::previewEnabled() {
ATRACE_CALL();
- Mutex::Autolock icl(mICameraLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
status_t res;
if ( (res = checkPid(__FUNCTION__) ) != OK) return false;
@@ -811,7 +775,7 @@
status_t Camera2Client::storeMetaDataInBuffers(bool enabled) {
ATRACE_CALL();
- Mutex::Autolock icl(mICameraLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
status_t res;
if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
@@ -836,7 +800,7 @@
status_t Camera2Client::startRecording() {
ATRACE_CALL();
ALOGV("%s: E", __FUNCTION__);
- Mutex::Autolock icl(mICameraLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
status_t res;
if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
SharedParameters::Lock l(mParameters);
@@ -927,7 +891,7 @@
void Camera2Client::stopRecording() {
ATRACE_CALL();
ALOGV("%s: E", __FUNCTION__);
- Mutex::Autolock icl(mICameraLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
SharedParameters::Lock l(mParameters);
status_t res;
@@ -959,7 +923,7 @@
bool Camera2Client::recordingEnabled() {
ATRACE_CALL();
- Mutex::Autolock icl(mICameraLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
if ( checkPid(__FUNCTION__) != OK) return false;
@@ -976,7 +940,7 @@
void Camera2Client::releaseRecordingFrame(const sp<IMemory>& mem) {
ATRACE_CALL();
- Mutex::Autolock icl(mICameraLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
if ( checkPid(__FUNCTION__) != OK) return;
mStreamingProcessor->releaseRecordingFrame(mem);
@@ -984,7 +948,7 @@
status_t Camera2Client::autoFocus() {
ATRACE_CALL();
- Mutex::Autolock icl(mICameraLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
ALOGV("%s: Camera %d", __FUNCTION__, mCameraId);
status_t res;
if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
@@ -1022,9 +986,9 @@
* Send immediate notification back to client
*/
if (notifyImmediately) {
- SharedCameraClient::Lock l(mSharedCameraClient);
- if (l.mCameraClient != 0) {
- l.mCameraClient->notifyCallback(CAMERA_MSG_FOCUS,
+ SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
+ if (l.mRemoteCallback != 0) {
+ l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS,
notifySuccess ? 1 : 0, 0);
}
return OK;
@@ -1055,7 +1019,7 @@
status_t Camera2Client::cancelAutoFocus() {
ATRACE_CALL();
- Mutex::Autolock icl(mICameraLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
ALOGV("%s: Camera %d", __FUNCTION__, mCameraId);
status_t res;
if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
@@ -1087,7 +1051,7 @@
status_t Camera2Client::takePicture(int msgType) {
ATRACE_CALL();
- Mutex::Autolock icl(mICameraLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
status_t res;
if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
@@ -1146,7 +1110,7 @@
status_t Camera2Client::setParameters(const String8& params) {
ATRACE_CALL();
ALOGV("%s: Camera %d", __FUNCTION__, mCameraId);
- Mutex::Autolock icl(mICameraLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
status_t res;
if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
@@ -1163,7 +1127,7 @@
String8 Camera2Client::getParameters() const {
ATRACE_CALL();
ALOGV("%s: Camera %d", __FUNCTION__, mCameraId);
- Mutex::Autolock icl(mICameraLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
if ( checkPid(__FUNCTION__) != OK) return String8();
SharedParameters::ReadLock l(mParameters);
@@ -1173,7 +1137,7 @@
status_t Camera2Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) {
ATRACE_CALL();
- Mutex::Autolock icl(mICameraLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
status_t res;
if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
@@ -1348,18 +1312,6 @@
}
/** Device-related methods */
-
-void Camera2Client::notifyError(int errorCode, int arg1, int arg2) {
- ALOGE("Error condition %d reported by HAL, arguments %d, %d", errorCode, arg1, arg2);
-}
-
-void Camera2Client::notifyShutter(int frameNumber, nsecs_t timestamp) {
- (void)frameNumber;
- (void)timestamp;
- ALOGV("%s: Shutter notification for frame %d at time %lld", __FUNCTION__,
- frameNumber, timestamp);
-}
-
void Camera2Client::notifyAutoFocus(uint8_t newState, int triggerId) {
ALOGV("%s: Autofocus state now %d, last trigger %d",
__FUNCTION__, newState, triggerId);
@@ -1455,16 +1407,16 @@
}
}
if (sendMovingMessage) {
- SharedCameraClient::Lock l(mSharedCameraClient);
- if (l.mCameraClient != 0) {
- l.mCameraClient->notifyCallback(CAMERA_MSG_FOCUS_MOVE,
+ SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
+ if (l.mRemoteCallback != 0) {
+ l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS_MOVE,
afInMotion ? 1 : 0, 0);
}
}
if (sendCompletedMessage) {
- SharedCameraClient::Lock l(mSharedCameraClient);
- if (l.mCameraClient != 0) {
- l.mCameraClient->notifyCallback(CAMERA_MSG_FOCUS,
+ SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
+ if (l.mRemoteCallback != 0) {
+ l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS,
success ? 1 : 0, 0);
}
}
@@ -1476,25 +1428,6 @@
mCaptureSequencer->notifyAutoExposure(newState, triggerId);
}
-void Camera2Client::notifyAutoWhitebalance(uint8_t newState, int triggerId) {
- (void)newState;
- (void)triggerId;
- ALOGV("%s: Auto-whitebalance state now %d, last trigger %d",
- __FUNCTION__, newState, triggerId);
-}
-
-int Camera2Client::getCameraId() const {
- return mCameraId;
-}
-
-const sp<CameraDeviceBase>& Camera2Client::getCameraDevice() {
- return mDevice;
-}
-
-const sp<CameraService>& Camera2Client::getCameraService() {
- return mCameraService;
-}
-
camera2::SharedParameters& Camera2Client::getParameters() {
return mParameters;
}
@@ -1533,32 +1466,6 @@
return mStreamingProcessor->stopStream();
}
-Camera2Client::SharedCameraClient::Lock::Lock(SharedCameraClient &client):
- mCameraClient(client.mCameraClient),
- mSharedClient(client) {
- mSharedClient.mCameraClientLock.lock();
-}
-
-Camera2Client::SharedCameraClient::Lock::~Lock() {
- mSharedClient.mCameraClientLock.unlock();
-}
-
-Camera2Client::SharedCameraClient::SharedCameraClient(const sp<ICameraClient>&client):
- mCameraClient(client) {
-}
-
-Camera2Client::SharedCameraClient& Camera2Client::SharedCameraClient::operator=(
- const sp<ICameraClient>&client) {
- Mutex::Autolock l(mCameraClientLock);
- mCameraClient = client;
- return *this;
-}
-
-void Camera2Client::SharedCameraClient::clear() {
- Mutex::Autolock l(mCameraClientLock);
- mCameraClient.clear();
-}
-
const int32_t Camera2Client::kPreviewRequestIdStart;
const int32_t Camera2Client::kPreviewRequestIdEnd;
const int32_t Camera2Client::kRecordingRequestIdStart;
@@ -1660,4 +1567,5 @@
return res;
}
+
} // namespace android
diff --git a/services/camera/libcameraservice/Camera2Client.h b/services/camera/libcameraservice/Camera2Client.h
index 80b88f4..713fab3 100644
--- a/services/camera/libcameraservice/Camera2Client.h
+++ b/services/camera/libcameraservice/Camera2Client.h
@@ -26,6 +26,7 @@
#include "camera2/ZslProcessor.h"
#include "camera2/CaptureSequencer.h"
#include "camera2/CallbackProcessor.h"
+#include "Camera2ClientBase.h"
namespace android {
@@ -35,8 +36,7 @@
* CAMERA_DEVICE_API_VERSION_2_0 and 3_0.
*/
class Camera2Client :
- public CameraService::Client,
- public CameraDeviceBase::NotificationListener
+ public Camera2ClientBase<CameraService::Client>
{
public:
/**
@@ -90,19 +90,13 @@
* Interface used by CameraDeviceBase
*/
- virtual void notifyError(int errorCode, int arg1, int arg2);
- virtual void notifyShutter(int frameNumber, nsecs_t timestamp);
virtual void notifyAutoFocus(uint8_t newState, int triggerId);
virtual void notifyAutoExposure(uint8_t newState, int triggerId);
- virtual void notifyAutoWhitebalance(uint8_t newState, int triggerId);
/**
* Interface used by independent components of Camera2Client.
*/
- int getCameraId() const;
- const sp<CameraDeviceBase>& getCameraDevice();
- const sp<CameraService>& getCameraService();
camera2::SharedParameters& getParameters();
int getPreviewStreamId() const;
@@ -118,27 +112,6 @@
status_t stopStream();
- // Simple class to ensure that access to ICameraClient is serialized by
- // requiring mCameraClientLock to be locked before access to mCameraClient
- // is possible.
- class SharedCameraClient {
- public:
- class Lock {
- public:
- Lock(SharedCameraClient &client);
- ~Lock();
- sp<ICameraClient> &mCameraClient;
- private:
- SharedCameraClient &mSharedClient;
- };
- SharedCameraClient(const sp<ICameraClient>& client);
- SharedCameraClient& operator=(const sp<ICameraClient>& client);
- void clear();
- private:
- sp<ICameraClient> mCameraClient;
- mutable Mutex mCameraClientLock;
- } mSharedCameraClient;
-
static size_t calculateBufferSize(int width, int height,
int format, int stride);
@@ -153,13 +126,6 @@
private:
/** ICamera interface-related private members */
-
- // Mutex that must be locked by methods implementing the ICamera interface.
- // Ensures serialization between incoming ICamera calls. All methods below
- // that append 'L' to the name assume that mICameraLock is locked when
- // they're called
- mutable Mutex mICameraLock;
-
typedef camera2::Parameters Parameters;
status_t setPreviewWindowL(const sp<IBinder>& binder,
@@ -213,17 +179,10 @@
bool mAfInMotion;
- /** CameraDevice instance, wraps HAL camera device */
-
- sp<CameraDeviceBase> mDevice;
-
/** Utility members */
// Wait until the camera device has received the latest control settings
status_t syncWithDevice();
-
- // Verify that caller is the owner of the camera
- status_t checkPid(const char *checkLocation) const;
};
}; // namespace android
diff --git a/services/camera/libcameraservice/Camera2ClientBase.cpp b/services/camera/libcameraservice/Camera2ClientBase.cpp
new file mode 100644
index 0000000..0623b89
--- /dev/null
+++ b/services/camera/libcameraservice/Camera2ClientBase.cpp
@@ -0,0 +1,329 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "Camera2ClientBase"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <utils/Trace.h>
+
+#include <cutils/properties.h>
+#include <gui/Surface.h>
+#include <gui/Surface.h>
+#include "camera2/Parameters.h"
+#include "Camera2ClientBase.h"
+#include "camera2/ProFrameProcessor.h"
+
+#include "Camera2Device.h"
+
+namespace android {
+using namespace camera2;
+
+static int getCallingPid() {
+ return IPCThreadState::self()->getCallingPid();
+}
+
+// Interface used by CameraService
+
+template <typename TClientBase>
+Camera2ClientBase<TClientBase>::Camera2ClientBase(
+ const sp<CameraService>& cameraService,
+ const sp<TCamCallbacks>& remoteCallback,
+ const String16& clientPackageName,
+ int cameraId,
+ int cameraFacing,
+ int clientPid,
+ uid_t clientUid,
+ int servicePid):
+ TClientBase(cameraService, remoteCallback, clientPackageName,
+ cameraId, cameraFacing, clientPid, clientUid, servicePid),
+ mSharedCameraCallbacks(remoteCallback)
+{
+ ALOGI("Camera %d: Opened", cameraId);
+ mDevice = new Camera2Device(cameraId);
+}
+
+template <typename TClientBase>
+status_t Camera2ClientBase<TClientBase>::checkPid(const char* checkLocation)
+ const {
+
+ int callingPid = getCallingPid();
+ if (callingPid == TClientBase::mClientPid) return NO_ERROR;
+
+ ALOGE("%s: attempt to use a locked camera from a different process"
+ " (old pid %d, new pid %d)", checkLocation, TClientBase::mClientPid, callingPid);
+ return PERMISSION_DENIED;
+}
+
+template <typename TClientBase>
+status_t Camera2ClientBase<TClientBase>::initialize(camera_module_t *module) {
+ ATRACE_CALL();
+ ALOGV("%s: Initializing client for camera %d", __FUNCTION__,
+ TClientBase::mCameraId);
+ status_t res;
+
+ // Verify ops permissions
+ res = TClientBase::startCameraOps();
+ if (res != OK) {
+ return res;
+ }
+
+ if (mDevice == NULL) {
+ ALOGE("%s: Camera %d: No device connected",
+ __FUNCTION__, TClientBase::mCameraId);
+ return NO_INIT;
+ }
+
+ res = mDevice->initialize(module);
+ if (res != OK) {
+ ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
+ __FUNCTION__, TClientBase::mCameraId, strerror(-res), res);
+ return NO_INIT;
+ }
+
+ res = mDevice->setNotifyCallback(this);
+
+ return OK;
+}
+
+template <typename TClientBase>
+Camera2ClientBase<TClientBase>::~Camera2ClientBase() {
+ ATRACE_CALL();
+
+ TClientBase::mDestructionStarted = true;
+
+ TClientBase::finishCameraOps();
+
+ disconnect();
+
+ ALOGI("Closed Camera %d", TClientBase::mCameraId);
+}
+
+template <typename TClientBase>
+status_t Camera2ClientBase<TClientBase>::dump(int fd,
+ const Vector<String16>& args) {
+ String8 result;
+ result.appendFormat("Camera2ClientBase[%d] (%p) PID: %d, dump:\n",
+ TClientBase::mCameraId,
+ TClientBase::getRemoteCallback()->asBinder().get(),
+ TClientBase::mClientPid);
+ result.append(" State: ");
+
+ write(fd, result.string(), result.size());
+ // TODO: print dynamic/request section from most recent requests
+
+ return dumpDevice(fd, args);
+}
+
+template <typename TClientBase>
+status_t Camera2ClientBase<TClientBase>::dumpDevice(
+ int fd,
+ const Vector<String16>& args) {
+ String8 result;
+
+ result = " Device dump:\n";
+ write(fd, result.string(), result.size());
+
+ if (!mDevice.get()) {
+ result = " *** Device is detached\n";
+ write(fd, result.string(), result.size());
+ return NO_ERROR;
+ }
+
+ 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());
+ }
+
+ return NO_ERROR;
+}
+
+// ICameraClient2BaseUser interface
+
+
+template <typename TClientBase>
+void Camera2ClientBase<TClientBase>::disconnect() {
+ ATRACE_CALL();
+ Mutex::Autolock icl(mBinderSerializationLock);
+
+ // Allow both client and the media server to disconnect at all times
+ int callingPid = getCallingPid();
+ if (callingPid != TClientBase::mClientPid &&
+ callingPid != TClientBase::mServicePid) return;
+
+ ALOGV("Camera %d: Shutting down", TClientBase::mCameraId);
+
+ detachDevice();
+
+ CameraService::BasicClient::disconnect();
+
+ ALOGV("Camera %d: Shut down complete complete", TClientBase::mCameraId);
+}
+
+template <typename TClientBase>
+void Camera2ClientBase<TClientBase>::detachDevice() {
+ if (mDevice == 0) return;
+ mDevice->disconnect();
+
+ mDevice.clear();
+
+ ALOGV("Camera %d: Detach complete", TClientBase::mCameraId);
+}
+
+template <typename TClientBase>
+status_t Camera2ClientBase<TClientBase>::connect(
+ const sp<TCamCallbacks>& client) {
+ ATRACE_CALL();
+ ALOGV("%s: E", __FUNCTION__);
+ Mutex::Autolock icl(mBinderSerializationLock);
+
+ if (TClientBase::mClientPid != 0 &&
+ getCallingPid() != TClientBase::mClientPid) {
+
+ ALOGE("%s: Camera %d: Connection attempt from pid %d; "
+ "current locked to pid %d",
+ __FUNCTION__,
+ TClientBase::mCameraId,
+ getCallingPid(),
+ TClientBase::mClientPid);
+ return BAD_VALUE;
+ }
+
+ TClientBase::mClientPid = getCallingPid();
+
+ TClientBase::mRemoteCallback = client;
+ mSharedCameraCallbacks = client;
+
+ return OK;
+}
+
+/** Device-related methods */
+
+template <typename TClientBase>
+void Camera2ClientBase<TClientBase>::notifyError(int errorCode, int arg1,
+ int arg2) {
+ ALOGE("Error condition %d reported by HAL, arguments %d, %d", errorCode,
+ arg1, arg2);
+}
+
+template <typename TClientBase>
+void Camera2ClientBase<TClientBase>::notifyShutter(int frameNumber,
+ nsecs_t timestamp) {
+ (void)frameNumber;
+ (void)timestamp;
+
+ ALOGV("%s: Shutter notification for frame %d at time %lld", __FUNCTION__,
+ frameNumber, timestamp);
+}
+
+template <typename TClientBase>
+void Camera2ClientBase<TClientBase>::notifyAutoFocus(uint8_t newState,
+ int triggerId) {
+ (void)newState;
+ (void)triggerId;
+
+ ALOGV("%s: Autofocus state now %d, last trigger %d",
+ __FUNCTION__, newState, triggerId);
+
+ typename SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
+ if (l.mRemoteCallback != 0) {
+ l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS_MOVE, 1, 0);
+ }
+ if (l.mRemoteCallback != 0) {
+ l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS, 1, 0);
+ }
+}
+
+template <typename TClientBase>
+void Camera2ClientBase<TClientBase>::notifyAutoExposure(uint8_t newState,
+ int triggerId) {
+ (void)newState;
+ (void)triggerId;
+
+ ALOGV("%s: Autoexposure state now %d, last trigger %d",
+ __FUNCTION__, newState, triggerId);
+}
+
+template <typename TClientBase>
+void Camera2ClientBase<TClientBase>::notifyAutoWhitebalance(uint8_t newState,
+ int triggerId) {
+ (void)newState;
+ (void)triggerId;
+
+ ALOGV("%s: Auto-whitebalance state now %d, last trigger %d",
+ __FUNCTION__, newState, triggerId);
+}
+
+template <typename TClientBase>
+int Camera2ClientBase<TClientBase>::getCameraId() const {
+ return TClientBase::mCameraId;
+}
+
+template <typename TClientBase>
+const sp<CameraDeviceBase>& Camera2ClientBase<TClientBase>::getCameraDevice() {
+ return mDevice;
+}
+
+template <typename TClientBase>
+const sp<CameraService>& Camera2ClientBase<TClientBase>::getCameraService() {
+ return TClientBase::mCameraService;
+}
+
+template <typename TClientBase>
+Camera2ClientBase<TClientBase>::SharedCameraCallbacks::Lock::Lock(
+ SharedCameraCallbacks &client) :
+
+ mRemoteCallback(client.mRemoteCallback),
+ mSharedClient(client) {
+
+ mSharedClient.mRemoteCallbackLock.lock();
+}
+
+template <typename TClientBase>
+Camera2ClientBase<TClientBase>::SharedCameraCallbacks::Lock::~Lock() {
+ mSharedClient.mRemoteCallbackLock.unlock();
+}
+
+template <typename TClientBase>
+Camera2ClientBase<TClientBase>::SharedCameraCallbacks::SharedCameraCallbacks(
+ const sp<TCamCallbacks>&client) :
+
+ mRemoteCallback(client) {
+}
+
+template <typename TClientBase>
+typename Camera2ClientBase<TClientBase>::SharedCameraCallbacks&
+Camera2ClientBase<TClientBase>::SharedCameraCallbacks::operator=(
+ const sp<TCamCallbacks>&client) {
+
+ Mutex::Autolock l(mRemoteCallbackLock);
+ mRemoteCallback = client;
+ return *this;
+}
+
+template <typename TClientBase>
+void Camera2ClientBase<TClientBase>::SharedCameraCallbacks::clear() {
+ Mutex::Autolock l(mRemoteCallbackLock);
+ mRemoteCallback.clear();
+}
+
+template class Camera2ClientBase<CameraService::ProClient>;
+template class Camera2ClientBase<CameraService::Client>;
+
+} // namespace android
diff --git a/services/camera/libcameraservice/Camera2ClientBase.h b/services/camera/libcameraservice/Camera2ClientBase.h
new file mode 100644
index 0000000..9001efb
--- /dev/null
+++ b/services/camera/libcameraservice/Camera2ClientBase.h
@@ -0,0 +1,128 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_SERVERS_CAMERA_CAMERA2CLIENT_BASE_H
+#define ANDROID_SERVERS_CAMERA_CAMERA2CLIENT_BASE_H
+
+#include "CameraDeviceBase.h"
+#include "CameraService.h"
+
+namespace android {
+
+class IMemory;
+
+template <typename TClientBase>
+class Camera2ClientBase :
+ public TClientBase,
+ public CameraDeviceBase::NotificationListener
+{
+public:
+ typedef typename TClientBase::TCamCallbacks TCamCallbacks;
+
+ /**
+ * Base binder interface (see ICamera/IProCameraUser for details)
+ */
+ virtual status_t connect(const sp<TCamCallbacks>& callbacks);
+ virtual void disconnect();
+
+ /**
+ * Interface used by CameraService
+ */
+
+ // TODO: too many params, move into a ClientArgs<T>
+ Camera2ClientBase(const sp<CameraService>& cameraService,
+ const sp<TCamCallbacks>& remoteCallback,
+ const String16& clientPackageName,
+ int cameraId,
+ int cameraFacing,
+ int clientPid,
+ uid_t clientUid,
+ int servicePid);
+ virtual ~Camera2ClientBase();
+
+ virtual status_t initialize(camera_module_t *module);
+ virtual status_t dump(int fd, const Vector<String16>& args);
+
+ /**
+ * CameraDeviceBase::NotificationListener implementation
+ */
+
+ virtual void notifyError(int errorCode, int arg1, int arg2);
+ virtual void notifyShutter(int frameNumber, nsecs_t timestamp);
+ virtual void notifyAutoFocus(uint8_t newState, int triggerId);
+ virtual void notifyAutoExposure(uint8_t newState, int triggerId);
+ virtual void notifyAutoWhitebalance(uint8_t newState,
+ int triggerId);
+
+
+ int getCameraId() const;
+ const sp<CameraDeviceBase>&
+ getCameraDevice();
+ const sp<CameraService>&
+ getCameraService();
+
+ /**
+ * Interface used by independent components of CameraClient2Base.
+ */
+
+ // Simple class to ensure that access to TCamCallbacks is serialized
+ // by requiring mRemoteCallbackLock to be locked before access to
+ // mRemoteCallback is possible.
+ class SharedCameraCallbacks {
+ public:
+ class Lock {
+ public:
+ Lock(SharedCameraCallbacks &client);
+ ~Lock();
+ sp<TCamCallbacks> &mRemoteCallback;
+ private:
+ SharedCameraCallbacks &mSharedClient;
+ };
+ SharedCameraCallbacks(const sp<TCamCallbacks>& client);
+ SharedCameraCallbacks& operator=(const sp<TCamCallbacks>& client);
+ void clear();
+ private:
+ sp<TCamCallbacks> mRemoteCallback;
+ mutable Mutex mRemoteCallbackLock;
+ } mSharedCameraCallbacks;
+
+protected:
+
+ virtual status_t dumpDevice(int fd, const Vector<String16>& args);
+
+ /** Binder client interface-related private members */
+
+ // Mutex that must be locked by methods implementing the binder client
+ // interface. Ensures serialization between incoming client calls.
+ // All methods in this class hierarchy that append 'L' to the name assume
+ // that mBinderSerializationLock is locked when they're called
+ mutable Mutex mBinderSerializationLock;
+
+ /** CameraDeviceBase instance wrapping HAL2+ entry */
+
+ sp<CameraDeviceBase> mDevice;
+
+ /** Utility members */
+
+ // Verify that caller is the owner of the camera
+ status_t checkPid(const char *checkLocation) const;
+
+ virtual void detachDevice();
+};
+
+}; // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/Camera2Device.cpp b/services/camera/libcameraservice/Camera2Device.cpp
index 81e58ca..37ba5ae 100644
--- a/services/camera/libcameraservice/Camera2Device.cpp
+++ b/services/camera/libcameraservice/Camera2Device.cpp
@@ -47,6 +47,10 @@
disconnect();
}
+int Camera2Device::getId() const {
+ return mId;
+}
+
status_t Camera2Device::initialize(camera_module_t *module)
{
ATRACE_CALL();
diff --git a/services/camera/libcameraservice/Camera2Device.h b/services/camera/libcameraservice/Camera2Device.h
index 1adb7a9..3034a1d 100644
--- a/services/camera/libcameraservice/Camera2Device.h
+++ b/services/camera/libcameraservice/Camera2Device.h
@@ -38,6 +38,7 @@
/**
* CameraDevice interface
*/
+ virtual int getId() const;
virtual status_t initialize(camera_module_t *module);
virtual status_t disconnect();
virtual status_t dump(int fd, const Vector<String16>& args);
diff --git a/services/camera/libcameraservice/Camera3Device.cpp b/services/camera/libcameraservice/Camera3Device.cpp
index 2a1be09..04a6e6a 100644
--- a/services/camera/libcameraservice/Camera3Device.cpp
+++ b/services/camera/libcameraservice/Camera3Device.cpp
@@ -50,6 +50,10 @@
disconnect();
}
+int Camera3Device::getId() const {
+ return mId;
+}
+
status_t Camera3Device::initialize(camera_module_t *module)
{
ATRACE_CALL();
diff --git a/services/camera/libcameraservice/Camera3Device.h b/services/camera/libcameraservice/Camera3Device.h
index 2bc7cf0..df7352c 100644
--- a/services/camera/libcameraservice/Camera3Device.h
+++ b/services/camera/libcameraservice/Camera3Device.h
@@ -57,6 +57,7 @@
/**
* CameraDevice interface
*/
+ virtual int getId() const;
virtual status_t initialize(camera_module_t *module);
virtual status_t disconnect();
virtual status_t dump(int fd, const Vector<String16> &args);
diff --git a/services/camera/libcameraservice/CameraClient.cpp b/services/camera/libcameraservice/CameraClient.cpp
index 90f8f40..e577fa3 100644
--- a/services/camera/libcameraservice/CameraClient.cpp
+++ b/services/camera/libcameraservice/CameraClient.cpp
@@ -117,7 +117,7 @@
size_t len = snprintf(buffer, SIZE, "Client[%d] (%p) PID: %d\n",
mCameraId,
- getCameraClient()->asBinder().get(),
+ getRemoteCallback()->asBinder().get(),
mClientPid);
len = (len > SIZE - 1) ? SIZE - 1 : len;
write(fd, buffer, len);
@@ -173,10 +173,10 @@
return INVALID_OPERATION;
}
mClientPid = 0;
- LOG1("clear mCameraClient (pid %d)", callingPid);
+ LOG1("clear mRemoteCallback (pid %d)", callingPid);
// we need to remove the reference to ICameraClient so that when the app
// goes away, the reference count goes to 0.
- mCameraClient.clear();
+ mRemoteCallback.clear();
}
return result;
}
@@ -193,14 +193,15 @@
return EBUSY;
}
- if (mCameraClient != 0 && (client->asBinder() == mCameraClient->asBinder())) {
+ if (mRemoteCallback != 0 &&
+ (client->asBinder() == mRemoteCallback->asBinder())) {
LOG1("Connect to the same client");
return NO_ERROR;
}
mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP;
mClientPid = callingPid;
- mCameraClient = client;
+ mRemoteCallback = client;
LOG1("connect X (pid %d)", callingPid);
return NO_ERROR;
@@ -780,7 +781,7 @@
mCameraService->playSound(CameraService::SOUND_SHUTTER);
}
- sp<ICameraClient> c = mCameraClient;
+ sp<ICameraClient> c = mRemoteCallback;
if (c != 0) {
mLock.unlock();
c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
@@ -811,7 +812,7 @@
}
// hold a strong pointer to the client
- sp<ICameraClient> c = mCameraClient;
+ sp<ICameraClient> c = mRemoteCallback;
// clear callback flags if no client or one-shot mode
if (c == 0 || (mPreviewCallbackFlag & CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) {
@@ -841,7 +842,7 @@
void CameraClient::handlePostview(const sp<IMemory>& mem) {
disableMsgType(CAMERA_MSG_POSTVIEW_FRAME);
- sp<ICameraClient> c = mCameraClient;
+ sp<ICameraClient> c = mRemoteCallback;
mLock.unlock();
if (c != 0) {
c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem, NULL);
@@ -856,7 +857,7 @@
size_t size;
sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
- sp<ICameraClient> c = mCameraClient;
+ sp<ICameraClient> c = mRemoteCallback;
mLock.unlock();
if (c != 0) {
c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem, NULL);
@@ -867,7 +868,7 @@
void CameraClient::handleCompressedPicture(const sp<IMemory>& mem) {
disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
- sp<ICameraClient> c = mCameraClient;
+ sp<ICameraClient> c = mRemoteCallback;
mLock.unlock();
if (c != 0) {
c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem, NULL);
@@ -877,7 +878,7 @@
void CameraClient::handleGenericNotify(int32_t msgType,
int32_t ext1, int32_t ext2) {
- sp<ICameraClient> c = mCameraClient;
+ sp<ICameraClient> c = mRemoteCallback;
mLock.unlock();
if (c != 0) {
c->notifyCallback(msgType, ext1, ext2);
@@ -886,7 +887,7 @@
void CameraClient::handleGenericData(int32_t msgType,
const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) {
- sp<ICameraClient> c = mCameraClient;
+ sp<ICameraClient> c = mRemoteCallback;
mLock.unlock();
if (c != 0) {
c->dataCallback(msgType, dataPtr, metadata);
@@ -895,7 +896,7 @@
void CameraClient::handleGenericDataTimestamp(nsecs_t timestamp,
int32_t msgType, const sp<IMemory>& dataPtr) {
- sp<ICameraClient> c = mCameraClient;
+ sp<ICameraClient> c = mRemoteCallback;
mLock.unlock();
if (c != 0) {
c->dataCallbackTimestamp(timestamp, msgType, dataPtr);
diff --git a/services/camera/libcameraservice/CameraDeviceBase.h b/services/camera/libcameraservice/CameraDeviceBase.h
index 8252af7..8c457d9 100644
--- a/services/camera/libcameraservice/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/CameraDeviceBase.h
@@ -36,6 +36,11 @@
public:
virtual ~CameraDeviceBase();
+ /**
+ * The device's camera ID
+ */
+ virtual int getId() const = 0;
+
virtual status_t initialize(camera_module_t *module) = 0;
virtual status_t disconnect() = 0;
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 8c4f619..7636143 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -176,18 +176,12 @@
return false;
}
-sp<ICamera> CameraService::connect(
- const sp<ICameraClient>& cameraClient,
- int cameraId,
- const String16& clientPackageName,
- int clientUid) {
+bool CameraService::validateConnect(int cameraId,
+ /*inout*/
+ int& clientUid) const {
- String8 clientName8(clientPackageName);
int callingPid = getCallingPid();
- LOG1("CameraService::connect E (pid %d \"%s\", id %d)", callingPid,
- clientName8.string(), cameraId);
-
if (clientUid == USE_CALLING_UID) {
clientUid = getCallingUid();
} else {
@@ -195,20 +189,19 @@
if (callingPid != getpid()) {
ALOGE("CameraService::connect X (pid %d) rejected (don't trust clientUid)",
callingPid);
- return NULL;
+ return false;
}
}
if (!mModule) {
ALOGE("Camera HAL module not loaded");
- return NULL;
+ return false;
}
- sp<Client> client;
if (cameraId < 0 || cameraId >= mNumberOfCameras) {
ALOGE("CameraService::connect X (pid %d) rejected (invalid cameraId %d).",
callingPid, cameraId);
- return NULL;
+ return false;
}
char value[PROPERTY_VALUE_MAX];
@@ -216,22 +209,32 @@
if (strcmp(value, "1") == 0) {
// Camera is disabled by DevicePolicyManager.
ALOGI("Camera is disabled. connect X (pid %d) rejected", callingPid);
- return NULL;
+ return false;
}
- Mutex::Autolock lock(mServiceLock);
+ return true;
+}
+
+bool CameraService::canConnectUnsafe(int cameraId,
+ const String16& clientPackageName,
+ const sp<IBinder>& remoteCallback,
+ sp<Client> &client) {
+ String8 clientName8(clientPackageName);
+ int callingPid = getCallingPid();
+
if (mClient[cameraId] != 0) {
client = mClient[cameraId].promote();
if (client != 0) {
- if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) {
+ if (remoteCallback == client->getRemoteCallback()->asBinder()) {
LOG1("CameraService::connect X (pid %d) (the same client)",
callingPid);
- return client;
+ return true;
} else {
- // TODOSC: need to support 1 regular client, multiple shared clients here
- ALOGW("CameraService::connect X (pid %d) rejected (existing client).",
- callingPid);
- return NULL;
+ // TODOSC: need to support 1 regular client,
+ // multiple shared clients here
+ ALOGW("CameraService::connect X (pid %d) rejected"
+ " (existing client).", callingPid);
+ return false;
}
}
mClient[cameraId].clear();
@@ -247,16 +250,47 @@
would be fine
*/
if (mBusy[cameraId]) {
-
ALOGW("CameraService::connect X (pid %d, \"%s\") rejected"
" (camera %d is still busy).", callingPid,
clientName8.string(), cameraId);
+ return false;
+ }
+
+ return true;
+}
+
+sp<ICamera> CameraService::connect(
+ const sp<ICameraClient>& cameraClient,
+ int cameraId,
+ const String16& clientPackageName,
+ int clientUid) {
+
+ String8 clientName8(clientPackageName);
+ int callingPid = getCallingPid();
+
+ LOG1("CameraService::connect E (pid %d \"%s\", id %d)", callingPid,
+ clientName8.string(), cameraId);
+
+ if (!validateConnect(cameraId, /*inout*/clientUid)) {
return NULL;
}
+ sp<Client> client;
+
+ Mutex::Autolock lock(mServiceLock);
+ if (!canConnectUnsafe(cameraId, clientPackageName,
+ cameraClient->asBinder(),
+ /*out*/client)) {
+ return NULL;
+ } else if (client.get() != NULL) {
+ return client;
+ }
+
int facing = -1;
int deviceVersion = getDeviceVersion(cameraId, &facing);
+ // If there are other non-exclusive users of the camera,
+ // this will tear them down before we can reuse the camera
if (isValidCameraId(cameraId)) {
updateStatus(ICameraServiceListener::STATUS_NOT_AVAILABLE, cameraId);
}
@@ -283,21 +317,30 @@
return NULL;
}
- if (client->initialize(mModule) != OK) {
+ if (!connectFinishUnsafe(client, client->asBinder())) {
// this is probably not recoverable.. but maybe the client can try again
updateStatus(ICameraServiceListener::STATUS_AVAILABLE, cameraId);
return NULL;
}
- cameraClient->asBinder()->linkToDeath(this);
-
mClient[cameraId] = client;
LOG1("CameraService::connect X (id %d, this pid is %d)", cameraId, getpid());
return client;
}
+bool CameraService::connectFinishUnsafe(const sp<BasicClient>& client,
+ const sp<IBinder>& clientBinder) {
+ if (client->initialize(mModule) != OK) {
+ return false;
+ }
+
+ clientBinder->linkToDeath(this);
+
+ return true;
+}
+
sp<IProCameraUser> CameraService::connect(
const sp<IProCameraCallbacks>& cameraCb,
int cameraId,
@@ -307,38 +350,24 @@
String8 clientName8(clientPackageName);
int callingPid = getCallingPid();
- // TODO: use clientPackageName and clientUid with appOpsMangr
+ LOG1("CameraService::connectPro E (pid %d \"%s\", id %d)", callingPid,
+ clientName8.string(), cameraId);
- LOG1("CameraService::connectPro E (pid %d, id %d)", callingPid, cameraId);
-
- if (!mModule) {
- ALOGE("Camera HAL module not loaded");
+ if (!validateConnect(cameraId, /*inout*/clientUid)) {
return NULL;
}
+ Mutex::Autolock lock(mServiceLock);
+ {
+ sp<Client> client;
+ if (!canConnectUnsafe(cameraId, clientPackageName,
+ cameraCb->asBinder(),
+ /*out*/client)) {
+ return NULL;
+ }
+ }
+
sp<ProClient> client;
- if (cameraId < 0 || cameraId >= mNumberOfCameras) {
- ALOGE("CameraService::connectPro X (pid %d) rejected (invalid cameraId %d).",
- callingPid, cameraId);
- return NULL;
- }
-
- char value[PROPERTY_VALUE_MAX];
- property_get("sys.secpolicy.camera.disabled", value, "0");
- if (strcmp(value, "1") == 0) {
- // Camera is disabled by DevicePolicyManager.
- ALOGI("Camera is disabled. connect X (pid %d) rejected", callingPid);
- return NULL;
- }
-
- // TODO: allow concurrent connections with a ProCamera
- if (mBusy[cameraId]) {
-
- ALOGW("CameraService::connectPro X (pid %d, \"%s\") rejected"
- " (camera %d is still busy).", callingPid,
- clientName8.string(), cameraId);
- return NULL;
- }
int facing = -1;
int deviceVersion = getDeviceVersion(cameraId, &facing);
@@ -361,16 +390,15 @@
return NULL;
}
- if (client->initialize(mModule) != OK) {
+ if (!connectFinishUnsafe(client, client->asBinder())) {
return NULL;
}
mProClientList[cameraId].push(client);
- cameraCb->asBinder()->linkToDeath(this);
-
LOG1("CameraService::connectPro X (id %d, this pid is %d)", cameraId,
getpid());
+
return client;
}
@@ -496,7 +524,7 @@
continue;
}
- if (cameraClient == client->getCameraClient()->asBinder()) {
+ if (cameraClient == client->getRemoteCallback()->asBinder()) {
// Found our camera
outIndex = i;
return client;
@@ -639,7 +667,7 @@
int callingPid = getCallingPid();
LOG1("Client::Client E (pid %d, id %d)", callingPid, cameraId);
- mCameraClient = cameraClient;
+ mRemoteCallback = cameraClient;
cameraService->setCameraBusy(cameraId);
cameraService->loadSound();
@@ -652,7 +680,6 @@
mDestructionStarted = true;
mCameraService->releaseSound();
- finishCameraOps();
// unconditionally disconnect. function is idempotent
Client::disconnect();
}
@@ -666,7 +693,7 @@
mClientPackageName(clientPackageName)
{
mCameraService = cameraService;
- mRemoteCallback = remoteCallback;
+ mRemoteBinder = remoteCallback;
mCameraId = cameraId;
mCameraFacing = cameraFacing;
mClientPid = clientPid;
@@ -681,7 +708,7 @@
}
void CameraService::BasicClient::disconnect() {
- mCameraService->removeClientByRemote(mRemoteCallback);
+ mCameraService->removeClientByRemote(mRemoteBinder);
}
status_t CameraService::BasicClient::startCameraOps() {
@@ -689,6 +716,11 @@
mOpsCallback = new OpsCallback(this);
+ {
+ ALOGV("%s: Start camera ops, package name = %s, client UID = %d",
+ __FUNCTION__, String8(mClientPackageName).string(), mClientUid);
+ }
+
mAppOpsManager.startWatchingMode(AppOpsManager::OP_CAMERA,
mClientPackageName, mOpsCallback);
res = mAppOpsManager.startOp(AppOpsManager::OP_CAMERA,
@@ -767,7 +799,7 @@
}
void CameraService::Client::notifyError() {
- mCameraClient->notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_RELEASED, 0);
+ mRemoteCallback->notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_RELEASED, 0);
}
// NOTE: function is idempotent
@@ -810,79 +842,10 @@
}
CameraService::ProClient::~ProClient() {
- mDestructionStarted = true;
-
- ProClient::disconnect();
-}
-
-status_t CameraService::ProClient::connect(const sp<IProCameraCallbacks>& callbacks) {
- ALOGE("%s: not implemented yet", __FUNCTION__);
-
- return INVALID_OPERATION;
-}
-
-void CameraService::ProClient::disconnect() {
- BasicClient::disconnect();
-}
-
-status_t CameraService::ProClient::initialize(camera_module_t* module)
-{
- ALOGW("%s: not implemented yet", __FUNCTION__);
- return OK;
-}
-
-status_t CameraService::ProClient::exclusiveTryLock() {
- ALOGE("%s: not implemented yet", __FUNCTION__);
- return INVALID_OPERATION;
-}
-
-status_t CameraService::ProClient::exclusiveLock() {
- ALOGE("%s: not implemented yet", __FUNCTION__);
- return INVALID_OPERATION;
-}
-
-status_t CameraService::ProClient::exclusiveUnlock() {
- ALOGE("%s: not implemented yet", __FUNCTION__);
- return INVALID_OPERATION;
-}
-
-bool CameraService::ProClient::hasExclusiveLock() {
- ALOGE("%s: not implemented yet", __FUNCTION__);
- return false;
-}
-
-void CameraService::ProClient::onExclusiveLockStolen() {
- ALOGE("%s: not implemented yet", __FUNCTION__);
-}
-
-status_t CameraService::ProClient::submitRequest(camera_metadata_t* request, bool streaming) {
- ALOGE("%s: not implemented yet", __FUNCTION__);
-
- free_camera_metadata(request);
-
- return INVALID_OPERATION;
-}
-
-status_t CameraService::ProClient::cancelRequest(int requestId) {
- ALOGE("%s: not implemented yet", __FUNCTION__);
-
- return INVALID_OPERATION;
-}
-
-status_t CameraService::ProClient::requestStream(int streamId) {
- ALOGE("%s: not implemented yet", __FUNCTION__);
-
- return INVALID_OPERATION;
-}
-
-status_t CameraService::ProClient::cancelStream(int streamId) {
- ALOGE("%s: not implemented yet", __FUNCTION__);
-
- return INVALID_OPERATION;
}
void CameraService::ProClient::notifyError() {
- ALOGE("%s: not implemented yet", __FUNCTION__);
+ mRemoteCallback->notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_RELEASED, 0);
}
// ----------------------------------------------------------------------------
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 8acc63f..c5e495f 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -108,8 +108,9 @@
virtual void disconnect() = 0;
+ // Return the remote callback binder object (e.g. IProCameraCallbacks)
wp<IBinder> getRemote() {
- return mRemoteCallback;
+ return mRemoteBinder;
}
protected:
@@ -140,7 +141,7 @@
pid_t mServicePid; // immutable after constructor
// - The app-side Binder interface to receive callbacks from us
- wp<IBinder> mRemoteCallback; // immutable after constructor
+ wp<IBinder> mRemoteBinder; // immutable after constructor
// permissions management
status_t startCameraOps();
@@ -173,6 +174,8 @@
class Client : public BnCamera, public BasicClient
{
public:
+ typedef ICameraClient TCamCallbacks;
+
// ICamera interface (see ICamera for details)
virtual void disconnect();
virtual status_t connect(const sp<ICameraClient>& client) = 0;
@@ -208,8 +211,8 @@
~Client();
// return our camera client
- const sp<ICameraClient>& getCameraClient() {
- return mCameraClient;
+ const sp<ICameraClient>& getRemoteCallback() {
+ return mRemoteCallback;
}
protected:
@@ -222,12 +225,14 @@
// Initialized in constructor
// - The app-side Binder interface to receive callbacks from us
- sp<ICameraClient> mCameraClient;
+ sp<ICameraClient> mRemoteCallback;
}; // class Client
class ProClient : public BnProCameraUser, public BasicClient {
public:
+ typedef IProCameraCallbacks TCamCallbacks;
+
ProClient(const sp<CameraService>& cameraService,
const sp<IProCameraCallbacks>& remoteCallback,
const String16& clientPackageName,
@@ -243,34 +248,24 @@
return mRemoteCallback;
}
- // BasicClient implementation
- virtual status_t initialize(camera_module_t *module);
-
/***
IProCamera implementation
***/
+ virtual status_t connect(const sp<IProCameraCallbacks>& callbacks)
+ = 0;
+ virtual status_t exclusiveTryLock() = 0;
+ virtual status_t exclusiveLock() = 0;
+ virtual status_t exclusiveUnlock() = 0;
-
- virtual status_t connect(
- const sp<IProCameraCallbacks>& callbacks);
- virtual void disconnect();
-
- virtual status_t exclusiveTryLock();
- virtual status_t exclusiveLock();
- virtual status_t exclusiveUnlock();
-
- virtual bool hasExclusiveLock();
+ virtual bool hasExclusiveLock() = 0;
// Note that the callee gets a copy of the metadata.
virtual int submitRequest(camera_metadata_t* metadata,
- bool streaming = false);
- virtual status_t cancelRequest(int requestId);
-
- virtual status_t requestStream(int streamId);
- virtual status_t cancelStream(int streamId);
+ bool streaming = false) = 0;
+ virtual status_t cancelRequest(int requestId) = 0;
// Callbacks from camera service
- virtual void onExclusiveLockStolen();
+ virtual void onExclusiveLockStolen() = 0;
protected:
virtual void notifyError();
@@ -283,6 +278,22 @@
// Delay-load the Camera HAL module
virtual void onFirstRef();
+ // Step 1. Check if we can connect, before we acquire the service lock.
+ bool validateConnect(int cameraId,
+ /*inout*/
+ int& clientUid) const;
+
+ // Step 2. Check if we can connect, after we acquire the service lock.
+ bool canConnectUnsafe(int cameraId,
+ const String16& clientPackageName,
+ const sp<IBinder>& remoteCallback,
+ /*out*/
+ sp<Client> &client);
+
+ // When connection is successful, initialize client and track its death
+ bool connectFinishUnsafe(const sp<BasicClient>& client,
+ const sp<IBinder>& clientBinder);
+
virtual sp<BasicClient> getClientByRemote(const wp<IBinder>& cameraClient);
Mutex mServiceLock;
diff --git a/services/camera/libcameraservice/ProCamera2Client.cpp b/services/camera/libcameraservice/ProCamera2Client.cpp
index 6fed8b4..575b075 100644
--- a/services/camera/libcameraservice/ProCamera2Client.cpp
+++ b/services/camera/libcameraservice/ProCamera2Client.cpp
@@ -27,68 +27,43 @@
#include "camera2/Parameters.h"
#include "ProCamera2Client.h"
#include "camera2/ProFrameProcessor.h"
+#include "CameraDeviceBase.h"
namespace android {
using namespace camera2;
-static int getCallingPid() {
- return IPCThreadState::self()->getCallingPid();
-}
-
-static int getCallingUid() {
- return IPCThreadState::self()->getCallingUid();
-}
-
// Interface used by CameraService
ProCamera2Client::ProCamera2Client(const sp<CameraService>& cameraService,
- const sp<IProCameraCallbacks>& remoteCallback,
- const String16& clientPackageName,
- int cameraId,
- int cameraFacing,
- int clientPid,
- uid_t clientUid,
- int servicePid):
- ProClient(cameraService, remoteCallback, clientPackageName,
- cameraId, cameraFacing, clientPid, clientUid, servicePid),
- mSharedCameraCallbacks(remoteCallback)
+ const sp<IProCameraCallbacks>& remoteCallback,
+ const String16& clientPackageName,
+ int cameraId,
+ int cameraFacing,
+ int clientPid,
+ uid_t clientUid,
+ int servicePid) :
+ Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
+ cameraId, cameraFacing, clientPid, clientUid, servicePid)
{
ATRACE_CALL();
ALOGI("ProCamera %d: Opened", cameraId);
- mDevice = new Camera2Device(cameraId);
-
mExclusiveLock = false;
}
-status_t ProCamera2Client::checkPid(const char* checkLocation) const {
- int callingPid = getCallingPid();
- if (callingPid == mClientPid) return NO_ERROR;
-
- ALOGE("%s: attempt to use a locked camera from a different process"
- " (old pid %d, new pid %d)", checkLocation, mClientPid, callingPid);
- return PERMISSION_DENIED;
-}
-
status_t ProCamera2Client::initialize(camera_module_t *module)
{
ATRACE_CALL();
- ALOGV("%s: Initializing client for camera %d", __FUNCTION__, mCameraId);
status_t res;
- res = mDevice->initialize(module);
+ res = Camera2ClientBase::initialize(module);
if (res != OK) {
- ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
- __FUNCTION__, mCameraId, strerror(-res), res);
- return NO_INIT;
+ return res;
}
- res = mDevice->setNotifyCallback(this);
-
String8 threadName;
- mFrameProcessor = new ProFrameProcessor(this);
- threadName = String8::format("PC2-%d-FrameProc",
- mCameraId);
+ mFrameProcessor = new ProFrameProcessor(mDevice);
+ threadName = String8::format("PC2-%d-FrameProc", mCameraId);
mFrameProcessor->run(threadName.string());
mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
@@ -99,20 +74,13 @@
}
ProCamera2Client::~ProCamera2Client() {
- ATRACE_CALL();
-
- mDestructionStarted = true;
-
- disconnect();
-
- ALOGI("ProCamera %d: Closed", mCameraId);
}
status_t ProCamera2Client::exclusiveTryLock() {
ATRACE_CALL();
ALOGV("%s", __FUNCTION__);
- Mutex::Autolock icl(mIProCameraUserLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
if (!mDevice.get()) return PERMISSION_DENIED;
@@ -143,7 +111,7 @@
ATRACE_CALL();
ALOGV("%s", __FUNCTION__);
- Mutex::Autolock icl(mIProCameraUserLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
if (!mDevice.get()) return PERMISSION_DENIED;
@@ -177,7 +145,7 @@
ATRACE_CALL();
ALOGV("%s", __FUNCTION__);
- Mutex::Autolock icl(mIProCameraUserLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
// don't allow unlocking if we have no lock
@@ -198,6 +166,7 @@
}
bool ProCamera2Client::hasExclusiveLock() {
+ Mutex::Autolock icl(mBinderSerializationLock);
return mExclusiveLock;
}
@@ -205,7 +174,7 @@
ALOGV("%s: ProClient lost exclusivity (id %d)",
__FUNCTION__, mCameraId);
- Mutex::Autolock icl(mIProCameraUserLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
if (mExclusiveLock && mRemoteCallback.get() != NULL) {
@@ -224,7 +193,7 @@
ATRACE_CALL();
ALOGV("%s", __FUNCTION__);
- Mutex::Autolock icl(mIProCameraUserLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
if (!mDevice.get()) return DEAD_OBJECT;
@@ -248,7 +217,7 @@
ATRACE_CALL();
ALOGV("%s", __FUNCTION__);
- Mutex::Autolock icl(mIProCameraUserLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
if (!mDevice.get()) return DEAD_OBJECT;
@@ -256,24 +225,19 @@
return PERMISSION_DENIED;
}
+ // TODO: implement
ALOGE("%s: not fully implemented yet", __FUNCTION__);
return INVALID_OPERATION;
}
-status_t ProCamera2Client::requestStream(int streamId) {
- ALOGE("%s: not implemented yet", __FUNCTION__);
-
- return INVALID_OPERATION;
-}
-
-status_t ProCamera2Client::cancelStream(int streamId) {
+status_t ProCamera2Client::deleteStream(int streamId) {
ATRACE_CALL();
ALOGV("%s (streamId = 0x%x)", __FUNCTION__, streamId);
status_t res;
if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
- Mutex::Autolock icl(mIProCameraUserLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
if (!mDevice.get()) return DEAD_OBJECT;
mDevice->clearStreamingRequest();
@@ -301,7 +265,7 @@
status_t res;
if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
- Mutex::Autolock icl(mIProCameraUserLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
if (!mDevice.get()) return DEAD_OBJECT;
@@ -332,7 +296,7 @@
status_t res;
if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
- Mutex::Autolock icl(mIProCameraUserLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
if (!mDevice.get()) return DEAD_OBJECT;
@@ -352,7 +316,7 @@
return INVALID_OPERATION;
}
- Mutex::Autolock icl(mIProCameraUserLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
if (!mDevice.get()) return DEAD_OBJECT;
@@ -373,47 +337,11 @@
// TODO: print dynamic/request section from most recent requests
mFrameProcessor->dump(fd, args);
-#define CASE_APPEND_ENUM(x) case x: result.append(#x "\n"); break;
-
- result = " Device dump:\n";
- write(fd, result.string(), result.size());
-
- if (!mDevice.get()) {
- result = " *** Device is detached\n";
- write(fd, result.string(), result.size());
- return NO_ERROR;
- }
-
- 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;
+ return dumpDevice(fd, args);
}
// IProCameraUser interface
-void ProCamera2Client::disconnect() {
- ATRACE_CALL();
- Mutex::Autolock icl(mIProCameraUserLock);
- status_t res;
-
- // Allow both client and the media server to disconnect at all times
- int callingPid = getCallingPid();
- if (callingPid != mClientPid && callingPid != mServicePid) return;
-
- ALOGV("Camera %d: Shutting down", mCameraId);
-
- detachDevice();
- ProClient::disconnect();
-
- ALOGV("Camera %d: Shut down complete complete", mCameraId);
-}
-
void ProCamera2Client::detachDevice() {
if (mDevice == 0) return;
@@ -438,117 +366,16 @@
}
}
- mDevice->disconnect();
-
- mDevice.clear();
-
- ALOGV("Camera %d: Detach complete", mCameraId);
-}
-
-status_t ProCamera2Client::connect(const sp<IProCameraCallbacks>& client) {
- ATRACE_CALL();
- ALOGV("%s: E", __FUNCTION__);
- Mutex::Autolock icl(mIProCameraUserLock);
-
- if (mClientPid != 0 && getCallingPid() != mClientPid) {
- ALOGE("%s: Camera %d: Connection attempt from pid %d; "
- "current locked to pid %d", __FUNCTION__,
- mCameraId, getCallingPid(), mClientPid);
- return BAD_VALUE;
- }
-
- mClientPid = getCallingPid();
-
- mRemoteCallback = client;
- mSharedCameraCallbacks = client;
-
- return OK;
+ Camera2ClientBase::detachDevice();
}
/** Device-related methods */
-
-void ProCamera2Client::notifyError(int errorCode, int arg1, int arg2) {
- ALOGE("Error condition %d reported by HAL, arguments %d, %d", errorCode,
- arg1, arg2);
-}
-
-void ProCamera2Client::notifyShutter(int frameNumber, nsecs_t timestamp) {
- ALOGV("%s: Shutter notification for frame %d at time %lld", __FUNCTION__,
- frameNumber, timestamp);
-}
-
-void ProCamera2Client::notifyAutoFocus(uint8_t newState, int triggerId) {
- ALOGV("%s: Autofocus state now %d, last trigger %d",
- __FUNCTION__, newState, triggerId);
-
- SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
- if (l.mRemoteCallback != 0) {
- l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS_MOVE,
- 1, 0);
- }
- if (l.mRemoteCallback != 0) {
- l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS,
- 1, 0);
- }
-}
-
-void ProCamera2Client::notifyAutoExposure(uint8_t newState, int triggerId) {
- ALOGV("%s: Autoexposure state now %d, last trigger %d",
- __FUNCTION__, newState, triggerId);
-}
-
-void ProCamera2Client::notifyAutoWhitebalance(uint8_t newState, int triggerId) {
- ALOGV("%s: Auto-whitebalance state now %d, last trigger %d",
- __FUNCTION__, newState, triggerId);
-}
-
-int ProCamera2Client::getCameraId() const {
- return mCameraId;
-}
-
-const sp<Camera2Device>& ProCamera2Client::getCameraDevice() {
- return mDevice;
-}
-
-const sp<CameraService>& ProCamera2Client::getCameraService() {
- return mCameraService;
-}
-
-ProCamera2Client::SharedCameraCallbacks::Lock::Lock(
- SharedCameraCallbacks &client):
- mRemoteCallback(client.mRemoteCallback),
- mSharedClient(client) {
- mSharedClient.mRemoteCallbackLock.lock();
-}
-
-ProCamera2Client::SharedCameraCallbacks::Lock::~Lock() {
- mSharedClient.mRemoteCallbackLock.unlock();
-}
-
-ProCamera2Client::SharedCameraCallbacks::SharedCameraCallbacks
- (const sp<IProCameraCallbacks>&client):
- mRemoteCallback(client) {
-}
-
-ProCamera2Client::SharedCameraCallbacks&
- ProCamera2Client::SharedCameraCallbacks::operator=(
- const sp<IProCameraCallbacks>&client) {
- Mutex::Autolock l(mRemoteCallbackLock);
- mRemoteCallback = client;
- return *this;
-}
-
-void ProCamera2Client::SharedCameraCallbacks::clear() {
- Mutex::Autolock l(mRemoteCallbackLock);
- mRemoteCallback.clear();
-}
-
void ProCamera2Client::onFrameAvailable(int32_t frameId,
const CameraMetadata& frame) {
ATRACE_CALL();
ALOGV("%s", __FUNCTION__);
- Mutex::Autolock icl(mIProCameraUserLock);
+ Mutex::Autolock icl(mBinderSerializationLock);
SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
if (mRemoteCallback != NULL) {
diff --git a/services/camera/libcameraservice/ProCamera2Client.h b/services/camera/libcameraservice/ProCamera2Client.h
index ff6f4e2..1dec263 100644
--- a/services/camera/libcameraservice/ProCamera2Client.h
+++ b/services/camera/libcameraservice/ProCamera2Client.h
@@ -20,6 +20,7 @@
#include "Camera2Device.h"
#include "CameraService.h"
#include "camera2/ProFrameProcessor.h"
+#include "Camera2ClientBase.h"
namespace android {
@@ -29,17 +30,13 @@
* meant for HAL2-level private API access.
*/
class ProCamera2Client :
- public CameraService::ProClient,
- public Camera2Device::NotificationListener,
+ public Camera2ClientBase<CameraService::ProClient>,
public camera2::ProFrameProcessor::FilteredListener
{
public:
/**
* IProCameraUser interface (see IProCameraUser for details)
*/
- virtual status_t connect(const sp<IProCameraCallbacks>& callbacks);
- virtual void disconnect();
-
virtual status_t exclusiveTryLock();
virtual status_t exclusiveLock();
virtual status_t exclusiveUnlock();
@@ -51,13 +48,15 @@
bool streaming = false);
virtual status_t cancelRequest(int requestId);
- virtual status_t requestStream(int streamId);
- virtual status_t cancelStream(int streamId);
+ virtual status_t deleteStream(int streamId);
- virtual status_t createStream(int width, int height, int format,
- const sp<IGraphicBufferProducer>& bufferProducer,
- /*out*/
- int* streamId);
+ virtual status_t createStream(
+ int width,
+ int height,
+ int format,
+ const sp<IGraphicBufferProducer>& bufferProducer,
+ /*out*/
+ int* streamId);
// Create a request object from a template.
// -- Caller owns the newly allocated metadata
@@ -85,24 +84,9 @@
int servicePid);
virtual ~ProCamera2Client();
- status_t initialize(camera_module_t *module);
+ virtual status_t initialize(camera_module_t *module);
- virtual status_t dump(int fd, const Vector<String16>& args);
-
- /**
- * Interface used by Camera2Device
- */
-
- virtual void notifyError(int errorCode, int arg1, int arg2);
- virtual void notifyShutter(int frameNumber, nsecs_t timestamp);
- virtual void notifyAutoFocus(uint8_t newState, int triggerId);
- virtual void notifyAutoExposure(uint8_t newState, int triggerId);
- virtual void notifyAutoWhitebalance(uint8_t newState, int triggerId);
-
-
- int getCameraId() const;
- const sp<Camera2Device>& getCameraDevice();
- const sp<CameraService>& getCameraService();
+ virtual status_t dump(int fd, const Vector<String16>& args);
// Callbacks from camera service
virtual void onExclusiveLockStolen();
@@ -111,67 +95,26 @@
* Interface used by independent components of ProCamera2Client.
*/
- // Simple class to ensure that access to IProCameraCallbacks is serialized
- // by requiring mRemoteCallbackLock to be locked before access to
- // mCameraClient is possible.
- class SharedCameraCallbacks {
- public:
- class Lock {
- public:
- Lock(SharedCameraCallbacks &client);
- ~Lock();
- sp<IProCameraCallbacks> &mRemoteCallback;
- private:
- SharedCameraCallbacks &mSharedClient;
- };
- SharedCameraCallbacks(const sp<IProCameraCallbacks>& client);
- SharedCameraCallbacks& operator=(const sp<IProCameraCallbacks>& client);
- void clear();
- private:
- sp<IProCameraCallbacks> mRemoteCallback;
- mutable Mutex mRemoteCallbackLock;
- } mSharedCameraCallbacks;
-
protected:
/** FilteredListener implementation **/
- virtual void onFrameAvailable(int32_t frameId, const CameraMetadata& frame);
+ virtual void onFrameAvailable(int32_t frameId,
+ const CameraMetadata& frame);
+ virtual void detachDevice();
private:
/** IProCameraUser interface-related private members */
- // Mutex that must be locked by methods implementing the IProCameraUser
- // interface. Ensures serialization between incoming IProCameraUser calls.
- // All methods below that append 'L' to the name assume that
- // mIProCameraUserLock is locked when they're called
- mutable Mutex mIProCameraUserLock;
-
- // Used with stream IDs
- static const int NO_STREAM = -1;
-
- /* Preview/Recording related members */
-
- sp<IBinder> mPreviewSurface;
-
/** Preview callback related members */
sp<camera2::ProFrameProcessor> mFrameProcessor;
static const int32_t FRAME_PROCESSOR_LISTENER_MIN_ID = 0;
static const int32_t FRAME_PROCESSOR_LISTENER_MAX_ID = 0x7fffffffL;
- /** Camera2Device instance wrapping HAL2 entry */
-
- sp<Camera2Device> mDevice;
-
/** Utility members */
- // Verify that caller is the owner of the camera
- status_t checkPid(const char *checkLocation) const;
-
// Whether or not we have an exclusive lock on the device
// - if no we can't modify the request queue.
// note that creating/deleting streams we own is still OK
bool mExclusiveLock;
-
- void detachDevice();
};
}; // namespace android
diff --git a/services/camera/libcameraservice/camera2/CallbackProcessor.cpp b/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
index 9a14758..30c14ef 100644
--- a/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
@@ -278,11 +278,12 @@
// Call outside parameter lock to allow re-entrancy from notification
{
- Camera2Client::SharedCameraClient::Lock l(client->mSharedCameraClient);
- if (l.mCameraClient != 0) {
+ Camera2Client::SharedCameraCallbacks::Lock
+ l(client->mSharedCameraCallbacks);
+ if (l.mRemoteCallback != 0) {
ALOGV("%s: Camera %d: Invoking client data callback",
__FUNCTION__, client->getCameraId());
- l.mCameraClient->dataCallback(CAMERA_MSG_PREVIEW_FRAME,
+ l.mRemoteCallback->dataCallback(CAMERA_MSG_PREVIEW_FRAME,
mCallbackHeap->mBuffers[heapIdx], NULL);
}
}
diff --git a/services/camera/libcameraservice/camera2/CaptureSequencer.cpp b/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
index 513a47e..1880912 100644
--- a/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
+++ b/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
@@ -271,10 +271,11 @@
}
if (mCaptureBuffer != 0 && res == OK) {
- Camera2Client::SharedCameraClient::Lock l(client->mSharedCameraClient);
+ Camera2Client::SharedCameraCallbacks::Lock
+ l(client->mSharedCameraCallbacks);
ALOGV("%s: Sending still image to client", __FUNCTION__);
- if (l.mCameraClient != 0) {
- l.mCameraClient->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE,
+ if (l.mRemoteCallback != 0) {
+ l.mRemoteCallback->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE,
mCaptureBuffer, NULL);
} else {
ALOGV("%s: No client!", __FUNCTION__);
@@ -344,7 +345,7 @@
}
SharedParameters::Lock l(client->getParameters());
- /* warning: this also locks a SharedCameraClient */
+ /* warning: this also locks a SharedCameraCallbacks */
shutterNotifyLocked(l.mParameters, client, mMsgType);
mShutterNotified = true;
mTimeoutCount = kMaxTimeoutsForCaptureEnd;
@@ -496,7 +497,7 @@
}
if (mNewFrameReceived && !mShutterNotified) {
SharedParameters::Lock l(client->getParameters());
- /* warning: this also locks a SharedCameraClient */
+ /* warning: this also locks a SharedCameraCallbacks */
shutterNotifyLocked(l.mParameters, client, mMsgType);
mShutterNotified = true;
}
@@ -651,16 +652,17 @@
}
{
- Camera2Client::SharedCameraClient::Lock l(client->mSharedCameraClient);
+ Camera2Client::SharedCameraCallbacks::Lock
+ l(client->mSharedCameraCallbacks);
ALOGV("%s: Notifying of shutter close to client", __FUNCTION__);
- if (l.mCameraClient != 0) {
+ if (l.mRemoteCallback != 0) {
// ShutterCallback
- l.mCameraClient->notifyCallback(CAMERA_MSG_SHUTTER,
+ l.mRemoteCallback->notifyCallback(CAMERA_MSG_SHUTTER,
/*ext1*/0, /*ext2*/0);
// RawCallback with null buffer
- l.mCameraClient->notifyCallback(CAMERA_MSG_RAW_IMAGE_NOTIFY,
+ l.mRemoteCallback->notifyCallback(CAMERA_MSG_RAW_IMAGE_NOTIFY,
/*ext1*/0, /*ext2*/0);
} else {
ALOGV("%s: No client!", __FUNCTION__);
diff --git a/services/camera/libcameraservice/camera2/FrameProcessor.cpp b/services/camera/libcameraservice/camera2/FrameProcessor.cpp
index 1f2659c..d13d398 100644
--- a/services/camera/libcameraservice/camera2/FrameProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/FrameProcessor.cpp
@@ -28,146 +28,37 @@
namespace android {
namespace camera2 {
-FrameProcessor::FrameProcessor(wp<Camera2Client> client):
- Thread(false), mClient(client), mLastFrameNumberOfFaces(0) {
+FrameProcessor::FrameProcessor(wp<CameraDeviceBase> device,
+ wp<Camera2Client> client) :
+ ProFrameProcessor(device),
+ mClient(client),
+ mLastFrameNumberOfFaces(0) {
}
FrameProcessor::~FrameProcessor() {
- ALOGV("%s: Exit", __FUNCTION__);
}
-status_t FrameProcessor::registerListener(int32_t minId,
- int32_t maxId, wp<FilteredListener> listener) {
- Mutex::Autolock l(mInputMutex);
- ALOGV("%s: Registering listener for frame id range %d - %d",
- __FUNCTION__, minId, maxId);
- RangeListener rListener = { minId, maxId, listener };
- mRangeListeners.push_back(rListener);
- return OK;
-}
+bool FrameProcessor::processSingleFrame(CameraMetadata &frame,
+ const sp<CameraDeviceBase> &device) {
-status_t FrameProcessor::removeListener(int32_t minId,
- int32_t maxId, wp<FilteredListener> listener) {
- Mutex::Autolock l(mInputMutex);
- List<RangeListener>::iterator item = mRangeListeners.begin();
- while (item != mRangeListeners.end()) {
- if (item->minId == minId &&
- item->maxId == maxId &&
- item->listener == listener) {
- item = mRangeListeners.erase(item);
- } else {
- item++;
- }
- }
- return OK;
-}
-
-void FrameProcessor::dump(int fd, const Vector<String16>& /*args*/) {
- String8 result(" Latest received frame:\n");
- write(fd, result.string(), result.size());
- mLastFrame.dump(fd, 2, 6);
-}
-
-bool FrameProcessor::threadLoop() {
- status_t res;
-
- sp<CameraDeviceBase> device;
- {
- sp<Camera2Client> client = mClient.promote();
- if (client == 0) return false;
- device = client->getCameraDevice();
- if (device == 0) return false;
+ sp<Camera2Client> client = mClient.promote();
+ if (!client.get()) {
+ return false;
}
- res = device->waitForNextFrame(kWaitDuration);
- if (res == OK) {
- sp<Camera2Client> client = mClient.promote();
- if (client == 0) return false;
- processNewFrames(client);
- } else if (res != TIMED_OUT) {
- ALOGE("Camera2Client::FrameProcessor: Error waiting for new "
- "frames: %s (%d)", strerror(-res), res);
+ if (processFaceDetect(frame, client) != OK) {
+ return false;
+ }
+
+ if (!ProFrameProcessor::processSingleFrame(frame, device)) {
+ return false;
}
return true;
}
-void FrameProcessor::processNewFrames(sp<Camera2Client> &client) {
- status_t res;
- ATRACE_CALL();
- CameraMetadata frame;
- while ( (res = client->getCameraDevice()->getNextFrame(&frame)) == OK) {
- camera_metadata_entry_t entry;
-
- entry = frame.find(ANDROID_REQUEST_FRAME_COUNT);
- if (entry.count == 0) {
- ALOGE("%s: Camera %d: Error reading frame number",
- __FUNCTION__, client->getCameraId());
- break;
- }
- ATRACE_INT("cam2_frame", entry.data.i32[0]);
-
- res = processFaceDetect(frame, client);
- if (res != OK) break;
-
- res = processListeners(frame, client);
- if (res != OK) break;
-
- if (!frame.isEmpty()) {
- mLastFrame.acquire(frame);
- }
- }
- if (res != NOT_ENOUGH_DATA) {
- ALOGE("%s: Camera %d: Error getting next frame: %s (%d)",
- __FUNCTION__, client->getCameraId(), strerror(-res), res);
- return;
- }
-
- return;
-}
-
-status_t FrameProcessor::processListeners(const CameraMetadata &frame,
- sp<Camera2Client> &client) {
- ATRACE_CALL();
- camera_metadata_ro_entry_t entry;
-
- entry = frame.find(ANDROID_REQUEST_ID);
- if (entry.count == 0) {
- ALOGE("%s: Camera %d: Error reading frame id",
- __FUNCTION__, client->getCameraId());
- return BAD_VALUE;
- }
- int32_t frameId = entry.data.i32[0];
-
- List<sp<FilteredListener> > listeners;
- {
- Mutex::Autolock l(mInputMutex);
-
- List<RangeListener>::iterator item = mRangeListeners.begin();
- while (item != mRangeListeners.end()) {
- if (frameId >= item->minId &&
- frameId < item->maxId) {
- sp<FilteredListener> listener = item->listener.promote();
- if (listener == 0) {
- item = mRangeListeners.erase(item);
- continue;
- } else {
- listeners.push_back(listener);
- }
- }
- item++;
- }
- }
- ALOGV("Got %d range listeners out of %d", listeners.size(), mRangeListeners.size());
- List<sp<FilteredListener> >::iterator item = listeners.begin();
- for (; item != listeners.end(); item++) {
- (*item)->onFrameAvailable(frameId, frame);
- }
- return OK;
-}
-
status_t FrameProcessor::processFaceDetect(const CameraMetadata &frame,
- sp<Camera2Client> &client) {
+ const sp<Camera2Client> &client) {
status_t res = BAD_VALUE;
ATRACE_CALL();
camera_metadata_ro_entry_t entry;
@@ -190,12 +81,14 @@
Vector<camera_face_t> faces;
metadata.number_of_faces = 0;
- if (enableFaceDetect && faceDetectMode != ANDROID_STATISTICS_FACE_DETECT_MODE_OFF) {
+ if (enableFaceDetect &&
+ faceDetectMode != ANDROID_STATISTICS_FACE_DETECT_MODE_OFF) {
+
SharedParameters::Lock l(client->getParameters());
entry = frame.find(ANDROID_STATISTICS_FACE_RECTANGLES);
if (entry.count == 0) {
// No faces this frame
- /* warning: locks SharedCameraClient */
+ /* warning: locks SharedCameraCallbacks */
callbackFaceDetection(client, metadata);
return OK;
}
@@ -263,17 +156,17 @@
if (faceDetectMode == ANDROID_STATISTICS_FACE_DETECT_MODE_FULL) {
face.id = faceIds[i];
face.left_eye[0] =
- l.mParameters.arrayXToNormalized(faceLandmarks[i*6 + 0]);
+ l.mParameters.arrayXToNormalized(faceLandmarks[i*6 + 0]);
face.left_eye[1] =
- l.mParameters.arrayYToNormalized(faceLandmarks[i*6 + 1]);
+ l.mParameters.arrayYToNormalized(faceLandmarks[i*6 + 1]);
face.right_eye[0] =
- l.mParameters.arrayXToNormalized(faceLandmarks[i*6 + 2]);
+ l.mParameters.arrayXToNormalized(faceLandmarks[i*6 + 2]);
face.right_eye[1] =
- l.mParameters.arrayYToNormalized(faceLandmarks[i*6 + 3]);
+ l.mParameters.arrayYToNormalized(faceLandmarks[i*6 + 3]);
face.mouth[0] =
- l.mParameters.arrayXToNormalized(faceLandmarks[i*6 + 4]);
+ l.mParameters.arrayXToNormalized(faceLandmarks[i*6 + 4]);
face.mouth[1] =
- l.mParameters.arrayYToNormalized(faceLandmarks[i*6 + 5]);
+ l.mParameters.arrayYToNormalized(faceLandmarks[i*6 + 5]);
} else {
face.id = 0;
face.left_eye[0] = face.left_eye[1] = -2000;
@@ -286,21 +179,31 @@
metadata.faces = faces.editArray();
}
- /* warning: locks SharedCameraClient */
+ /* warning: locks SharedCameraCallbacks */
callbackFaceDetection(client, metadata);
return OK;
}
void FrameProcessor::callbackFaceDetection(sp<Camera2Client> client,
- /*in*/camera_frame_metadata &metadata) {
+ const camera_frame_metadata &metadata) {
- /* Filter out repeated 0-face callbacks, but not when the last frame was >0 */
- if (metadata.number_of_faces != 0 || mLastFrameNumberOfFaces != metadata.number_of_faces) {
- Camera2Client::SharedCameraClient::Lock l(client->mSharedCameraClient);
- if (l.mCameraClient != NULL) {
- l.mCameraClient->dataCallback(CAMERA_MSG_PREVIEW_METADATA,
- NULL, &metadata);
+ camera_frame_metadata *metadata_ptr =
+ const_cast<camera_frame_metadata*>(&metadata);
+
+ /**
+ * Filter out repeated 0-face callbacks,
+ * but not when the last frame was >0
+ */
+ if (metadata.number_of_faces != 0 ||
+ mLastFrameNumberOfFaces != metadata.number_of_faces) {
+
+ Camera2Client::SharedCameraCallbacks::Lock
+ l(client->mSharedCameraCallbacks);
+ if (l.mRemoteCallback != NULL) {
+ l.mRemoteCallback->dataCallback(CAMERA_MSG_PREVIEW_METADATA,
+ NULL,
+ metadata_ptr);
}
}
diff --git a/services/camera/libcameraservice/camera2/FrameProcessor.h b/services/camera/libcameraservice/camera2/FrameProcessor.h
index 66e3cda..27ed8f6 100644
--- a/services/camera/libcameraservice/camera2/FrameProcessor.h
+++ b/services/camera/libcameraservice/camera2/FrameProcessor.h
@@ -22,7 +22,9 @@
#include <utils/Vector.h>
#include <utils/KeyedVector.h>
#include <utils/List.h>
-#include "camera/CameraMetadata.h"
+#include <camera/CameraMetadata.h>
+
+#include "ProFrameProcessor.h"
struct camera_frame_metadata;
@@ -35,51 +37,26 @@
/* Output frame metadata processing thread. This thread waits for new
* frames from the device, and analyzes them as necessary.
*/
-class FrameProcessor: public Thread {
+class FrameProcessor : public ProFrameProcessor {
public:
- FrameProcessor(wp<Camera2Client> client);
+ FrameProcessor(wp<CameraDeviceBase> device, wp<Camera2Client> client);
~FrameProcessor();
- struct FilteredListener: virtual public RefBase {
- virtual void onFrameAvailable(int32_t frameId,
- const CameraMetadata &frame) = 0;
- };
-
- // Register a listener for a range of IDs [minId, maxId). Multiple listeners
- // can be listening to the same range
- status_t registerListener(int32_t minId, int32_t maxId, wp<FilteredListener> listener);
- status_t removeListener(int32_t minId, int32_t maxId, wp<FilteredListener> listener);
-
- void dump(int fd, const Vector<String16>& args);
private:
- static const nsecs_t kWaitDuration = 10000000; // 10 ms
wp<Camera2Client> mClient;
+ int mLastFrameNumberOfFaces;
- virtual bool threadLoop();
+ void processNewFrames(const sp<Camera2Client> &client);
- Mutex mInputMutex;
-
- struct RangeListener {
- int32_t minId;
- int32_t maxId;
- wp<FilteredListener> listener;
- };
- List<RangeListener> mRangeListeners;
-
- void processNewFrames(sp<Camera2Client> &client);
+ virtual bool processSingleFrame(CameraMetadata &frame,
+ const sp<CameraDeviceBase> &device);
status_t processFaceDetect(const CameraMetadata &frame,
- sp<Camera2Client> &client);
-
- status_t processListeners(const CameraMetadata &frame,
- sp<Camera2Client> &client);
-
- CameraMetadata mLastFrame;
- int mLastFrameNumberOfFaces;
+ const sp<Camera2Client> &client);
// Emit FaceDetection event to java if faces changed
void callbackFaceDetection(sp<Camera2Client> client,
- camera_frame_metadata &metadata);
+ const camera_frame_metadata &metadata);
};
diff --git a/services/camera/libcameraservice/camera2/ProFrameProcessor.cpp b/services/camera/libcameraservice/camera2/ProFrameProcessor.cpp
index 8d4933c..257a45f 100644
--- a/services/camera/libcameraservice/camera2/ProFrameProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/ProFrameProcessor.cpp
@@ -22,14 +22,14 @@
#include <utils/Trace.h>
#include "ProFrameProcessor.h"
-#include "../Camera2Device.h"
-#include "../ProCamera2Client.h"
+#include "../CameraDeviceBase.h"
namespace android {
namespace camera2 {
-ProFrameProcessor::ProFrameProcessor(wp<ProCamera2Client> client):
- Thread(false), mClient(client) {
+ProFrameProcessor::ProFrameProcessor(wp<CameraDeviceBase> device) :
+ Thread(/*canCallJava*/false),
+ mDevice(device) {
}
ProFrameProcessor::~ProFrameProcessor() {
@@ -47,7 +47,8 @@
}
status_t ProFrameProcessor::removeListener(int32_t minId,
- int32_t maxId, wp<FilteredListener> listener) {
+ int32_t maxId,
+ wp<FilteredListener> listener) {
Mutex::Autolock l(mInputMutex);
List<RangeListener>::iterator item = mRangeListeners.begin();
while (item != mRangeListeners.end()) {
@@ -62,7 +63,7 @@
return OK;
}
-void ProFrameProcessor::dump(int fd, const Vector<String16>& args) {
+void ProFrameProcessor::dump(int fd, const Vector<String16>& /*args*/) {
String8 result(" Latest received frame:\n");
write(fd, result.string(), result.size());
mLastFrame.dump(fd, 2, 6);
@@ -71,44 +72,42 @@
bool ProFrameProcessor::threadLoop() {
status_t res;
- sp<Camera2Device> device;
+ sp<CameraDeviceBase> device;
{
- sp<ProCamera2Client> client = mClient.promote();
- if (client == 0) return false;
- device = client->getCameraDevice();
+ device = mDevice.promote();
if (device == 0) return false;
}
res = device->waitForNextFrame(kWaitDuration);
if (res == OK) {
- sp<ProCamera2Client> client = mClient.promote();
- if (client == 0) return false;
- processNewFrames(client);
+ processNewFrames(device);
} else if (res != TIMED_OUT) {
- ALOGE("ProCamera2Client::ProFrameProcessor: Error waiting for new "
+ ALOGE("ProFrameProcessor: Error waiting for new "
"frames: %s (%d)", strerror(-res), res);
}
return true;
}
-void ProFrameProcessor::processNewFrames(sp<ProCamera2Client> &client) {
+void ProFrameProcessor::processNewFrames(const sp<CameraDeviceBase> &device) {
status_t res;
ATRACE_CALL();
CameraMetadata frame;
- while ( (res = client->getCameraDevice()->getNextFrame(&frame)) == OK) {
+ while ( (res = device->getNextFrame(&frame)) == OK) {
+
camera_metadata_entry_t entry;
entry = frame.find(ANDROID_REQUEST_FRAME_COUNT);
if (entry.count == 0) {
ALOGE("%s: Camera %d: Error reading frame number",
- __FUNCTION__, client->getCameraId());
+ __FUNCTION__, device->getId());
break;
}
ATRACE_INT("cam2_frame", entry.data.i32[0]);
- res = processListeners(frame, client);
- if (res != OK) break;
+ if (!processSingleFrame(frame, device)) {
+ break;
+ }
if (!frame.isEmpty()) {
mLastFrame.acquire(frame);
@@ -116,23 +115,27 @@
}
if (res != NOT_ENOUGH_DATA) {
ALOGE("%s: Camera %d: Error getting next frame: %s (%d)",
- __FUNCTION__, client->getCameraId(), strerror(-res), res);
+ __FUNCTION__, device->getId(), strerror(-res), res);
return;
}
return;
}
+bool ProFrameProcessor::processSingleFrame(CameraMetadata &frame,
+ const sp<CameraDeviceBase> &device) {
+ return processListeners(frame, device) == OK;
+}
+
status_t ProFrameProcessor::processListeners(const CameraMetadata &frame,
- sp<ProCamera2Client> &client) {
- status_t res;
+ const sp<CameraDeviceBase> &device) {
ATRACE_CALL();
camera_metadata_ro_entry_t entry;
entry = frame.find(ANDROID_REQUEST_ID);
if (entry.count == 0) {
ALOGE("%s: Camera %d: Error reading frame id",
- __FUNCTION__, client->getCameraId());
+ __FUNCTION__, device->getId());
return BAD_VALUE;
}
int32_t frameId = entry.data.i32[0];
diff --git a/services/camera/libcameraservice/camera2/ProFrameProcessor.h b/services/camera/libcameraservice/camera2/ProFrameProcessor.h
index e4094a6..b82942c 100644
--- a/services/camera/libcameraservice/camera2/ProFrameProcessor.h
+++ b/services/camera/libcameraservice/camera2/ProFrameProcessor.h
@@ -24,11 +24,9 @@
#include <utils/List.h>
#include <camera/CameraMetadata.h>
-struct camera_frame_metadata;
-
namespace android {
-class ProCamera2Client;
+class CameraDeviceBase;
namespace camera2 {
@@ -37,23 +35,25 @@
*/
class ProFrameProcessor: public Thread {
public:
- ProFrameProcessor(wp<ProCamera2Client> client);
- ~ProFrameProcessor();
+ ProFrameProcessor(wp<CameraDeviceBase> device);
+ virtual ~ProFrameProcessor();
struct FilteredListener: virtual public RefBase {
virtual void onFrameAvailable(int32_t frameId,
- const CameraMetadata &frame) = 0;
+ const CameraMetadata &frame) = 0;
};
// Register a listener for a range of IDs [minId, maxId). Multiple listeners
// can be listening to the same range
- status_t registerListener(int32_t minId, int32_t maxId, wp<FilteredListener> listener);
- status_t removeListener(int32_t minId, int32_t maxId, wp<FilteredListener> listener);
+ status_t registerListener(int32_t minId, int32_t maxId,
+ wp<FilteredListener> listener);
+ status_t removeListener(int32_t minId, int32_t maxId,
+ wp<FilteredListener> listener);
void dump(int fd, const Vector<String16>& args);
- private:
+ protected:
static const nsecs_t kWaitDuration = 10000000; // 10 ms
- wp<ProCamera2Client> mClient;
+ wp<CameraDeviceBase> mDevice;
virtual bool threadLoop();
@@ -66,10 +66,13 @@
};
List<RangeListener> mRangeListeners;
- void processNewFrames(sp<ProCamera2Client> &client);
+ void processNewFrames(const sp<CameraDeviceBase> &device);
+
+ virtual bool processSingleFrame(CameraMetadata &frame,
+ const sp<CameraDeviceBase> &device);
status_t processListeners(const CameraMetadata &frame,
- sp<ProCamera2Client> &client);
+ const sp<CameraDeviceBase> &device);
CameraMetadata mLastFrame;
};
diff --git a/services/camera/libcameraservice/camera2/StreamingProcessor.cpp b/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
index 6a4b95d..fbc5b93 100644
--- a/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
@@ -556,9 +556,9 @@
}
// Call outside locked parameters to allow re-entrancy from notification
- Camera2Client::SharedCameraClient::Lock l(client->mSharedCameraClient);
- if (l.mCameraClient != 0) {
- l.mCameraClient->dataCallbackTimestamp(timestamp,
+ Camera2Client::SharedCameraCallbacks::Lock l(client->mSharedCameraCallbacks);
+ if (l.mRemoteCallback != 0) {
+ l.mRemoteCallback->dataCallbackTimestamp(timestamp,
CAMERA_MSG_VIDEO_FRAME,
recordingHeap->mBuffers[heapIdx]);
}