diff options
author | Android (Google) Code Review <android-gerrit@google.com> | 2009-06-24 13:53:24 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-06-24 13:53:24 -0700 |
commit | 5310745b14f2f03e70af2e9592a73cee7d3f8324 (patch) | |
tree | 492740c3de101be0c76cee1f2eab8b75fe40c46a /camera/libcameraservice | |
parent | 2ac3412001f7dceb0d3a7641359e3718179b2613 (diff) | |
parent | 82a32714f07d25259b91163d383ccdb74a166d2d (diff) | |
download | frameworks_base-5310745b14f2f03e70af2e9592a73cee7d3f8324.zip frameworks_base-5310745b14f2f03e70af2e9592a73cee7d3f8324.tar.gz frameworks_base-5310745b14f2f03e70af2e9592a73cee7d3f8324.tar.bz2 |
am 82a32714: Merge change 5190 into donut
Merge commit '82a32714f07d25259b91163d383ccdb74a166d2d'
* commit '82a32714f07d25259b91163d383ccdb74a166d2d':
Fix 1933269: startPreview failed.
Diffstat (limited to 'camera/libcameraservice')
-rw-r--r-- | camera/libcameraservice/CameraService.cpp | 51 | ||||
-rw-r--r-- | camera/libcameraservice/CameraService.h | 5 |
2 files changed, 44 insertions, 12 deletions
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp index 980ce78..2f4a1c9 100644 --- a/camera/libcameraservice/CameraService.cpp +++ b/camera/libcameraservice/CameraService.cpp @@ -32,6 +32,7 @@ #include <media/AudioSystem.h> #include "CameraService.h" +#include <cutils/atomic.h> #include <cutils/properties.h> namespace android { @@ -81,6 +82,7 @@ CameraService::CameraService() : BnCameraService() { LOGI("CameraService started: pid=%d", getpid()); + mUsers = 0; } CameraService::~CameraService() @@ -113,7 +115,7 @@ sp<ICamera> CameraService::connect(const sp<ICameraClient>& cameraClient) "(old pid %d, old client %p)", callingPid, cameraClient->asBinder().get(), currentClient->mClientPid, currentCameraClient->asBinder().get()); - if (kill(currentClient->mClientPid, 0) == ESRCH) { + if (kill(currentClient->mClientPid, 0) == -1 && errno == ESRCH) { LOGD("The old client is dead!"); } return client; @@ -123,6 +125,10 @@ sp<ICamera> CameraService::connect(const sp<ICameraClient>& cameraClient) LOGD("New client (pid %d) connecting, old reference was dangling...", callingPid); mClient.clear(); + if (mUsers > 0) { + LOGD("Still have client, rejected"); + return client; + } } } @@ -174,6 +180,20 @@ void CameraService::removeClient(const sp<ICameraClient>& cameraClient) LOGD("removeClient (pid %d) done", callingPid); } +// The reason we need this count is a new CameraService::connect() request may +// come in while the previous Client's destructor has not been run or is still +// running. If the last strong reference of the previous Client is gone but +// destructor has not been run, we should not allow the new Client to be created +// because we need to wait for the previous Client to tear down the hardware +// first. +void CameraService::incUsers() { + android_atomic_inc(&mUsers); +} + +void CameraService::decUsers() { + android_atomic_dec(&mUsers); +} + static sp<MediaPlayer> newMediaPlayer(const char *file) { sp<MediaPlayer> mp = new MediaPlayer(); @@ -209,6 +229,7 @@ CameraService::Client::Client(const sp<CameraService>& cameraService, // Callback is disabled by default mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP; + cameraService->incUsers(); LOGD("Client::Client X (pid %d)", callingPid); } @@ -350,7 +371,7 @@ CameraService::Client::~Client() void CameraService::Client::disconnect() { - int callingPid = getCallingPid(); + int callingPid = getCallingPid(); LOGD("Client::disconnect() E (pid %d client %p)", callingPid, getCameraClient()->asBinder().get()); @@ -365,18 +386,24 @@ void CameraService::Client::disconnect() return; } + // Make sure disconnect() is done once and once only, whether it is called + // from the user directly, or called by the destructor. + if (mHardware == 0) return; + mCameraService->removeClient(mCameraClient); - if (mHardware != 0) { - LOGD("hardware teardown"); - // Before destroying mHardware, we must make sure it's in the - // idle state. - mHardware->stopPreview(); - // Cancel all picture callbacks. - mHardware->cancelPicture(true, true, true); - // Release the hardware resources. - mHardware->release(); - } + + LOGD("hardware teardown"); + // Before destroying mHardware, we must make sure it's in the + // idle state. + mHardware->stopPreview(); + // Cancel all picture callbacks. + mHardware->cancelPicture(true, true, true); + // Release the hardware resources. + mHardware->release(); mHardware.clear(); + + mCameraService->decUsers(); + LOGD("Client::disconnect() X (pid %d)", callingPid); } diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h index a421fd3..729e539 100644 --- a/camera/libcameraservice/CameraService.h +++ b/camera/libcameraservice/CameraService.h @@ -194,6 +194,11 @@ private: CameraService(); virtual ~CameraService(); + // We use a count for number of clients (shoule only be 0 or 1). + volatile int32_t mUsers; + virtual void incUsers(); + virtual void decUsers(); + mutable Mutex mLock; wp<Client> mClient; |