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

Commit 3ae16620 authored by Sudheer Shanka's avatar Sudheer Shanka Committed by android-build-merger
Browse files

Merge "Add time spent by uid per cpu frequency to batterystats." into oc-dev

am: 5df9c557

Change-Id: Ia15bc54c61a692a37ad9b84a28643afc798b52c7
parents 9d9655a6 5df9c557
Loading
Loading
Loading
Loading
+91 −0
Original line number Diff line number Diff line
@@ -203,6 +203,8 @@ public abstract class BatteryStats implements Parcelable {
    private static final String APK_DATA = "apk";
    private static final String PROCESS_DATA = "pr";
    private static final String CPU_DATA = "cpu";
    private static final String GLOBAL_CPU_FREQ_DATA = "gcf";
    private static final String CPU_TIMES_AT_FREQ_DATA = "ctf";
    private static final String SENSOR_DATA = "sr";
    private static final String VIBRATOR_DATA = "vib";
    private static final String FOREGROUND_DATA = "fg";
@@ -264,6 +266,13 @@ public abstract class BatteryStats implements Parcelable {
    private final StringBuilder mFormatBuilder = new StringBuilder(32);
    private final Formatter mFormatter = new Formatter(mFormatBuilder);

    /**
     * Indicates times spent by the uid at each cpu frequency in all process states.
     *
     * Other types might include times spent in foreground, background etc.
     */
    private final String UID_TIMES_TYPE_ALL = "A";

    /**
     * State for keeping track of counting information.
     */
@@ -302,6 +311,24 @@ public abstract class BatteryStats implements Parcelable {
        public abstract void logState(Printer pw, String prefix);
    }

    /**
     * State for keeping track of array of long counting information.
     */
    public static abstract class LongCounterArray {
        /**
         * Returns the counts associated with this Counter for the
         * selected type of statistics.
         *
         * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT
         */
        public abstract long[] getCountsLocked(int which);

        /**
         * Temporary for debugging.
         */
        public abstract void logState(Printer pw, String prefix);
    }

    /**
     * Container class that aggregates counters for transmit, receive, and idle state of a
     * radio controller.
@@ -523,6 +550,9 @@ public abstract class BatteryStats implements Parcelable {
        public abstract Timer getBluetoothScanBackgroundTimer();
        public abstract Counter getBluetoothScanResultCounter();

        public abstract long[] getCpuFreqTimes(int which);
        public abstract long[] getScreenOffCpuFreqTimes(int which);

        // Note: the following times are disjoint.  They can be added together to find the
        // total time a uid has had any processes running at all.

@@ -1077,6 +1107,8 @@ public abstract class BatteryStats implements Parcelable {

    public abstract long getNextMaxDailyDeadline();

    public abstract long[] getCpuFreqs();

    public final static class HistoryTag {
        public String string;
        public int uid;
@@ -3274,6 +3306,15 @@ public abstract class BatteryStats implements Parcelable {
            }
        }

        final long[] cpuFreqs = getCpuFreqs();
        if (cpuFreqs != null) {
            sb.setLength(0);
            for (int i = 0; i < cpuFreqs.length; ++i) {
                sb.append((i == 0 ? "" : ",") + cpuFreqs[i]);
            }
            dumpLine(pw, 0 /* uid */, category, GLOBAL_CPU_FREQ_DATA, sb.toString());
        }

        for (int iu = 0; iu < NU; iu++) {
            final int uid = uidStats.keyAt(iu);
            if (reqUid >= 0 && uid != reqUid) {
@@ -3506,6 +3547,27 @@ public abstract class BatteryStats implements Parcelable {
                        0 /* old cpu power, keep for compatibility */);
            }

            final long[] cpuFreqTimeMs = u.getCpuFreqTimes(which);
            // If total cpuFreqTimes is null, then we don't need to check for screenOffCpuFreqTimes.
            if (cpuFreqTimeMs != null) {
                sb.setLength(0);
                for (int i = 0; i < cpuFreqTimeMs.length; ++i) {
                    sb.append((i == 0 ? "" : ",") + cpuFreqTimeMs[i]);
                }
                final long[] screenOffCpuFreqTimeMs = u.getScreenOffCpuFreqTimes(which);
                if (screenOffCpuFreqTimeMs != null) {
                    for (int i = 0; i < screenOffCpuFreqTimeMs.length; ++i) {
                        sb.append("," + screenOffCpuFreqTimeMs[i]);
                    }
                } else {
                    for (int i = 0; i < cpuFreqTimeMs.length; ++i) {
                        sb.append(",0");
                    }
                }
                dumpLine(pw, uid, category, CPU_TIMES_AT_FREQ_DATA, UID_TIMES_TYPE_ALL,
                        cpuFreqTimeMs.length, sb.toString());
            }

            final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats
                    = u.getProcessStats();
            for (int ipr=processStats.size()-1; ipr>=0; ipr--) {
@@ -4373,6 +4435,16 @@ public abstract class BatteryStats implements Parcelable {
            pw.println(sb.toString());
        }

        final long[] cpuFreqs = getCpuFreqs();
        if (cpuFreqs != null) {
            sb.setLength(0);
            sb.append("CPU freqs:");
            for (int i = 0; i < cpuFreqs.length; ++i) {
                sb.append(" " + cpuFreqs[i]);
            }
            pw.println(sb.toString());
        }

        for (int iu=0; iu<NU; iu++) {
            final int uid = uidStats.keyAt(iu);
            if (reqUid >= 0 && uid != reqUid && uid != Process.SYSTEM_UID) {
@@ -4835,6 +4907,25 @@ public abstract class BatteryStats implements Parcelable {
                pw.println(sb.toString());
            }

            final long[] cpuFreqTimes = u.getCpuFreqTimes(which);
            if (cpuFreqTimes != null) {
                sb.setLength(0);
                sb.append("    Total cpu time per freq:");
                for (int i = 0; i < cpuFreqTimes.length; ++i) {
                    sb.append(" " + cpuFreqTimes[i]);
                }
                pw.println(sb.toString());
            }
            final long[] screenOffCpuFreqTimes = u.getScreenOffCpuFreqTimes(which);
            if (screenOffCpuFreqTimes != null) {
                sb.setLength(0);
                sb.append("    Total screen-off cpu time per freq:");
                for (int i = 0; i < screenOffCpuFreqTimes.length; ++i) {
                    sb.append(" " + screenOffCpuFreqTimes[i]);
                }
                pw.println(sb.toString());
            }

            final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats
                    = u.getProcessStats();
            for (int ipr=processStats.size()-1; ipr>=0; ipr--) {
+275 −1
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.internal.os;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.bluetooth.BluetoothActivityEnergyInfo;
@@ -87,6 +88,7 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
@@ -114,7 +116,7 @@ public class BatteryStatsImpl extends BatteryStats {
    private static final int MAGIC = 0xBA757475; // 'BATSTATS'

    // Current on-disk Parcel version
    private static final int VERSION = 156 + (USE_OLD_HISTORY ? 1000 : 0);
    private static final int VERSION = 157 + (USE_OLD_HISTORY ? 1000 : 0);

    // Maximum number of items we will record in the history.
    private static final int MAX_HISTORY_ITEMS = 2000;
@@ -149,6 +151,8 @@ public class BatteryStatsImpl extends BatteryStats {

    private final KernelUidCpuTimeReader mKernelUidCpuTimeReader = new KernelUidCpuTimeReader();
    private KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
    private final KernelUidCpuFreqTimeReader mKernelUidCpuFreqTimeReader =
            new KernelUidCpuFreqTimeReader();

    private final KernelMemoryBandwidthStats mKernelMemoryBandwidthStats
            = new KernelMemoryBandwidthStats();
@@ -570,6 +574,8 @@ public class BatteryStatsImpl extends BatteryStats {

    private final NetworkStats.Entry mTmpNetworkStatsEntry = new NetworkStats.Entry();

    private long[] mCpuFreqs;

    private PowerProfile mPowerProfile;

    /*
@@ -957,6 +963,131 @@ public class BatteryStatsImpl extends BatteryStats {
        }
    }

    public static class LongSamplingCounterArray extends LongCounterArray implements TimeBaseObs {
        final TimeBase mTimeBase;
        long[] mCounts;
        long[] mLoadedCounts;
        long[] mUnpluggedCounts;
        long[] mPluggedCounts;

        LongSamplingCounterArray(TimeBase timeBase, Parcel in) {
            mTimeBase = timeBase;
            mPluggedCounts = in.createLongArray();
            mCounts = copyArray(mPluggedCounts, mCounts);
            mLoadedCounts = in.createLongArray();
            mUnpluggedCounts = in.createLongArray();
            timeBase.add(this);
        }

        LongSamplingCounterArray(TimeBase timeBase) {
            mTimeBase = timeBase;
            timeBase.add(this);
        }

        public void writeToParcel(Parcel out) {
            out.writeLongArray(mCounts);
            out.writeLongArray(mLoadedCounts);
            out.writeLongArray(mUnpluggedCounts);
        }

        @Override
        public void onTimeStarted(long elapsedRealTime, long baseUptime, long baseRealtime) {
            mUnpluggedCounts = copyArray(mPluggedCounts, mUnpluggedCounts);
            mCounts = copyArray(mPluggedCounts, mCounts);
        }

        @Override
        public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
            mPluggedCounts = copyArray(mCounts, mPluggedCounts);
        }

        @Override
        public long[] getCountsLocked(int which) {
            long[] val = copyArray(mTimeBase.isRunning() ? mCounts : mPluggedCounts, null);
            if (which == STATS_SINCE_UNPLUGGED) {
                subtract(val, mUnpluggedCounts);
            } else if (which != STATS_SINCE_CHARGED) {
                subtract(val, mLoadedCounts);
            }
            return val;
        }

        @Override
        public void logState(Printer pw, String prefix) {
            pw.println(prefix + "mCounts=" + Arrays.toString(mCounts)
                    + " mLoadedCounts=" + Arrays.toString(mLoadedCounts)
                    + " mUnpluggedCounts=" + Arrays.toString(mUnpluggedCounts)
                    + " mPluggedCounts=" + Arrays.toString(mPluggedCounts));
        }

        void addCountLocked(long[] counts) {
            if (counts == null) {
                return;
            }
            if (mCounts == null) {
                mCounts = new long[counts.length];
            }
            for (int i = 0; i < counts.length; ++i) {
                mCounts[i] += counts[i];
            }
        }

        /**
         * Clear state of this counter.
         */
        void reset(boolean detachIfReset) {
            fillArray(mCounts, 0);
            fillArray(mLoadedCounts, 0);
            fillArray(mPluggedCounts, 0);
            fillArray(mUnpluggedCounts, 0);
            if (detachIfReset) {
                detach();
            }
        }

        void detach() {
            mTimeBase.remove(this);
        }

        void writeSummaryFromParcelLocked(Parcel out) {
            out.writeLongArray(mCounts);
        }

        void readSummaryFromParcelLocked(Parcel in) {
            mCounts = in.createLongArray();
            mLoadedCounts = copyArray(mCounts, mLoadedCounts);
            mUnpluggedCounts = copyArray(mCounts, mUnpluggedCounts);
            mPluggedCounts = copyArray(mCounts, mPluggedCounts);
        }

        private void fillArray(long[] a, long val) {
            if (a != null) {
                Arrays.fill(a, val);
            }
        }

        private void subtract(@NonNull long[] val, long[] toSubtract) {
            if (toSubtract == null) {
                return;
            }
            for (int i = 0; i < val.length; i++) {
                val[i] -= toSubtract[i];
            }
        }

        private long[] copyArray(long[] src, long[] dest) {
            if (src == null) {
                return null;
            } else {
                if (dest == null) {
                    dest = new long[src.length];
                }
                System.arraycopy(src, 0, dest, 0, src.length);
                return dest;
            }
        }
    }

    public static class LongSamplingCounter extends LongCounter implements TimeBaseObs {
        final TimeBase mTimeBase;
        long mCount;
@@ -5483,6 +5614,9 @@ public class BatteryStatsImpl extends BatteryStats {
        LongSamplingCounter mSystemCpuTime;
        LongSamplingCounter[][] mCpuClusterSpeed;

        LongSamplingCounterArray mCpuFreqTimeMs;
        LongSamplingCounterArray mScreenOffCpuFreqTimeMs;

        /**
         * The statistics we have collected for this uid's wake locks.
         */
@@ -5559,6 +5693,42 @@ public class BatteryStatsImpl extends BatteryStats {
            mProcessStateTimer = new StopwatchTimer[NUM_PROCESS_STATE];
        }

        @Override
        public long[] getCpuFreqTimes(int which) {
            if (mCpuFreqTimeMs == null) {
                return null;
            }
            final long[] cpuFreqTimes = mCpuFreqTimeMs.getCountsLocked(which);
            if (cpuFreqTimes == null) {
                return null;
            }
            // Return cpuFreqTimes only if atleast one of the elements in non-zero.
            for (int i = 0; i < cpuFreqTimes.length; ++i) {
                if (cpuFreqTimes[i] != 0) {
                    return cpuFreqTimes;
                }
            }
            return null;
        }

        @Override
        public long[] getScreenOffCpuFreqTimes(int which) {
            if (mScreenOffCpuFreqTimeMs == null) {
                return null;
            }
            final long[] cpuFreqTimes = mScreenOffCpuFreqTimeMs.getCountsLocked(which);
            if (cpuFreqTimes == null) {
                return null;
            }
            // Return cpuFreqTimes only if atleast one of the elements in non-zero.
            for (int i = 0; i < cpuFreqTimes.length; ++i) {
                if (cpuFreqTimes[i] != 0) {
                    return cpuFreqTimes;
                }
            }
            return null;
        }

        @Override
        public ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
            return mWakelockStats.getMap();
@@ -6354,6 +6524,13 @@ public class BatteryStatsImpl extends BatteryStats {
                }
            }

            if (mCpuFreqTimeMs != null) {
                mCpuFreqTimeMs.reset(false);
            }
            if (mScreenOffCpuFreqTimeMs != null) {
                mScreenOffCpuFreqTimeMs.reset(false);
            }

            resetLongCounterIfNotNull(mMobileRadioApWakeupCount, false);
            resetLongCounterIfNotNull(mWifiRadioApWakeupCount, false);

@@ -6523,6 +6700,13 @@ public class BatteryStatsImpl extends BatteryStats {
                    }
                }

                if (mCpuFreqTimeMs != null) {
                    mCpuFreqTimeMs.detach();
                }
                if (mScreenOffCpuFreqTimeMs != null) {
                    mScreenOffCpuFreqTimeMs.detach();
                }

                detachLongCounterIfNotNull(mMobileRadioApWakeupCount);
                detachLongCounterIfNotNull(mWifiRadioApWakeupCount);
            }
@@ -6739,6 +6923,19 @@ public class BatteryStatsImpl extends BatteryStats {
                out.writeInt(0);
            }

            if (mCpuFreqTimeMs != null) {
                out.writeInt(1);
                mCpuFreqTimeMs.writeToParcel(out);
            } else {
                out.writeInt(0);
            }
            if (mScreenOffCpuFreqTimeMs != null) {
                out.writeInt(1);
                mScreenOffCpuFreqTimeMs.writeToParcel(out);
            } else {
                out.writeInt(0);
            }

            if (mMobileRadioApWakeupCount != null) {
                out.writeInt(1);
                mMobileRadioApWakeupCount.writeToParcel(out);
@@ -6986,6 +7183,18 @@ public class BatteryStatsImpl extends BatteryStats {
                mCpuClusterSpeed = null;
            }

            if (in.readInt() != 0) {
                mCpuFreqTimeMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase, in);
            } else {
                mCpuFreqTimeMs = null;
            }
            if (in.readInt() != 0) {
                mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
                        mBsi.mOnBatteryScreenOffTimeBase, in);
            } else {
                mScreenOffCpuFreqTimeMs = null;
            }

            if (in.readInt() != 0) {
                mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
            } else {
@@ -8192,6 +8401,10 @@ public class BatteryStatsImpl extends BatteryStats {
        }
    }

    public long[] getCpuFreqs() {
        return mCpuFreqs;
    }

    public BatteryStatsImpl(File systemDir, Handler handler, ExternalStatsSync externalSync) {
        this(new SystemClocks(), systemDir, handler, externalSync, null);
    }
@@ -9812,6 +10025,8 @@ public class BatteryStatsImpl extends BatteryStats {
                    }
                });

        readKernelUidCpuFreqTimesLocked();

        final long elapse = (mClocks.elapsedRealtime() - startTimeMs);
        if (DEBUG_ENERGY_CPU || (elapse >= 100)) {
            Slog.d(TAG, "Reading cpu stats took " + elapse + " ms");
@@ -9900,6 +10115,30 @@ public class BatteryStatsImpl extends BatteryStats {
        }
    }

    void readKernelUidCpuFreqTimesLocked() {
        mKernelUidCpuFreqTimeReader.readDelta(!mOnBatteryInternal ? null :
                new KernelUidCpuFreqTimeReader.Callback() {
                    @Override
                    public void onCpuFreqs(long[] cpuFreqs) {
                        mCpuFreqs = cpuFreqs;
                    }

                    @Override
                    public void onUidCpuFreqTime(int uid, long[] cpuFreqTimeMs) {
                        final Uid u = getUidStatsLocked(uid);
                        if (u.mCpuFreqTimeMs == null) {
                            u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
                        }
                        u.mCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs);
                        if (u.mScreenOffCpuFreqTimeMs == null) {
                            u.mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
                                    mOnBatteryScreenOffTimeBase);
                        }
                        u.mScreenOffCpuFreqTimeMs.addCountLocked(cpuFreqTimeMs);
                    }
                });
    }

    boolean setChargingLocked(boolean charging) {
        if (mCharging != charging) {
            mCharging = charging;
@@ -10988,6 +11227,8 @@ public class BatteryStatsImpl extends BatteryStats {
            }
        }

        mCpuFreqs = in.createLongArray();

        final int NU = in.readInt();
        if (NU > 10000) {
            throw new ParcelFormatException("File corrupt: too many uids " + NU);
@@ -11110,6 +11351,20 @@ public class BatteryStatsImpl extends BatteryStats {
                u.mCpuClusterSpeed = null;
            }

            if (in.readInt() != 0) {
                u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
                u.mCpuFreqTimeMs.readSummaryFromParcelLocked(in);
            } else {
                u.mCpuFreqTimeMs = null;
            }
            if (in.readInt() != 0) {
                u.mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
                        mOnBatteryScreenOffTimeBase);
                u.mScreenOffCpuFreqTimeMs.readSummaryFromParcelLocked(in);
            } else {
                u.mScreenOffCpuFreqTimeMs = null;
            }

            if (in.readInt() != 0) {
                u.mMobileRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
                u.mMobileRadioApWakeupCount.readSummaryFromParcelLocked(in);
@@ -11360,6 +11615,8 @@ public class BatteryStatsImpl extends BatteryStats {
            }
        }

        out.writeLongArray(mCpuFreqs);

        final int NU = mUidStats.size();
        out.writeInt(NU);
        for (int iu = 0; iu < NU; iu++) {
@@ -11504,6 +11761,19 @@ public class BatteryStatsImpl extends BatteryStats {
                out.writeInt(0);
            }

            if (u.mCpuFreqTimeMs != null) {
                out.writeInt(1);
                u.mCpuFreqTimeMs.writeSummaryFromParcelLocked(out);
            } else {
                out.writeInt(0);
            }
            if (u.mScreenOffCpuFreqTimeMs != null) {
                out.writeInt(1);
                u.mScreenOffCpuFreqTimeMs.writeSummaryFromParcelLocked(out);
            } else {
                out.writeInt(0);
            }

            if (u.mMobileRadioApWakeupCount != null) {
                out.writeInt(1);
                u.mMobileRadioApWakeupCount.writeSummaryFromParcelLocked(out);
@@ -11794,6 +12064,8 @@ public class BatteryStatsImpl extends BatteryStats {
        mFlashlightTurnedOnTimers.clear();
        mCameraTurnedOnTimers.clear();

        mCpuFreqs = in.createLongArray();

        int numUids = in.readInt();
        mUidStats.clear();
        for (int i = 0; i < numUids; i++) {
@@ -11953,6 +12225,8 @@ public class BatteryStatsImpl extends BatteryStats {
            }
        }

        out.writeLongArray(mCpuFreqs);

        if (inclUids) {
            int size = mUidStats.size();
            out.writeInt(size);
+117 −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 com.android.internal.os;

import android.annotation.Nullable;
import android.util.Slog;
import android.util.SparseArray;

import com.android.internal.annotations.VisibleForTesting;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

/**
 * Reads /proc/uid_time_in_state which has the format:
 *
 * uid: [freq1] [freq2] [freq3] ...
 * [uid1]: [time in freq1] [time in freq2] [time in freq3] ...
 * [uid2]: [time in freq1] [time in freq2] [time in freq3] ...
 * ...
 *
 * This provides the times a UID's processes spent executing at each different cpu frequency.
 * The file contains a monotonically increasing count of time for a single boot. This class
 * maintains the previous results of a call to {@link #readDelta} in order to provide a proper
 * delta.
 */
public class KernelUidCpuFreqTimeReader {
    private static final String TAG = "KernelUidCpuFreqTimeReader";
    private static final String UID_TIMES_PROC_FILE = "/proc/uid_time_in_state";

    public interface Callback {
        void onCpuFreqs(long[] cpuFreqs);
        void onUidCpuFreqTime(int uid, long[] cpuFreqTimeMs);
    }

    private long[] mCpuFreqs;
    private int mCpuFreqsCount;

    private SparseArray<long[]> mLastUidCpuFreqTimeMs = new SparseArray<>();

    public void readDelta(@Nullable Callback callback) {
        try (BufferedReader reader = new BufferedReader(new FileReader(UID_TIMES_PROC_FILE))) {
            readDelta(reader, callback);
        } catch (IOException e) {
            Slog.e(TAG, "Failed to read " + UID_TIMES_PROC_FILE + ": " + e);
        }
    }

    @VisibleForTesting
    public void readDelta(BufferedReader reader, @Nullable Callback callback) throws IOException {
        String line = reader.readLine();
        if (line == null) {
            return;
        }
        readCpuFreqs(line, callback);
        while ((line = reader.readLine()) != null) {
            final int index = line.indexOf(' ');
            final int uid = Integer.parseInt(line.substring(0, index - 1), 10);
            readTimesForUid(uid, line.substring(index + 1, line.length()), callback);
        }
    }

    private void readTimesForUid(int uid, String line, Callback callback) {
        long[] uidTimeMs = mLastUidCpuFreqTimeMs.get(uid);
        if (uidTimeMs == null) {
            uidTimeMs = new long[mCpuFreqsCount];
            mLastUidCpuFreqTimeMs.put(uid, uidTimeMs);
        }
        final String[] timesStr = line.split(" ");
        final int size = timesStr.length;
        if (size != uidTimeMs.length) {
            Slog.e(TAG, "No. of readings don't match cpu freqs, readings: " + size
                    + " cpuFreqsCount: " + uidTimeMs.length);
            return;
        }
        final long[] deltaUidTimeMs = new long[size];
        for (int i = 0; i < size; ++i) {
            // Times read will be in units of 10ms
            final long totalTimeMs = Long.parseLong(timesStr[i], 10) * 10;
            deltaUidTimeMs[i] = totalTimeMs - uidTimeMs[i];
            uidTimeMs[i] = totalTimeMs;
        }
        if (callback != null) {
            callback.onUidCpuFreqTime(uid, deltaUidTimeMs);
        }
    }

    private void readCpuFreqs(String line, Callback callback) {
        if (mCpuFreqs == null) {
            final String[] freqStr = line.split(" ");
            // First item would be "uid:" which needs to be ignored
            mCpuFreqsCount = freqStr.length - 1;
            mCpuFreqs = new long[mCpuFreqsCount];
            for (int i = 0; i < mCpuFreqsCount; ++i) {
                mCpuFreqs[i] = Long.parseLong(freqStr[i + 1], 10);
            }
        }
        if (callback != null) {
            callback.onCpuFreqs(mCpuFreqs);
        }
    }
}
+109 −0

File added.

Preview size limit exceeded, changes collapsed.