diff options
| author | 2012-03-01 20:50:32 -0800 | |
|---|---|---|
| committer | 2012-03-01 21:10:05 -0800 | |
| commit | d7026f1612a7c1e8cc9b484038fa99b7fc29cfd7 (patch) | |
| tree | 2ba3ba651643d5b3fb1a1dec88445d26538fead3 | |
| parent | c81ec3637b8e3c177ec041aeb3863e123924505b (diff) | |
Report leaked Context registrations to StrictMode.
When tearing down any leaked BroadcastReceiver or ServiceConnection
Context registrations, report through StrictMode.
Bug: 6084353
Change-Id: I5e78039299e2c9c1440cd1fd09317da78ffee82a
| -rw-r--r-- | api/current.txt | 1 | ||||
| -rw-r--r-- | core/java/android/app/LoadedApk.java | 7 | ||||
| -rw-r--r-- | core/java/android/os/StrictMode.java | 45 |
3 files changed, 50 insertions, 3 deletions
diff --git a/api/current.txt b/api/current.txt index 81f7a824df21..51946a98c23a 100644 --- a/api/current.txt +++ b/api/current.txt @@ -15322,6 +15322,7 @@ package android.os { method public android.os.StrictMode.VmPolicy.Builder detectActivityLeaks(); method public android.os.StrictMode.VmPolicy.Builder detectAll(); method public android.os.StrictMode.VmPolicy.Builder detectLeakedClosableObjects(); + method public android.os.StrictMode.VmPolicy.Builder detectLeakedRegistrationObjects(); method public android.os.StrictMode.VmPolicy.Builder detectLeakedSqlLiteObjects(); method public android.os.StrictMode.VmPolicy.Builder penaltyDeath(); method public android.os.StrictMode.VmPolicy.Builder penaltyDropBox(); diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index d9bbb4a33b4a..de9470e7ecc9 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -512,6 +512,7 @@ public final class LoadedApk { public void removeContextRegistrations(Context context, String who, String what) { + final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled(); HashMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap = mReceivers.remove(context); if (rmap != null) { @@ -525,6 +526,9 @@ public final class LoadedApk { "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()); @@ -546,6 +550,9 @@ public final class LoadedApk { + 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()); diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java index 99f58a0b9199..a0ad9c0a0d7b 100644 --- a/core/java/android/os/StrictMode.java +++ b/core/java/android/os/StrictMode.java @@ -20,7 +20,10 @@ import android.app.ActivityManagerNative; import android.app.ActivityThread; import android.app.ApplicationErrorReport; import android.app.IActivityManager; +import android.content.BroadcastReceiver; +import android.content.Context; import android.content.Intent; +import android.content.ServiceConnection; import android.util.Log; import android.util.Printer; import android.util.Singleton; @@ -195,9 +198,15 @@ public final class StrictMode { */ private static final int DETECT_VM_INSTANCE_LEAKS = 0x1000; // for VmPolicy + /** + * @hide + */ + public static final int DETECT_VM_REGISTRATION_LEAKS = 0x2000; // for VmPolicy + private static final int ALL_VM_DETECT_BITS = DETECT_VM_CURSOR_LEAKS | DETECT_VM_CLOSABLE_LEAKS | - DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_INSTANCE_LEAKS; + DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_INSTANCE_LEAKS | + DETECT_VM_REGISTRATION_LEAKS; /** * @hide @@ -618,8 +627,8 @@ public final class StrictMode { * but will likely expand in future releases. */ public Builder detectAll() { - return enable(DETECT_VM_ACTIVITY_LEAKS | - DETECT_VM_CURSOR_LEAKS | DETECT_VM_CLOSABLE_LEAKS); + return enable(DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_CURSOR_LEAKS + | DETECT_VM_CLOSABLE_LEAKS | DETECT_VM_REGISTRATION_LEAKS); } /** @@ -648,6 +657,15 @@ public final class StrictMode { } /** + * Detect when a {@link BroadcastReceiver} or + * {@link ServiceConnection} is leaked during {@link Context} + * teardown. + */ + public Builder detectLeakedRegistrationObjects() { + return enable(DETECT_VM_REGISTRATION_LEAKS); + } + + /** * Crashes the whole process on violation. This penalty runs at * the end of all enabled penalties so yo you'll still get * your logging or other violations before the process dies. @@ -1499,6 +1517,13 @@ public final class StrictMode { /** * @hide */ + public static boolean vmRegistrationLeaksEnabled() { + return (sVmPolicyMask & DETECT_VM_REGISTRATION_LEAKS) != 0; + } + + /** + * @hide + */ public static void onSqliteObjectLeaked(String message, Throwable originStack) { onVmPolicyViolation(message, originStack); } @@ -1510,6 +1535,20 @@ public final class StrictMode { onVmPolicyViolation(null, originStack); } + /** + * @hide + */ + public static void onIntentReceiverLeaked(Throwable originStack) { + onVmPolicyViolation(null, originStack); + } + + /** + * @hide + */ + public static void onServiceConnectionLeaked(Throwable originStack) { + onVmPolicyViolation(null, originStack); + } + // Map from VM violation fingerprint to uptime millis. private static final HashMap<Integer, Long> sLastVmViolationTime = new HashMap<Integer, Long>(); |