Add dumpsys cpuinfo proto

Add protobuf dumpsys of cpuinfo, invoked by dumpsys cpuinfo --proto.
Also add "dumpsys cpuinfo --proto" section to incident.proto

Bug: 146086163
Test: adb shell dumpsys cpuinfo --proto, then verify its content
Change-Id: I84ed623dee9708e36c75d8effb71408401e0dac0
diff --git a/core/java/com/android/internal/os/ProcessCpuTracker.java b/core/java/com/android/internal/os/ProcessCpuTracker.java
index f7b7742..5e3c5df 100644
--- a/core/java/com/android/internal/os/ProcessCpuTracker.java
+++ b/core/java/com/android/internal/os/ProcessCpuTracker.java
@@ -24,6 +24,7 @@
 import static android.os.Process.PROC_SPACE_TERM;
 
 import android.compat.annotation.UnsupportedAppUsage;
+import android.os.CpuUsageProto;
 import android.os.Process;
 import android.os.StrictMode;
 import android.os.SystemClock;
@@ -31,10 +32,12 @@
 import android.system.Os;
 import android.system.OsConstants;
 import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.util.FastPrintWriter;
 
 import java.io.File;
+import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.text.SimpleDateFormat;
@@ -740,6 +743,63 @@
         return mWorkingProcs.get(index);
     }
 
