diff options
6 files changed, 160 insertions, 3 deletions
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java index 2c272dea073b..7f4d8a2d0587 100644 --- a/core/java/com/android/internal/os/BinderCallsStats.java +++ b/core/java/com/android/internal/os/BinderCallsStats.java @@ -52,6 +52,8 @@ public class BinderCallsStats implements BinderInternal.Observer { public static final boolean ENABLED_DEFAULT = true; public static final boolean DETAILED_TRACKING_DEFAULT = true; public static final int PERIODIC_SAMPLING_INTERVAL_DEFAULT = 100; + public static final boolean DEFAULT_TRACK_SCREEN_INTERACTIVE = false; + public static final boolean DEFAULT_TRACK_DIRECT_CALLING_UID = true; public static final int MAX_BINDER_CALL_STATS_COUNT_DEFAULT = 5000; private static final String DEBUG_ENTRY_PREFIX = "__DEBUG_"; @@ -85,6 +87,8 @@ public class BinderCallsStats implements BinderInternal.Observer { private long mStartElapsedTime = SystemClock.elapsedRealtime(); private long mCallStatsCount = 0; private boolean mAddDebugEntries = false; + private boolean mTrackDirectCallingUid = DEFAULT_TRACK_DIRECT_CALLING_UID; + private boolean mTrackScreenInteractive = DEFAULT_TRACK_SCREEN_INTERACTIVE; private CachedDeviceState.Readonly mDeviceState; private CachedDeviceState.TimeInStateStopwatch mBatteryStopwatch; @@ -160,7 +164,12 @@ public class BinderCallsStats implements BinderInternal.Observer { duration = 0; latencyDuration = 0; } - final int callingUid = getCallingUid(); + final boolean screenInteractive = mTrackScreenInteractive + ? mDeviceState.isScreenInteractive() + : OVERFLOW_SCREEN_INTERACTIVE; + final int callingUid = mTrackDirectCallingUid + ? getCallingUid() + : OVERFLOW_DIRECT_CALLING_UID; synchronized (mLock) { // This was already checked in #callStart but check again while synchronized. @@ -177,7 +186,7 @@ public class BinderCallsStats implements BinderInternal.Observer { final CallStat callStat = uidEntry.getOrCreate( callingUid, s.binderClass, s.transactionCode, - mDeviceState.isScreenInteractive(), + screenInteractive, mCallStatsCount >= mMaxBinderCallStatsCount); final boolean isNewCallStat = callStat.callCount == 0; if (isNewCallStat) { @@ -484,6 +493,30 @@ public class BinderCallsStats implements BinderInternal.Observer { } } + /** + * Whether to track the screen state. + */ + public void setTrackScreenInteractive(boolean enabled) { + synchronized (mLock) { + if (enabled != mTrackScreenInteractive) { + mTrackScreenInteractive = enabled; + reset(); + } + } + } + + /** + * Whether to track direct caller uid. + */ + public void setTrackDirectCallerUid(boolean enabled) { + synchronized (mLock) { + if (enabled != mTrackDirectCallingUid) { + mTrackDirectCallingUid = enabled; + reset(); + } + } + } + public void setAddDebugEntries(boolean addDebugEntries) { mAddDebugEntries = addDebugEntries; } diff --git a/core/java/com/android/internal/os/LooperStats.java b/core/java/com/android/internal/os/LooperStats.java index b3d9ca7670b5..c059721eb2d3 100644 --- a/core/java/com/android/internal/os/LooperStats.java +++ b/core/java/com/android/internal/os/LooperStats.java @@ -39,6 +39,7 @@ import java.util.concurrent.ThreadLocalRandom; public class LooperStats implements Looper.Observer { public static final String DEBUG_ENTRY_PREFIX = "__DEBUG_"; private static final int SESSION_POOL_SIZE = 50; + private static final boolean DISABLED_SCREEN_STATE_TRACKING_VALUE = false; @GuardedBy("mLock") private final SparseArray<Entry> mEntries = new SparseArray<>(512); @@ -54,6 +55,7 @@ public class LooperStats implements Looper.Observer { private long mStartCurrentTime = System.currentTimeMillis(); private long mStartElapsedTime = SystemClock.elapsedRealtime(); private boolean mAddDebugEntries = false; + private boolean mTrackScreenInteractive = false; public LooperStats(int samplingInterval, int entriesSizeCap) { this.mSamplingInterval = samplingInterval; @@ -218,9 +220,15 @@ public class LooperStats implements Looper.Observer { mSamplingInterval = samplingInterval; } + public void setTrackScreenInteractive(boolean enabled) { + mTrackScreenInteractive = enabled; + } + @Nullable private Entry findEntry(Message msg, boolean allowCreateNew) { - final boolean isInteractive = mDeviceState.isScreenInteractive(); + final boolean isInteractive = mTrackScreenInteractive + ? mDeviceState.isScreenInteractive() + : DISABLED_SCREEN_STATE_TRACKING_VALUE; final int id = Entry.idFor(msg, isInteractive); Entry entry; synchronized (mLock) { 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 1d35143e3fab..e375af3f7b0e 100644 --- a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java @@ -658,6 +658,67 @@ public class BinderCallsStatsTest { assertTrue(debugEntry3.latencyMicros >= 0); } + @Test + public void testTrackScreenInteractiveDisabled() { + TestBinderCallsStats bcs = new TestBinderCallsStats(); + bcs.setTrackScreenInteractive(false); + Binder binder = new Binder(); + + mDeviceState.setScreenInteractive(false); + CallSession callSession = bcs.callStarted(binder, 1, WORKSOURCE_UID); + bcs.time += 10; + bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID); + + mDeviceState.setScreenInteractive(true); + callSession = bcs.callStarted(binder, 1, WORKSOURCE_UID); + bcs.time += 1000; // shoud be ignored. + bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID); + + SparseArray<BinderCallsStats.UidEntry> uidEntries = bcs.getUidEntries(); + assertEquals(1, uidEntries.size()); + BinderCallsStats.UidEntry uidEntry = uidEntries.get(WORKSOURCE_UID); + Assert.assertNotNull(uidEntry); + assertEquals(2, uidEntry.callCount); + + List<BinderCallsStats.CallStat> callStatsList = new ArrayList(uidEntry.getCallStatsList()); + assertEquals(1, callStatsList.size()); + BinderCallsStats.CallStat callStats = callStatsList.get(0); + assertEquals(false, callStats.screenInteractive); + assertEquals(2, callStats.callCount); + assertEquals(2, callStats.recordedCallCount); + } + + @Test + public void testTrackCallingUidDisabled() { + TestBinderCallsStats bcs = new TestBinderCallsStats(); + bcs.setTrackDirectCallerUid(false); + Binder binder = new Binder(); + + bcs.setCallingUid(1); + CallSession callSession = bcs.callStarted(binder, 1, WORKSOURCE_UID); + bcs.time += 10; + bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID); + + bcs.setCallingUid(2); + callSession = bcs.callStarted(binder, 1, WORKSOURCE_UID); + bcs.time += 1000; // shoud be ignored. + bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID); + + SparseArray<BinderCallsStats.UidEntry> uidEntries = bcs.getUidEntries(); + assertEquals(1, uidEntries.size()); + BinderCallsStats.UidEntry uidEntry = uidEntries.get(WORKSOURCE_UID); + Assert.assertNotNull(uidEntry); + assertEquals(2, uidEntry.callCount); + + List<BinderCallsStats.CallStat> callStatsList = new ArrayList(uidEntry.getCallStatsList()); + assertEquals(1, callStatsList.size()); + BinderCallsStats.CallStat callStats = callStatsList.get(0); + assertEquals(-1, callStats.callingUid); + assertEquals(2, callStats.callCount); + assertEquals(2, callStats.recordedCallCount); + } + + class TestBinderCallsStats extends BinderCallsStats { public int callingUid = CALLING_UID; public long time = 1234; @@ -682,6 +743,8 @@ public class BinderCallsStatsTest { }); setSamplingInterval(1); setAddDebugEntries(false); + setTrackScreenInteractive(true); + setTrackDirectCallerUid(true); if (deviceState != null) { setDeviceState(deviceState.getReadonlyClient()); } @@ -701,6 +764,10 @@ public class BinderCallsStatsTest { protected int getCallingUid() { return callingUid; } + + protected void setCallingUid(int uid) { + callingUid = uid; + } } } diff --git a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java index 79b847754311..3edf5f87258b 100644 --- a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java +++ b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java @@ -476,6 +476,33 @@ public final class LooperStatsTest { assertThat(debugEntry3.totalLatencyMicros).isAtLeast(0L); } + @Test + public void testScreenStateTrackingDisabled() { + TestableLooperStats looperStats = new TestableLooperStats(1, 100); + looperStats.setTrackScreenInteractive(false); + + Message message = mHandlerFirst.obtainMessage(1000); + message.workSourceUid = 1000; + message.when = looperStats.getSystemUptimeMillis(); + + looperStats.tickUptime(30); + mDeviceState.setScreenInteractive(false); + Object token = looperStats.messageDispatchStarting(); + looperStats.messageDispatched(token, message); + + looperStats.tickUptime(30); + mDeviceState.setScreenInteractive(true); + token = looperStats.messageDispatchStarting(); + looperStats.messageDispatched(token, message); + + List<LooperStats.ExportedEntry> entries = looperStats.getEntries(); + assertThat(entries).hasSize(1); + LooperStats.ExportedEntry entry = entries.get(0); + assertThat(entry.isInteractive).isEqualTo(false); + assertThat(entry.messageCount).isEqualTo(2); + assertThat(entry.recordedMessageCount).isEqualTo(2); + } + private static void assertThrows(Class<? extends Exception> exceptionClass, Runnable r) { try { r.run(); @@ -501,6 +528,7 @@ public final class LooperStatsTest { super(samplingInterval, sizeCap); mSamplingInterval = samplingInterval; setAddDebugEntries(false); + setTrackScreenInteractive(true); if (deviceState != null) { setDeviceState(deviceState.getReadonlyClient()); } diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java index eafa0e2a6786..e51025943df4 100644 --- a/services/core/java/com/android/server/BinderCallsStatsService.java +++ b/services/core/java/com/android/server/BinderCallsStatsService.java @@ -121,6 +121,8 @@ 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_TRACK_SCREEN_INTERACTIVE_KEY = "track_screen_state"; + private static final String SETTINGS_TRACK_DIRECT_CALLING_UID_KEY = "track_calling_uid"; private static final String SETTINGS_MAX_CALL_STATS_KEY = "max_call_stats_count"; private boolean mEnabled; @@ -169,6 +171,12 @@ public class BinderCallsStatsService extends Binder { mBinderCallsStats.setMaxBinderCallStats(mParser.getInt( SETTINGS_MAX_CALL_STATS_KEY, BinderCallsStats.MAX_BINDER_CALL_STATS_COUNT_DEFAULT)); + mBinderCallsStats.setTrackScreenInteractive( + mParser.getBoolean(SETTINGS_TRACK_SCREEN_INTERACTIVE_KEY, + BinderCallsStats.DEFAULT_TRACK_SCREEN_INTERACTIVE)); + mBinderCallsStats.setTrackDirectCallerUid( + mParser.getBoolean(SETTINGS_TRACK_DIRECT_CALLING_UID_KEY, + BinderCallsStats.DEFAULT_TRACK_DIRECT_CALLING_UID)); final boolean enabled = diff --git a/services/core/java/com/android/server/LooperStatsService.java b/services/core/java/com/android/server/LooperStatsService.java index 9184128d466f..c334540f48cc 100644 --- a/services/core/java/com/android/server/LooperStatsService.java +++ b/services/core/java/com/android/server/LooperStatsService.java @@ -51,16 +51,19 @@ public class LooperStatsService extends Binder { private static final String LOOPER_STATS_SERVICE_NAME = "looper_stats"; private static final String SETTINGS_ENABLED_KEY = "enabled"; private static final String SETTINGS_SAMPLING_INTERVAL_KEY = "sampling_interval"; + private static final String SETTINGS_TRACK_SCREEN_INTERACTIVE_KEY = "track_screen_state"; private static final String DEBUG_SYS_LOOPER_STATS_ENABLED = "debug.sys.looper_stats_enabled"; private static final int DEFAULT_SAMPLING_INTERVAL = 100; private static final int DEFAULT_ENTRIES_SIZE_CAP = 2000; private static final boolean DEFAULT_ENABLED = true; + private static final boolean DEFAULT_TRACK_SCREEN_INTERACTIVE = false; private final Context mContext; private final LooperStats mStats; // Default should be false so that the first call to #setEnabled installed the looper observer. private boolean mEnabled = false; + private boolean mTrackScreenInteractive = false; private LooperStatsService(Context context, LooperStats stats) { this.mContext = context; @@ -79,6 +82,9 @@ public class LooperStatsService extends Binder { setSamplingInterval( parser.getInt(SETTINGS_SAMPLING_INTERVAL_KEY, DEFAULT_SAMPLING_INTERVAL)); + setTrackScreenInteractive( + parser.getBoolean(SETTINGS_TRACK_SCREEN_INTERACTIVE_KEY, + DEFAULT_TRACK_SCREEN_INTERACTIVE)); // Manually specified value takes precedence over Settings. setEnabled(SystemProperties.getBoolean( DEBUG_SYS_LOOPER_STATS_ENABLED, @@ -155,6 +161,13 @@ public class LooperStatsService extends Binder { } } + private void setTrackScreenInteractive(boolean enabled) { + if (mTrackScreenInteractive != enabled) { + mTrackScreenInteractive = enabled; + mStats.reset(); + } + } + private void setSamplingInterval(int samplingInterval) { if (samplingInterval > 0) { mStats.setSamplingInterval(samplingInterval); |