From 23d40c40aa70866e12ccba640a71bbbf8d492a87 Mon Sep 17 00:00:00 2001 From: Adam Lesinski Date: Thu, 20 Nov 2014 11:58:21 -0800 Subject: [PATCH] Fix race when cleaning up receivers/services in Context Bug:18135575 Change-Id: I2c69c8189d9ebd297c8a83fe84658b26cbb0528f --- core/java/android/app/LoadedApk.java | 91 +++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 43 deletions(-) diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index aa98e973855c..ece2a331c079 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -632,55 +632,60 @@ public final class LoadedApk { public void removeContextRegistrations(Context context, String who, String what) { final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled(); - ArrayMap rmap = - mReceivers.remove(context); - if (rmap != null) { - for (int i=0; i rmap = + mReceivers.remove(context); + if (rmap != null) { + for (int i = 0; i < rmap.size(); i++) { + LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i); + IntentReceiverLeaked leak = new IntentReceiverLeaked( + what + " " + who + " has leaked IntentReceiver " + + rd.getIntentReceiver() + " that was " + + "originally registered here. Are you missing a " + + "call to unregisterReceiver()?"); + leak.setStackTrace(rd.getLocation().getStackTrace()); + Slog.e(ActivityThread.TAG, leak.getMessage(), leak); + if (reportRegistrationLeaks) { + StrictMode.onIntentReceiverLeaked(leak); + } + try { + ActivityManagerNative.getDefault().unregisterReceiver( + rd.getIIntentReceiver()); + } catch (RemoteException e) { + // system crashed, nothing we can do + } } } + mUnregisteredReceivers.remove(context); } - mUnregisteredReceivers.remove(context); - //Slog.i(TAG, "Receiver registrations: " + mReceivers); - ArrayMap smap = - mServices.remove(context); - if (smap != null) { - for (int i=0; i smap = + mServices.remove(context); + if (smap != null) { + for (int i = 0; i < smap.size(); i++) { + LoadedApk.ServiceDispatcher sd = smap.valueAt(i); + ServiceConnectionLeaked leak = new ServiceConnectionLeaked( + what + " " + who + " has leaked ServiceConnection " + + sd.getServiceConnection() + " that was originally bound here"); + leak.setStackTrace(sd.getLocation().getStackTrace()); + Slog.e(ActivityThread.TAG, leak.getMessage(), leak); + if (reportRegistrationLeaks) { + StrictMode.onServiceConnectionLeaked(leak); + } + try { + ActivityManagerNative.getDefault().unbindService( + sd.getIServiceConnection()); + } catch (RemoteException e) { + // system crashed, nothing we can do + } + sd.doForget(); } - sd.doForget(); } + mUnboundServices.remove(context); + //Slog.i(TAG, "Service registrations: " + mServices); } - mUnboundServices.remove(context); - //Slog.i(TAG, "Service registrations: " + mServices); } public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r, -- 2.11.0