From 63909886b2e594a9aec27fe6e4e540e97dcde5a6 Mon Sep 17 00:00:00 2001 From: Koji Fukui Date: Fri, 21 Feb 2014 21:31:14 +0900 Subject: [PATCH] Skip broadcasting to a receiver if the receiver seems to be dead If an application that has a broadcast receiver is killed during broadcasting, thread variable of ProcessRecord becomes null so that IIntentReceiver#performReceive() is called in BroadcastQueue#performReceiveLocked(). But if binder driver has not noticed the death of the application yet, it can't throw DeadObjectException. After that, binder driver notices. But it can't notify DeadObjectException to the caller because performReceive() is async call. So broadcasting keeps on waiting for finishing performReceive() until timeout. This change checks the death of the application before calling performReceive() and skips broadcasting to the receiver if the application has already died. Change-Id: Ifa02b8b1a7e7b6fd314de90fedff5b7a5326825d --- .../com/android/server/am/BroadcastQueue.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/services/java/com/android/server/am/BroadcastQueue.java b/services/java/com/android/server/am/BroadcastQueue.java index bfb667f8aca00..ea1565332f56a 100644 --- a/services/java/com/android/server/am/BroadcastQueue.java +++ b/services/java/com/android/server/am/BroadcastQueue.java @@ -415,11 +415,16 @@ public final class BroadcastQueue { Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) throws RemoteException { // Send the intent to the receiver asynchronously using one-way binder calls. - if (app != null && app.thread != null) { - // If we have an app thread, do the call through that so it is - // correctly ordered with other one-way calls. - app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode, - data, extras, ordered, sticky, sendingUser, app.repProcState); + if (app != null) { + if (app.thread != null) { + // If we have an app thread, do the call through that so it is + // correctly ordered with other one-way calls. + app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode, + data, extras, ordered, sticky, sendingUser, app.repProcState); + } else { + // Application has died. Receiver doesn't exist. + throw new RemoteException("app.thread must not be null"); + } } else { receiver.performReceive(intent, resultCode, data, extras, ordered, sticky, sendingUser); @@ -661,6 +666,7 @@ public final class BroadcastQueue { // (local and remote) isn't kept in the mBroadcastHistory. r.resultTo = null; } catch (RemoteException e) { + r.resultTo = null; Slog.w(TAG, "Failure [" + mQueueName + "] sending broadcast result of " + r.intent, e);