stagefright: fix unreleased OMX handle
- Ensure OMX handle is freed even if binder death notification comes
first.
- Add DeathRecipient in ResourceManagerService so that it could
handle dead clients properly.
Fix: 28824626
Fix: 34252788
Test: adb shell am instrument -e size small -w 'android.media.cts/android.support.test.runner.AndroidJUnitRunner'
Change-Id: Ifc441a2771b5674749ff65a4520177dda115b292
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index 7346f51..78bb587 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -34,6 +34,31 @@
namespace android {
+namespace {
+
+class DeathNotifier : public IBinder::DeathRecipient {
+public:
+ DeathNotifier(const wp<ResourceManagerService> &service, int pid, int64_t clientId)
+ : mService(service), mPid(pid), mClientId(clientId) {}
+
+ virtual void binderDied(const wp<IBinder> & /* who */) override {
+ // Don't check for pid validity since we know it's already dead.
+ sp<ResourceManagerService> service = mService.promote();
+ if (service == nullptr) {
+ ALOGW("ResourceManagerService is dead as well.");
+ return;
+ }
+ service->removeResource(mPid, mClientId, false);
+ }
+
+private:
+ wp<ResourceManagerService> mService;
+ int mPid;
+ int64_t mClientId;
+};
+
+} // namespace
+
template <typename T>
static String8 getString(const Vector<T> &items) {
String8 itemsStr;
@@ -214,17 +239,25 @@
ResourceInfo& info = getResourceInfoForEdit(clientId, client, infos);
// TODO: do the merge instead of append.
info.resources.appendVector(resources);
+ if (info.deathNotifier == nullptr) {
+ info.deathNotifier = new DeathNotifier(this, pid, clientId);
+ IInterface::asBinder(client)->linkToDeath(info.deathNotifier);
+ }
notifyResourceGranted(pid, resources);
}
void ResourceManagerService::removeResource(int pid, int64_t clientId) {
+ removeResource(pid, clientId, true);
+}
+
+void ResourceManagerService::removeResource(int pid, int64_t clientId, bool checkValid) {
String8 log = String8::format(
"removeResource(pid %d, clientId %lld)",
pid, (long long) clientId);
mServiceLog->add(log);
Mutex::Autolock lock(mLock);
- if (!mProcessInfo->isValidPid(pid)) {
+ if (checkValid && !mProcessInfo->isValidPid(pid)) {
ALOGE("Rejected removeResource call with invalid pid.");
return;
}
@@ -237,6 +270,7 @@
ResourceInfos &infos = mMap.editValueAt(index);
for (size_t j = 0; j < infos.size(); ++j) {
if (infos[j].clientId == clientId) {
+ IInterface::asBinder(infos[j].client)->unlinkToDeath(infos[j].deathNotifier);
j = infos.removeAt(j);
found = true;
break;
diff --git a/services/mediaresourcemanager/ResourceManagerService.h b/services/mediaresourcemanager/ResourceManagerService.h
index 2a4a6b2..9e97ac0 100644
--- a/services/mediaresourcemanager/ResourceManagerService.h
+++ b/services/mediaresourcemanager/ResourceManagerService.h
@@ -36,6 +36,7 @@
struct ResourceInfo {
int64_t clientId;
sp<IResourceManagerClient> client;
+ sp<IBinder::DeathRecipient> deathNotifier;
Vector<MediaResource> resources;
};
@@ -70,6 +71,8 @@
// Returns true if any resource has been reclaimed, otherwise returns false.
virtual bool reclaimResource(int callingPid, const Vector<MediaResource> &resources);
+ void removeResource(int pid, int64_t clientId, bool checkValid);
+
protected:
virtual ~ResourceManagerService();