Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8cf1ffec authored by Yi Jin's avatar Yi Jin Committed by Android (Google) Code Review
Browse files

Merge "Implement procstats dumpsys section"

parents dbdc059d 9680cfae
Loading
Loading
Loading
Loading
+39 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.
 */

package android.util.proto;

import android.util.AggStats;

/**
 * This class contains a list of helper functions to write common proto in
 * //frameworks/base/core/proto/android/base directory
 */
public class ProtoUtils {

    /**
     * Dump AggStats to ProtoOutputStream
     * @hide
     */
    public static void toAggStatsProto(ProtoOutputStream proto, long fieldId,
            long min, long average, long max) {
        final long aggStatsToken = proto.start(fieldId);
        proto.write(AggStats.MIN, min);
        proto.write(AggStats.AVERAGE, average);
        proto.write(AggStats.MAX, max);
        proto.end(aggStatsToken);
    }
}
+19 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;

import static com.android.internal.app.procstats.ProcessStats.*;

@@ -66,6 +67,8 @@ public final class DumpUtils {
            "cch-activity", "cch-aclient", "cch-empty"
    };

    // State enum is defined in frameworks/base/core/proto/android/service/procstats.proto
    // Update states must sync enum definition as well, the ordering must not be changed.
    static final String[] ADJ_SCREEN_TAGS = new String[] {
            "0", "1"
    };
