summaryrefslogtreecommitdiffstats
path: root/services/camera
diff options
context:
space:
mode:
authorEino-Ville Talvala <etalvala@google.com>2015-09-04 14:15:58 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2015-10-29 12:07:04 -0700
commit4f33629b62ad90687973c8496d9b60f4f18e26b1 (patch)
treec29eb1898a2daa8d4b3c0f98d96512cb67c16a59 /services/camera
parentce9e446bd8c72972af86917563225e618b49d451 (diff)
downloadframeworks_av-4f33629b62ad90687973c8496d9b60f4f18e26b1.zip
frameworks_av-4f33629b62ad90687973c8496d9b60f4f18e26b1.tar.gz
frameworks_av-4f33629b62ad90687973c8496d9b60f4f18e26b1.tar.bz2
DO NOT MERGE: CameraService: Link to client binder death at end of connect
If, within a binder Looper thread, a Binder object death notifier is registered, and then a nested Binder transaction is begun, that transaction may process a death notification callback for the just-registered object, if it was dead at the time of registration. This can lead to an unexpected nested call into the service, and cause deadlock. To avoid this, move the death notifier registration to the end of handling the connect transaction. Also remove one extra bit of disconnect logging. Bug: 23525545 Change-Id: If01cbaf42704f55134118afefc9a8f7bdb014e09
Diffstat (limited to 'services/camera')
-rw-r--r--services/camera/libcameraservice/CameraService.cpp14
-rw-r--r--services/camera/libcameraservice/CameraService.h5
2 files changed, 11 insertions, 8 deletions
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 9a1101a..e4f792d 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -935,6 +935,16 @@ void CameraService::finishConnectLocked(const sp<BasicClient>& client,
LOG_ALWAYS_FATAL("%s: Invalid state for CameraService, clients not evicted properly",
__FUNCTION__);
}
+
+ // And register a death notification for the client callback. Do
+ // this last to avoid Binder policy where a nested Binder
+ // transaction might be pre-empted to service the client death
+ // notification if the client process dies before linkToDeath is
+ // invoked.
+ sp<IBinder> remoteCallback = client->getRemote();
+ if (remoteCallback != nullptr) {
+ remoteCallback->linkToDeath(this);
+ }
}
status_t CameraService::handleEvictionsLocked(const String8& cameraId, int clientPid,
@@ -1874,11 +1884,9 @@ CameraService::BasicClient::~BasicClient() {
void CameraService::BasicClient::disconnect() {
if (mDisconnected) {
- ALOGE("%s: Disconnect called on already disconnected client for device %d", __FUNCTION__,
- mCameraId);
return;
}
- mDisconnected = true;;
+ mDisconnected = true;
mCameraService->removeByClient(this);
mCameraService->logDisconnected(String8::format("%d", mCameraId), mClientPid,
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index b56c161..b29317e 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -861,11 +861,6 @@ status_t CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String
return ret;
}
- sp<IBinder> remoteCallback = client->getRemote();
- if (remoteCallback != nullptr) {
- remoteCallback->linkToDeath(this);
- }
-
// Update shim paremeters for legacy clients
if (effectiveApiLevel == API_1) {
// Assume we have always received a Client subclass for API1