Use the UID as the package name in procstat assoc proto dump

And try to compress the process name if possible

Bug: 155980964
Test: Manual
Change-Id: I689724e7c271ba8d85608c3f484250e13c1a1c92
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 36a8b2c..39b5be4 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -5798,7 +5798,7 @@
     optional string process = 1;
 
     // Uid of the process.
-    optional int32 uid = 2;
+    optional int32 uid = 2 [(is_uid) = true];
 
     // Information about how often kills occurred
     message Kill {
@@ -5825,13 +5825,16 @@
     repeated ProcessStatsAssociationProto assocs = 7;
 }
 
-// Next Tag: 5
+// Next Tag: 6
 message ProcessStatsAssociationProto {
     // Procss Name of the associated process (client process of service binding)
     optional string assoc_process_name = 1;
 
     // Package Name of the associated package (client package of service binding)
-    optional string assoc_package_name = 2;
+    optional string assoc_package_name = 2 [deprecated = true];
+
+    // UID of the associated process/package (client package of service binding)
+    optional int32 assoc_uid = 5 [(is_uid) = true];
 
     // Total count of the times this association (service binding) appeared.
     optional int32 total_count = 3;
diff --git a/core/java/com/android/internal/app/procstats/ProcessState.java b/core/java/com/android/internal/app/procstats/ProcessState.java
index b814260..ab58fc0e 100644
--- a/core/java/com/android/internal/app/procstats/ProcessState.java
+++ b/core/java/com/android/internal/app/procstats/ProcessState.java
@@ -49,12 +49,14 @@
 import android.os.UserHandle;
 import android.service.procstats.ProcessStatsProto;
 import android.service.procstats.ProcessStatsStateProto;
+import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.DebugUtils;
 import android.util.Log;
 import android.util.LongSparseArray;
 import android.util.Slog;
+import android.util.SparseArray;
 import android.util.SparseLongArray;
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
@@ -1420,10 +1422,38 @@
         proto.end(token);
     }
 
+    /**
+     * Assume the atom already includes a UID field, write the process name only if
+     * it's different from the package name; and only write the suffix if possible.
+     */
+    static void writeCompressedProcessName(final ProtoOutputStream proto, final long fieldId,
+            final String procName, final String packageName, final boolean sharedUid) {
+        if (sharedUid) {
+            // This UID has multiple packages running, write the full process name here
+            proto.write(fieldId, procName);
+            return;
+        }
+        if (TextUtils.equals(procName, packageName)) {
+            // Same name, don't bother to write the process name here.
+            return;
+        }
+        if (procName.startsWith(packageName)) {
+            final int pkgLength = packageName.length();
+            if (procName.charAt(pkgLength) == ':') {
+                // Only write the suffix starting with ':'
+                proto.write(fieldId, procName.substring(pkgLength));
+                return;
+            }
+        }
+        // Write the full process name
+        proto.write(fieldId, procName);
+    }
+
     /** Similar to {@code #dumpDebug}, but with a reduced/aggregated subset of states. */
     public void dumpAggregatedProtoForStatsd(ProtoOutputStream proto, long fieldId,
             String procName, int uid, long now,
-            final ProcessMap<ArraySet<PackageState>> procToPkgMap) {
+            final ProcessMap<ArraySet<PackageState>> procToPkgMap,
+            final SparseArray<ArraySet<String>> uidToPkgMap) {
         // Group proc stats by aggregated type (only screen state + process state)
         SparseLongArray durationByState = new SparseLongArray();
         boolean didCurState = false;
@@ -1503,7 +1533,8 @@
 
         // build the output
         final long token = proto.start(fieldId);
-        proto.write(ProcessStatsProto.PROCESS, procName);
+        writeCompressedProcessName(proto, ProcessStatsProto.PROCESS, procName, mPackage,
+                mMultiPackage || (uidToPkgMap.get(mUid).size() > 1));
         proto.write(ProcessStatsProto.UID, uid);
 
         for (int i = 0; i < durationByState.size(); i++) {
@@ -1528,7 +1559,7 @@
         }
 
         mStats.dumpFilteredAssociationStatesProtoForProc(proto, ProcessStatsProto.ASSOCS,
-                now, this, procToPkgMap);
+                now, this, procToPkgMap, uidToPkgMap);
         proto.end(token);
     }
 }
