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

Commit 9801ed11 authored by Dmitri Plotnikov's avatar Dmitri Plotnikov
Browse files

Fix keeping track of binder native thread IDs

Test: atest FrameworksCoreTests:com.android.internal.os.BatteryStatsBinderCallStatsTest
Bug: 169094825

Change-Id: If503327bd6f7fa022a1d261edb0746f710b1410c
parent b5671dc8
Loading
Loading
Loading
Loading
+11 −4
Original line number Diff line number Diff line
@@ -6612,21 +6612,28 @@ public class BatteryStatsImpl extends BatteryStats {
     * the power consumption to the calling app.
     */
    public void noteBinderCallStats(int workSourceUid, long incrementalCallCount,
            Collection<BinderCallsStats.CallStat> callStats, int[] binderThreadNativeTids) {
        noteBinderCallStats(workSourceUid, incrementalCallCount, callStats, binderThreadNativeTids,
            Collection<BinderCallsStats.CallStat> callStats) {
        noteBinderCallStats(workSourceUid, incrementalCallCount, callStats,
                mClocks.elapsedRealtime(), mClocks.uptimeMillis());
    }
    public void noteBinderCallStats(int workSourceUid, long incrementalCallCount,
            Collection<BinderCallsStats.CallStat> callStats, int[] binderThreadNativeTids,
            Collection<BinderCallsStats.CallStat> callStats,
            long elapsedRealtimeMs, long uptimeMs) {
        synchronized (this) {
            getUidStatsLocked(workSourceUid, elapsedRealtimeMs, uptimeMs)
                    .noteBinderCallStatsLocked(incrementalCallCount, callStats);
            mSystemServerCpuThreadReader.setBinderThreadNativeTids(binderThreadNativeTids);
        }
    }
    /**
     * Takes note of native IDs of threads taking incoming binder calls. The CPU time
     * of these threads is attributed to the apps making those binder calls.
     */
    public void noteBinderThreadNativeIds(int[] binderThreadNativeTids) {
        mSystemServerCpuThreadReader.setBinderThreadNativeTids(binderThreadNativeTids);
    }
    /**
     * Estimates the proportion of system server CPU activity handling incoming binder calls
     * that can be attributed to each app
+15 −4
Original line number Diff line number Diff line
@@ -119,8 +119,8 @@ public class BinderCallsStats implements BinderInternal.Observer {
                    if (uidEntry != null) {
                        ArrayMap<CallStatKey, CallStat> callStats = uidEntry.mCallStats;
                        mCallStatsObserver.noteCallStats(uidEntry.workSourceUid,
                                uidEntry.incrementalCallCount, callStats.values(),
                                mNativeTids.toArray());
                                uidEntry.incrementalCallCount, callStats.values()
                        );
                        uidEntry.incrementalCallCount = 0;
                        for (int j = callStats.size() - 1; j >= 0; j--) {
                            callStats.valueAt(j).incrementalCallCount = 0;
@@ -168,6 +168,7 @@ public class BinderCallsStats implements BinderInternal.Observer {
    public void setCallStatsObserver(
            BinderInternal.CallStatsObserver callStatsObserver) {
        mCallStatsObserver = callStatsObserver;
        noteBinderThreadNativeIds();
        noteCallsStatsDelayed();
    }

@@ -182,13 +183,13 @@ public class BinderCallsStats implements BinderInternal.Observer {
    @Override
    @Nullable
    public CallSession callStarted(Binder binder, int code, int workSourceUid) {
        noteNativeThreadId();

        if (!mRecordingAllTransactionsForUid
                && (mDeviceState == null || mDeviceState.isCharging())) {
            return null;
        }

        noteNativeThreadId();

        final CallSession s = obtainCallSession();
        s.binderClass = binder.getClass();
        s.transactionCode = code;
@@ -359,6 +360,16 @@ public class BinderCallsStats implements BinderInternal.Observer {
                mNativeTids = copyOnWriteArray;
            }
        }

        noteBinderThreadNativeIds();
    }

    private void noteBinderThreadNativeIds() {
        if (mCallStatsObserver == null) {
            return;
        }

        mCallStatsObserver.noteBinderThreadNativeIds(getNativeTids());
    }

    /**
+6 −2
Original line number Diff line number Diff line
@@ -143,8 +143,12 @@ public class BinderInternal {
         * Notes incoming binder call stats associated with this work source UID.
         */
        void noteCallStats(int workSourceUid, long incrementalCallCount,
                Collection<BinderCallsStats.CallStat> callStats,
                int[] binderThreadNativeTids);
                Collection<BinderCallsStats.CallStat> callStats);

        /**
         * Notes the native IDs of threads taking incoming binder calls.
         */
        void noteBinderThreadNativeIds(int[] binderThreadNativeTids);
    }

    /**
+5 −13
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@ import java.util.Arrays;
 */
