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

Commit 2bccbc8e authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Don't drop system server StrictMode violations.

The system server doesn't have a ProcessRecord, and all the
downstream already checks if it's null.  (Someone incorrectly added
a bailout-when-null check.)

We've actively burned down the number of system violations to a
minimum, and we're chasing the remaining violations with the intent
of them staying at 0, meaning we're okay to remove the batching
logic.  (The output format of batched violations is tricky for
dashboards to parse.)

Test: cts-tradefed run commandAndExit cts-dev -m CtsOsTestCases -t android.os.cts.StrictModeTest
Bug: 68662870
Change-Id: Ic1b81200c9550a316939e890a8cea8f37cfbb30b
parent aa422681
Loading
Loading
Loading
Loading
+10 −77
Original line number Original line Diff line number Diff line
@@ -401,6 +401,7 @@ import com.android.server.AppOpsService;
import com.android.server.AttributeCache;
import com.android.server.AttributeCache;
import com.android.server.DeviceIdleController;
import com.android.server.DeviceIdleController;
import com.android.server.IntentResolver;
import com.android.server.IntentResolver;
import com.android.server.IoThread;
import com.android.server.LocalServices;
import com.android.server.LocalServices;
import com.android.server.LockGuard;
import com.android.server.LockGuard;
import com.android.server.NetworkManagementInternal;
import com.android.server.NetworkManagementInternal;
@@ -1010,15 +1011,6 @@ public class ActivityManagerService extends IActivityManager.Stub
    private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
    private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
    private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
    private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
    /**
     * Strict Mode background batched logging state.
     *
     * The string buffer is guarded by itself, and its lock is also
     * used to determine if another batched write is already
     * in-flight.
     */
    private final StringBuilder mStrictModeBuffer = new StringBuilder();
    /**
    /**
     * Keeps track of all IIntentReceivers that have been registered for broadcasts.
     * Keeps track of all IIntentReceivers that have been registered for broadcasts.
     * Hash keys are the receiver IBinder, hash value is a ReceiverList.
     * Hash keys are the receiver IBinder, hash value is a ReceiverList.
@@ -14273,10 +14265,9 @@ public class ActivityManagerService extends IActivityManager.Stub
            IBinder app,
            IBinder app,
            int violationMask,
            int violationMask,
            StrictMode.ViolationInfo info) {
            StrictMode.ViolationInfo info) {
        ProcessRecord r = findAppProcess(app, "StrictMode");
        // We're okay if the ProcessRecord is missing; it probably means that
        if (r == null) {
        // we're reporting a violation from the system process itself.
            return;
        final ProcessRecord r = findAppProcess(app, "StrictMode");
        }
        if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
        if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
            Integer stackFingerprint = info.hashCode();
            Integer stackFingerprint = info.hashCode();
@@ -14338,18 +14329,15 @@ public class ActivityManagerService extends IActivityManager.Stub
                (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
                (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
                                       ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
                                       ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
        final String processName = process == null ? "unknown" : process.processName;
        final String processName = process == null ? "unknown" : process.processName;
        final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
        final DropBoxManager dbox = (DropBoxManager)
        final DropBoxManager dbox = (DropBoxManager)
                mContext.getSystemService(Context.DROPBOX_SERVICE);
                mContext.getSystemService(Context.DROPBOX_SERVICE);
        // Exit early if the dropbox isn't configured to accept this report type.
        // Exit early if the dropbox isn't configured to accept this report type.
        final String dropboxTag = processClass(process) + "_strictmode";
        if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
        if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
        boolean bufferWasEmpty;
        final StringBuilder sb = new StringBuilder(1024);
        boolean needsFlush;
        final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
        synchronized (sb) {
        synchronized (sb) {
            bufferWasEmpty = sb.length() == 0;
            appendDropBoxProcessHeaders(process, processName, sb);
            appendDropBoxProcessHeaders(process, processName, sb);
            sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
            sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
            sb.append("System-App: ").append(isSystemApp).append("\n");
            sb.append("System-App: ").append(isSystemApp).append("\n");
@@ -14381,67 +14369,12 @@ public class ActivityManagerService extends IActivityManager.Stub
                sb.append(info.getViolationDetails());
                sb.append(info.getViolationDetails());
                sb.append("\n");
                sb.append("\n");
            }
            }
            // Only buffer up to ~64k.  Various logging bits truncate
            // things at 128k.
            needsFlush = (sb.length() > 64 * 1024);
        }
        // Flush immediately if the buffer's grown too large, or this
        // is a non-system app.  Non-system apps are isolated with a
        // different tag & policy and not batched.
        //
        // Batching is useful during internal testing with
        // StrictMode settings turned up high.  Without batching,
        // thousands of separate files could be created on boot.
        if (!isSystemApp || needsFlush) {
            new Thread("Error dump: " + dropboxTag) {
                @Override
                public void run() {
                    String report;
                    synchronized (sb) {
                        report = sb.toString();
                        sb.delete(0, sb.length());
                        sb.trimToSize();
                    }
                    if (report.length() != 0) {
                        dbox.addText(dropboxTag, report);
        }
        }
                }
            }.start();
            return;
        }
        // System app batching:
        if (!bufferWasEmpty) {
            // An existing dropbox-writing thread is outstanding, so
            // we don't need to start it up.  The existing thread will
            // catch the buffer appends we just did.
            return;
        }
        // Worker thread to both batch writes and to avoid blocking the caller on I/O.
        // (After this point, we shouldn't access AMS internal data structures.)
        new Thread("Error dump: " + dropboxTag) {
            @Override
            public void run() {
                // 5 second sleep to let stacks arrive and be batched together
                try {
                    Thread.sleep(5000);  // 5 seconds
                } catch (InterruptedException e) {}
                String errorReport;
        final String res = sb.toString();
                synchronized (mStrictModeBuffer) {
        IoThread.getHandler().post(() -> {
                    errorReport = mStrictModeBuffer.toString();
            dbox.addText(dropboxTag, res);
                    if (errorReport.length() == 0) {
        });
                        return;
                    }
                    mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
                    mStrictModeBuffer.trimToSize();
                }
                dbox.addText(dropboxTag, errorReport);
            }
        }.start();
    }
    }
    /**
    /**