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

Commit a7c90c84 authored by Adam Lesinski's avatar Adam Lesinski
Browse files

BatteryStats: Update external stats individually.

When wifi traffic causes a stats collection, we shouldn't care about
cpu or bluetooth updates.

Bug:21478443
Change-Id: I177dc0fc09951813cb4a702ad0e5d951d69f8c22
parent 72478f05
Loading
Loading
Loading
Loading
+26 −7
Original line number Diff line number Diff line
@@ -95,8 +95,8 @@ import java.util.concurrent.locks.ReentrantLock;
public final class BatteryStatsImpl extends BatteryStats {
    private static final String TAG = "BatteryStatsImpl";
    private static final boolean DEBUG = false;
    private static final boolean DEBUG_ENERGY = false;
    public static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY || false;
    public static final boolean DEBUG_ENERGY = false;
    private static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY || false;
    private static final boolean DEBUG_HISTORY = false;
    private static final boolean USE_OLD_HISTORY = false;   // for debugging.

@@ -182,6 +182,7 @@ public final class BatteryStatsImpl extends BatteryStats {

    public interface ExternalStatsSync {
        void scheduleSync(String reason);
        void scheduleWifiSync(String reason);
    }

    public final MyHandler mHandler;
@@ -3496,7 +3497,7 @@ public final class BatteryStatsImpl extends BatteryStats {
            addHistoryRecordLocked(elapsedRealtime, uptime);
            mWifiOn = true;
            mWifiOnTimer.startRunningLocked(elapsedRealtime);
            scheduleSyncExternalStatsLocked("wifi-off");
            scheduleSyncExternalWifiStatsLocked("wifi-off");
        }
    }

@@ -3510,7 +3511,7 @@ public final class BatteryStatsImpl extends BatteryStats {
            addHistoryRecordLocked(elapsedRealtime, uptime);
            mWifiOn = false;
            mWifiOnTimer.stopRunningLocked(elapsedRealtime);
            scheduleSyncExternalStatsLocked("wifi-on");
            scheduleSyncExternalWifiStatsLocked("wifi-on");
        }
    }

@@ -3762,7 +3763,7 @@ public final class BatteryStatsImpl extends BatteryStats {
                int uid = mapUid(ws.get(i));
                getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
            }
            scheduleSyncExternalStatsLocked("wifi-running");
            scheduleSyncExternalWifiStatsLocked("wifi-running");
        } else {
            Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
        }
@@ -3801,7 +3802,7 @@ public final class BatteryStatsImpl extends BatteryStats {
                int uid = mapUid(ws.get(i));
                getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
            }
            scheduleSyncExternalStatsLocked("wifi-stopped");
            scheduleSyncExternalWifiStatsLocked("wifi-stopped");
        } else {
            Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
        }
@@ -3816,7 +3817,7 @@ public final class BatteryStatsImpl extends BatteryStats {
            }
            mWifiState = wifiState;
            mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtime);
            scheduleSyncExternalStatsLocked("wifi-state");
            scheduleSyncExternalWifiStatsLocked("wifi-state");
        }
    }

