Merge "Merge "expose the UID in the EventLog API" into oc-dev am: 8ae5e04636 am: 21abf1cd20"
diff --git a/api/system-current.txt b/api/system-current.txt
index b86af54..ec31c2b 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -27295,6 +27295,7 @@
     method public java.lang.Object getTaggedData(int);
     method public long getTimestamp();
     method public int getType();
+    method public int getUid();
     method public boolean isLongCounterBucket();
     method public boolean isSubsetOf(android.metrics.LogMaker);
     method public boolean isValidValue(java.lang.Object);
@@ -46768,6 +46769,7 @@
     method public int getTag();
     method public int getThreadId();
     method public long getTimeNanos();
+    method public int getUid();
   }
 
   public deprecated class EventLogTags {
diff --git a/core/java/android/metrics/LogMaker.java b/core/java/android/metrics/LogMaker.java
index 3c6baa7..2bb43bd 100644
--- a/core/java/android/metrics/LogMaker.java
+++ b/core/java/android/metrics/LogMaker.java
@@ -170,6 +170,27 @@
     }
 
     /**
+     * This will be set by the system when the log is persisted.
+     * Client-supplied values will be ignored.
+     *
+     * @param uid to replace the existing setting.
+     * @hide
+     */
+    public LogMaker setUid(int uid) {
+        entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_UID, uid);
+        return this;
+    }
+
+    /**
+     * Remove the UID property.
+     * @hide
+     */
+    public LogMaker clearUid() {
+        entries.remove(MetricsEvent.RESERVED_FOR_LOGBUILDER_UID);
+        return this;
+    }
+
+    /**
      * The name of the counter or histogram.
      * Only useful for counter or histogram category objects.
      * @param name to replace the existing setting.
@@ -319,6 +340,16 @@
         }
     }
 
+    /** @return the UID of the log, or -1. */
+    public int getUid() {
+        Object obj = entries.get(MetricsEvent.RESERVED_FOR_LOGBUILDER_UID);
+        if (obj instanceof Integer) {
+            return (Integer) obj;
+        } else {
+            return -1;
+        }
+    }
+
     /** @return the name of the counter, or null. */
     public String getCounterName() {
         Object obj = entries.get(MetricsEvent.RESERVED_FOR_LOGBUILDER_NAME);
diff --git a/core/java/android/metrics/MetricsReader.java b/core/java/android/metrics/MetricsReader.java
index 5be977a..5f356ca 100644
--- a/core/java/android/metrics/MetricsReader.java
+++ b/core/java/android/metrics/MetricsReader.java
@@ -93,6 +93,7 @@
             }
             final LogMaker log = new LogMaker(objects)
                     .setTimestamp(eventTimestampMs)
