From c073ba525404f3416c2824c435d3d926a9892f1b 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/CameraBase.cpp | 237 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100644 camera/CameraBase.cpp (limited to 'camera/CameraBase.cpp') 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 -- cgit v1.1