@@ -7548,6 +7549,10 @@ public final class BatteryStatsImpl extends BatteryStats {
     * @param info The energy information from the WiFi controller.
     */
    public void updateWifiStateLocked(@Nullable final WifiActivityEnergyInfo info) {
        if (DEBUG_ENERGY) {
            Slog.d(TAG, "Updating wifi stats");
        }

        final long elapsedRealtimeMs = SystemClock.elapsedRealtime();
        NetworkStats delta = null;
        try {
@@ -7745,6 +7750,10 @@ public final class BatteryStatsImpl extends BatteryStats {
     * Distribute Cell radio energy info and network traffic to apps.
     */
    public void updateMobileRadioStateLocked(final long elapsedRealtimeMs) {
        if (DEBUG_ENERGY) {
            Slog.d(TAG, "Updating mobile radio stats");
        }

        NetworkStats delta = null;
        try {
            if (!ArrayUtils.isEmpty(mMobileIfaces)) {
@@ -7817,6 +7826,10 @@ public final class BatteryStatsImpl extends BatteryStats {
     * @param info The energy information from the bluetooth controller.
     */
    public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info) {
        if (DEBUG_ENERGY) {
            Slog.d(TAG, "Updating bluetooth stats");
        }

        if (info != null && mOnBatteryInternal) {
            mHasBluetoothEnergyReporting = true;
            mBluetoothActivityCounters[CONTROLLER_RX_TIME].addCountLocked(
@@ -8239,6 +8252,12 @@ public final class BatteryStatsImpl extends BatteryStats {
        }
    }

    private void scheduleSyncExternalWifiStatsLocked(String reason) {
        if (mExternalSync != null) {
            mExternalSync.scheduleWifiSync(reason);
        }
    }

    // This should probably be exposed in the API, though it's not critical
    public static final int BATTERY_PLUGGED_NONE = 0;

+71 −34
Original line number Diff line number Diff line
@@ -70,9 +70,16 @@ public final class BatteryStatsService extends IBatteryStats.Stub
    Context mContext;
    PowerManagerInternal mPowerManagerInternal;

    final int UPDATE_CPU = 0x01;
    final int UPDATE_WIFI = 0x02;
    final int UPDATE_RADIO = 0x04;
    final int UPDATE_BT = 0x08;
    final int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT;

    class BatteryStatsHandler extends Handler implements BatteryStatsImpl.ExternalStatsSync {
        public static final int MSG_SYNC_EXTERNAL_STATS = 1;
        public static final int MSG_WRITE_TO_DISK = 2;
        private int mUpdateFlags = 0;

        public BatteryStatsHandler(Looper looper) {
            super(looper);
@@ -82,11 +89,17 @@ public final class BatteryStatsService extends IBatteryStats.Stub
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_SYNC_EXTERNAL_STATS:
                    updateExternalStats((String)msg.obj, false);
                    final int updateFlags;
                    synchronized (this) {
                        removeMessages(MSG_SYNC_EXTERNAL_STATS);
                        updateFlags = mUpdateFlags;
                        mUpdateFlags = 0;
                    }
                    updateExternalStats((String)msg.obj, updateFlags);
                    break;

                case MSG_WRITE_TO_DISK:
                    updateExternalStats("write", true);
                    updateExternalStats("write", UPDATE_ALL);
                    synchronized (mStats) {
                        mStats.writeAsyncLocked();
                    }
@@ -96,9 +109,20 @@ public final class BatteryStatsService extends IBatteryStats.Stub

        @Override
        public void scheduleSync(String reason) {
            if (!hasMessages(MSG_SYNC_EXTERNAL_STATS)) {
                Message msg = Message.obtain(this, MSG_SYNC_EXTERNAL_STATS, reason);
                sendMessage(msg);
            scheduleSyncImpl(reason, UPDATE_ALL);
        }

        @Override
        public void scheduleWifiSync(String reason) {
            scheduleSyncImpl(reason, UPDATE_WIFI);
        }

        private void scheduleSyncImpl(String reason, int updateFlags) {
            synchronized (this) {
                if (mUpdateFlags == 0) {
                    sendMessage(Message.obtain(this, MSG_SYNC_EXTERNAL_STATS, reason));
                }
                mUpdateFlags |= updateFlags;
            }
        }
    }
@@ -136,7 +160,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
    public void shutdown() {
        Slog.w("BatteryStats", "Writing battery stats before shutdown...");

        updateExternalStats("shutdown", true);
        updateExternalStats("shutdown", UPDATE_ALL);
        synchronized (mStats) {
            mStats.shutdownLocked();
        }
@@ -236,7 +260,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
        //Slog.i("foo", "SENDING BATTERY INFO:");
        //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
        Parcel out = Parcel.obtain();
        updateExternalStats("get-stats", true);
        updateExternalStats("get-stats", UPDATE_ALL);
        synchronized (mStats) {
            mStats.writeToParcel(out, 0);
        }
@@ -251,7 +275,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
        //Slog.i("foo", "SENDING BATTERY INFO:");
        //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
        Parcel out = Parcel.obtain();
        updateExternalStats("get-stats", true);
        updateExternalStats("get-stats", UPDATE_ALL);
        synchronized (mStats) {
            mStats.writeToParcel(out, 0);
        }
@@ -602,8 +626,10 @@ public final class BatteryStatsService extends IBatteryStats.Stub

        // There was a change in WiFi power state.
        // Collect data now for the past activity.
        mHandler.scheduleSync("wifi-data");
        synchronized (mStats) {
            if (mStats.isOnBattery()) {
                mHandler.scheduleWifiSync("wifi-data");
            }
            mStats.noteWifiRadioPowerState(powerState, tsNanos);
        }
    }
@@ -806,7 +832,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub

        // Sync external stats first as the battery has changed states. If we don't sync
        // immediately here, we may not collect the relevant data later.
        updateExternalStats("battery-state", true);
        updateExternalStats("battery-state", UPDATE_ALL);
        synchronized (mStats) {
            mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt);
        }
@@ -960,9 +986,9 @@ public final class BatteryStatsService extends IBatteryStats.Stub
                        pw.println("Battery stats reset.");
                        noOutput = true;
                    }
                    updateExternalStats("dump", true);
                    updateExternalStats("dump", UPDATE_ALL);
                } else if ("--write".equals(arg)) {
                    updateExternalStats("dump", true);
                    updateExternalStats("dump", UPDATE_ALL);
                    synchronized (mStats) {
                        mStats.writeSyncLocked();
                        pw.println("Battery stats written.");
@@ -1026,7 +1052,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
                flags |= BatteryStats.DUMP_DEVICE_WIFI_ONLY;
            }
            // Fetch data from external sources and update the BatteryStatsImpl object with them.
            updateExternalStats("dump", true);
            updateExternalStats("dump", UPDATE_ALL);
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
@@ -1183,15 +1209,12 @@ public final class BatteryStatsService extends IBatteryStats.Stub
     * We first grab a lock specific to this method, then once all the data has been collected,
     * we grab the mStats lock and update the data.
     *
     * TODO(adamlesinski): When we start distributing bluetooth data to apps, we'll want to
     * separate these external stats so that they can be collected individually and on different
     * intervals.
     *
     * @param reason The reason why this collection was requested. Useful for debugging.
     * @param force If false, some stats may decide not to be collected for efficiency as their
     *              results aren't needed immediately. When true, collect all stats unconditionally.
     * @param updateFlags Which external stats to update. Can be a combination of
     *                    {@link #UPDATE_CPU}, {@link #UPDATE_RADIO}, {@link #UPDATE_WIFI},
     *                    and {@link #UPDATE_BT}.
     */
    void updateExternalStats(String reason, boolean force) {
    void updateExternalStats(final String reason, final int updateFlags) {
        synchronized (mExternalStatsLock) {
            if (mContext == null) {
                // We haven't started yet (which means the BatteryStatsImpl object has
@@ -1199,33 +1222,47 @@ public final class BatteryStatsService extends IBatteryStats.Stub
                return;
            }

            final WifiActivityEnergyInfo wifiEnergyInfo = pullWifiEnergyInfoLocked();
            final BluetoothActivityEnergyInfo bluetoothEnergyInfo;
            if (force) {
            if (BatteryStatsImpl.DEBUG_ENERGY) {
                Slog.d(TAG, "Updating external stats: reason=" + reason);
            }

            WifiActivityEnergyInfo wifiEnergyInfo = null;
            if ((updateFlags & UPDATE_WIFI) != 0) {
                wifiEnergyInfo = pullWifiEnergyInfoLocked();
            }

            BluetoothActivityEnergyInfo bluetoothEnergyInfo = null;
            if ((updateFlags & UPDATE_BT) != 0) {
                // We only pull bluetooth stats when we have to, as we are not distributing its
                // use amongst apps and the sampling frequency does not matter.
                bluetoothEnergyInfo = pullBluetoothEnergyInfoLocked();
            } else {
                bluetoothEnergyInfo = null;
            }

            synchronized (mStats) {
                if (mStats.mRecordAllHistory) {
                final long elapsedRealtime = SystemClock.elapsedRealtime();
                final long uptime = SystemClock.uptimeMillis();
                if (mStats.mRecordAllHistory) {
                    mStats.addHistoryEventLocked(elapsedRealtime, uptime,
                            BatteryStats.HistoryItem.EVENT_COLLECT_EXTERNAL_STATS, reason, 0);
                }

                if (BatteryStatsImpl.DEBUG_ENERGY_CPU) {
                    Slog.d(TAG, "Updating cpu time from external: " + reason);
                }
                if ((updateFlags & UPDATE_CPU) != 0) {
                    mStats.updateCpuTimeLocked();
                    mStats.updateKernelWakelocksLocked();
                mStats.updateMobileRadioStateLocked(SystemClock.elapsedRealtime());
                }

                if ((updateFlags & UPDATE_RADIO) != 0) {
                    mStats.updateMobileRadioStateLocked(elapsedRealtime);
                }

                if ((updateFlags & UPDATE_WIFI) != 0) {
                    mStats.updateWifiStateLocked(wifiEnergyInfo);
                }

                if ((updateFlags & UPDATE_BT) != 0) {
                    mStats.updateBluetoothStateLocked(bluetoothEnergyInfo);
                }
            }
        }
    }
}