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

Commit 761b3329 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Log deferred jobs metrics to batterystats"

parents 414189fe 977e11f3
Loading
Loading
Loading
Loading
+48 −0
Original line number Diff line number Diff line
@@ -287,6 +287,16 @@ public abstract class BatteryStats implements Parcelable {
    private static final String SYNC_DATA = "sy";
    private static final String JOB_DATA = "jb";
    private static final String JOB_COMPLETION_DATA = "jbc";

    /**
     * jbd line is:
     * BATTERY_STATS_CHECKIN_VERSION, uid, which, "jbd",
     * jobsDeferredEventCount, jobsDeferredCount, averageLatencyMillis,
     * count at latency < 1 hr, count at latency < 2 hrs, count at latency < 6 hrs, beyond 6 hrs
     * <p>
     * @see #JOB_FRESHNESS_BUCKETS
     */
    private static final String JOBS_DEFERRED_DATA = "jbd";
    private static final String KERNEL_WAKELOCK_DATA = "kwl";
    private static final String WAKEUP_REASON_DATA = "wr";
    private static final String NETWORK_DATA = "nt";
@@ -348,6 +358,19 @@ public abstract class BatteryStats implements Parcelable {
    @VisibleForTesting
    public static final String UID_TIMES_TYPE_ALL = "A";

    /**
     * These are the thresholds for bucketing last time since a job was run for an app
     * that just moved to ACTIVE due to a launch. So if the last time a job ran was less
     * than 30 minutes ago, then it's reasonably fresh, 2 hours ago, not so fresh and so
     * on.
     */
    public static final long[] JOB_FRESHNESS_BUCKETS = {
            1 * 60 * 60 * 1000L,
            2 * 60 * 60 * 1000L,
            6 * 60 * 60 * 1000L,
            Long.MAX_VALUE
    };

    /**
     * State for keeping track of counting information.
     */
@@ -846,6 +869,20 @@ public abstract class BatteryStats implements Parcelable {
         */
        public abstract long getWifiRadioApWakeupCount(int which);

        /**
         * Appends the deferred jobs data to the StringBuilder passed in, in checkin format
         * @param sb StringBuilder that can be overwritten with the deferred jobs data
         * @param which one of STATS_*
         */
        public abstract void getDeferredJobsCheckinLineLocked(StringBuilder sb, int which);

        /**
         * Appends the deferred jobs data to the StringBuilder passed in
         * @param sb StringBuilder that can be overwritten with the deferred jobs data
         * @param which one of STATS_*
         */
        public abstract void getDeferredJobsLineLocked(StringBuilder sb, int which);

        public static abstract class Sensor {
            /*
             * FIXME: it's not correct to use this magic value because it
@@ -4070,6 +4107,12 @@ public abstract class BatteryStats implements Parcelable {
                }
            }

            // Dump deferred jobs stats
            u.getDeferredJobsCheckinLineLocked(sb, which);
            if (sb.length() > 0) {
                dumpLine(pw, uid, category, JOBS_DEFERRED_DATA, sb.toString());
            }

            dumpTimer(pw, uid, category, FLASHLIGHT_DATA, u.getFlashlightTurnedOnTimer(),
                    rawRealtime, which);
            dumpTimer(pw, uid, category, CAMERA_DATA, u.getCameraTurnedOnTimer(),
@@ -5698,6 +5741,11 @@ public abstract class BatteryStats implements Parcelable {
                }
            }

            u.getDeferredJobsLineLocked(sb, which);
            if (sb.length() > 0) {
                pw.print("    Jobs deferred on launch "); pw.println(sb.toString());
            }

            uidActivity |= printTimer(pw, sb, u.getFlashlightTurnedOnTimer(), rawRealtime, which,
                    prefix, "Flashlight");
            uidActivity |= printTimer(pw, sb, u.getCameraTurnedOnTimer(), rawRealtime, which,
+10 −1
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@ package android.os;

/**
 * Battery stats local system service interface. This is used to pass internal data out of
 * BatteryStatsImpl.
 * BatteryStatsImpl, as well as make unchecked calls into BatteryStatsImpl.
 *
 * @hide Only for use within Android OS.
 */
@@ -32,4 +32,13 @@ public abstract class BatteryStatsInternal {
     * Returns the mobile data interfaces.
     */
    public abstract String[] getMobileIfaces();

    /**
     * Inform battery stats how many deferred jobs existed when the app got launched and how
     * long ago was the last job execution for the app.
     * @param uid the uid of the app.
     * @param numDeferred number of deferred jobs.
     * @param sinceLast how long in millis has it been since a job was run
     */
    public abstract void noteJobsDeferred(int uid, int numDeferred, long sinceLast);
}
+163 −2
Original line number Diff line number Diff line
@@ -134,7 +134,7 @@ public class BatteryStatsImpl extends BatteryStats {
    private static final int MAGIC = 0xBA757475; // 'BATSTATS'
    // Current on-disk Parcel version
    private static final int VERSION = 174 + (USE_OLD_HISTORY ? 1000 : 0);
    private static final int VERSION = 175 + (USE_OLD_HISTORY ? 1000 : 0);
    // Maximum number of items we will record in the history.
    private static final int MAX_HISTORY_ITEMS;
@@ -1222,7 +1222,7 @@ public class BatteryStatsImpl extends BatteryStats {
         * @param out the Parcel to be written to.
         * @param counter a Counter, or null.
         */
        public static void writeCounterToParcel(Parcel out, Counter counter) {
        public static void writeCounterToParcel(Parcel out, @Nullable Counter counter) {
            if (counter == null) {
                out.writeInt(0); // indicates null
                return;
@@ -1232,6 +1232,19 @@ public class BatteryStatsImpl extends BatteryStats {
            counter.writeToParcel(out);
        }
        /**
         * Reads a Counter that was written using {@link #writeCounterToParcel(Parcel, Counter)}.
         * @param timeBase the timebase to assign to the Counter
         * @param in the parcel to read from
         * @return the Counter or null.
         */
        public static @Nullable Counter readCounterFromParcel(TimeBase timeBase, Parcel in) {
            if (in.readInt() == 0) {
                return null;
            }
            return new Counter(timeBase, in);
        }
        @Override
        public int getCountLocked(int which) {
            int val = mCount.get();
@@ -4071,6 +4084,11 @@ public class BatteryStatsImpl extends BatteryStats {
        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_FINISH, name, uid);
    }
    public void noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast) {
        uid = mapUid(uid);
        getUidStatsLocked(uid).noteJobsDeferredLocked(numDeferred, sinceLast);
    }
    public void noteAlarmStartLocked(String name, WorkSource workSource, int uid) {
        noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_START, name, workSource, uid);
    }
@@ -6748,6 +6766,29 @@ public class BatteryStatsImpl extends BatteryStats {
         */
        final ArrayMap<String, SparseIntArray> mJobCompletions = new ArrayMap<>();
        /**
         * Count of app launch events that had associated deferred job counts or info about
         * last time a job was run.
         */
        Counter mJobsDeferredEventCount;
        /**
         * Count of deferred jobs that were pending when the app was launched or brought to
         * the foreground through a user interaction.
         */
        Counter mJobsDeferredCount;
        /**
         * Sum of time since the last time a job was run for this app before it was launched.
         */
        LongSamplingCounter mJobsFreshnessTimeMs;
        /**
         * Array of counts of instances where the time since the last job was run for the app
         * fell within one of the thresholds in {@link #JOB_FRESHNESS_BUCKETS}.
         */
        final Counter[] mJobsFreshnessBuckets;
        /**
         * The statistics we have collected for this uid's sensor activations.
         */
@@ -6822,6 +6863,10 @@ public class BatteryStatsImpl extends BatteryStats {
            mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_MULTICAST_ENABLED,
                    mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
            mProcessStateTimer = new StopwatchTimer[NUM_PROCESS_STATE];
            mJobsDeferredEventCount = new Counter(mBsi.mOnBatteryTimeBase);
            mJobsDeferredCount = new Counter(mBsi.mOnBatteryTimeBase);
            mJobsFreshnessTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
            mJobsFreshnessBuckets = new Counter[JOB_FRESHNESS_BUCKETS.length];
        }
        @VisibleForTesting
@@ -7799,6 +7844,55 @@ public class BatteryStatsImpl extends BatteryStats {
            return 0;
        }
        @Override
        public void getDeferredJobsCheckinLineLocked(StringBuilder sb, int which) {
            sb.setLength(0);
            final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
            if (deferredEventCount == 0) {
                return;
            }
            final int deferredCount = mJobsDeferredCount.getCountLocked(which);
            final long averageLatency = deferredEventCount != 0
                    ? mJobsFreshnessTimeMs.getCountLocked(which) / deferredEventCount
                    : 0L;
            sb.append(deferredEventCount); sb.append(',');
            sb.append(deferredCount); sb.append(',');
            sb.append(averageLatency);
            for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
                if (mJobsFreshnessBuckets[i] == null) {
                    sb.append(",0");
                } else {
                    sb.append(",");
                    sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
                }
            }
        }
        @Override
        public void getDeferredJobsLineLocked(StringBuilder sb, int which) {
            sb.setLength(0);
            final int deferredEventCount = mJobsDeferredEventCount.getCountLocked(which);
            if (deferredEventCount == 0) {
                return;
            }
            final int deferredCount = mJobsDeferredCount.getCountLocked(which);
            final long averageLatency = deferredEventCount != 0
                    ? mJobsFreshnessTimeMs.getCountLocked(which) / deferredEventCount
                    : 0L;
            sb.append("times="); sb.append(deferredEventCount); sb.append(", ");
            sb.append("count="); sb.append(deferredCount); sb.append(", ");
            sb.append("avgLatency="); sb.append(averageLatency); sb.append(", ");
            for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
                sb.append("<"); sb.append(JOB_FRESHNESS_BUCKETS[i]); sb.append("ms=");
                if (mJobsFreshnessBuckets[i] == null) {
                    sb.append("0");
                } else {
                    sb.append(mJobsFreshnessBuckets[i].getCountLocked(which));
                }
                sb.append(" ");
            }
        }
        void initNetworkActivityLocked() {
            mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
            mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
@@ -7982,6 +8076,16 @@ public class BatteryStatsImpl extends BatteryStats {
            }
            mJobStats.cleanup();
            mJobCompletions.clear();
            mJobsDeferredEventCount.reset(false);
            mJobsDeferredCount.reset(false);
            mJobsFreshnessTimeMs.reset(false);
            for (int ij = 0; ij < JOB_FRESHNESS_BUCKETS.length; ij++) {
                if (mJobsFreshnessBuckets[ij] != null) {
                    mJobsFreshnessBuckets[ij].reset(false);
                }
            }
            for (int ise=mSensorStats.size()-1; ise>=0; ise--) {
                Sensor s = mSensorStats.valueAt(ise);
                if (s.reset()) {
@@ -7990,6 +8094,7 @@ public class BatteryStatsImpl extends BatteryStats {
                    active = true;
                }
            }
            for (int ip=mProcessStats.size()-1; ip>=0; ip--) {
                Proc proc = mProcessStats.valueAt(ip);
                proc.detach();
@@ -8207,6 +8312,13 @@ public class BatteryStatsImpl extends BatteryStats {
            writeJobCompletionsToParcelLocked(out);
            mJobsDeferredEventCount.writeToParcel(out);
            mJobsDeferredCount.writeToParcel(out);
            mJobsFreshnessTimeMs.writeToParcel(out);
            for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
                Counter.writeCounterToParcel(out, mJobsFreshnessBuckets[i]);
            }
            int NSE = mSensorStats.size();
            out.writeInt(NSE);
            for (int ise=0; ise<NSE; ise++) {
@@ -8502,6 +8614,14 @@ public class BatteryStatsImpl extends BatteryStats {
            readJobCompletionsFromParcelLocked(in);
            mJobsDeferredEventCount = new Counter(mBsi.mOnBatteryTimeBase, in);
            mJobsDeferredCount = new Counter(mBsi.mOnBatteryTimeBase, in);
            mJobsFreshnessTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
            for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
                mJobsFreshnessBuckets[i] = Counter.readCounterFromParcel(mBsi.mOnBatteryTimeBase,
                        in);
            }
            int numSensors = in.readInt();
            mSensorStats.clear();
            for (int k = 0; k < numSensors; k++) {
@@ -8770,6 +8890,26 @@ public class BatteryStatsImpl extends BatteryStats {
            }
        }
        public void noteJobsDeferredLocked(int numDeferred, long sinceLast) {
            mJobsDeferredEventCount.addAtomic(1);
            mJobsDeferredCount.addAtomic(numDeferred);
            if (sinceLast != 0) {
                // Add the total time, which can be divided by the event count to get an average
                mJobsFreshnessTimeMs.addCountLocked(sinceLast);
                // Also keep track of how many times there were in these different buckets.
                for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
                    if (sinceLast < JOB_FRESHNESS_BUCKETS[i]) {
                        if (mJobsFreshnessBuckets[i] == null) {
                            mJobsFreshnessBuckets[i] = new Counter(
                                    mBsi.mOnBatteryTimeBase);
                        }
                        mJobsFreshnessBuckets[i].addAtomic(1);
                        break;
                    }
                }
            }
        }
        /**
         * The statistics associated with a particular wake lock.
         */
@@ -13921,6 +14061,16 @@ public class BatteryStatsImpl extends BatteryStats {
            u.readJobCompletionsFromParcelLocked(in);
            u.mJobsDeferredEventCount.readSummaryFromParcelLocked(in);
            u.mJobsDeferredCount.readSummaryFromParcelLocked(in);
            u.mJobsFreshnessTimeMs.readSummaryFromParcelLocked(in);
            for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
                if (in.readInt() != 0) {
                    u.mJobsFreshnessBuckets[i] = new Counter(u.mBsi.mOnBatteryTimeBase);
                    u.mJobsFreshnessBuckets[i].readSummaryFromParcelLocked(in);
                }
            }
            int NP = in.readInt();
            if (NP > 1000) {
                throw new ParcelFormatException("File corrupt: too many sensors " + NP);
@@ -14419,6 +14569,17 @@ public class BatteryStatsImpl extends BatteryStats {
            u.writeJobCompletionsToParcelLocked(out);
            u.mJobsDeferredEventCount.writeSummaryFromParcelLocked(out);
            u.mJobsDeferredCount.writeSummaryFromParcelLocked(out);
            u.mJobsFreshnessTimeMs.writeSummaryFromParcelLocked(out);
            for (int i = 0; i < JOB_FRESHNESS_BUCKETS.length; i++) {
                if (u.mJobsFreshnessBuckets[i] != null) {
                    u.mJobsFreshnessBuckets[i].writeSummaryFromParcelLocked(out);
                } else {
                    out.writeInt(0);
                }
            }
            int NSE = u.mSensorStats.size();
            out.writeInt(NSE);
            for (int ise=0; ise<NSE; ise++) {
+13 −0
Original line number Diff line number Diff line
@@ -202,6 +202,12 @@ public final class BatteryStatsService extends IBatteryStats.Stub
        public String[] getMobileIfaces() {
            return mStats.getMobileIfaces().clone();
        }

        @Override
        public void noteJobsDeferred(int uid, int numDeferred, long sinceLast) {
            if (DBG) Slog.d(TAG, "Jobs deferred " + uid + ": " + numDeferred + " " + sinceLast);
            BatteryStatsService.this.noteJobsDeferred(uid, numDeferred, sinceLast);
        }
    }

    private static void awaitUninterruptibly(Future<?> future) {
@@ -456,6 +462,13 @@ public final class BatteryStatsService extends IBatteryStats.Stub
        }
    }

    void noteJobsDeferred(int uid, int numDeferred, long sinceLast) {
        // No need to enforce calling permission, as it is called from an internal interface
        synchronized (mStats) {
            mStats.noteJobsDeferredLocked(uid, numDeferred, sinceLast);
        }
    }

    public void noteWakupAlarm(String name, int uid, WorkSource workSource, String tag) {
        enforceCallingPermission();
        synchronized (mStats) {
+12 −4
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ import android.content.pm.ServiceInfo;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.BatteryStats;
import android.os.BatteryStatsInternal;
import android.os.Binder;
import android.os.Handler;
import android.os.Looper;
@@ -62,6 +63,7 @@ import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManagerInternal;
import android.provider.Settings;
import android.text.format.DateUtils;
import android.util.KeyValueListParser;
import android.util.Slog;
import android.util.SparseArray;
@@ -2282,14 +2284,20 @@ public final class JobSchedulerService extends com.android.server.SystemService
                return;
            }

            final long sinceLast = sElapsedRealtimeClock.millis() -
                    mUsageStats.getTimeSinceLastJobRun(packageName, userId);
            long sinceLast = mUsageStats.getTimeSinceLastJobRun(packageName, userId);
            if (sinceLast > 2 * DateUtils.DAY_IN_MILLIS) {
                // Too long ago, not worth logging
                sinceLast = 0L;
            }
            final DeferredJobCounter counter = new DeferredJobCounter();
            synchronized (mLock) {
                mJobs.forEachJobForSourceUid(uid, counter);
            }

            mUsageStats.reportAppJobState(packageName, userId, counter.numDeferred(), sinceLast);
            if (counter.numDeferred() > 0 || sinceLast > 0) {
                BatteryStatsInternal mBatteryStatsInternal = LocalServices.getService
                        (BatteryStatsInternal.class);
                mBatteryStatsInternal.noteJobsDeferred(uid, counter.numDeferred(), sinceLast);
            }
        }
    }