diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java index 70b1ad49d8b84..aa42979ed53cf 100644 --- a/core/java/com/android/internal/os/BinderCallsStats.java +++ b/core/java/com/android/internal/os/BinderCallsStats.java @@ -56,6 +56,7 @@ public class BinderCallsStats implements BinderInternal.Observer { public static final int PERIODIC_SAMPLING_INTERVAL_DEFAULT = 1000; public static final boolean DEFAULT_TRACK_SCREEN_INTERACTIVE = false; public static final boolean DEFAULT_TRACK_DIRECT_CALLING_UID = true; + public static final boolean DEFAULT_IGNORE_BATTERY_STATUS = false; public static final int MAX_BINDER_CALL_STATS_COUNT_DEFAULT = 1500; private static final String DEBUG_ENTRY_PREFIX = "__DEBUG_"; @@ -95,6 +96,7 @@ public class BinderCallsStats implements BinderInternal.Observer { private boolean mAddDebugEntries = false; private boolean mTrackDirectCallingUid = DEFAULT_TRACK_DIRECT_CALLING_UID; private boolean mTrackScreenInteractive = DEFAULT_TRACK_SCREEN_INTERACTIVE; + private boolean mIgnoreBatteryStatus = DEFAULT_IGNORE_BATTERY_STATUS; private CachedDeviceState.Readonly mDeviceState; private CachedDeviceState.TimeInStateStopwatch mBatteryStopwatch; @@ -185,8 +187,7 @@ public class BinderCallsStats implements BinderInternal.Observer { public CallSession callStarted(Binder binder, int code, int workSourceUid) { noteNativeThreadId(); - if (!mRecordingAllTransactionsForUid - && (mDeviceState == null || mDeviceState.isCharging())) { + if (!canCollect()) { return null; } @@ -255,8 +256,7 @@ public class BinderCallsStats implements BinderInternal.Observer { synchronized (mLock) { // This was already checked in #callStart but check again while synchronized. - if (!mRecordingAllTransactionsForUid - && (mDeviceState == null || mDeviceState.isCharging())) { + if (!canCollect()) { return; } @@ -372,6 +372,22 @@ public class BinderCallsStats implements BinderInternal.Observer { mCallStatsObserver.noteBinderThreadNativeIds(getNativeTids()); } + private boolean canCollect() { + if (mRecordingAllTransactionsForUid) { + return true; + } + if (mIgnoreBatteryStatus) { + return true; + } + if (mDeviceState == null) { + return false; + } + if (mDeviceState.isCharging()) { + return false; + } + return true; + } + /** * This method is expensive to call. */ @@ -671,6 +687,18 @@ public class BinderCallsStats implements BinderInternal.Observer { } } + /** + * Whether to ignore battery status when collecting stats + */ + public void setIgnoreBatteryStatus(boolean ignored) { + synchronized (mLock) { + if (ignored != mIgnoreBatteryStatus) { + mIgnoreBatteryStatus = ignored; + reset(); + } + } + } + /** * Marks the specified work source UID for total binder call tracking: detailed information * will be recorded for all calls from this source ID. diff --git a/core/java/com/android/internal/os/LooperStats.java b/core/java/com/android/internal/os/LooperStats.java index 932ff572219f6..2805dccffe506 100644 --- a/core/java/com/android/internal/os/LooperStats.java +++ b/core/java/com/android/internal/os/LooperStats.java @@ -40,6 +40,7 @@ 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; + public static final boolean DEFAULT_IGNORE_BATTERY_STATUS = false; @GuardedBy("mLock") private final SparseArray mEntries = new SparseArray<>(512); @@ -56,6 +57,7 @@ public class LooperStats implements Looper.Observer { private long mStartElapsedTime = SystemClock.elapsedRealtime(); private boolean mAddDebugEntries = false; private boolean mTrackScreenInteractive = false; + private boolean mIgnoreBatteryStatus = DEFAULT_IGNORE_BATTERY_STATUS; public LooperStats(int samplingInterval, int entriesSizeCap) { this.mSamplingInterval = samplingInterval; @@ -139,8 +141,16 @@ public class LooperStats implements Looper.Observer { } private boolean deviceStateAllowsCollection() { - // Do not collect data if on charger or the state is not set. - return mDeviceState != null && !mDeviceState.isCharging(); + if (mIgnoreBatteryStatus) { + return true; + } + if (mDeviceState == null) { + return false; + } + if (mDeviceState.isCharging()) { + return false; + } + return true; } /** Returns an array of {@link ExportedEntry entries} with the aggregated statistics. */ @@ -225,6 +235,10 @@ public class LooperStats implements Looper.Observer { mTrackScreenInteractive = enabled; } + public void setIgnoreBatteryStatus(boolean ignore) { + mIgnoreBatteryStatus = ignore; + } + @Nullable private Entry findEntry(Message msg, boolean allowCreateNew) { final boolean isInteractive = mTrackScreenInteractive 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 3117935fb3edc..561c549676da8 100644 --- a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java @@ -46,7 +46,6 @@ import java.io.StringWriter; 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; @@ -427,6 +426,19 @@ public class BinderCallsStatsTest { assertEquals(0, bcs.getUidEntries().size()); } + @Test + public void testIgnoreBatteryStatusFlag() { + TestBinderCallsStats bcs = new TestBinderCallsStats(); + mDeviceState.setCharging(true); + bcs.setIgnoreBatteryStatus(true); + + Binder binder = new Binder(); + CallSession callSession = bcs.callStarted(binder, 1, WORKSOURCE_UID); + bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID); + + assertEquals(1, bcs.getExportedCallStats().size()); + } + @Test public void testScreenOff() { TestBinderCallsStats bcs = new TestBinderCallsStats(); 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 7917a06cb9b7b..fdfc7ac5587cc 100644 --- a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java +++ b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java @@ -321,6 +321,23 @@ public final class LooperStatsTest { assertThat(entries).hasSize(0); } + @Test + public void testDataCollectedIfIgnoreBatteryStatusFlagSet() { + TestableLooperStats looperStats = new TestableLooperStats(1, 100); + mDeviceState.setCharging(true); + looperStats.setIgnoreBatteryStatus(true); + + Object token1 = looperStats.messageDispatchStarting(); + looperStats.messageDispatched(token1, mHandlerFirst.obtainMessage(1000)); + Object token2 = looperStats.messageDispatchStarting(); + looperStats.dispatchingThrewException(token2, mHandlerFirst.obtainMessage(1000), + new IllegalArgumentException()); + + List entries = looperStats.getEntries(); + assertThat(entries).hasSize(1); + + } + @Test public void testScreenStateCollected() { TestableLooperStats looperStats = new TestableLooperStats(1, 100); diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java index 66ac889ff2ca2..fdda239e7fde1 100644 --- a/services/core/java/com/android/server/BinderCallsStatsService.java +++ b/services/core/java/com/android/server/BinderCallsStatsService.java @@ -131,6 +131,7 @@ public class BinderCallsStatsService extends Binder { 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 static final String SETTINGS_IGNORE_BATTERY_STATUS_KEY = "ignore_battery_status"; private boolean mEnabled; private final Uri mUri = Settings.Global.getUriFor(Settings.Global.BINDER_CALLS_STATS); @@ -184,6 +185,9 @@ public class BinderCallsStatsService extends Binder { mBinderCallsStats.setTrackDirectCallerUid( mParser.getBoolean(SETTINGS_TRACK_DIRECT_CALLING_UID_KEY, BinderCallsStats.DEFAULT_TRACK_DIRECT_CALLING_UID)); + mBinderCallsStats.setIgnoreBatteryStatus( + mParser.getBoolean(SETTINGS_IGNORE_BATTERY_STATUS_KEY, + BinderCallsStats.DEFAULT_IGNORE_BATTERY_STATUS)); final boolean enabled = diff --git a/services/core/java/com/android/server/LooperStatsService.java b/services/core/java/com/android/server/LooperStatsService.java index 965b64bd98536..de40b5207a6ea 100644 --- a/services/core/java/com/android/server/LooperStatsService.java +++ b/services/core/java/com/android/server/LooperStatsService.java @@ -52,6 +52,7 @@ public class LooperStatsService extends Binder { 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 SETTINGS_IGNORE_BATTERY_STATUS_KEY = "ignore_battery_status"; private static final String DEBUG_SYS_LOOPER_STATS_ENABLED = "debug.sys.looper_stats_enabled"; private static final int DEFAULT_SAMPLING_INTERVAL = 1000; @@ -64,6 +65,7 @@ public class LooperStatsService extends Binder { // Default should be false so that the first call to #setEnabled installed the looper observer. private boolean mEnabled = false; private boolean mTrackScreenInteractive = false; + private boolean mIgnoreBatteryStatus = LooperStats.DEFAULT_IGNORE_BATTERY_STATUS; private LooperStatsService(Context context, LooperStats stats) { this.mContext = context; @@ -85,6 +87,9 @@ public class LooperStatsService extends Binder { setTrackScreenInteractive( parser.getBoolean(SETTINGS_TRACK_SCREEN_INTERACTIVE_KEY, DEFAULT_TRACK_SCREEN_INTERACTIVE)); + setIgnoreBatteryStatus( + parser.getBoolean(SETTINGS_IGNORE_BATTERY_STATUS_KEY, + LooperStats.DEFAULT_IGNORE_BATTERY_STATUS)); // Manually specified value takes precedence over Settings. setEnabled(SystemProperties.getBoolean( DEBUG_SYS_LOOPER_STATS_ENABLED, @@ -168,6 +173,14 @@ public class LooperStatsService extends Binder { } } + private void setIgnoreBatteryStatus(boolean ignore) { + if (mIgnoreBatteryStatus != ignore) { + mStats.setIgnoreBatteryStatus(ignore); + mIgnoreBatteryStatus = ignore; + mStats.reset(); + } + } + private void setSamplingInterval(int samplingInterval) { if (samplingInterval > 0) { mStats.setSamplingInterval(samplingInterval);