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

Commit c14454d6 authored by Michael Wachenschwanz's avatar Michael Wachenschwanz Committed by Android (Google) Code Review
Browse files

Merge "Rate limit BatteryStats' ModemActivityInfo querying"

parents 6af45b8f be40990e
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -1331,6 +1331,13 @@ public class BatteryStatsImpl extends BatteryStats {
    LongSamplingCounter mMobileRadioActiveUnknownTime;
    LongSamplingCounter mMobileRadioActiveUnknownCount;
    /**
     * The soonest the Mobile Radio stats can be updated due to a mobile radio power state change
     * after it was last updated.
     */
    @VisibleForTesting
    protected static final long MOBILE_RADIO_POWER_STATE_UPDATE_FREQ_MS = 1000 * 60 * 10;
    int mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
    @GuardedBy("this")
@@ -5531,6 +5538,15 @@ public class BatteryStatsImpl extends BatteryStats {
            } else {
                mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
                mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
                if (mLastModemActivityInfo != null) {
                    if (elapsedRealtimeMs < mLastModemActivityInfo.getTimestampMillis()
                            + MOBILE_RADIO_POWER_STATE_UPDATE_FREQ_MS) {
                        // Modem Activity info has been collected recently, don't bother
                        // triggering another update.
                        return false;
                    }
                }
                // Tell the caller to collect radio network/power stats.
                return true;
            }
+109 −0
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import android.telephony.DataConnectionRealTimeInfo;
import android.telephony.ModemActivityInfo;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.util.MutableInt;
import android.util.SparseIntArray;
import android.util.SparseLongArray;
@@ -83,6 +84,7 @@ import java.util.function.IntConsumer;
 *      com.android.frameworks.coretests/androidx.test.runner.AndroidJUnitRunner
 */
public class BatteryStatsNoteTest extends TestCase {
    private static final String TAG = BatteryStatsNoteTest.class.getSimpleName();

    private static final int UID = 10500;
    private static final int ISOLATED_APP_ID = Process.FIRST_ISOLATED_UID + 23;
@@ -2030,6 +2032,113 @@ public class BatteryStatsNoteTest extends TestCase {
                noRadioProcFlags, lastProcStateChangeFlags.value);
    }

    @SmallTest
    public void testNoteMobileRadioPowerStateLocked() {
        long curr;
        boolean update;
        final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
        final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
        bi.setOnBatteryInternal(true);

        // Note mobile radio is on.
        curr = 1000L * (clocks.realtime = clocks.uptime = 1001);
        bi.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH, curr,
                UID);

        // Note mobile radio is still on.
        curr = 1000L * (clocks.realtime = clocks.uptime = 2001);
        update = bi.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH,
                curr, UID);
        assertFalse(
                "noteMobileRadioPowerStateLocked should not request an update when the power "
                        + "state does not change from HIGH.",
                update);

        // Note mobile radio is off.
        curr = 1000L * (clocks.realtime = clocks.uptime = 3001);
        update = bi.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_LOW,
                curr, UID);
        assertTrue(
                "noteMobileRadioPowerStateLocked should request an update when the power state "
                        + "changes from HIGH to LOW.",
                update);

        // Note mobile radio is still off.
        curr = 1000L * (clocks.realtime = clocks.uptime = 4001);
        update = bi.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_LOW,
                curr, UID);
        assertFalse(
                "noteMobileRadioPowerStateLocked should not request an update when the power "
                        + "state does not change from LOW.",
                update);

        // Note mobile radio is on.
        curr = 1000L * (clocks.realtime = clocks.uptime = 5001);
        update = bi.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH,
                curr, UID);
        assertFalse(
                "noteMobileRadioPowerStateLocked should not request an update when the power "
                        + "state changes from LOW to HIGH.",
                update);
    }

    @SmallTest
    public void testNoteMobileRadioPowerStateLocked_rateLimited() {
        long curr;
        boolean update;
        final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
        final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
        bi.setPowerProfile(mock(PowerProfile.class));

        final int txLevelCount = CellSignalStrength.getNumSignalStrengthLevels();
        final ModemActivityInfo mai = new ModemActivityInfo(0L, 0L, 0L, new int[txLevelCount], 0L);

        final long rateLimit = bi.getMobileRadioPowerStateUpdateRateLimit();
        if (rateLimit < 0) {
            Log.w(TAG, "Skipping testNoteMobileRadioPowerStateLocked_rateLimited, rateLimit = "
                    + rateLimit);
            return;
        }
        bi.setOnBatteryInternal(true);

        // Note mobile radio is on.
        curr = 1000L * (clocks.realtime = clocks.uptime = 1001);
        bi.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH, curr,
                UID);

        clocks.realtime = clocks.uptime = 2001;
        mai.setTimestamp(clocks.realtime);
        bi.noteModemControllerActivity(mai, POWER_DATA_UNAVAILABLE,
                clocks.realtime, clocks.uptime, mNetworkStatsManager);

        // Note mobile radio is off within the rate limit duration.
        clocks.realtime = clocks.uptime = clocks.realtime + (long) (rateLimit * 0.7);
        curr = 1000L * clocks.realtime;
        update = bi.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_LOW,
                curr, UID);
        assertFalse(
                "noteMobileRadioPowerStateLocked should not request an update when the power "
                        + "state so soon after a noteModemControllerActivity",
                update);

        // Note mobile radio is on.
        clocks.realtime = clocks.uptime = clocks.realtime + (long) (rateLimit * 0.7);
        curr = 1000L * clocks.realtime;
        bi.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH, curr,
                UID);

        // Note mobile radio is off much later
        clocks.realtime = clocks.uptime = clocks.realtime + rateLimit;
        curr = 1000L * clocks.realtime;
        update = bi.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_LOW,
                curr, UID);
        assertTrue(
                "noteMobileRadioPowerStateLocked should request an update when the power state "
                        + "changes from HIGH to LOW much later after a "
                        + "noteModemControllerActivity.",
                update);
    }

    private void setFgState(int uid, boolean fgOn, MockBatteryStatsImpl bi) {
        // Note that noteUidProcessStateLocked uses ActivityManager process states.
        if (fgOn) {
+4 −0
Original line number Diff line number Diff line
@@ -113,6 +113,10 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl {
        return getUidStatsLocked(uid).mOnBatteryScreenOffBackgroundTimeBase;
    }

    public long getMobileRadioPowerStateUpdateRateLimit() {
        return MOBILE_RADIO_POWER_STATE_UPDATE_FREQ_MS;
    }

    public MockBatteryStatsImpl setNetworkStats(NetworkStats networkStats) {
        mNetworkStats = networkStats;
        return this;