diff --git a/core/java/com/android/internal/app/procstats/ProcessStats.java b/core/java/com/android/internal/app/procstats/ProcessStats.java
index 928ba35..7455ad0 100644
--- a/core/java/com/android/internal/app/procstats/ProcessStats.java
+++ b/core/java/com/android/internal/app/procstats/ProcessStats.java
@@ -2235,8 +2235,9 @@
     public void dumpAggregatedProtoForStatsd(ProtoOutputStream proto) {
         dumpProtoPreamble(proto);
         final ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
-        final ProcessMap<ArraySet<PackageState>> procToPkgMap =
-                collectProcessPackageMaps(null, false);
+        final ProcessMap<ArraySet<PackageState>> procToPkgMap = new ProcessMap<>();
+        final SparseArray<ArraySet<String>> uidToPkgMap = new SparseArray<>();
+        collectProcessPackageMaps(null, false, procToPkgMap, uidToPkgMap);
         for (int ip = 0; ip < procMap.size(); ip++) {
             final String procName = procMap.keyAt(ip);
             final SparseArray<ProcessState> uids = procMap.valueAt(ip);
@@ -2245,7 +2246,8 @@
                 final ProcessState procState = uids.valueAt(iu);
                 procState.dumpAggregatedProtoForStatsd(proto,
                         ProcessStatsSectionProto.PROCESS_STATS,
-                        procName, uid, mTimePeriodEndRealtime, procToPkgMap);
+                        procName, uid, mTimePeriodEndRealtime,
+                        procToPkgMap, uidToPkgMap);
             }
         }
     }
@@ -2279,10 +2281,9 @@
     /**
      * Walk through the known processes and build up the process -> packages map if necessary.
      */
-    public ProcessMap<ArraySet<PackageState>> collectProcessPackageMaps(
-            String reqPackage, boolean activeOnly) {
-        final ProcessMap<ArraySet<PackageState>> map = new ProcessMap<>();
-
+    private void collectProcessPackageMaps(String reqPackage, boolean activeOnly,
+            final ProcessMap<ArraySet<PackageState>> procToPkgMap,
+            final SparseArray<ArraySet<String>> uidToPkgMap) {
         final ArrayMap<String, SparseArray<LongSparseArray<PackageState>>> pkgMap =
                 mPackages.getMap();
         for (int ip = pkgMap.size() - 1; ip >= 0; ip--) {
@@ -2304,17 +2305,22 @@
 
                         final String name = proc.getName();
                         final int uid = proc.getUid();
-                        ArraySet<PackageState> pkgStates = map.get(name, uid);
+                        ArraySet<PackageState> pkgStates = procToPkgMap.get(name, uid);
                         if (pkgStates == null) {
                             pkgStates = new ArraySet<>();
-                            map.put(name, uid, pkgStates);
+                            procToPkgMap.put(name, uid, pkgStates);
                         }
                         pkgStates.add(state);
+                        ArraySet<String> packages = uidToPkgMap.get(uid);
+                        if (packages == null) {
+                            packages = new ArraySet<>();
+                            uidToPkgMap.put(uid, packages);
+                        }
+                        packages.add(state.mPackageName);
                     }
                 }
             }
         }
-        return map;
     }
 
     /**
@@ -2329,10 +2335,12 @@
      * @param now       The timestamp when the dump was initiated.
      * @param procState The target process where its association states should be dumped.
      * @param proc2Pkg  The map between process to packages running within it.
+     * @param uidToPkgMap The map between UID to packages with this UID
      */
     public void dumpFilteredAssociationStatesProtoForProc(ProtoOutputStream proto,
             long fieldId, long now, ProcessState procState,
-            final ProcessMap<ArraySet<PackageState>> proc2Pkg) {
+            final ProcessMap<ArraySet<PackageState>> proc2Pkg,
+            final SparseArray<ArraySet<String>> uidToPkgMap) {
         if (procState.isMultiPackage() && procState.getCommonProcess() != procState) {
             // It's a per-package process state, don't bother to write into statsd
             return;
@@ -2395,8 +2403,11 @@
                 final SourceKey key = assocVals.keyAt(i);
                 final long[] vals = assocVals.valueAt(i);
                 final long token = proto.start(fieldId);
-                proto.write(ProcessStatsAssociationProto.ASSOC_PROCESS_NAME, key.mProcess);
-                proto.write(ProcessStatsAssociationProto.ASSOC_PACKAGE_NAME, key.mPackage);
+                ProcessState.writeCompressedProcessName(proto,
+                        ProcessStatsAssociationProto.ASSOC_PROCESS_NAME,
+                        key.mProcess, key.mPackage,
+                        uidToPkgMap.get(key.mUid).size() > 1);
+                proto.write(ProcessStatsAssociationProto.ASSOC_UID, key.mUid);
                 proto.write(ProcessStatsAssociationProto.TOTAL_COUNT, (int) vals[1]);
                 proto.write(ProcessStatsAssociationProto.TOTAL_DURATION_SECS,
                         (int) (vals[0] / 1000));
diff --git a/core/proto/android/service/procstats.proto b/core/proto/android/service/procstats.proto
index dd830a8..7a4c070 100644
--- a/core/proto/android/service/procstats.proto
+++ b/core/proto/android/service/procstats.proto
@@ -179,13 +179,16 @@
     repeated ProcessStatsAssociationProto assocs = 7;
 }
 
-// Next Tag: 5
+// Next Tag: 6
 message ProcessStatsAssociationProto {
     // Procss Name of the associated process/package
     optional string assoc_process_name = 1;
 
     // Package Name of the associated process/package
-    optional string assoc_package_name = 2;
+    optional string assoc_package_name = 2 [deprecated = true];
+
+    // UID of the associated process/package
+    optional int32 assoc_uid = 5;
 
     // Total count of the times this association appeared.
     optional int32 total_count = 3;