summaryrefslogtreecommitdiffstats
path: root/camera/libcameraservice
diff options
context:
space:
mode:
authorAndroid (Google) Code Review <android-gerrit@google.com>2009-06-24 13:53:24 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2009-06-24 13:53:24 -0700
commit5310745b14f2f03e70af2e9592a73cee7d3f8324 (patch)
tree492740c3de101be0c76cee1f2eab8b75fe40c46a /camera/libcameraservice
parent2ac3412001f7dceb0d3a7641359e3718179b2613 (diff)
parent82a32714f07d25259b91163d383ccdb74a166d2d (diff)
downloadframeworks_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.cpp51
-rw-r--r--camera/libcameraservice/CameraService.h5
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;