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

Commit e9fbacf6 authored by Jing Ji's avatar Jing Ji Committed by Android (Google) Code Review
Browse files

Merge "Support to pull aggregated procstats associations" into rvc-dev

parents 316bc6ff 060d6863
Loading
Loading
Loading
Loading
+20 −1
Original line number Original line Diff line number Diff line
@@ -5699,7 +5699,7 @@ message ProcessStatsStateProto {
    optional AggStats rss = 8;
    optional AggStats rss = 8;
}
}


// Next Tag: 7
// Next Tag: 8
message ProcessStatsProto {
message ProcessStatsProto {
    // Name of process.
    // Name of process.
    optional string process = 1;
    optional string process = 1;
@@ -5726,6 +5726,25 @@ message ProcessStatsProto {
    // Total time process has been running...  screen_state, memory_state, and process_state
    // Total time process has been running...  screen_state, memory_state, and process_state
    // will not be set.
    // will not be set.
    optional ProcessStatsStateProto total_running_state = 6;
    optional ProcessStatsStateProto total_running_state = 6;

    // Association data for this process in this state;
    // each entry here is one association.
    repeated ProcessStatsAssociationProto assocs = 7;
}

// Next Tag: 5
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;

    // Total count of the times this association (service binding) appeared.
    optional int32 total_count = 3;

    // Uptime total duration in seconds this association (service binding) was around.
    optional int32 total_duration_secs = 4;
}
}


message PackageServiceOperationStatsProto {
message PackageServiceOperationStatsProto {
+1 −1
Original line number Original line Diff line number Diff line
@@ -288,7 +288,7 @@ public final class AssociationState {
    /**
    /**
     * All known sources for this target component...  uid -> process name -> source state.
     * All known sources for this target component...  uid -> process name -> source state.
     */
     */
    private final ArrayMap<SourceKey, SourceState> mSources = new ArrayMap<>();
    final ArrayMap<SourceKey, SourceState> mSources = new ArrayMap<>();


    private static final SourceKey sTmpSourceKey = new SourceKey(0, null, null);
    private static final SourceKey sTmpSourceKey = new SourceKey(0, null, null);


+5 −0
Original line number Original line Diff line number Diff line
@@ -45,4 +45,9 @@ interface IProcessStats {
     */
     */
     long getCommittedStatsMerged(long highWaterMarkMs, int section, boolean doAggregate,
     long getCommittedStatsMerged(long highWaterMarkMs, int section, boolean doAggregate,
        out List<ParcelFileDescriptor> committedStats, out ProcessStats mergedStats);
        out List<ParcelFileDescriptor> committedStats, out ProcessStats mergedStats);

    /**
     * @return The threshold to decide if a given association should be dumped into metrics.
     */
    long getMinAssociationDumpDuration();
}
}
+6 −1
Original line number Original line Diff line number Diff line
@@ -50,6 +50,7 @@ import android.os.UserHandle;
import android.service.procstats.ProcessStatsProto;
import android.service.procstats.ProcessStatsProto;
import android.service.procstats.ProcessStatsStateProto;
import android.service.procstats.ProcessStatsStateProto;
import android.util.ArrayMap;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.DebugUtils;
import android.util.DebugUtils;
import android.util.Log;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.LongSparseArray;
@@ -59,6 +60,7 @@ import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
import android.util.proto.ProtoOutputStream;
import android.util.proto.ProtoUtils;
import android.util.proto.ProtoUtils;


import com.android.internal.app.ProcessMap;
import com.android.internal.app.procstats.ProcessStats.PackageState;
import com.android.internal.app.procstats.ProcessStats.PackageState;
import com.android.internal.app.procstats.ProcessStats.ProcessStateHolder;
import com.android.internal.app.procstats.ProcessStats.ProcessStateHolder;
import com.android.internal.app.procstats.ProcessStats.TotalMemoryUseCollection;
import com.android.internal.app.procstats.ProcessStats.TotalMemoryUseCollection;
@@ -1420,7 +1422,8 @@ public final class ProcessState {


    /** Similar to {@code #dumpDebug}, but with a reduced/aggregated subset of states. */
    /** Similar to {@code #dumpDebug}, but with a reduced/aggregated subset of states. */
    public void dumpAggregatedProtoForStatsd(ProtoOutputStream proto, long fieldId,
    public void dumpAggregatedProtoForStatsd(ProtoOutputStream proto, long fieldId,
            String procName, int uid, long now) {
            String procName, int uid, long now,
            final ProcessMap<ArraySet<PackageState>> procToPkgMap) {
        // Group proc stats by aggregated type (only screen state + process state)
        // Group proc stats by aggregated type (only screen state + process state)
        SparseLongArray durationByState = new SparseLongArray();
        SparseLongArray durationByState = new SparseLongArray();
        boolean didCurState = false;
        boolean didCurState = false;
@@ -1524,6 +1527,8 @@ public final class ProcessState {
            proto.end(stateToken);
            proto.end(stateToken);
        }
        }


        mStats.dumpFilteredAssociationStatesProtoForProc(proto, ProcessStatsProto.ASSOCS,
                now, this, procToPkgMap);
        proto.end(token);
        proto.end(token);
    }
    }
}
}
+138 −1
Original line number Original line Diff line number Diff line
@@ -20,12 +20,16 @@ import android.content.ComponentName;
import android.os.Debug;
import android.os.Debug;
import android.os.Parcel;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserHandle;
import android.service.procstats.ProcessStatsAssociationProto;
import android.service.procstats.ProcessStatsAvailablePagesProto;
import android.service.procstats.ProcessStatsAvailablePagesProto;
import android.service.procstats.ProcessStatsPackageProto;
import android.service.procstats.ProcessStatsPackageProto;
import android.service.procstats.ProcessStatsSectionProto;
import android.service.procstats.ProcessStatsSectionProto;
import android.text.TextUtils;
import android.text.format.DateFormat;
import android.text.format.DateFormat;
import android.util.ArrayMap;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.ArraySet;
@@ -38,6 +42,8 @@ import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
import android.util.proto.ProtoOutputStream;


