Merge "Add a flag to disable optional dimensions."
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
index 2c272de..7f4d8a2 100644
--- a/core/java/com/android/internal/os/BinderCallsStats.java
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -52,6 +52,8 @@
     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 @@
     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 @@
             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 @@
 
                 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 @@
         }
     }
 
+    /**
+     * 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 b3d9ca7..c059721 100644
--- a/core/java/com/android/internal/os/LooperStats.java
+++ b/core/java/com/android/internal/os/LooperStats.java
@@ -39,6 +39,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;
 
     @GuardedBy("mLock")
     private final SparseArray<Entry> mEntries = new SparseArray<>(512);
@@ -54,6 +55,7 @@
     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 @@
         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 1d35143..e375af3 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 @@
         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 @@
             });
             setSamplingInterval(1);
             setAddDebugEntries(false);
+            setTrackScreenInteractive(true);
+            setTrackDirectCallerUid(true);
             if (deviceState != null) {
                 setDeviceState(deviceState.getReadonlyClient());
             }
@@ -701,6 +764,10 @@
         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 79b8477..3edf5f8 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 @@
         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 @@
             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 eafa0e2..e510259 100644
--- a/services/core/java/com/android/server/BinderCallsStatsService.java
+++ b/services/core/java/com/android/server/BinderCallsStatsService.java
@@ -121,6 +121,8 @@
         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 @@
             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 9184128..c334540 100644
--- a/services/core/java/com/android/server/LooperStatsService.java
+++ b/services/core/java/com/android/server/LooperStatsService.java
@@ -51,16 +51,19 @@
     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 @@
 
         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 @@
         }
     }
 
+    private void setTrackScreenInteractive(boolean enabled) {
+        if (mTrackScreenInteractive != enabled) {
+            mTrackScreenInteractive = enabled;
+            mStats.reset();
+        }
+    }
+
     private void setSamplingInterval(int samplingInterval) {
         if (samplingInterval > 0) {
             mStats.setSamplingInterval(samplingInterval);