public class SystemServerCpuThreadReader {
    private KernelCpuThreadReader mKernelCpuThreadReader;
    private int[] mBinderThreadNativeTids;
    private int[] mBinderThreadNativeTids = new int[0];  // Sorted

    private int[] mThreadCpuTimesUs;
    private int[] mBinderThreadCpuTimesUs;
@@ -75,7 +75,8 @@ public class SystemServerCpuThreadReader {
    }

    public void setBinderThreadNativeTids(int[] nativeTids) {
        mBinderThreadNativeTids = nativeTids;
        mBinderThreadNativeTids = nativeTids.clone();
        Arrays.sort(mBinderThreadNativeTids);
    }

    /**
@@ -107,7 +108,8 @@ public class SystemServerCpuThreadReader {
                int threadCpuUsagesSize = threadCpuUsages.size();
                for (int j = 0; j < threadCpuUsagesSize; j++) {
                    KernelCpuThreadReader.ThreadCpuUsage tcu = threadCpuUsages.get(j);
                    boolean isBinderThread = isBinderThread(tcu.threadId);
                    boolean isBinderThread =
                            Arrays.binarySearch(mBinderThreadNativeTids, tcu.threadId) >= 0;

                    final int len = Math.min(tcu.usageTimesMillis.length, mThreadCpuTimesUs.length);
                    for (int k = 0; k < len; k++) {
@@ -138,14 +140,4 @@ public class SystemServerCpuThreadReader {
        return mDeltaCpuThreadTimes;
    }

    private boolean isBinderThread(int threadId) {
        if (mBinderThreadNativeTids != null) {
            for (int i = 0; i < mBinderThreadNativeTids.length; i++) {
                if (threadId == mBinderThreadNativeTids[i]) {
                    return true;
                }
            }
        }
        return false;
    }
}
+5 −5
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@ public class BatteryStatsBinderCallStatsTest extends TestCase {
        stat1.cpuTimeMicros = 1000;
        callStats.add(stat1);

        bi.noteBinderCallStats(workSourceUid, 42, callStats, null);
        bi.noteBinderCallStats(workSourceUid, 42, callStats);

        callStats.clear();
        BinderCallsStats.CallStat stat2 = new BinderCallsStats.CallStat(callingUid,
@@ -70,7 +70,7 @@ public class BatteryStatsBinderCallStatsTest extends TestCase {
        stat2.cpuTimeMicros = 500;
        callStats.add(stat2);

        bi.noteBinderCallStats(workSourceUid, 8, callStats, null);
        bi.noteBinderCallStats(workSourceUid, 8, callStats);

        BatteryStatsImpl.Uid uid = bi.getUidStatsLocked(workSourceUid);
        assertEquals(42 + 8, uid.getBinderCallCount());
@@ -112,7 +112,7 @@ public class BatteryStatsBinderCallStatsTest extends TestCase {
        stat1b.cpuTimeMicros = 1500;
        callStats.add(stat1b);

        bi.noteBinderCallStats(workSourceUid1, 65, callStats, null);
        bi.noteBinderCallStats(workSourceUid1, 65, callStats);

        // No recorded stats for some methods. Must use the global average.
        callStats.clear();
@@ -121,11 +121,11 @@ public class BatteryStatsBinderCallStatsTest extends TestCase {
        stat2.incrementalCallCount = 10;
        callStats.add(stat2);

        bi.noteBinderCallStats(workSourceUid2, 40, callStats, null);
        bi.noteBinderCallStats(workSourceUid2, 40, callStats);

        // No stats for any calls. Must use the global average
        callStats.clear();
        bi.noteBinderCallStats(workSourceUid3, 50, callStats, null);
        bi.noteBinderCallStats(workSourceUid3, 50, callStats);

        bi.updateSystemServiceCallStats();

Loading