Camera: Drop ProCamera connections when a Camera connection happens
* Also adds an ICameraServiceListener with available/not available statuses
Bug: 8291653
Change-Id: I24680f1a2dc109510caf451cf7c7bd180b670d84
diff --git a/services/camera/libcameraservice/ProCamera2Client.cpp b/services/camera/libcameraservice/ProCamera2Client.cpp
index eda3012..6fed8b4 100644
--- a/services/camera/libcameraservice/ProCamera2Client.cpp
+++ b/services/camera/libcameraservice/ProCamera2Client.cpp
@@ -115,6 +115,8 @@
Mutex::Autolock icl(mIProCameraUserLock);
SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
+ if (!mDevice.get()) return PERMISSION_DENIED;
+
if (!mExclusiveLock) {
mExclusiveLock = true;
@@ -144,6 +146,8 @@
Mutex::Autolock icl(mIProCameraUserLock);
SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
+ if (!mDevice.get()) return PERMISSION_DENIED;
+
/**
* TODO: this should asynchronously 'wait' until the lock becomes available
* if another client already has an exclusive lock.
@@ -197,12 +201,33 @@
return mExclusiveLock;
}
+void ProCamera2Client::onExclusiveLockStolen() {
+ ALOGV("%s: ProClient lost exclusivity (id %d)",
+ __FUNCTION__, mCameraId);
+
+ Mutex::Autolock icl(mIProCameraUserLock);
+ SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
+
+ if (mExclusiveLock && mRemoteCallback.get() != NULL) {
+ mRemoteCallback->onLockStatusChanged(
+ IProCameraCallbacks::LOCK_STOLEN);
+ }
+
+ mExclusiveLock = false;
+
+ //TODO: we should not need to detach the device, merely reset it.
+ detachDevice();
+}
+
status_t ProCamera2Client::submitRequest(camera_metadata_t* request,
bool streaming) {
ATRACE_CALL();
ALOGV("%s", __FUNCTION__);
Mutex::Autolock icl(mIProCameraUserLock);
+
+ if (!mDevice.get()) return DEAD_OBJECT;
+
if (!mExclusiveLock) {
return PERMISSION_DENIED;
}
@@ -224,6 +249,9 @@
ALOGV("%s", __FUNCTION__);
Mutex::Autolock icl(mIProCameraUserLock);
+
+ if (!mDevice.get()) return DEAD_OBJECT;
+
if (!mExclusiveLock) {
return PERMISSION_DENIED;
}
@@ -247,6 +275,7 @@
Mutex::Autolock icl(mIProCameraUserLock);
+ if (!mDevice.get()) return DEAD_OBJECT;
mDevice->clearStreamingRequest();
status_t code;
@@ -274,6 +303,8 @@
Mutex::Autolock icl(mIProCameraUserLock);
+ if (!mDevice.get()) return DEAD_OBJECT;
+
sp<IBinder> binder;
sp<ANativeWindow> window;
if (bufferProducer != 0) {
@@ -303,6 +334,8 @@
Mutex::Autolock icl(mIProCameraUserLock);
+ if (!mDevice.get()) return DEAD_OBJECT;
+
CameraMetadata metadata;
if ( (res = mDevice->createDefaultRequest(templateId, &metadata) ) == OK) {
*request = metadata.release();
@@ -319,6 +352,10 @@
return INVALID_OPERATION;
}
+ Mutex::Autolock icl(mIProCameraUserLock);
+
+ if (!mDevice.get()) return DEAD_OBJECT;
+
CameraMetadata deviceInfo = mDevice->info();
*info = deviceInfo.release();
@@ -341,6 +378,12 @@
result = " Device dump:\n";
write(fd, result.string(), result.size());
+ if (!mDevice.get()) {
+ result = " *** Device is detached\n";
+ write(fd, result.string(), result.size());
+ return NO_ERROR;
+ }
+
status_t res = mDevice->dump(fd, args);
if (res != OK) {
result = String8::format(" Error dumping device: %s (%d)",
@@ -363,9 +406,19 @@
int callingPid = getCallingPid();
if (callingPid != mClientPid && callingPid != mServicePid) return;
+ ALOGV("Camera %d: Shutting down", mCameraId);
+
+ detachDevice();
+ ProClient::disconnect();
+
+ ALOGV("Camera %d: Shut down complete complete", mCameraId);
+}
+
+void ProCamera2Client::detachDevice() {
if (mDevice == 0) return;
- ALOGV("Camera %d: Shutting down", mCameraId);
+ ALOGV("Camera %d: Stopping processors", mCameraId);
+
mFrameProcessor->removeListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
FRAME_PROCESSOR_LISTENER_MAX_ID,
/*listener*/this);
@@ -374,11 +427,22 @@
mFrameProcessor->join();
ALOGV("Camera %d: Disconnecting device", mCameraId);
+ // WORKAROUND: HAL refuses to disconnect while there's streams in flight
+ {
+ mDevice->clearStreamingRequest();
+
+ status_t code;
+ if ((code = mDevice->waitUntilDrained()) != OK) {
+ ALOGE("%s: waitUntilDrained failed with code 0x%x", __FUNCTION__,
+ code);
+ }
+ }
+
mDevice->disconnect();
mDevice.clear();
- ProClient::disconnect();
+ ALOGV("Camera %d: Detach complete", mCameraId);
}
status_t ProCamera2Client::connect(const sp<IProCameraCallbacks>& client) {