summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2020-06-19 02:07:35 +0000
committer Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> 2020-06-19 02:07:35 +0000
commitd3cc05fe3767d39f55e290731c395f79cbc7e143 (patch)
tree49a38f6ec96fbad81c582f22b2f665757dae31cc
parentcec50cfc7aab522f24572ad221c2aad81e245cb4 (diff)
parentb36f94690245698505ba77c8a1096080171978e0 (diff)
Merge "Include binder stats in battery stats" am: b36f946902
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/11856226 Change-Id: If03e13360110d75e8bc86ac15ab0a826ef84598f
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java156
-rw-r--r--core/java/com/android/internal/os/BinderCallsStats.java64
-rw-r--r--core/java/com/android/internal/os/BinderInternal.java3
-rw-r--r--core/java/com/android/internal/os/BinderTransactionNameResolver.java89
-rw-r--r--core/tests/coretests/src/com/android/internal/os/BatteryStatsBinderCallStatsTest.java93
-rw-r--r--core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java1
-rw-r--r--core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java4
-rw-r--r--services/core/java/android/os/BatteryStatsInternal.java2
-rw-r--r--services/core/java/com/android/server/am/BatteryStatsService.java4
9 files changed, 365 insertions, 51 deletions
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 2f3def240341..58ba16bc61dd 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -39,6 +39,7 @@ import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.BatteryManager;
import android.os.BatteryStats;
+import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBatteryPropertiesRegistrar;
@@ -70,6 +71,7 @@ import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.IntArray;
import android.util.KeyValueListParser;
@@ -120,6 +122,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -6127,10 +6130,11 @@ public class BatteryStatsImpl extends BatteryStats {
* Records timing data related to an incoming Binder call in order to attribute
* the power consumption to the calling app.
*/
- public void noteBinderCallStats(int workSourceUid,
+ public void noteBinderCallStats(int workSourceUid, long incrementalCallCount,
Collection<BinderCallsStats.CallStat> callStats) {
synchronized (this) {
- getUidStatsLocked(workSourceUid).noteBinderCallStatsLocked(callStats);
+ getUidStatsLocked(workSourceUid).noteBinderCallStatsLocked(incrementalCallCount,
+ callStats);
}
}
@@ -6577,6 +6581,65 @@ public class BatteryStatsImpl extends BatteryStats {
}
/**
+ * Accumulates stats for a specific binder transaction.
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ protected static class BinderCallStats {
+ static final Comparator<BinderCallStats> COMPARATOR =
+ Comparator.comparing(BinderCallStats::getClassName)
+ .thenComparing(BinderCallStats::getMethodName);
+
+ public Class<? extends Binder> binderClass;
+ public int transactionCode;
+ public String methodName;
+
+ public long callCount;
+ public long recordedCallCount;
+ public long recordedCpuTimeMicros;
+
+
+ @Override
+ public int hashCode() {
+ return binderClass.hashCode() * 31 + transactionCode;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof BinderCallStats)) {
+ return false;
+ }
+ BinderCallStats bcsk = (BinderCallStats) obj;
+ return binderClass.equals(bcsk.binderClass) && transactionCode == bcsk.transactionCode;
+ }
+
+ public String getClassName() {
+ return binderClass.getName();
+ }
+
+ public String getMethodName() {
+ return methodName;
+ }
+
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public void ensureMethodName(BinderTransactionNameResolver resolver) {
+ if (methodName == null) {
+ methodName = resolver.getMethodName(binderClass, transactionCode);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "BinderCallStats{"
+ + binderClass
+ + " transaction=" + transactionCode
+ + " callCount=" + callCount
+ + " recordedCallCount=" + recordedCallCount
+ + " recorderCpuTimeMicros=" + recordedCpuTimeMicros
+ + "}";
+ }
+ }
+
+ /**
* The statistics associated with a particular uid.
*/
public static class Uid extends BatteryStats.Uid {
@@ -6749,6 +6812,16 @@ public class BatteryStatsImpl extends BatteryStats {
*/
final SparseArray<Pid> mPids = new SparseArray<>();
+ /**
+ * Grand total of system server binder calls made by this uid.
+ */
+ private long mBinderCallCount;
+
+ /**
+ * Detailed information about system server binder calls made by this uid.
+ */
+ private final ArraySet<BinderCallStats> mBinderCallStats = new ArraySet<>();
+
public Uid(BatteryStatsImpl bsi, int uid) {
mBsi = bsi;
mUid = uid;
@@ -6857,6 +6930,14 @@ public class BatteryStatsImpl extends BatteryStats {
return nullIfAllZeros(mProcStateScreenOffTimeMs[procState], which);
}
+ public long getBinderCallCount() {
+ return mBinderCallCount;
+ }
+
+ public ArraySet<BinderCallStats> getBinderCallStats() {
+ return mBinderCallStats;
+ }
+
public void addIsolatedUid(int isolatedUid) {
if (mChildUids == null) {
mChildUids = new IntArray();
@@ -7945,6 +8026,9 @@ public class BatteryStatsImpl extends BatteryStats {
}
mPackageStats.clear();
+ mBinderCallCount = 0;
+ mBinderCallStats.clear();
+
mLastStepUserTime = mLastStepSystemTime = 0;
mCurStepUserTime = mCurStepSystemTime = 0;
@@ -8700,15 +8784,38 @@ public class BatteryStatsImpl extends BatteryStats {
}
}
+ // Reusable object used as a key to lookup values in mBinderCallStats
+ private static BinderCallStats sTempBinderCallStats = new BinderCallStats();
+
/**
* Notes incoming binder call stats associated with this work source UID.
*/
- public void noteBinderCallStatsLocked(Collection<BinderCallsStats.CallStat> callStats) {
+ public void noteBinderCallStatsLocked(long incrementalCallCount,
+ Collection<BinderCallsStats.CallStat> callStats) {
if (DEBUG) {
- Slog.d(TAG, "noteBinderCalls() workSourceUid = [" + mUid + "], callStats = ["
+ Slog.d(TAG, "noteBinderCalls() workSourceUid = [" + mUid + "], "
+ + " incrementalCallCount: " + incrementalCallCount + " callStats = ["
+ new ArrayList<>(callStats) + "]");
}
- // TODO(dplotnikov): finish the implementation by actually remembering the stats
+ mBinderCallCount += incrementalCallCount;
+ for (BinderCallsStats.CallStat stat : callStats) {
+ BinderCallStats bcs;
+ sTempBinderCallStats.binderClass = stat.binderClass;
+ sTempBinderCallStats.transactionCode = stat.transactionCode;
+ int index = mBinderCallStats.indexOf(sTempBinderCallStats);
+ if (index >= 0) {
+ bcs = mBinderCallStats.valueAt(index);
+ } else {
+ bcs = new BinderCallStats();
+ bcs.binderClass = stat.binderClass;
+ bcs.transactionCode = stat.transactionCode;
+ mBinderCallStats.add(bcs);
+ }
+
+ bcs.callCount += stat.incrementalCallCount;
+ bcs.recordedCallCount = stat.recordedCallCount;
+ bcs.recordedCpuTimeMicros = stat.cpuTimeMicros;
+ }
}
/**
@@ -13220,6 +13327,45 @@ public class BatteryStatsImpl extends BatteryStats {
pw.print(uid.getUserCpuTimeUs(STATS_SINCE_CHARGED) / 1000); pw.print(" ");
pw.println(uid.getSystemCpuTimeUs(STATS_SINCE_CHARGED) / 1000);
}
+ pw.println("Per UID system service calls:");
+ BinderTransactionNameResolver nameResolver = new BinderTransactionNameResolver();
+ for (int i = 0; i < size; i++) {
+ int u = mUidStats.keyAt(i);
+ Uid uid = mUidStats.get(u);
+ long binderCallCount = uid.getBinderCallCount();
+ if (binderCallCount != 0) {
+ pw.print(" ");
+ pw.print(u);
+ pw.print(" system service calls: ");
+ pw.print(binderCallCount);
+ ArraySet<BinderCallStats> binderCallStats = uid.getBinderCallStats();
+ if (!binderCallStats.isEmpty()) {
+ pw.println(", including");
+ BinderCallStats[] bcss = new BinderCallStats[binderCallStats.size()];
+ binderCallStats.toArray(bcss);
+ for (BinderCallStats bcs : bcss) {
+ bcs.ensureMethodName(nameResolver);
+ }
+ Arrays.sort(bcss, BinderCallStats.COMPARATOR);
+ for (BinderCallStats callStats : bcss) {
+ pw.print(" ");
+ pw.print(callStats.getClassName());
+ pw.print('#');
+ pw.print(callStats.getMethodName());
+ pw.print(" calls: ");
+ pw.print(callStats.callCount);
+ if (callStats.recordedCallCount != 0) {
+ pw.print(" time: ");
+ pw.print(callStats.callCount * callStats.recordedCpuTimeMicros
+ / callStats.recordedCallCount / 1000);
+ }
+ pw.println();
+ }
+ } else {
+ pw.println();
+ }
+ }
+ }
pw.println("Per UID CPU active time in ms:");
for (int i = 0; i < size; i++) {
int u = mUidStats.keyAt(i);
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
index 6135072f6c3b..cc55cff262a3 100644
--- a/core/java/com/android/internal/os/BinderCallsStats.java
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -36,13 +36,10 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BinderInternal.CallSession;
import java.io.PrintWriter;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
-import java.util.Map;
import java.util.Queue;
import java.util.Random;
import java.util.concurrent.ConcurrentLinkedQueue;
@@ -115,8 +112,13 @@ public class BinderCallsStats implements BinderInternal.Observer {
for (int i = 0; i < size; i++) {
UidEntry uidEntry = mUidEntries.get(mSendUidsToObserver.valueAt(i));
if (uidEntry != null) {
+ ArrayMap<CallStatKey, CallStat> callStats = uidEntry.mCallStats;
mCallStatsObserver.noteCallStats(uidEntry.workSourceUid,
- uidEntry.getCallStatsList());
+ uidEntry.incrementalCallCount, callStats.values());
+ uidEntry.incrementalCallCount = 0;
+ for (int j = callStats.size() - 1; j >= 0; j--) {
+ callStats.valueAt(j).incrementalCallCount = 0;
+ }
}
}
mSendUidsToObserver.clear();
@@ -233,6 +235,7 @@ public class BinderCallsStats implements BinderInternal.Observer {
final UidEntry uidEntry = getUidEntry(workSourceUid);
uidEntry.callCount++;
+ uidEntry.incrementalCallCount++;
if (recordCall) {
uidEntry.cpuTimeMicros += duration;
@@ -248,6 +251,7 @@ public class BinderCallsStats implements BinderInternal.Observer {
}
callStat.callCount++;
+ callStat.incrementalCallCount++;
callStat.recordedCallCount++;
callStat.cpuTimeMicros += duration;
callStat.maxCpuTimeMicros = Math.max(callStat.maxCpuTimeMicros, duration);
@@ -269,6 +273,7 @@ public class BinderCallsStats implements BinderInternal.Observer {
screenInteractive);
if (callStat != null) {
callStat.callCount++;
+ callStat.incrementalCallCount++;
}
}
if (mCallStatsObserver != null && !UserHandle.isCore(workSourceUid)) {
@@ -307,30 +312,6 @@ public class BinderCallsStats implements BinderInternal.Observer {
}
}
- @Nullable
- private static Method getDefaultTransactionNameMethod(Class<? extends Binder> binder) {
- try {
- return binder.getMethod("getDefaultTransactionName", int.class);
- } catch (NoSuchMethodException e) {
- // The method might not be present for stubs not generated with AIDL.
- return null;
- }
- }
-
- @Nullable
- private static String resolveTransactionCode(Method getDefaultTransactionName,
- int transactionCode) {
- String resolvedCode = null;
- if (getDefaultTransactionName != null) {
- try {
- resolvedCode = (String) getDefaultTransactionName.invoke(null, transactionCode);
- } catch (IllegalAccessException | InvocationTargetException | ClassCastException e) {
- throw new RuntimeException(e);
- }
- }
- return resolvedCode == null ? String.valueOf(transactionCode) : resolvedCode;
- }
-
/**
* This method is expensive to call.
*/
@@ -369,28 +350,23 @@ public class BinderCallsStats implements BinderInternal.Observer {
// Resolve codes outside of the lock since it can be slow.
ExportedCallStat previous = null;
- // Cache the previous method/transaction code.
- Method getDefaultTransactionName = null;
String previousMethodName = null;
resultCallStats.sort(BinderCallsStats::compareByBinderClassAndCode);
+ BinderTransactionNameResolver resolver = new BinderTransactionNameResolver();
for (ExportedCallStat exported : resultCallStats) {
final boolean isClassDifferent = previous == null
|| !previous.className.equals(exported.className);
- if (isClassDifferent) {
- getDefaultTransactionName = getDefaultTransactionNameMethod(exported.binderClass);
- }
-
final boolean isCodeDifferent = previous == null
|| previous.transactionCode != exported.transactionCode;
final String methodName;
if (isClassDifferent || isCodeDifferent) {
- methodName = resolveTransactionCode(
- getDefaultTransactionName, exported.transactionCode);
+ methodName = resolver.getMethodName(exported.binderClass, exported.transactionCode);
} else {
methodName = previousMethodName;
}
previousMethodName = methodName;
exported.methodName = methodName;
+ previous = exported;
}
// Debug entries added to help validate the data.
@@ -675,8 +651,10 @@ public class BinderCallsStats implements BinderInternal.Observer {
public long maxRequestSizeBytes;
public long maxReplySizeBytes;
public long exceptionCount;
+ // Call count since reset
+ public long incrementalCallCount;
- CallStat(int callingUid, Class<? extends Binder> binderClass, int transactionCode,
+ public CallStat(int callingUid, Class<? extends Binder> binderClass, int transactionCode,
boolean screenInteractive) {
this.callingUid = callingUid;
this.binderClass = binderClass;
@@ -686,12 +664,14 @@ public class BinderCallsStats implements BinderInternal.Observer {
@Override
public String toString() {
+ // This is expensive, but CallStat.toString() is only used for debugging.
+ String methodName = new BinderTransactionNameResolver().getMethodName(binderClass,
+ transactionCode);
return "CallStat{"
+ "callingUid=" + callingUid
- + ", transaction=" + binderClass.getSimpleName()
- + '.' + resolveTransactionCode(
- getDefaultTransactionNameMethod(binderClass), transactionCode)
+ + ", transaction=" + binderClass.getSimpleName() + '.' + methodName
+ ", callCount=" + callCount
+ + ", incrementalCallCount=" + incrementalCallCount
+ ", recordedCallCount=" + recordedCallCount
+ ", cpuTimeMicros=" + cpuTimeMicros
+ ", latencyMicros=" + latencyMicros
@@ -744,13 +724,15 @@ public class BinderCallsStats implements BinderInternal.Observer {
// Approximate total CPU usage can be computed by
// cpuTimeMicros * callCount / recordedCallCount
public long cpuTimeMicros;
+ // Call count that gets reset after delivery to BatteryStats
+ public long incrementalCallCount;
UidEntry(int uid) {
this.workSourceUid = uid;
}
// Aggregate time spent per each call name: call_desc -> cpu_time_micros
- private Map<CallStatKey, CallStat> mCallStats = new ArrayMap<>();
+ private ArrayMap<CallStatKey, CallStat> mCallStats = new ArrayMap<>();
private CallStatKey mTempKey = new CallStatKey();
@Nullable
diff --git a/core/java/com/android/internal/os/BinderInternal.java b/core/java/com/android/internal/os/BinderInternal.java
index 7253307feb63..feb5aab94adc 100644
--- a/core/java/com/android/internal/os/BinderInternal.java
+++ b/core/java/com/android/internal/os/BinderInternal.java
@@ -141,7 +141,8 @@ public class BinderInternal {
/**
* Notes incoming binder call stats associated with this work source UID.
*/
- void noteCallStats(int workSourceUid, Collection<BinderCallsStats.CallStat> callStats);
+ void noteCallStats(int workSourceUid, long incrementalCallCount,
+ Collection<BinderCallsStats.CallStat> callStats);
}
/**
diff --git a/core/java/com/android/internal/os/BinderTransactionNameResolver.java b/core/java/com/android/internal/os/BinderTransactionNameResolver.java
new file mode 100644
index 000000000000..5f6f427d344c
--- /dev/null
+++ b/core/java/com/android/internal/os/BinderTransactionNameResolver.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import android.os.Binder;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+
+/**
+ * Maps a binder class and transaction code to the default transaction name. Since this
+ * resolution is class-based as opposed to instance-based, any custom implementation of
+ * {@link Binder#getTransactionName} will be ignored.
+ *
+ * The class is NOT thread safe
+ *
+ * @hide
+ */
+@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+public class BinderTransactionNameResolver {
+ private static final Method NO_GET_DEFAULT_TRANSACTION_NAME_METHOD;
+
+ /**
+ * Generates the default transaction method name, which is just the transaction code.
+ * Used when the binder does not define a static "getDefaultTransactionName" method.
+ *
+ * @hide
+ */
+ public static String noDefaultTransactionName(int transactionCode) {
+ return String.valueOf(transactionCode);
+ }
+
+ static {
+ try {
+ NO_GET_DEFAULT_TRANSACTION_NAME_METHOD = BinderTransactionNameResolver.class.getMethod(
+ "noDefaultTransactionName", int.class);
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private final HashMap<Class<? extends Binder>, Method>
+ mGetDefaultTransactionNameMethods = new HashMap<>();
+
+ /**
+ * Given a binder class name and transaction code, returns the corresponding method name.
+ *
+ * @hide
+ */
+ public String getMethodName(Class<? extends Binder> binderClass, int transactionCode) {
+ Method method = mGetDefaultTransactionNameMethods.get(binderClass);
+ if (method == null) {
+ try {
+ method = binderClass.getMethod("getDefaultTransactionName", int.class);
+ } catch (NoSuchMethodException e) {
+ method = NO_GET_DEFAULT_TRANSACTION_NAME_METHOD;
+ }
+ if (method.getReturnType() != String.class
+ || !Modifier.isStatic(method.getModifiers())) {
+ method = NO_GET_DEFAULT_TRANSACTION_NAME_METHOD;
+ }
+ mGetDefaultTransactionNameMethods.put(binderClass, method);
+ }
+
+ try {
+ return (String) method.invoke(null, transactionCode);
+ } catch (IllegalAccessException | InvocationTargetException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsBinderCallStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsBinderCallStatsTest.java
new file mode 100644
index 000000000000..3e67b8bffa63
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsBinderCallStatsTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import android.os.Binder;
+import android.os.Process;
+import android.util.ArraySet;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import junit.framework.TestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * Test cases for android.os.BatteryStats, system server Binder call stats.
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class BatteryStatsBinderCallStatsTest extends TestCase {
+
+ private static final int TRANSACTION_CODE = 100;
+
+ /**
+ * Test BatteryStatsImpl.Uid.noteBinderCallStats.
+ */
+ @Test
+ public void testNoteBinderCallStats() throws Exception {
+ final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
+ MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
+
+ int callingUid = Process.FIRST_APPLICATION_UID + 1;
+ int workSourceUid = Process.FIRST_APPLICATION_UID + 1;
+
+ Collection<BinderCallsStats.CallStat> callStats = new ArrayList<>();
+ BinderCallsStats.CallStat stat1 = new BinderCallsStats.CallStat(callingUid,
+ MockBinder.class, TRANSACTION_CODE, true /*screenInteractive */);
+ stat1.incrementalCallCount = 21;
+ stat1.recordedCallCount = 5;
+ stat1.cpuTimeMicros = 1000;
+ callStats.add(stat1);
+
+ bi.noteBinderCallStats(workSourceUid, 42, callStats);
+
+ callStats.clear();
+ BinderCallsStats.CallStat stat2 = new BinderCallsStats.CallStat(callingUid,
+ MockBinder.class, TRANSACTION_CODE, true /*screenInteractive */);
+ stat2.incrementalCallCount = 9;
+ stat2.recordedCallCount = 8;
+ stat2.cpuTimeMicros = 500;
+ callStats.add(stat2);
+
+ bi.noteBinderCallStats(workSourceUid, 8, callStats);
+
+ BatteryStatsImpl.Uid uid = bi.getUidStatsLocked(workSourceUid);
+ assertEquals(42 + 8, uid.getBinderCallCount());
+
+ BinderTransactionNameResolver resolver = new BinderTransactionNameResolver();
+ ArraySet<BatteryStatsImpl.BinderCallStats> stats = uid.getBinderCallStats();
+ assertEquals(1, stats.size());
+ BatteryStatsImpl.BinderCallStats value = stats.valueAt(0);
+ value.ensureMethodName(resolver);
+ assertEquals("testMethod", value.getMethodName());
+ assertEquals(21 + 9, value.callCount);
+ assertEquals(8, value.recordedCallCount);
+ assertEquals(500, value.recordedCpuTimeMicros);
+ }
+
+ private static class MockBinder extends Binder {
+ public static String getDefaultTransactionName(int txCode) {
+ return txCode == TRANSACTION_CODE ? "testMethod" : "unknown";
+ }
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
index 2ad8e18741f9..7807f019914e 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
@@ -23,6 +23,7 @@ import org.junit.runners.Suite;
@Suite.SuiteClasses({
BatteryStatsCpuTimesTest.class,
BatteryStatsBackgroundStatsTest.class,
+ BatteryStatsBinderCallStatsTest.class,
BatteryStatsCounterTest.class,
BatteryStatsDualTimerTest.class,
BatteryStatsDurationTimerTest.class,
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 60d4f563a7fe..b7d1c9b993d9 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
@@ -767,7 +767,9 @@ public class BinderCallsStatsTest {
bcs.setTrackScreenInteractive(false);
final ArrayList<BinderCallsStats.CallStat> callStatsList = new ArrayList<>();
- bcs.setCallStatsObserver((workSourceUid, callStats) -> callStatsList.addAll(callStats));
+ bcs.setCallStatsObserver(
+ (workSourceUid, incrementalCallCount, callStats) -> callStatsList.addAll(
+ callStats));
Binder binder = new Binder();
diff --git a/services/core/java/android/os/BatteryStatsInternal.java b/services/core/java/android/os/BatteryStatsInternal.java
index 5c5edb2bcd49..7cf5fd621f18 100644
--- a/services/core/java/android/os/BatteryStatsInternal.java
+++ b/services/core/java/android/os/BatteryStatsInternal.java
@@ -49,6 +49,6 @@ public abstract class BatteryStatsInternal {
/**
* Informs battery stats of binder stats for the given work source UID.
*/
- public abstract void noteBinderCallStats(int workSourceUid,
+ public abstract void noteBinderCallStats(int workSourceUid, long incrementalBinderCallCount,
Collection<BinderCallsStats.CallStat> callStats);
}
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 20b67e226555..5081b360b4fe 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -226,9 +226,9 @@ public final class BatteryStatsService extends IBatteryStats.Stub
}
@Override
- public void noteBinderCallStats(int workSourceUid,
+ public void noteBinderCallStats(int workSourceUid, long incrementatCallCount,
Collection<BinderCallsStats.CallStat> callStats) {
- mStats.noteBinderCallStats(workSourceUid, callStats);
+ mStats.noteBinderCallStats(workSourceUid, incrementatCallCount, callStats);
}
}