summaryrefslogtreecommitdiffstats
path: root/camera
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-01-20 14:03:58 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-01-20 14:03:58 -0800
commit22f7dfd23490a3de2f21ff96949ba47003aac8f8 (patch)
tree41bc290bb2f1f08a0e37cfda4955742a85d42ecf /camera
parent9266c558bf1d21ff647525ff99f7dadbca417309 (diff)
downloadframeworks_base-22f7dfd23490a3de2f21ff96949ba47003aac8f8.zip
frameworks_base-22f7dfd23490a3de2f21ff96949ba47003aac8f8.tar.gz
frameworks_base-22f7dfd23490a3de2f21ff96949ba47003aac8f8.tar.bz2
auto import from //branches/cupcake/...@127101
Diffstat (limited to 'camera')
-rw-r--r--camera/libcameraservice/CameraService.cpp56
1 files changed, 42 insertions, 14 deletions
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index 33987c3..36c5ada 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -166,22 +166,26 @@ CameraService::Client::Client(const sp<CameraService>& cameraService,
status_t CameraService::Client::checkPid()
{
- // zero means the interface is not locked down
- if (mClientPid == 0) return NO_ERROR;
- return (int) mClientPid == IPCThreadState::self()->getCallingPid() ? NO_ERROR : -EBUSY;
+ if (mClientPid == IPCThreadState::self()->getCallingPid()) return NO_ERROR;
+ LOGW("Attempt to use locked camera from different process");
+ return -EBUSY;
}
status_t CameraService::Client::lock()
{
- // lock camera to this client
- status_t result = checkPid();
- if (result == NO_ERROR) mClientPid = IPCThreadState::self()->getCallingPid();
- return result;
+ // lock camera to this client if the the camera is unlocked
+ if (mClientPid == 0) {
+ mClientPid = IPCThreadState::self()->getCallingPid();
+ return NO_ERROR;
+ }
+ // returns NO_ERROR if the client already owns the camera, -EBUSY otherwise
+ return checkPid();
}
status_t CameraService::Client::unlock()
{
// allow anyone to use camera
+ LOGV("unlock");
status_t result = checkPid();
if (result == NO_ERROR) mClientPid = 0;
return result;
@@ -189,12 +193,29 @@ status_t CameraService::Client::unlock()
status_t CameraService::Client::connect(const sp<ICameraClient>& client)
{
- // remove old client
- LOGV("connect new client to existing camera");
- Mutex::Autolock _l(mLock);
- mCameraClient = client;
- mClientPid = IPCThreadState::self()->getCallingPid();
- mFrameCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
+ // connect a new process to the camera
+ LOGV("connect");
+
+ // hold a reference to the old client or we will deadlock if the client is
+ // in the same process and we hold the lock when we remove the reference
+ sp<ICameraClient> oldClient;
+ {
+ Mutex::Autolock _l(mLock);
+ if (mClientPid != 0) {
+ LOGW("Tried to connect to locked camera");
+ return -EBUSY;
+ }
+ oldClient = mCameraClient;
+
+ // did the client actually change?
+ if (client->asBinder() == mCameraClient->asBinder()) return NO_ERROR;
+
+ LOGV("connect new process to existing camera client");
+ mCameraClient = client;
+ mClientPid = IPCThreadState::self()->getCallingPid();
+ mFrameCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
+ }
+
return NO_ERROR;
}
@@ -210,7 +231,7 @@ static void *unregister_surface(void *arg)
CameraService::Client::~Client()
{
- // spin down hardware
+ // tear down client
LOGD("Client E destructor");
if (mSurface != 0) {
#if HAVE_ANDROID_OS
@@ -227,6 +248,8 @@ CameraService::Client::~Client()
#endif
}
+ // make sure we tear down the hardware
+ mClientPid = IPCThreadState::self()->getCallingPid();
disconnect();
LOGD("Client X destructor");
}
@@ -235,7 +258,12 @@ void CameraService::Client::disconnect()
{
LOGD("Client E disconnect");
Mutex::Autolock lock(mLock);
+ if (mClientPid == 0) {
+ LOGV("camera is unlocked, don't tear down hardware");
+ return;
+ }
if (checkPid() != NO_ERROR) return;
+
mCameraService->removeClient(mCameraClient);
if (mHardware != 0) {
// Before destroying mHardware, we must make sure it's in the