@@ -177,6 +180,13 @@ public final class DumpUtils {
        printArrayEntry(pw, STATE_TAGS,  state, 1);
    }

    public static void printProcStateTagProto(ProtoOutputStream proto, long screenId, long memId,
            long stateId, int state) {
        state = printProto(proto, screenId, ADJ_SCREEN_TAGS, state, ADJ_SCREEN_MOD * STATE_COUNT);
        state = printProto(proto, memId, ADJ_MEM_TAGS, state, STATE_COUNT);
        printProto(proto, stateId, STATE_TAGS, state, 1);
    }

    public static void printAdjTag(PrintWriter pw, int state) {
        state = printArrayEntry(pw, ADJ_SCREEN_TAGS,  state, ADJ_SCREEN_MOD);
        printArrayEntry(pw, ADJ_MEM_TAGS, state, 1);
@@ -352,6 +362,15 @@ public final class DumpUtils {
        return value - index*mod;
    }

    public static int printProto(ProtoOutputStream proto, long fieldId, String[] array, int value, int mod) {
        int index = value/mod;
        if (index >= 0 && index < array.length) {
            // Valid state enum number starts at 1, 0 stands for unknown.
            proto.write(fieldId, index + 1);
        } // else enum default is always zero in proto3
        return value - index*mod;
    }

    public static String collapseString(String pkgName, String itemName) {
        if (itemName.startsWith(pkgName)) {
            final int ITEMLEN = itemName.length();
+81 −0
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ import android.os.Parcelable;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.service.pm.PackageProto;
import android.service.procstats.ProcessStatsProto;
import android.text.format.DateFormat;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -29,6 +31,8 @@ import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
import android.util.proto.ProtoUtils;

import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.app.procstats.ProcessStats.PackageState;
@@ -69,6 +73,9 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public final class ProcessState {
@@ -1157,6 +1164,7 @@ public final class ProcessState {
        }
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder(128);
        sb.append("ProcessState{").append(Integer.toHexString(System.identityHashCode(this)))
@@ -1167,4 +1175,77 @@ public final class ProcessState {
        sb.append("}");
        return sb.toString();
    }

    public void toProto(ProtoOutputStream proto, String procName, int uid, long now) {
        proto.write(ProcessStatsProto.PROCESS, procName);
        proto.write(ProcessStatsProto.UID, uid);
        if (mNumExcessiveCpu > 0 || mNumCachedKill > 0 ) {
            final long killToken = proto.start(ProcessStatsProto.KILL);
            proto.write(ProcessStatsProto.Kill.WAKES, mNumExcessiveWake);
            proto.write(ProcessStatsProto.Kill.CPU, mNumExcessiveCpu);
            proto.write(ProcessStatsProto.Kill.CACHED, mNumCachedKill);
            ProtoUtils.toAggStatsProto(proto, ProcessStatsProto.Kill.CACHED_PSS,
                    mMinCachedKillPss, mAvgCachedKillPss, mMaxCachedKillPss);
            proto.end(killToken);
        }

        // Group proc stats by type (screen state + mem state + process state)
        Map<Integer, Long> durationByState = new HashMap<>();
        boolean didCurState = false;
        for (int i=0; i<mDurations.getKeyCount(); i++) {
            final int key = mDurations.getKeyAt(i);
            final int type = SparseMappingTable.getIdFromKey(key);
            long time = mDurations.getValue(key);
            if (mCurState == type) {
                didCurState = true;
                time += now - mStartTime;
            }
            durationByState.put(type, time);
        }
        if (!didCurState && mCurState != STATE_NOTHING) {
            durationByState.put(mCurState, now - mStartTime);
        }

        for (int i=0; i<mPssTable.getKeyCount(); i++) {
            final int key = mPssTable.getKeyAt(i);
            final int type = SparseMappingTable.getIdFromKey(key);
            if (!durationByState.containsKey(type)) {
                // state without duration should not have stats!
                continue;
            }
            final long stateToken = proto.start(ProcessStatsProto.STATES);
            DumpUtils.printProcStateTagProto(proto,
                    ProcessStatsProto.State.SCREEN_STATE,
                    ProcessStatsProto.State.MEMORY_STATE,
                    ProcessStatsProto.State.PROCESS_STATE,
                    type);

            long duration = durationByState.get(type);
            durationByState.remove(type); // remove the key since it is already being dumped.
            proto.write(ProcessStatsProto.State.DURATION_MS, duration);

            proto.write(ProcessStatsProto.State.SAMPLE_SIZE, mPssTable.getValue(key, PSS_SAMPLE_COUNT));
            ProtoUtils.toAggStatsProto(proto, ProcessStatsProto.State.PSS,
                    mPssTable.getValue(key, PSS_MINIMUM),
                    mPssTable.getValue(key, PSS_AVERAGE),
                    mPssTable.getValue(key, PSS_MAXIMUM));
            ProtoUtils.toAggStatsProto(proto, ProcessStatsProto.State.USS,
                    mPssTable.getValue(key, PSS_USS_MINIMUM),
                    mPssTable.getValue(key, PSS_USS_AVERAGE),
                    mPssTable.getValue(key, PSS_USS_MAXIMUM));

            proto.end(stateToken);
        }

        for (Map.Entry<Integer, Long> entry : durationByState.entrySet()) {
            final long stateToken = proto.start(ProcessStatsProto.STATES);
            DumpUtils.printProcStateTagProto(proto,
                    ProcessStatsProto.State.SCREEN_STATE,
                    ProcessStatsProto.State.MEMORY_STATE,
                    ProcessStatsProto.State.PROCESS_STATE,
                    entry.getKey());
            proto.write(ProcessStatsProto.State.DURATION_MS, entry.getValue());
            proto.end(stateToken);
        }
    }
}
+42 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.os.Parcelable;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.service.procstats.ProcessStatsSectionProto;
import android.text.format.DateFormat;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -30,6 +31,7 @@ import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;

import com.android.internal.app.ProcessMap;
import com.android.internal.app.procstats.DurationsTable;
@@ -1706,6 +1708,46 @@ public final class ProcessStats implements Parcelable {
        }
    }

    public void toProto(ProtoOutputStream proto, long now) {
        final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap();

        proto.write(ProcessStatsSectionProto.START_REALTIME_MS, mTimePeriodStartRealtime);
        proto.write(ProcessStatsSectionProto.END_REALTIME_MS,
                mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime);
        proto.write(ProcessStatsSectionProto.START_UPTIME_MS, mTimePeriodStartUptime);
        proto.write(ProcessStatsSectionProto.END_UPTIME_MS, mTimePeriodEndUptime);
        proto.write(ProcessStatsSectionProto.RUNTIME, mRuntime);
        proto.write(ProcessStatsSectionProto.HAS_SWAPPED_PSS, mHasSwappedOutPss);
        boolean partial = true;
        if ((mFlags&FLAG_SHUTDOWN) != 0) {
            proto.write(ProcessStatsSectionProto.STATUS, ProcessStatsSectionProto.STATUS_SHUTDOWN);
            partial = false;
        }
        if ((mFlags&FLAG_SYSPROPS) != 0) {
            proto.write(ProcessStatsSectionProto.STATUS, ProcessStatsSectionProto.STATUS_SYSPROPS);
            partial = false;
        }
        if ((mFlags&FLAG_COMPLETE) != 0) {
            proto.write(ProcessStatsSectionProto.STATUS, ProcessStatsSectionProto.STATUS_COMPLETE);
            partial = false;
        }
        if (partial) {
            proto.write(ProcessStatsSectionProto.STATUS, ProcessStatsSectionProto.STATUS_PARTIAL);
        }

        ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
        for (int ip=0; ip<procMap.size(); ip++) {
            String procName = procMap.keyAt(ip);
            SparseArray<ProcessState> uids = procMap.valueAt(ip);
            for (int iu=0; iu<uids.size(); iu++) {
                final int uid = uids.keyAt(iu);
                final ProcessState procState = uids.valueAt(iu);
                final long processStateToken = proto.start(ProcessStatsSectionProto.PROCESS_STATS);
                procState.toProto(proto, procName, uid, now);
                proto.end(processStateToken);
            }
        }
    }

    final public static class ProcessStateHolder {
        public final int appVersion;
+6 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import "frameworks/base/core/proto/android/service/notification.proto";
import "frameworks/base/core/proto/android/service/package.proto";
import "frameworks/base/core/proto/android/service/power.proto";
import "frameworks/base/core/proto/android/service/print.proto";
import "frameworks/base/core/proto/android/service/procstats.proto";
import "frameworks/base/core/proto/android/providers/settings.proto";
import "frameworks/base/core/proto/android/os/incidentheader.proto";
import "frameworks/base/core/proto/android/os/kernelwake.proto";
@@ -96,4 +97,9 @@ message IncidentProto {
    android.service.pm.PackageServiceDumpProto package = 3008;
    android.service.power.PowerServiceDumpProto power = 3009;
    android.service.print.PrintServiceDumpProto print = 3010;

    android.service.procstats.ProcessStatsServiceDumpProto procstats = 3011 [
        (section).type = SECTION_DUMPSYS,
        (section).args = "procstats --proto"
    ];
}
Loading