import com.android.internal.app.ProcessMap;
import com.android.internal.app.ProcessMap;
import com.android.internal.app.procstats.AssociationState.SourceKey;
import com.android.internal.app.procstats.AssociationState.SourceState;


import dalvik.system.VMRuntime;
import dalvik.system.VMRuntime;


@@ -2229,6 +2235,8 @@ public final class ProcessStats implements Parcelable {
    public void dumpAggregatedProtoForStatsd(ProtoOutputStream proto) {
    public void dumpAggregatedProtoForStatsd(ProtoOutputStream proto) {
        dumpProtoPreamble(proto);
        dumpProtoPreamble(proto);
        final ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
        final ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
        final ProcessMap<ArraySet<PackageState>> procToPkgMap =
                collectProcessPackageMaps(null, false);
        for (int ip = 0; ip < procMap.size(); ip++) {
        for (int ip = 0; ip < procMap.size(); ip++) {
            final String procName = procMap.keyAt(ip);
            final String procName = procMap.keyAt(ip);
            final SparseArray<ProcessState> uids = procMap.valueAt(ip);
            final SparseArray<ProcessState> uids = procMap.valueAt(ip);
@@ -2237,7 +2245,7 @@ public final class ProcessStats implements Parcelable {
                final ProcessState procState = uids.valueAt(iu);
                final ProcessState procState = uids.valueAt(iu);
                procState.dumpAggregatedProtoForStatsd(proto,
                procState.dumpAggregatedProtoForStatsd(proto,
                        ProcessStatsSectionProto.PROCESS_STATS,
                        ProcessStatsSectionProto.PROCESS_STATS,
                        procName, uid, mTimePeriodEndRealtime);
                        procName, uid, mTimePeriodEndRealtime, procToPkgMap);
            }
            }
        }
        }
    }
    }
