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

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

Log Bundle statistics when too large.

When we have trouble pushing a saved instance state Bundle out of
a process, log high-level statistics to help narrow down where bloat
is coming from.

Bug: 62409379
Test: builds, boots, stats logged
Change-Id: Iaff01eaf31ff0fd4d0fde3da15e9526dac559af9
parent f4d4f9b9
Loading
Loading
Loading
Loading
+12 −3
Original line number Diff line number Diff line
@@ -100,6 +100,7 @@ import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
import android.util.LogPrinter;
import android.util.LogWriter;
import android.util.Pair;
import android.util.PrintWriterPrinter;
import android.util.Slog;
@@ -125,6 +126,7 @@ import com.android.internal.os.RuntimeInit;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.IndentingPrintWriter;
import com.android.org.conscrypt.OpenSSLSocketImpl;
import com.android.org.conscrypt.TrustedCertificateStore;

@@ -133,8 +135,6 @@ import dalvik.system.CloseGuard;
import dalvik.system.VMDebug;
import dalvik.system.VMRuntime;

import com.google.android.collect.Lists;

import libcore.io.DropBox;
import libcore.io.EventLogger;
import libcore.io.IoUtils;
@@ -152,6 +152,7 @@ import java.lang.reflect.Field;
import java.net.InetAddress;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -3052,7 +3053,7 @@ public final class ActivityThread {
    public void handleInstallProvider(ProviderInfo info) {
        final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
        try {
            installContentProviders(mInitialApplication, Lists.newArrayList(info));
            installContentProviders(mInitialApplication, Arrays.asList(info));
        } finally {
            StrictMode.setThreadPolicy(oldPolicy);
        }
@@ -3935,6 +3936,14 @@ public final class ActivityThread {
                ActivityManager.getService().activityStopped(
                    activity.token, state, persistentState, description);
            } catch (RemoteException ex) {
                // Dump statistics about bundle to help developers debug
                final LogWriter writer = new LogWriter(Log.WARN, TAG);
                final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
                pw.println("Bundle stats:");
                Bundle.dumpStats(pw, state);
                pw.println("PersistableBundle stats:");
                Bundle.dumpStats(pw, persistentState);

                if (ex instanceof TransactionTooLargeException
                        && activity.packageInfo.getTargetSdkVersion() < Build.VERSION_CODES.N) {
                    Log.e(TAG, "App sent too much data in instance state, so it was ignored", ex);
+48 −0
Original line number Diff line number Diff line
@@ -21,6 +21,9 @@ import android.util.ArrayMap;
import android.util.Log;
import android.util.MathUtils;
import android.util.Slog;
import android.util.SparseArray;

import com.android.internal.util.IndentingPrintWriter;

import java.io.Serializable;
import java.util.ArrayList;
@@ -1555,4 +1558,49 @@ public class BaseBundle {

        mParcelledData = p;
    }

    /** {@hide} */
    public static void dumpStats(IndentingPrintWriter pw, String key, Object value) {
        final Parcel tmp = Parcel.obtain();
        tmp.writeValue(value);
        final int size = tmp.dataPosition();
        tmp.recycle();

        // We only really care about logging large values
        if (size > 1024) {
            pw.println(key + " [size=" + size + "]");
            if (value instanceof BaseBundle) {
                dumpStats(pw, (BaseBundle) value);
            } else if (value instanceof SparseArray) {
                dumpStats(pw, (SparseArray) value);
            }
        }
    }

    /** {@hide} */
    public static void dumpStats(IndentingPrintWriter pw, SparseArray array) {
        pw.increaseIndent();
        if (array == null) {
            pw.println("[null]");
            return;
        }
        for (int i = 0; i < array.size(); i++) {
            dumpStats(pw, "0x" + Integer.toHexString(array.keyAt(i)), array.valueAt(i));
        }
        pw.decreaseIndent();
    }

    /** {@hide} */
    public static void dumpStats(IndentingPrintWriter pw, BaseBundle bundle) {
        pw.increaseIndent();
        if (bundle == null) {
            pw.println("[null]");
            return;
        }
        final ArrayMap<String, Object> map = bundle.getMap();
        for (int i = 0; i < map.size(); i++) {
            dumpStats(pw, map.keyAt(i), map.valueAt(i));
        }
        pw.decreaseIndent();
    }
}