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

Commit 45e52a40 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Adds an overflow mechanism for binder calls."

parents c7f839b7 79490618
Loading
Loading
Loading
Loading
+46 −3
Original line number Diff line number Diff line
@@ -52,17 +52,23 @@ public class BinderCallsStats implements BinderInternal.Observer {
    public static final boolean ENABLED_DEFAULT = false;
    public static final boolean DETAILED_TRACKING_DEFAULT = true;
    public static final int PERIODIC_SAMPLING_INTERVAL_DEFAULT = 100;
    public static final int MAX_BINDER_CALL_STATS_COUNT_DEFAULT = 5000;

    private static class OverflowBinder extends Binder {}

    private static final String TAG = "BinderCallsStats";
    private static final int CALL_SESSIONS_POOL_SIZE = 100;
    private static final int MAX_EXCEPTION_COUNT_SIZE = 50;
    private static final String EXCEPTION_COUNT_OVERFLOW_NAME = "overflow";
    private static final Class<? extends Binder> OVERFLOW_BINDER = OverflowBinder.class;
    private static final int OVERFLOW_TRANSACTION_CODE = -1;

    // Whether to collect all the data: cpu + exceptions + reply/request sizes.
    private boolean mDetailedTracking = DETAILED_TRACKING_DEFAULT;
    // Sampling period to control how often to track CPU usage. 1 means all calls, 100 means ~1 out
    // of 100 requests.
    private int mPeriodicSamplingInterval = PERIODIC_SAMPLING_INTERVAL_DEFAULT;
    private int mMaxBinderCallStatsCount = MAX_BINDER_CALL_STATS_COUNT_DEFAULT;
    @GuardedBy("mLock")
    private final SparseArray<UidEntry> mUidEntries = new SparseArray<>();
    @GuardedBy("mLock")
@@ -71,6 +77,7 @@ public class BinderCallsStats implements BinderInternal.Observer {
    private final Object mLock = new Object();
    private final Random mRandom;
    private long mStartTime = System.currentTimeMillis();
    private long mCallStatsCount = 0;

    private CachedDeviceState.Readonly mDeviceState;

@@ -158,7 +165,13 @@ public class BinderCallsStats implements BinderInternal.Observer {

                final CallStat callStat = uidEntry.getOrCreate(
                        callingUid, s.binderClass, s.transactionCode,
                        mDeviceState.isScreenInteractive());
                        mDeviceState.isScreenInteractive(),
                        mCallStatsCount >= mMaxBinderCallStatsCount);
                final boolean isNewCallStat = callStat.callCount == 0;
                if (isNewCallStat) {
                    mCallStatsCount++;
                }

                callStat.callCount++;
                callStat.recordedCallCount++;
                callStat.cpuTimeMicros += duration;
@@ -444,6 +457,24 @@ public class BinderCallsStats implements BinderInternal.Observer {
        }
    }

    /**
     * Sets the maximum number of items to track.
     */
    public void setMaxBinderCallStats(int maxKeys) {
        if (maxKeys <= 0) {
            Slog.w(TAG, "Ignored invalid max value (value must be positive): "
                    + maxKeys);
            return;
        }

        synchronized (mLock) {
            if (maxKeys != mMaxBinderCallStatsCount) {
                mMaxBinderCallStatsCount = maxKeys;
                reset();
            }
        }
    }

    public void setSamplingInterval(int samplingInterval) {
        if (samplingInterval <= 0) {
            Slog.w(TAG, "Ignored invalid sampling interval (value must be positive): "
@@ -461,6 +492,7 @@ public class BinderCallsStats implements BinderInternal.Observer {

    public void reset() {
        synchronized (mLock) {
            mCallStatsCount = 0;
            mUidEntries.clear();
            mExceptionCounts.clear();
            mStartTime = System.currentTimeMillis();
@@ -595,10 +627,21 @@ public class BinderCallsStats implements BinderInternal.Observer {
        }

        CallStat getOrCreate(int callingUid, Class<? extends Binder> binderClass,
                int transactionCode, boolean screenInteractive) {
                int transactionCode, boolean screenInteractive, boolean maxCallStatsReached) {
            CallStat mapCallStat = get(callingUid, binderClass, transactionCode, screenInteractive);
            // Only create CallStat if it's a new entry, otherwise update existing instance
            // Only create CallStat if it's a new entry, otherwise update existing instance.
            if (mapCallStat == null) {
                if (maxCallStatsReached) {
                    mapCallStat = get(callingUid, OVERFLOW_BINDER, OVERFLOW_TRANSACTION_CODE,
                            screenInteractive);
                    if (mapCallStat != null) {
                        return mapCallStat;
                    }

                    binderClass = OVERFLOW_BINDER;
                    transactionCode = OVERFLOW_TRANSACTION_CODE;
                }

                mapCallStat = new CallStat(callingUid, binderClass, transactionCode,
                        screenInteractive);
                CallStatKey key = new CallStatKey();
+56 −0
Original line number Diff line number Diff line
@@ -557,6 +557,62 @@ public class BinderCallsStatsTest {
        assertEquals(0, bcs.getExceptionCounts().size());
    }

    @Test
    public void testOverflow_sameEntry() {
        TestBinderCallsStats bcs = new TestBinderCallsStats();
        bcs.setDetailedTracking(true);
        bcs.setSamplingInterval(1);
        bcs.setMaxBinderCallStats(2);

        Binder binder = new Binder();
        CallSession callSession = bcs.callStarted(binder, 1);
        bcs.time += 10;
        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);

        callSession = bcs.callStarted(binder, 1);
        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);

        callSession = bcs.callStarted(binder, 1);
        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);

        BinderCallsStats.UidEntry uidEntry = bcs.getUidEntries().get(WORKSOURCE_UID);
        List<BinderCallsStats.CallStat> callStatsList = new ArrayList(uidEntry.getCallStatsList());
        assertEquals(1, callStatsList.size());
        BinderCallsStats.CallStat callStats = callStatsList.get(0);
        assertEquals(3, callStats.callCount);
    }

    @Test
    public void testOverflow_overflowEntry() {
        TestBinderCallsStats bcs = new TestBinderCallsStats();
        bcs.setDetailedTracking(true);
        bcs.setSamplingInterval(1);
        bcs.setMaxBinderCallStats(1);

        Binder binder = new Binder();
        CallSession callSession = bcs.callStarted(binder, 1);
        bcs.time += 10;
        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);

        callSession = bcs.callStarted(binder, 2);
        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);

        List<BinderCallsStats.ExportedCallStat> callStatsList = bcs.getExportedCallStats();
        assertEquals(2, callStatsList.size());
        BinderCallsStats.ExportedCallStat callStats = callStatsList.get(0);
        assertEquals(1, callStats.callCount);
        assertEquals("1", callStats.methodName);
        assertEquals("android.os.Binder", callStats.className);
        assertEquals(CALLING_UID, callStats.callingUid);

        callStats = callStatsList.get(1);
        assertEquals(1, callStats.callCount);
        assertEquals("-1", callStats.methodName);
        assertEquals("com.android.internal.os.BinderCallsStats$OverflowBinder",
                callStats.className);
        assertEquals(CALLING_UID, callStats.callingUid);
    }

    class TestBinderCallsStats extends BinderCallsStats {
        public int callingUid = CALLING_UID;
        public int workSourceUid = WORKSOURCE_UID;
+4 −0
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ public class BinderCallsStatsService extends Binder {
        private static final String SETTINGS_DETAILED_TRACKING_KEY = "detailed_tracking";
        private static final String SETTINGS_UPLOAD_DATA_KEY = "upload_data";
        private static final String SETTINGS_SAMPLING_INTERVAL_KEY = "sampling_interval";
        private static final String SETTINGS_MAX_CALL_STATS_KEY = "max_call_stats_count";

        private boolean mEnabled;
        private final Uri mUri = Settings.Global.getUriFor(Settings.Global.BINDER_CALLS_STATS);
@@ -97,6 +98,9 @@ public class BinderCallsStatsService extends Binder {
            mBinderCallsStats.setSamplingInterval(mParser.getInt(
                    SETTINGS_SAMPLING_INTERVAL_KEY,
                    BinderCallsStats.PERIODIC_SAMPLING_INTERVAL_DEFAULT));
            mBinderCallsStats.setSamplingInterval(mParser.getInt(
                    SETTINGS_MAX_CALL_STATS_KEY,
                    BinderCallsStats.MAX_BINDER_CALL_STATS_COUNT_DEFAULT));


            final boolean enabled =