+    /** Dump cpuinfo in protobuf format. */
+    public final void dumpProto(FileDescriptor fd) {
+        final long now = SystemClock.uptimeMillis();
+        final ProtoOutputStream proto = new ProtoOutputStream(fd);
+        final long currentLoadToken = proto.start(CpuUsageProto.CURRENT_LOAD);
+        proto.write(CpuUsageProto.Load.LOAD1, mLoad1);
+        proto.write(CpuUsageProto.Load.LOAD5, mLoad5);
+        proto.write(CpuUsageProto.Load.LOAD15, mLoad15);
+        proto.end(currentLoadToken);
+
+        proto.write(CpuUsageProto.NOW, now);
+        proto.write(CpuUsageProto.LAST_SAMPLE_TIME, mLastSampleTime);
+        proto.write(CpuUsageProto.CURRENT_SAMPLE_TIME, mCurrentSampleTime);
+        proto.write(CpuUsageProto.LAST_SAMPLE_REAL_TIME, mLastSampleRealTime);
+        proto.write(CpuUsageProto.CURRENT_SAMPLE_REAL_TIME, mCurrentSampleRealTime);
+        proto.write(CpuUsageProto.LAST_SAMPLE_WALL_TIME, mLastSampleWallTime);
+        proto.write(CpuUsageProto.CURRENT_SAMPLE_WALL_TIME, mCurrentSampleWallTime);
+
+        proto.write(CpuUsageProto.TOTAL_USER_TIME, mRelUserTime);
+        proto.write(CpuUsageProto.TOTAL_SYSTEM_TIME, mRelSystemTime);
+        proto.write(CpuUsageProto.TOTAL_IOWAIT_TIME, mRelIoWaitTime);
+        proto.write(CpuUsageProto.TOTAL_IRQ_TIME, mRelIrqTime);
+        proto.write(CpuUsageProto.TOTAL_SOFT_IRQ_TIME, mRelSoftIrqTime);
+        proto.write(CpuUsageProto.TOTAL_IDLE_TIME, mRelIdleTime);
+        final int totalTime = mRelUserTime + mRelSystemTime + mRelIoWaitTime
+                + mRelIrqTime + mRelSoftIrqTime + mRelIdleTime;
+        proto.write(CpuUsageProto.TOTAL_TIME, totalTime);
+
+        for (Stats st : mWorkingProcs) {
+            dumpProcessCpuProto(proto, st, null);
+            if (!st.removed && st.workingThreads != null) {
+                for (Stats tst : st.workingThreads) {
+                    dumpProcessCpuProto(proto, tst, st);
+                }
+            }
+        }
+        proto.flush();
+    }
+
+    private static void dumpProcessCpuProto(ProtoOutputStream proto, Stats st, Stats proc) {
+        long statToken = proto.start(CpuUsageProto.PROCESSES);
+        proto.write(CpuUsageProto.Stat.UID, st.uid);
+        proto.write(CpuUsageProto.Stat.PID, st.pid);
+        proto.write(CpuUsageProto.Stat.NAME, st.name);
+        proto.write(CpuUsageProto.Stat.ADDED, st.added);
+        proto.write(CpuUsageProto.Stat.REMOVED, st.removed);
+        proto.write(CpuUsageProto.Stat.UPTIME, st.rel_uptime);
+        proto.write(CpuUsageProto.Stat.USER_TIME, st.rel_utime);
+        proto.write(CpuUsageProto.Stat.SYSTEM_TIME, st.rel_stime);
+        proto.write(CpuUsageProto.Stat.MINOR_FAULTS, st.rel_minfaults);
+        proto.write(CpuUsageProto.Stat.MAJOR_FAULTS, st.rel_majfaults);
+        if (proc != null) {
+            proto.write(CpuUsageProto.Stat.PARENT_PID, proc.pid);
+        }
+        proto.end(statToken);
+    }
+
     final public String printCurrentLoad() {
         StringWriter sw = new StringWriter();
         PrintWriter pw = new FastPrintWriter(sw, false, 128);
diff --git a/core/proto/android/os/cpu_usage.proto b/core/proto/android/os/cpu_usage.proto
new file mode 100644
index 0000000..ac98900
--- /dev/null
+++ b/core/proto/android/os/cpu_usage.proto
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+
+option java_multiple_files = true;
+
+import "frameworks/base/core/proto/android/privacy.proto";
+
+package android.os;
+
+message CpuUsageProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    message Load {
+        option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+        optional float load1 = 1;
+        optional float load5 = 2;
+        optional float load15 = 3;
+    }
+    optional Load current_load = 1;
+
+    optional int64 now = 2;
+    optional int64 last_sample_time = 3;
+    optional int64 current_sample_time = 4;
+    optional int64 last_sample_real_time = 5;
+    optional int64 current_sample_real_time = 6;
+    optional int64 last_sample_wall_time = 7;
+    optional int64 current_sample_wall_time = 8;
+
+    optional int32 total_user_time = 9;
+    optional int32 total_system_time = 10;
+    optional int32 total_iowait_time = 11;
+    optional int32 total_irq_time = 12;
+    optional int32 total_soft_irq_time = 13;
+    optional int32 total_idle_time = 14;
+    optional int32 total_time = 15;
+
+    message Stat {
+        option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+        optional int32 uid = 1;
+        optional int32 pid = 2;
+        optional string name = 3;
+        optional bool added = 4;
+        optional bool removed = 5;
+        optional int32 uptime = 6;
+        optional int32 user_time = 7;
+        optional int32 system_time = 8;
+        optional int32 minor_faults = 9;
+        optional int32 major_faults = 10;
+        optional int32 parent_pid = 11;
+    }
+    repeated Stat processes = 16;
+
+    // Next tag: 17
+}
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 6cf9424..8f9c041 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -21,6 +21,7 @@
 import "frameworks/base/core/proto/android/os/batterytype.proto";
 import "frameworks/base/core/proto/android/os/cpufreq.proto";
 import "frameworks/base/core/proto/android/os/cpuinfo.proto";
+import "frameworks/base/core/proto/android/os/cpu_usage.proto";
 import "frameworks/base/core/proto/android/os/data.proto";
 import "frameworks/base/core/proto/android/os/header.proto";
 import "frameworks/base/core/proto/android/os/kernelwake.proto";
@@ -469,6 +470,11 @@
         (section).args = "dropbox --proto SubsystemRestart"
     ];
 
+    optional CpuUsageProto process_cpu_usage = 3047 [
+        (section).type = SECTION_DUMPSYS,
+        (section).args = "cpuinfo --proto"
+    ];
+
     // Reserved for OEMs.
     extensions 50000 to 100000;
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index dd1f370..95e6895 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2176,10 +2176,13 @@
             @Override
             public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args,
                     boolean asProto) {
-                if (asProto) return;
                 if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext,
                         "cpuinfo", pw)) return;
                 synchronized (mActivityManagerService.mProcessCpuTracker) {
+                    if (asProto) {
+                        mActivityManagerService.mProcessCpuTracker.dumpProto(fd);
+                        return;
+                    }
                     pw.print(mActivityManagerService.mProcessCpuTracker.printCurrentLoad());
                     pw.print(mActivityManagerService.mProcessCpuTracker.printCurrentState(
                             SystemClock.uptimeMillis()));