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

Commit ceb24e88 authored by Adam Lesinski's avatar Adam Lesinski Committed by Android (Google) Code Review
Browse files

Merge "BatteryStats: Acquire network stats without BatteryStatsImpl lock" into oc-dev

parents 8837aff1 14ae39ac
Loading
Loading
Loading
Loading
+399 −378
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ import android.util.LogWriter;
import android.util.LongSparseArray;
import android.util.LongSparseLongArray;
import android.util.MutableInt;
import android.util.Pools;
import android.util.PrintWriterPrinter;
import android.util.Printer;
import android.util.Slog;
@@ -66,6 +67,7 @@ import android.util.TimeUtils;
import android.util.Xml;
import android.view.Display;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.net.NetworkStatsFactory;
import com.android.internal.util.ArrayUtils;
@@ -173,7 +175,6 @@ public class BatteryStatsImpl extends BatteryStats {

    private final PlatformIdleStateCallback mPlatformIdleStateCallback;


    final class MyHandler extends Handler {
        public MyHandler(Looper looper) {
            super(looper, null, true);
@@ -228,11 +229,11 @@ public class BatteryStatsImpl extends BatteryStats {
    }

    public interface ExternalStatsSync {
        public static final int UPDATE_CPU = 0x01;
        public static final int UPDATE_WIFI = 0x02;
        public static final int UPDATE_RADIO = 0x04;
        public static final int UPDATE_BT = 0x08;
        public static final int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT;
        int UPDATE_CPU = 0x01;
        int UPDATE_WIFI = 0x02;
        int UPDATE_RADIO = 0x04;
        int UPDATE_BT = 0x08;
        int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT;

        void scheduleSync(String reason, int flags);
        void scheduleCpuSyncDueToRemovedUid(int uid);
@@ -572,8 +573,6 @@ public class BatteryStatsImpl extends BatteryStats {
    private int mMinLearnedBatteryCapacity = -1;
    private int mMaxLearnedBatteryCapacity = -1;

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

    private long[] mCpuFreqs;

    private PowerProfile mPowerProfile;
@@ -637,19 +636,9 @@ public class BatteryStatsImpl extends BatteryStats {

    private void init(Clocks clocks) {
        mClocks = clocks;
        mMobileNetworkStats = new NetworkStats[] {
                new NetworkStats(mClocks.elapsedRealtime(), 50),
                new NetworkStats(mClocks.elapsedRealtime(), 50),
                new NetworkStats(mClocks.elapsedRealtime(), 50)
        };
        mWifiNetworkStats = new NetworkStats[] {
                new NetworkStats(mClocks.elapsedRealtime(), 50),
                new NetworkStats(mClocks.elapsedRealtime(), 50),
                new NetworkStats(mClocks.elapsedRealtime(), 50)
            };
    }

    public static interface TimeBaseObs {
    public interface TimeBaseObs {
        void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime);
        void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime);
    }
@@ -4200,7 +4189,10 @@ public class BatteryStatsImpl extends BatteryStats {
        getUidStatsLocked(uid).noteMobileRadioApWakeupLocked();
    }

    public void noteMobileRadioPowerState(int powerState, long timestampNs, int uid) {
    /**
     * Updates the radio power state and returns true if an external stats collection should occur.
     */
    public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid) {
        final long elapsedRealtime = mClocks.elapsedRealtime();
        final long uptime = mClocks.uptimeMillis();
        if (mMobileRadioPowerState != powerState) {
@@ -4237,13 +4229,15 @@ public class BatteryStatsImpl extends BatteryStats {
                mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime);
            } else {
                mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
                updateMobileRadioStateLocked(realElapsedRealtimeMs, null);
                mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
                // Tell the caller to collect radio network/power stats.
                return true;
            }
        }
        return false;
    }

    public void notePowerSaveMode(boolean enabled) {
    public void notePowerSaveModeLocked(boolean enabled) {
        if (mPowerSaveModeEnabled != enabled) {
            int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0;
            mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_POWER_SAVE) ^ stepState;
@@ -5243,13 +5237,18 @@ public class BatteryStatsImpl extends BatteryStats {

    public void noteNetworkInterfaceTypeLocked(String iface, int networkType) {
        if (TextUtils.isEmpty(iface)) return;

        synchronized (mModemNetworkLock) {
            if (ConnectivityManager.isNetworkTypeMobile(networkType)) {
            mMobileIfaces = includeInStringArray(mMobileIfaces, iface);
            if (DEBUG) Slog.d(TAG, "Note mobile iface " + iface + ": " + mMobileIfaces);
                mModemIfaces = includeInStringArray(mModemIfaces, iface);
                if (DEBUG) Slog.d(TAG, "Note mobile iface " + iface + ": " + mModemIfaces);
            } else {
            mMobileIfaces = excludeFromStringArray(mMobileIfaces, iface);
            if (DEBUG) Slog.d(TAG, "Note non-mobile iface " + iface + ": " + mMobileIfaces);
                mModemIfaces = excludeFromStringArray(mModemIfaces, iface);
                if (DEBUG) Slog.d(TAG, "Note non-mobile iface " + iface + ": " + mModemIfaces);
            }
        }

        synchronized (mWifiNetworkLock) {
            if (ConnectivityManager.isNetworkTypeWifi(networkType)) {
                mWifiIfaces = includeInStringArray(mWifiIfaces, iface);
                if (DEBUG) Slog.d(TAG, "Note wifi iface " + iface + ": " + mWifiIfaces);
@@ -5258,13 +5257,6 @@ public class BatteryStatsImpl extends BatteryStats {
                if (DEBUG) Slog.d(TAG, "Note non-wifi iface " + iface + ": " + mWifiIfaces);
            }
        }

    public void noteNetworkStatsEnabledLocked() {
        // During device boot, qtaguid isn't enabled until after the inital
        // loading of battery stats. Now that they're enabled, take our initial
        // snapshot for future delta calculation.
        updateMobileRadioStateLocked(mClocks.elapsedRealtime(), null);
        updateWifiStateLocked(null);
    }

    @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) {
@@ -8713,8 +8705,7 @@ public class BatteryStatsImpl extends BatteryStats {
        mPlatformIdleStateCallback = null;
    }

    public void setPowerProfile(PowerProfile profile) {
        synchronized (this) {
    public void setPowerProfileLocked(PowerProfile profile) {
        mPowerProfile = profile;

        // We need to initialize the KernelCpuSpeedReaders to read from
@@ -8735,13 +8726,12 @@ public class BatteryStatsImpl extends BatteryStats {
            mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
        }
    }
    }

    public void setCallback(BatteryCallback cb) {
        mCallback = cb;
    }

    public void setRadioScanningTimeout(long timeout) {
    public void setRadioScanningTimeoutLocked(long timeout) {
        if (mPhoneSignalScanningTimer != null) {
            mPhoneSignalScanningTimer.setTimeout(timeout);
        }
@@ -9433,72 +9423,76 @@ public class BatteryStatsImpl extends BatteryStats {
        }
    }

    private String[] mMobileIfaces = EmptyArray.STRING;
    private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory();
    private final Pools.Pool<NetworkStats> mNetworkStatsPool = new Pools.SynchronizedPool<>(6);

    private final Object mWifiNetworkLock = new Object();

    @GuardedBy("mWifiNetworkLock")
    private String[] mWifiIfaces = EmptyArray.STRING;

    private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory();
    @GuardedBy("mWifiNetworkLock")
    private NetworkStats mLastWifiNetworkStats = new NetworkStats(0, -1);

    private static final int NETWORK_STATS_LAST = 0;
    private static final int NETWORK_STATS_NEXT = 1;
    private static final int NETWORK_STATS_DELTA = 2;
    private final Object mModemNetworkLock = new Object();

    private NetworkStats[] mMobileNetworkStats;
    private NetworkStats[] mWifiNetworkStats;
    @GuardedBy("mModemNetworkLock")
    private String[] mModemIfaces = EmptyArray.STRING;

    /**
     * Retrieves the delta of network stats for the given network ifaces. Uses networkStatsBuffer
     * as a buffer of NetworkStats objects to cycle through when computing deltas.
     */
    private NetworkStats getNetworkStatsDeltaLocked(String[] ifaces,
                                                    NetworkStats[] networkStatsBuffer)
            throws IOException {
        if (!SystemProperties.getBoolean(NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED,
                false)) {
            return null;
        }
    @GuardedBy("mModemNetworkLock")
    private NetworkStats mLastModemNetworkStats = new NetworkStats(0, -1);

        final NetworkStats stats = mNetworkStatsFactory.readNetworkStatsDetail(NetworkStats.UID_ALL,
                ifaces, NetworkStats.TAG_NONE, networkStatsBuffer[NETWORK_STATS_NEXT]);
        networkStatsBuffer[NETWORK_STATS_DELTA] = NetworkStats.subtract(stats,
                networkStatsBuffer[NETWORK_STATS_LAST], null, null,
                networkStatsBuffer[NETWORK_STATS_DELTA]);
        networkStatsBuffer[NETWORK_STATS_NEXT] = networkStatsBuffer[NETWORK_STATS_LAST];
        networkStatsBuffer[NETWORK_STATS_LAST] = stats;
        return networkStatsBuffer[NETWORK_STATS_DELTA];
    private NetworkStats readNetworkStatsLocked(String[] ifaces) {
        try {
            if (!ArrayUtils.isEmpty(ifaces)) {
                return mNetworkStatsFactory.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces,
                        NetworkStats.TAG_NONE, mNetworkStatsPool.acquire());
            }
        } catch (IOException e) {
            Slog.e(TAG, "failed to read network stats for ifaces: " + Arrays.toString(ifaces));
        }
        return null;
    }

    /**
     * Distribute WiFi energy info and network traffic to apps.
     * @param info The energy information from the WiFi controller.
     */
    public void updateWifiStateLocked(@Nullable final WifiActivityEnergyInfo info) {
    public void updateWifiState(@Nullable final WifiActivityEnergyInfo info) {
        if (DEBUG_ENERGY) {
            Slog.d(TAG, "Updating wifi stats");
            Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces));
        }

        final long elapsedRealtimeMs = mClocks.elapsedRealtime();
        // Grab a separate lock to acquire the network stats, which may do I/O.
        NetworkStats delta = null;
        try {
            if (!ArrayUtils.isEmpty(mWifiIfaces)) {
                delta = getNetworkStatsDeltaLocked(mWifiIfaces, mWifiNetworkStats);
        synchronized (mWifiNetworkLock) {
            final NetworkStats latestStats = readNetworkStatsLocked(mWifiIfaces);
            if (latestStats != null) {
                delta = NetworkStats.subtract(latestStats, mLastWifiNetworkStats, null, null,
                        mNetworkStatsPool.acquire());
                mNetworkStatsPool.release(mLastWifiNetworkStats);
                mLastWifiNetworkStats = latestStats;
            }
        } catch (IOException e) {
            Slog.wtf(TAG, "Failed to get wifi network stats", e);
            return;
        }

        synchronized (this) {
            if (!mOnBatteryInternal) {
                if (delta != null) {
                    mNetworkStatsPool.release(delta);
                }
                return;
            }

            final long elapsedRealtimeMs = mClocks.elapsedRealtime();
            SparseLongArray rxPackets = new SparseLongArray();
            SparseLongArray txPackets = new SparseLongArray();
            long totalTxPackets = 0;
            long totalRxPackets = 0;
            if (delta != null) {
                NetworkStats.Entry entry = new NetworkStats.Entry();
                final int size = delta.size();
                for (int i = 0; i < size; i++) {
                final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
                    entry = delta.getValues(i, entry);

                    if (DEBUG_ENERGY) {
                        Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes
@@ -9550,6 +9544,8 @@ public class BatteryStatsImpl extends BatteryStats {
                        totalTxPackets += entry.txPackets;
                    }
                }
                mNetworkStatsPool.release(delta);
                delta = null;
            }

            if (info != null) {
@@ -9591,11 +9587,13 @@ public class BatteryStatsImpl extends BatteryStats {
                }

                if (DEBUG_ENERGY && totalScanTimeMs > rxTimeMs) {
                Slog.d(TAG, "  !Estimated scan time > Actual rx time (" + totalScanTimeMs + " ms > "
                    Slog.d(TAG,
                            "  !Estimated scan time > Actual rx time (" + totalScanTimeMs + " ms > "
                                    + rxTimeMs + " ms). Normalizing scan time.");
                }
                if (DEBUG_ENERGY && totalScanTimeMs > txTimeMs) {
                Slog.d(TAG, "  !Estimated scan time > Actual tx time (" + totalScanTimeMs + " ms > "
                    Slog.d(TAG,
                            "  !Estimated scan time > Actual tx time (" + totalScanTimeMs + " ms > "
                                    + txTimeMs + " ms). Normalizing scan time.");
                }

@@ -9637,14 +9635,16 @@ public class BatteryStatsImpl extends BatteryStats {
                        ControllerActivityCounterImpl activityCounter =
                                uid.getOrCreateWifiControllerActivityLocked();
                        activityCounter.getRxTimeCounter().addCountLocked(scanRxTimeSinceMarkMs);
                    activityCounter.getTxTimeCounters()[0].addCountLocked(scanTxTimeSinceMarkMs);
                        activityCounter.getTxTimeCounters()[0].addCountLocked(
                                scanTxTimeSinceMarkMs);
                        leftOverRxTimeMs -= scanRxTimeSinceMarkMs;
                        leftOverTxTimeMs -= scanTxTimeSinceMarkMs;
                    }

                    // Distribute evenly the power consumed while Idle to each app holding a WiFi
                    // lock.
                final long wifiLockTimeSinceMarkMs = uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
                    final long wifiLockTimeSinceMarkMs =
                            uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
                                    elapsedRealtimeMs * 1000) / 1000;
                    if (wifiLockTimeSinceMarkMs > 0) {
                        // Set the new mark so that next time we get new data since this point.
@@ -9670,7 +9670,8 @@ public class BatteryStatsImpl extends BatteryStats {
                // packets.
                for (int i = 0; i < txPackets.size(); i++) {
                    final Uid uid = getUidStatsLocked(txPackets.keyAt(i));
                final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs) / totalTxPackets;
                    final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs)
                            / totalTxPackets;
                    if (DEBUG_ENERGY) {
                        Slog.d(TAG, "  TxTime for UID " + uid.getUid() + ": " + myTxTimeMs + " ms");
                    }
@@ -9682,7 +9683,8 @@ public class BatteryStatsImpl extends BatteryStats {
                // packets.
                for (int i = 0; i < rxPackets.size(); i++) {
                    final Uid uid = getUidStatsLocked(rxPackets.keyAt(i));
                final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs) / totalRxPackets;
                    final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs)
                            / totalRxPackets;
                    if (DEBUG_ENERGY) {
                        Slog.d(TAG, "  RxTime for UID " + uid.getUid() + ": " + myRxTimeMs + " ms");
                    }
@@ -9692,10 +9694,13 @@ public class BatteryStatsImpl extends BatteryStats {

                // Any left over power use will be picked up by the WiFi category in BatteryStatsHelper.


                // Update WiFi controller stats.
                mWifiActivity.getRxTimeCounter().addCountLocked(info.getControllerRxTimeMillis());
            mWifiActivity.getTxTimeCounters()[0].addCountLocked(info.getControllerTxTimeMillis());
            mWifiActivity.getIdleTimeCounter().addCountLocked(info.getControllerIdleTimeMillis());
                mWifiActivity.getTxTimeCounters()[0].addCountLocked(
                        info.getControllerTxTimeMillis());
                mWifiActivity.getIdleTimeCounter().addCountLocked(
                        info.getControllerIdleTimeMillis());

                // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
                final double opVolt = mPowerProfile.getAveragePower(
@@ -9707,30 +9712,37 @@ public class BatteryStatsImpl extends BatteryStats {
                }
            }
        }
    }

    /**
     * Distribute Cell radio energy info and network traffic to apps.
     */
    public void updateMobileRadioStateLocked(final long elapsedRealtimeMs,
                                             final ModemActivityInfo activityInfo) {
    public void updateMobileRadioState(@Nullable final ModemActivityInfo activityInfo) {
        if (DEBUG_ENERGY) {
            Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
        }

        // Grab a separate lock to acquire the network stats, which may do I/O.
        NetworkStats delta = null;
        try {
            if (!ArrayUtils.isEmpty(mMobileIfaces)) {
                delta = getNetworkStatsDeltaLocked(mMobileIfaces, mMobileNetworkStats);
        synchronized (mModemNetworkLock) {
            final NetworkStats latestStats = readNetworkStatsLocked(mModemIfaces);
            if (latestStats != null) {
                delta = NetworkStats.subtract(latestStats, mLastModemNetworkStats, null, null,
                        mNetworkStatsPool.acquire());
                mNetworkStatsPool.release(mLastModemNetworkStats);
                mLastModemNetworkStats = latestStats;
            }
        } catch (IOException e) {
            Slog.wtf(TAG, "Failed to get mobile network stats", e);
            return;
        }

        synchronized (this) {
            if (!mOnBatteryInternal) {
                if (delta != null) {
                    mNetworkStatsPool.release(delta);
                }
                return;
            }

            final long elapsedRealtimeMs = SystemClock.elapsedRealtime();
            long radioTime = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
                    elapsedRealtimeMs * 1000);
            mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs);
@@ -9738,9 +9750,10 @@ public class BatteryStatsImpl extends BatteryStats {
            long totalRxPackets = 0;
            long totalTxPackets = 0;
            if (delta != null) {
                NetworkStats.Entry entry = new NetworkStats.Entry();
                final int size = delta.size();
                for (int i = 0; i < size; i++) {
                final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
                    entry = delta.getValues(i, entry);
                    if (entry.rxPackets == 0 && entry.txPackets == 0) {
                        continue;
                    }
@@ -9755,8 +9768,10 @@ public class BatteryStatsImpl extends BatteryStats {
                    totalTxPackets += entry.txPackets;

                    final Uid u = getUidStatsLocked(mapUid(entry.uid));
                u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes, entry.rxPackets);
                u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes, entry.txPackets);
                    u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes,
                            entry.rxPackets);
                    u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
                            entry.txPackets);
                    if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
                        u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_RX_DATA,
                                entry.rxBytes, entry.rxPackets);
@@ -9778,7 +9793,7 @@ public class BatteryStatsImpl extends BatteryStats {
                long totalPackets = totalRxPackets + totalTxPackets;
                if (totalPackets > 0) {
                    for (int i = 0; i < size; i++) {
                    final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
                        entry = delta.getValues(i, entry);
                        if (entry.rxPackets == 0 && entry.txPackets == 0) {
                            continue;
                        }
@@ -9806,7 +9821,8 @@ public class BatteryStatsImpl extends BatteryStats {

                            if (totalTxPackets > 0 && entry.txPackets > 0) {
                                for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
                                long txMs = entry.txPackets * activityInfo.getTxTimeMillis()[lvl];
                                    long txMs =
                                            entry.txPackets * activityInfo.getTxTimeMillis()[lvl];
                                    txMs /= totalTxPackets;
                                    activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs);
                                }
@@ -9820,11 +9836,15 @@ public class BatteryStatsImpl extends BatteryStats {
                    mMobileRadioActiveUnknownTime.addCountLocked(radioTime);
                    mMobileRadioActiveUnknownCount.addCountLocked(1);
                }

                mNetworkStatsPool.release(delta);
                delta = null;
            }

            if (activityInfo != null) {
                mHasModemReporting = true;
            mModemActivity.getIdleTimeCounter().addCountLocked(activityInfo.getIdleTimeMillis());
                mModemActivity.getIdleTimeCounter().addCountLocked(
                        activityInfo.getIdleTimeMillis());
                mModemActivity.getRxTimeCounter().addCountLocked(activityInfo.getRxTimeMillis());
                for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
                    mModemActivity.getTxTimeCounters()[lvl]
@@ -9841,6 +9861,7 @@ public class BatteryStatsImpl extends BatteryStats {
                }
            }
        }
    }

    /**
     * Distribute Bluetooth energy info and network traffic to apps.
+39 −35

File changed.

Preview size limit exceeded, changes collapsed.