@@ -2268,6 +2276,135 @@ public final class ProcessStats implements Parcelable {
        }
        }
    }
    }


    /**
     * 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<>();

        final ArrayMap<String, SparseArray<LongSparseArray<PackageState>>> pkgMap =
                mPackages.getMap();
        for (int ip = pkgMap.size() - 1; ip >= 0; ip--) {
            final String pkgName = pkgMap.keyAt(ip);
            final SparseArray<LongSparseArray<PackageState>> procs = pkgMap.valueAt(ip);
            for (int iu = procs.size() - 1; iu >= 0; iu--) {
                final LongSparseArray<PackageState> vpkgs = procs.valueAt(iu);
                for (int iv = vpkgs.size() - 1; iv >= 0; iv--) {
                    final PackageState state = vpkgs.valueAt(iv);
                    final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName);
                    for (int iproc = state.mProcesses.size() - 1; iproc >= 0; iproc--) {
                        final ProcessState proc = state.mProcesses.valueAt(iproc);
                        if (!pkgMatch && !reqPackage.equals(proc.getName())) {
                            continue;
                        }
                        if (activeOnly && !proc.isInUse()) {
                            continue;
                        }

                        final String name = proc.getName();
                        final int uid = proc.getUid();
                        ArraySet<PackageState> pkgStates = map.get(name, uid);
                        if (pkgStates == null) {
                            pkgStates = new ArraySet<>();
                            map.put(name, uid, pkgStates);
                        }
                        pkgStates.add(state);
                    }
                }
            }
        }
        return map;
    }

    /**
     * Dump the association states related to given process into statsd.
     *
     * <p> Note: Only dump the single-package process state, or the common process state of
     * multi-package process; while the per-package process state of a multi-package process
     * should not be dumped into the statsd due to its incompletion.</p>
     *
     * @param proto     The proto output stream
     * @param fieldId   The proto output field ID
     * @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.
     */
    public void dumpFilteredAssociationStatesProtoForProc(ProtoOutputStream proto,
            long fieldId, long now, ProcessState procState,
            final ProcessMap<ArraySet<PackageState>> proc2Pkg) {
        if (procState.isMultiPackage() && procState.getCommonProcess() != procState) {
            // It's a per-package process state, don't bother to write into statsd
            return;
        }
        ArrayMap<SourceKey, long[]> assocVals = new ArrayMap<>();
        final String procName = procState.getName();
        final int procUid = procState.getUid();
        final long procVersion = procState.getVersion();
        final ArraySet<PackageState> packages = proc2Pkg.get(procName, procUid);
        if (packages == null || packages.isEmpty()) {
            // Shouldn't happen
            return;
        }
        for (int i = packages.size() - 1; i >= 0; i--) {
            final PackageState pkgState = packages.valueAt(i);
            final ArrayMap<String, AssociationState> associations = pkgState.mAssociations;
            for (int j = associations.size() - 1; j >= 0; j--) {
                final AssociationState assoc = associations.valueAt(j);
                // Make sure this association is really about this process
                if (!TextUtils.equals(assoc.getProcessName(), procName)) {
                    continue;
                }
                final ArrayMap<SourceKey, SourceState> sources = assoc.mSources;
                for (int k = sources.size() - 1; k >= 0; k--) {
                    final SourceKey key = sources.keyAt(k);
                    final SourceState state = sources.valueAt(k);
                    long[] vals = assocVals.get(key);
                    if (vals == null) {
                        vals = new long[2];
                        assocVals.put(key, vals);
                    }
                    vals[0] += state.mDuration;
                    vals[1] += state.mCount;
                    if (state.mNesting > 0) {
                        vals[0] += now - state.mStartUptime;
                    }
                }
            }
        }
        final IProcessStats procStatsService = IProcessStats.Stub.asInterface(
                ServiceManager.getService(SERVICE_NAME));
        if (procStatsService != null) {
            try {
                final long minimum = procStatsService.getMinAssociationDumpDuration();
                if (minimum > 0) {
                    // Now filter out unnecessary ones.
                    for (int i = assocVals.size() - 1; i >= 0; i--) {
                        final long[] vals = assocVals.valueAt(i);
                        if (vals[0] < minimum) {
                            assocVals.removeAt(i);
                        }
                    }
                }
            } catch (RemoteException e) {
                // ignore.
            }
        }
        if (!assocVals.isEmpty()) {
            for (int i = assocVals.size() - 1; i >= 0; i--) {
                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);
                proto.write(ProcessStatsAssociationProto.TOTAL_COUNT, (int) vals[1]);
                proto.write(ProcessStatsAssociationProto.TOTAL_DURATION_SECS,
                        (int) (vals[0] / 1000));
                proto.end(token);
            }
        }
    }

    final public static class ProcessStateHolder {
    final public static class ProcessStateHolder {
        public final long appVersion;
        public final long appVersion;
        public ProcessState state;
        public ProcessState state;
Loading