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

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

Merge "Rate limit BatteryStats' ModemActivityInfo querying" into tm-qpr-dev

parents a832f8b8 9c841db3
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -1326,6 +1326,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")
@@ -6260,6 +6267,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;
            }
+111 −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;
@@ -82,6 +83,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;
@@ -2031,6 +2033,115 @@ 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
@@ -114,6 +114,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;