Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d7026f16 authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Report leaked Context registrations to StrictMode.

When tearing down any leaked BroadcastReceiver or ServiceConnection
Context registrations, report through StrictMode.

Bug: 6084353
Change-Id: I5e78039299e2c9c1440cd1fd09317da78ffee82a
parent c81ec363
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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();
+7 −0
Original line number Diff line number Diff line
@@ -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());
+42 −3
Original line number Diff line number Diff line
@@ -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);
            }

            /**
@@ -647,6 +656,15 @@ public final class StrictMode {
                return enable(DETECT_VM_CLOSABLE_LEAKS);
            }

            /**
             * 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
@@ -1496,6 +1514,13 @@ public final class StrictMode {
        return (sVmPolicyMask & DETECT_VM_CLOSABLE_LEAKS) != 0;
    }

    /**
     * @hide
     */
    public static boolean vmRegistrationLeaksEnabled() {
        return (sVmPolicyMask & DETECT_VM_REGISTRATION_LEAKS) != 0;
    }

    /**
     * @hide
     */
@@ -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>();