diff options
10 files changed, 97 insertions, 38 deletions
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index e58990eff2c8..7516a879211f 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -6613,22 +6613,29 @@ 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 */ diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java index f5bef0b006f5..70b1ad49d8b8 100644 --- a/core/java/com/android/internal/os/BinderCallsStats.java +++ b/core/java/com/android/internal/os/BinderCallsStats.java @@ -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()); } /** diff --git a/core/java/com/android/internal/os/BinderInternal.java b/core/java/com/android/internal/os/BinderInternal.java index 2645b8e84cf1..c14d8d805d29 100644 --- a/core/java/com/android/internal/os/BinderInternal.java +++ b/core/java/com/android/internal/os/BinderInternal.java @@ -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); } /** diff --git a/core/java/com/android/internal/os/SystemServerCpuThreadReader.java b/core/java/com/android/internal/os/SystemServerCpuThreadReader.java index 1cdd42c7403e..3aa2390375ec 100644 --- a/core/java/com/android/internal/os/SystemServerCpuThreadReader.java +++ b/core/java/com/android/internal/os/SystemServerCpuThreadReader.java @@ -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; - } } diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsBinderCallStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsBinderCallStatsTest.java index 22c41f3c9622..85f9c97629e3 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsBinderCallStatsTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsBinderCallStatsTest.java @@ -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(); diff --git a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java index 96250db4aa51..0eb34a993dec 100644 --- a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java @@ -47,8 +47,10 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Random; +import java.util.Set; @SmallTest @RunWith(AndroidJUnit4.class) @@ -770,13 +772,27 @@ public class BinderCallsStatsTest { bcs.setSamplingInterval(1); bcs.setTrackScreenInteractive(false); + final ArrayList<BinderCallsStats.CallStat> callStatsList = new ArrayList<>(); - bcs.setCallStatsObserver( - (workSourceUid, incrementalCallCount, callStats, binderThreadIds) -> - callStatsList.addAll(callStats)); + final Set<Integer> nativeTids = new HashSet<>(); + bcs.setCallStatsObserver(new BinderInternal.CallStatsObserver() { + @Override + public void noteCallStats(int workSourceUid, long incrementalCallCount, + Collection<BinderCallsStats.CallStat> callStats) { + callStatsList.addAll(callStats); + } + + @Override + public void noteBinderThreadNativeIds(int[] binderThreadNativeTids) { + for (int tid : binderThreadNativeTids) { + nativeTids.add(tid); + } + } + }); Binder binder = new Binder(); + bcs.nativeTid = 1000; CallSession callSession = bcs.callStarted(binder, 1, WORKSOURCE_UID); bcs.time += 10; bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID); @@ -785,6 +801,7 @@ public class BinderCallsStatsTest { bcs.time += 20; bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID); + bcs.nativeTid = 2000; callSession = bcs.callStarted(binder, 2, WORKSOURCE_UID); bcs.time += 30; bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID); @@ -809,6 +826,10 @@ public class BinderCallsStatsTest { assertEquals(30, callStats.maxCpuTimeMicros); } } + + assertEquals(2, nativeTids.size()); + assertTrue(nativeTids.contains(1000)); + assertTrue(nativeTids.contains(2000)); } @Test diff --git a/core/tests/coretests/src/com/android/internal/os/SystemServicePowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/SystemServicePowerCalculatorTest.java index ac5443e1c7ce..2eee140b921f 100644 --- a/core/tests/coretests/src/com/android/internal/os/SystemServicePowerCalculatorTest.java +++ b/core/tests/coretests/src/com/android/internal/os/SystemServicePowerCalculatorTest.java @@ -87,7 +87,7 @@ public class SystemServicePowerCalculatorTest { stat1.cpuTimeMicros = 1000000; callStats.add(stat1); - mMockBatteryStats.noteBinderCallStats(workSourceUid1, 100, callStats, null); + mMockBatteryStats.noteBinderCallStats(workSourceUid1, 100, callStats); callStats.clear(); BinderCallsStats.CallStat stat2 = new BinderCallsStats.CallStat(workSourceUid2, @@ -97,7 +97,7 @@ public class SystemServicePowerCalculatorTest { stat2.cpuTimeMicros = 9000000; callStats.add(stat2); - mMockBatteryStats.noteBinderCallStats(workSourceUid2, 100, callStats, null); + mMockBatteryStats.noteBinderCallStats(workSourceUid2, 100, callStats); mMockBatteryStats.updateSystemServiceCallStats(); mMockBatteryStats.updateSystemServerThreadStats(); diff --git a/services/core/java/android/os/BatteryStatsInternal.java b/services/core/java/android/os/BatteryStatsInternal.java index b7fed87d570d..958c15c8d432 100644 --- a/services/core/java/android/os/BatteryStatsInternal.java +++ b/services/core/java/android/os/BatteryStatsInternal.java @@ -50,5 +50,10 @@ public abstract class BatteryStatsInternal { * Informs battery stats of binder stats for the given work source UID. */ public abstract void noteBinderCallStats(int workSourceUid, long incrementalBinderCallCount, - Collection<BinderCallsStats.CallStat> callStats, int[] binderThreadNativeTids); + Collection<BinderCallsStats.CallStat> callStats); + + /** + * Informs battery stats of native thread IDs of threads taking incoming binder calls. + */ + public abstract void noteBinderThreadNativeIds(int[] binderThreadNativeTids); } diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java index c9513592ea79..66ac889ff2ca 100644 --- a/services/core/java/com/android/server/BinderCallsStatsService.java +++ b/services/core/java/com/android/server/BinderCallsStatsService.java @@ -49,6 +49,7 @@ import com.android.internal.util.DumpUtils; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Collection; import java.util.List; public class BinderCallsStatsService extends Binder { @@ -273,7 +274,19 @@ public class BinderCallsStatsService extends Binder { BatteryStatsInternal batteryStatsInternal = getLocalService( BatteryStatsInternal.class); - mBinderCallsStats.setCallStatsObserver(batteryStatsInternal::noteBinderCallStats); + mBinderCallsStats.setCallStatsObserver(new BinderInternal.CallStatsObserver() { + @Override + public void noteCallStats(int workSourceUid, long incrementalCallCount, + Collection<BinderCallsStats.CallStat> callStats) { + batteryStatsInternal.noteBinderCallStats(workSourceUid, + incrementalCallCount, callStats); + } + + @Override + public void noteBinderThreadNativeIds(int[] binderThreadNativeTids) { + batteryStatsInternal.noteBinderThreadNativeIds(binderThreadNativeTids); + } + }); // It needs to be called before mService.systemReady to make sure the observer is // initialized before installing it. diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index 808a6993af1a..76125aabc978 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -240,14 +240,20 @@ public final class BatteryStatsService extends IBatteryStats.Stub @Override public void noteBinderCallStats(int workSourceUid, long incrementatCallCount, - Collection<BinderCallsStats.CallStat> callStats, int[] binderThreadNativeTids) { + Collection<BinderCallsStats.CallStat> callStats) { synchronized (BatteryStatsService.this.mLock) { mHandler.sendMessage(PooledLambda.obtainMessage( - mStats::noteBinderCallStats, workSourceUid, incrementatCallCount, - callStats, binderThreadNativeTids, + mStats::noteBinderCallStats, workSourceUid, incrementatCallCount, callStats, SystemClock.elapsedRealtime(), SystemClock.uptimeMillis())); } } + + @Override + public void noteBinderThreadNativeIds(int[] binderThreadNativeTids) { + synchronized (BatteryStatsService.this.mLock) { + mStats.noteBinderThreadNativeIds(binderThreadNativeTids); + } + } } @Override |