diff options
author | Eino-Ville Talvala <etalvala@google.com> | 2015-09-04 14:15:58 -0700 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2015-10-29 12:07:04 -0700 |
commit | 4f33629b62ad90687973c8496d9b60f4f18e26b1 (patch) | |
tree | c29eb1898a2daa8d4b3c0f98d96512cb67c16a59 /services/camera | |
parent | ce9e446bd8c72972af86917563225e618b49d451 (diff) | |
download | frameworks_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.cpp | 14 | ||||
-rw-r--r-- | services/camera/libcameraservice/CameraService.h | 5 |
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 |