From b84d935c179a275a47e07291d2a983daf844de80 Mon Sep 17 00:00:00 2001 From: Igor Murashkin Date: Tue, 26 Feb 2013 14:32:34 -0800 Subject: camera_client: refactor Camera/ProCamera commonalities into BasicCamera Change-Id: Ie10a4094522d49683657665fe94ab0b7ccd280e9 --- camera/Android.mk | 1 + camera/Camera.cpp | 126 ++---------------------- camera/CameraBase.cpp | 237 ++++++++++++++++++++++++++++++++++++++++++++++ camera/ICameraService.cpp | 15 ++- camera/ProCamera.cpp | 153 +++++------------------------- 5 files changed, 283 insertions(+), 249 deletions(-) create mode 100644 camera/CameraBase.cpp (limited to 'camera') diff --git a/camera/Android.mk b/camera/Android.mk index 3e7e5a5..3f30079 100644 --- a/camera/Android.mk +++ b/camera/Android.mk @@ -16,6 +16,7 @@ LOCAL_SRC_FILES:= \ IProCameraUser.cpp \ IProCameraCallbacks.cpp \ ProCamera.cpp \ + CameraBase.cpp \ LOCAL_SHARED_LIBRARIES := \ libcutils \ diff --git a/camera/Camera.cpp b/camera/Camera.cpp index d8dc2a5..f417c90 100644 --- a/camera/Camera.cpp +++ b/camera/Camera.cpp @@ -27,46 +27,16 @@ #include #include #include +#include #include #include namespace android { -// client singleton for camera service binder interface -Mutex Camera::mLock; -sp Camera::mCameraService; -sp Camera::mDeathNotifier; - -// establish binder interface to camera service -const sp& Camera::getCameraService() +Camera::Camera(int cameraId) + : CameraBase(cameraId) { - Mutex::Autolock _l(mLock); - if (mCameraService.get() == 0) { - sp sm = defaultServiceManager(); - sp binder; - do { - binder = sm->getService(String16("media.camera")); - if (binder != 0) - break; - ALOGW("CameraService not published, waiting..."); - usleep(500000); // 0.5 s - } while(true); - if (mDeathNotifier == NULL) { - mDeathNotifier = new DeathNotifier(); - } - binder->linkToDeath(mDeathNotifier); - mCameraService = interface_cast(binder); - } - ALOGE_IF(mCameraService==0, "no CameraService!?"); - return mCameraService; -} - -// --------------------------------------------------------------------------- - -Camera::Camera() -{ - init(); } // construct a camera client from an existing camera remote @@ -78,7 +48,7 @@ sp Camera::create(const sp& camera) return 0; } - sp c = new Camera(); + sp c = new Camera(-1); if (camera->connect(c) == NO_ERROR) { c->mStatus = NO_ERROR; c->mCamera = camera; @@ -88,11 +58,6 @@ sp Camera::create(const sp& camera) return 0; } -void Camera::init() -{ - mStatus = UNKNOWN_ERROR; -} - Camera::~Camera() { // We don't need to call disconnect() here because if the CameraService @@ -103,47 +68,10 @@ Camera::~Camera() // deadlock if we call any method of ICamera here. } -int32_t Camera::getNumberOfCameras() -{ - const sp& cs = getCameraService(); - if (cs == 0) return 0; - return cs->getNumberOfCameras(); -} - -status_t Camera::getCameraInfo(int cameraId, - struct CameraInfo* cameraInfo) { - const sp& cs = getCameraService(); - if (cs == 0) return UNKNOWN_ERROR; - return cs->getCameraInfo(cameraId, cameraInfo); -} - sp Camera::connect(int cameraId, const String16& clientPackageName, int clientUid) { - ALOGV("connect"); - sp c = new Camera(); - sp cl = c; - const sp& cs = getCameraService(); - if (cs != 0) { - c->mCamera = cs->connect(cl, cameraId, clientPackageName, clientUid); - } - if (c->mCamera != 0) { - c->mCamera->asBinder()->linkToDeath(c); - c->mStatus = NO_ERROR; - } else { - c.clear(); - } - return c; -} - -void Camera::disconnect() -{ - ALOGV("disconnect"); - if (mCamera != 0) { - mCamera->disconnect(); - mCamera->asBinder()->unlinkToDeath(this); - mCamera = 0; - } + return CameraBaseT::connect(cameraId, clientPackageName, clientUid); } status_t Camera::reconnect() @@ -154,11 +82,6 @@ status_t Camera::reconnect() return c->connect(this); } -sp Camera::remote() -{ - return mCamera; -} - status_t Camera::lock() { sp c = mCamera; @@ -353,28 +276,14 @@ void Camera::setPreviewCallbackFlags(int flag) // callback from camera service void Camera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) { - sp listener; - { - Mutex::Autolock _l(mLock); - listener = mListener; - } - if (listener != NULL) { - listener->notify(msgType, ext1, ext2); - } + return CameraBaseT::notifyCallback(msgType, ext1, ext2); } // callback from camera service when frame or image is ready void Camera::dataCallback(int32_t msgType, const sp& dataPtr, camera_frame_metadata_t *metadata) { - sp listener; - { - Mutex::Autolock _l(mLock); - listener = mListener; - } - if (listener != NULL) { - listener->postData(msgType, dataPtr, metadata); - } + return CameraBaseT::dataCallback(msgType, dataPtr, metadata); } // callback from camera service when timestamped frame is ready @@ -393,31 +302,12 @@ void Camera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp< return; } - sp listener; - { - Mutex::Autolock _l(mLock); - listener = mListener; - } - if (listener != NULL) { - listener->postDataTimestamp(timestamp, msgType, dataPtr); - } else { + if (!CameraBaseT::dataCallbackTimestamp(timestamp, msgType, dataPtr)) { ALOGW("No listener was set. Drop a recording frame."); releaseRecordingFrame(dataPtr); } } -void Camera::binderDied(const wp& who) { - ALOGW("ICamera died"); - notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_SERVER_DIED, 0); -} - -void Camera::DeathNotifier::binderDied(const wp& who) { - ALOGV("binderDied"); - Mutex::Autolock _l(Camera::mLock); - Camera::mCameraService.clear(); - ALOGW("Camera server died!"); -} - sp Camera::getRecordingProxy() { ALOGV("getProxy"); return new RecordingProxy(this); diff --git a/camera/CameraBase.cpp b/camera/CameraBase.cpp new file mode 100644 index 0000000..9b0e6bf --- /dev/null +++ b/camera/CameraBase.cpp @@ -0,0 +1,237 @@ +/* +** +** 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_NDEBUG 0 +#define LOG_TAG "CameraBase" +#include +#include +#include + +#include +#include +#include + +#include +#include + +// needed to instantiate +#include +#include + +#include + +namespace android { + +namespace { + sp gCameraService; + const int kCameraServicePollDelay = 500000; // 0.5s + const char* kCameraServiceName = "media.camera"; + + Mutex gLock; + + class DeathNotifier : public IBinder::DeathRecipient + { + public: + DeathNotifier() { + } + + virtual void binderDied(const wp& who) { + ALOGV("binderDied"); + Mutex::Autolock _l(gLock); + gCameraService.clear(); + ALOGW("Camera service died!"); + } + }; + + sp gDeathNotifier; +}; // namespace anonymous + +/////////////////////////////////////////////////////////// +// CameraBase definition +/////////////////////////////////////////////////////////// + +// establish binder interface to camera service +template +const sp& CameraBase::getCameraService() +{ + Mutex::Autolock _l(gLock); + if (gCameraService.get() == 0) { + sp sm = defaultServiceManager(); + sp binder; + do { + binder = sm->getService(String16(kCameraServiceName)); + if (binder != 0) { + break; + } + ALOGW("CameraService not published, waiting..."); + usleep(kCameraServicePollDelay); + } while(true); + if (gDeathNotifier == NULL) { + gDeathNotifier = new DeathNotifier(); + } + binder->linkToDeath(gDeathNotifier); + gCameraService = interface_cast(binder); + } + ALOGE_IF(gCameraService == 0, "no CameraService!?"); + return gCameraService; +} + +template +sp CameraBase::connect(int cameraId, + const String16& clientPackageName, + int clientUid) +{ + ALOGV("%s: connect", __FUNCTION__); + sp c = new TCam(cameraId); + sp cl = c; + const sp& cs = getCameraService(); + if (cs != 0) { + c->mCamera = cs->connect(cl, cameraId, clientPackageName, clientUid); + } + if (c->mCamera != 0) { + c->mCamera->asBinder()->linkToDeath(c); + c->mStatus = NO_ERROR; + } else { + c.clear(); + } + return c; +} + +template +void CameraBase::disconnect() +{ + ALOGV("%s: disconnect", __FUNCTION__); + if (mCamera != 0) { + mCamera->disconnect(); + mCamera->asBinder()->unlinkToDeath(this); + mCamera = 0; + } + ALOGV("%s: disconnect (done)", __FUNCTION__); +} + +template +CameraBase::CameraBase(int cameraId) : + mStatus(UNKNOWN_ERROR), + mCameraId(cameraId) +{ +} + +template +CameraBase::~CameraBase() +{ +} + +template +sp CameraBase::remote() +{ + return mCamera; +} + +template +status_t CameraBase::getStatus() +{ + return mStatus; +} + +template +void CameraBase::binderDied(const wp& who) { + ALOGW("mediaserver's remote binder Camera object died"); + notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_SERVER_DIED, /*ext2*/0); +} + +template +void CameraBase::setListener(const sp& listener) +{ + Mutex::Autolock _l(mLock); + mListener = listener; +} + +// callback from camera service +template +void CameraBase::notifyCallback(int32_t msgType, + int32_t ext1, + int32_t ext2) +{ + sp listener; + { + Mutex::Autolock _l(mLock); + listener = mListener; + } + if (listener != NULL) { + listener->notify(msgType, ext1, ext2); + } +} + +// callback from camera service when frame or image is ready +template +void CameraBase::dataCallback(int32_t msgType, + const sp& dataPtr, + camera_frame_metadata *metadata) +{ + sp 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 +bool CameraBase::dataCallbackTimestamp(nsecs_t timestamp, + int32_t msgType, + const sp& dataPtr) +{ + sp listener; + { + Mutex::Autolock _l(mLock); + listener = mListener; + } + if (listener != NULL) { + listener->postDataTimestamp(timestamp, msgType, dataPtr); + return true; + } + + return false; +} + +template +int CameraBase::getNumberOfCameras() { + const sp cs = getCameraService(); + + if (!cs.get()) { + // as required by the public Java APIs + return 0; + } + return cs->getNumberOfCameras(); +} + +// this can be in BaseCamera but it should be an instance method +template +status_t CameraBase::getCameraInfo(int cameraId, + struct CameraInfo* cameraInfo) { + const sp& cs = getCameraService(); + if (cs == 0) return UNKNOWN_ERROR; + return cs->getCameraInfo(cameraId, cameraInfo); +} + +template class CameraBase; +template class CameraBase; + +} // namespace android diff --git a/camera/ICameraService.cpp b/camera/ICameraService.cpp index fdf20ff..b54d63f 100644 --- a/camera/ICameraService.cpp +++ b/camera/ICameraService.cpp @@ -23,6 +23,10 @@ #include #include +#include +#include +#include +#include namespace android { @@ -70,12 +74,15 @@ public: } // connect to camera service (pro client) - virtual sp connect(const sp& cameraCb, int cameraId) + virtual sp connect(const sp& cameraCb, int cameraId, + const String16 &clientPackageName, int clientUid) { Parcel data, reply; data.writeInterfaceToken(ICameraService::getInterfaceDescriptor()); data.writeStrongBinder(cameraCb->asBinder()); data.writeInt32(cameraId); + data.writeString16(clientPackageName); + data.writeInt32(clientUid); remote()->transact(BnCameraService::CONNECT_PRO, data, &reply); return interface_cast(reply.readStrongBinder()); } @@ -119,7 +126,11 @@ status_t BnCameraService::onTransact( case CONNECT_PRO: { CHECK_INTERFACE(ICameraService, data, reply); sp cameraClient = interface_cast(data.readStrongBinder()); - sp camera = connect(cameraClient, data.readInt32()); + int32_t cameraId = data.readInt32(); + const String16 clientName = data.readString16(); + int32_t clientUid = data.readInt32(); + sp camera = connect(cameraClient, cameraId, + clientName, clientUid); reply->writeStrongBinder(camera->asBinder()); return NO_ERROR; } break; diff --git a/camera/ProCamera.cpp b/camera/ProCamera.cpp index 7c66d62..13ba07c 100644 --- a/camera/ProCamera.cpp +++ b/camera/ProCamera.cpp @@ -31,71 +31,19 @@ #include #include -#include #include namespace android { -// client singleton for camera service binder interface -Mutex ProCamera::mLock; -sp ProCamera::mCameraService; -sp ProCamera::mDeathNotifier; - -// establish binder interface to camera service -const sp& ProCamera::getCameraService() -{ - Mutex::Autolock _l(mLock); - if (mCameraService.get() == 0) { - sp sm = defaultServiceManager(); - sp binder; - do { - binder = sm->getService(String16("media.camera")); - if (binder != 0) - break; - ALOGW("CameraService not published, waiting..."); - usleep(500000); // 0.5 s - } while(true); - if (mDeathNotifier == NULL) { - mDeathNotifier = new DeathNotifier(); - } - binder->linkToDeath(mDeathNotifier); - mCameraService = interface_cast(binder); - } - ALOGE_IF(mCameraService==0, "no CameraService!?"); - return mCameraService; -} - sp ProCamera::connect(int cameraId) { - ALOGV("connect"); - sp c = new ProCamera(); - sp cl = c; - const sp& cs = getCameraService(); - if (cs != 0) { - c->mCamera = cs->connect(cl, cameraId); - } - if (c->mCamera != 0) { - c->mCamera->asBinder()->linkToDeath(c); - c->mStatus = NO_ERROR; - } else { - c.clear(); - } - return c; -} - -void ProCamera::disconnect() -{ - ALOGV("%s: disconnect", __FUNCTION__); - if (mCamera != 0) { - mCamera->disconnect(); - mCamera->asBinder()->unlinkToDeath(this); - mCamera = 0; - } - ALOGV("%s: disconnect (done)", __FUNCTION__); + return CameraBaseT::connect(cameraId, String16(), + ICameraService::USE_CALLING_UID); } -ProCamera::ProCamera() +ProCamera::ProCamera(int cameraId) + : CameraBase(cameraId) { } @@ -104,74 +52,28 @@ ProCamera::~ProCamera() } -sp ProCamera::remote() -{ - return mCamera; -} - -void ProCamera::binderDied(const wp& who) { - ALOGW("IProCameraUser died"); - notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_SERVER_DIED, 0); -} - -void ProCamera::DeathNotifier::binderDied(const wp& who) { - ALOGV("binderDied"); - Mutex::Autolock _l(ProCamera::mLock); - ProCamera::mCameraService.clear(); - ALOGW("Camera service died!"); -} - -void ProCamera::setListener(const sp& listener) -{ - Mutex::Autolock _l(mLock); - mListener = listener; -} - +/* IProCameraUser's implementation */ // callback from camera service void ProCamera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) { - sp listener; - { - Mutex::Autolock _l(mLock); - listener = mListener; - } - if (listener != NULL) { - listener->notify(msgType, ext1, ext2); - } + return CameraBaseT::notifyCallback(msgType, ext1, ext2); } // callback from camera service when frame or image is ready void ProCamera::dataCallback(int32_t msgType, const sp& dataPtr, camera_frame_metadata_t *metadata) { - sp listener; - { - Mutex::Autolock _l(mLock); - listener = mListener; - } - if (listener != NULL) { - listener->postData(msgType, dataPtr, 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& dataPtr) + const sp& dataPtr) { - sp 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."); - } + CameraBaseT::dataCallbackTimestamp(timestamp, msgType, dataPtr); } -/* IProCameraUser's implementation */ void ProCamera::onLockStatusChanged( IProCameraCallbacks::LockStatus newLockStatus) @@ -291,9 +193,9 @@ status_t ProCamera::deleteStream(int streamId) } status_t ProCamera::createStream(int width, int height, int format, - const sp& surface, - /*out*/ - int* streamId) + const sp& surface, + /*out*/ + int* streamId) { *streamId = -1; @@ -304,14 +206,15 @@ status_t ProCamera::createStream(int width, int height, int format, return BAD_VALUE; } - return createStream(width, height, format, surface->getIGraphicBufferProducer(), + return createStream(width, height, format, + surface->getIGraphicBufferProducer(), streamId); } status_t ProCamera::createStream(int width, int height, int format, - const sp& bufferProducer, - /*out*/ - int* streamId) { + const sp& bufferProducer, + /*out*/ + int* streamId) { *streamId = -1; ALOGV("%s: createStreamT %dx%d (fmt=0x%x)", __FUNCTION__, width, height, @@ -335,10 +238,10 @@ status_t ProCamera::createStream(int width, int height, int format, } status_t ProCamera::createStreamCpu(int width, int height, int format, - int heapCount, - /*out*/ - sp* cpuConsumer, - int* streamId) + int heapCount, + /*out*/ + sp* cpuConsumer, + int* streamId) { ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height, format); @@ -354,8 +257,9 @@ status_t ProCamera::createStreamCpu(int width, int height, int format, sp stc = new Surface( cc->getProducerInterface()); - status_t s = createStream(width, height, format, stc->getIGraphicBufferProducer(), - streamId); + status_t s = createStream(width, height, format, + stc->getIGraphicBufferProducer(), + streamId); if (s != OK) { ALOGE("%s: Failure to create stream %dx%d (fmt=0x%x)", __FUNCTION__, @@ -379,15 +283,6 @@ status_t ProCamera::createStreamCpu(int width, int height, int format, return s; } -int ProCamera::getNumberOfCameras() { - const sp cs = getCameraService(); - - if (!cs.get()) { - return DEAD_OBJECT; - } - return cs->getNumberOfCameras(); -} - camera_metadata* ProCamera::getCameraInfo(int cameraId) { ALOGV("%s: cameraId = %d", __FUNCTION__, cameraId); -- cgit v1.1