+                    .setUid(event.getUid())
                     .setProcessId(event.getProcessId());
             if (log.getCategory() == MetricsEvent.METRICS_CHECKPOINT) {
                 if (log.getSubtype() == mCheckpointTag) {
@@ -155,11 +156,13 @@
     public static class Event {
         long mTimeMillis;
         int mPid;
+        int mUid;
         Object mData;
 
-        public Event(long timeMillis, int pid, Object data) {
+        public Event(long timeMillis, int pid, int uid, Object data) {
             mTimeMillis = timeMillis;
             mPid = pid;
+            mUid = uid;
             mData = data;
         }
 
@@ -167,6 +170,7 @@
             mTimeMillis = TimeUnit.MILLISECONDS.convert(
                     nativeEvent.getTimeNanos(), TimeUnit.NANOSECONDS);
             mPid = nativeEvent.getProcessId();
+            mUid = nativeEvent.getUid();
             mData = nativeEvent.getData();
         }
 
@@ -178,6 +182,10 @@
             return mPid;
         }
 
+        public int getUid() {
+            return mUid;
+        }
+
         public Object getData() {
             return mData;
         }
diff --git a/core/java/android/util/EventLog.java b/core/java/android/util/EventLog.java
index 6d4281b..92f218b 100644
--- a/core/java/android/util/EventLog.java
+++ b/core/java/android/util/EventLog.java
@@ -68,6 +68,7 @@
         private static final int THREAD_OFFSET = 8;
         private static final int SECONDS_OFFSET = 12;
         private static final int NANOSECONDS_OFFSET = 16;
+        private static final int UID_OFFSET = 24;
 
         // Layout for event log v1 format, v2 and v3 use HEADER_SIZE_OFFSET
         private static final int V1_PAYLOAD_START = 20;
@@ -91,6 +92,20 @@
             return mBuffer.getInt(PROCESS_OFFSET);
         }
 
+        /**
+         * @return the UID which wrote the log entry
+         * @hide
+         */
+        @SystemApi
+        public int getUid() {
+            try {
+                return mBuffer.getInt(UID_OFFSET);
+            } catch (IndexOutOfBoundsException e) {
+                // buffer won't contain the UID if the caller doesn't have permission.
+                return -1;
+            }
+        }
+
         /** @return the thread ID which wrote the log entry */
         public int getThreadId() {
             return mBuffer.getInt(THREAD_OFFSET);
diff --git a/core/tests/coretests/src/android/metrics/LogMakerTest.java b/core/tests/coretests/src/android/metrics/LogMakerTest.java
index 63c1f87..ada59cd 100644
--- a/core/tests/coretests/src/android/metrics/LogMakerTest.java
+++ b/core/tests/coretests/src/android/metrics/LogMakerTest.java
@@ -179,6 +179,14 @@
         assertEquals(-1, builder.getProcessId());
     }
 
+    public void testSetAndClearUid() {
+        LogMaker builder = new LogMaker(0);
+        builder.setUid(1);
+        assertEquals(1, builder.getUid());
+        builder.clearUid();
+        assertEquals(-1, builder.getUid());
+    }
+
     public void testGiantLogOmitted() {
         LogMaker badBuilder = new LogMaker(0);
         StringBuilder b = new StringBuilder();
diff --git a/core/tests/coretests/src/android/metrics/MetricsReaderTest.java b/core/tests/coretests/src/android/metrics/MetricsReaderTest.java
index d06f522..d10b351 100644
--- a/core/tests/coretests/src/android/metrics/MetricsReaderTest.java
+++ b/core/tests/coretests/src/android/metrics/MetricsReaderTest.java
@@ -26,6 +26,8 @@
 public class MetricsReaderTest extends TestCase {
     private static final int FULL_N = 10;
     private static final int CHECKPOINTED_N = 4;
+    private static final int PID = 1;
+    private static final int UID = 2;
 
     class FakeLogReader extends MetricsReader.LogReader {
         MetricsReader.Event[] mEvents;
@@ -36,7 +38,8 @@
             for (int i = 0; i < FULL_N; i++) {
                 mEvents[i] = new MetricsReader.Event(
                         1000L + i,
-                        1,
+                        PID,
+                        UID,
                         new LogMaker(i).serialize());
             }
         }
@@ -88,6 +91,13 @@
         }
     }
 
+    public void testPidUid() {
+        mReader.read(0);
+        LogMaker log = mReader.next();
+        assertEquals(PID, log.getProcessId());
+        assertEquals(UID, log.getUid());
+    }
+
     public void testBlockingRead_readResetsHorizon() {
         mReader.read(1000);
         assertEquals(1000, mLogReader.mHorizonMs);
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 7396a01..87f1cdb 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -3636,7 +3636,7 @@
     // OS: N
     ACTION_GET_CONTACT = 864;
 
-    // This values should never appear in log outputs - it is reserved for
+    // This value should never appear in log outputs - it is reserved for
     // internal platform metrics use.
     RESERVED_FOR_LOGBUILDER_PID = 865;
 
@@ -3948,6 +3948,10 @@
     // OS: O
     NOTIFICATION_CHANNEL_LOCK_SCREEN_VIS = 942;
 
+    // This value should never appear in log outputs - it is reserved for
+    // internal platform metrics use.
+    RESERVED_FOR_LOGBUILDER_UID = 943;
+
     // ---- End O Constants, all O constants go above this line ----
 
     // OPEN: Settings > System > Languages & input > Advanced > Lift to open camera