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

Commit b409ef7c authored by Kuan Wang's avatar Kuan Wang Committed by Android (Google) Code Review
Browse files

Merge "Use battery unplugging event to compute the full charge start time on Pixel devices."

parents 928b9904 c28daecb
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -3051,11 +3051,12 @@
            android:exported="false"
            android:authorities="${applicationId}.battery.usage.bugreport"/>

        <receiver android:name=".fuelgauge.batteryusage.BatteryUsageBroadcastReceiver"
        <receiver android:name="com.android.settings.fuelgauge.batteryusage.BatteryUsageBroadcastReceiver"
                  android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.BATTERY_LEVEL_CHANGED"/>
                <action android:name="com.android.settings.battery.action.CLEAR_BATTERY_CACHE_DATA"/>
                <action android:name="com.android.settings.battery.action.ACTION_BATTERY_UNPLUGGING"/>
            </intent-filter>
        </receiver>

+6 −1
Original line number Diff line number Diff line
@@ -133,10 +133,15 @@ public interface PowerUsageFeatureProvider {
    boolean delayHourlyJobWhenBooting();

    /**
     * Gets a intent for one time bypass charge limited to resume charging.
     * Gets an intent for one time bypass charge limited to resume charging.
     */
    Intent getResumeChargeIntent(boolean isDockDefender);

    /**
     * Returns the intent action used to mark as the full charge start event.
     */
    String getFullChargeIntentAction();

    /**
     * Returns {@link Set} for the system component ids which are combined into others
     */
+5 −0
Original line number Diff line number Diff line
@@ -147,6 +147,11 @@ public class PowerUsageFeatureProviderImpl implements PowerUsageFeatureProvider
        return null;
    }

    @Override
    public String getFullChargeIntentAction() {
        return Intent.ACTION_BATTERY_LEVEL_CHANGED;
    }

    @Override
    public boolean isExtraDefend() {
        return false;
+24 −2
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.util.Log;
import androidx.annotation.VisibleForTesting;

import com.android.settings.fuelgauge.BatteryUtils;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.fuelgauge.BatteryStatus;

import java.time.Duration;
@@ -36,6 +37,9 @@ public final class BatteryUsageBroadcastReceiver extends BroadcastReceiver {
    /** An intent action to request Settings to clear cache data. */
    public static final String ACTION_CLEAR_BATTERY_CACHE_DATA =
            "com.android.settings.battery.action.CLEAR_BATTERY_CACHE_DATA";
    /** An intent action to request Settings to clear cache data. */
    public static final String ACTION_BATTERY_UNPLUGGING =
            "com.android.settings.battery.action.ACTION_BATTERY_UNPLUGGING";

    @VisibleForTesting
    static long sBroadcastDelayFromBoot = Duration.ofMinutes(40).toMillis();
@@ -51,9 +55,27 @@ public final class BatteryUsageBroadcastReceiver extends BroadcastReceiver {
            return;
        }
        Log.d(TAG, "onReceive:" + intent.getAction());
        final String fullChargeIntentAction = FeatureFactory.getFactory(context)
                .getPowerUsageFeatureProvider(context)
                .getFullChargeIntentAction();
        switch (intent.getAction()) {
            case Intent.ACTION_BATTERY_LEVEL_CHANGED:
                // Only when fullChargeIntentAction is ACTION_BATTERY_LEVEL_CHANGED,
                // ACTION_BATTERY_LEVEL_CHANGED will be considered as the full charge event and then
                // start usage events fetching.
                if (Intent.ACTION_BATTERY_LEVEL_CHANGED.equals(fullChargeIntentAction)) {
                    Log.d(TAG, "fetch data because of event: ACTION_BATTERY_LEVEL_CHANGED");
                    tryToFetchUsageData(context);
                }
                break;
            case ACTION_BATTERY_UNPLUGGING:
                // Only when fullChargeIntentAction is ACTION_POWER_DISCONNECTED,
                // ACTION_BATTERY_UNPLUGGING will be considered as the full charge event and then
                // start usage events fetching.
                if (Intent.ACTION_POWER_DISCONNECTED.equals(fullChargeIntentAction)) {
                    Log.d(TAG, "fetch data because of event: ACTION_POWER_DISCONNECTED");
                    tryToFetchUsageData(context);
                }
                break;
            case ACTION_CLEAR_BATTERY_CACHE_DATA:
                if (sIsDebugMode) {
+91 −2
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

import android.content.Context;
import android.content.Intent;
@@ -29,6 +30,8 @@ import android.os.BatteryManager;
import android.os.SystemClock;
import android.text.format.DateUtils;

import com.android.settings.testutils.FakeFeatureFactory;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -42,6 +45,8 @@ public final class BatteryUsageBroadcastReceiverTest {

    private Context mContext;
    private BatteryUsageBroadcastReceiver mBatteryUsageBroadcastReceiver;
    private FakeFeatureFactory mFakeFeatureFactory;

    @Mock
    private PackageManager mPackageManager;

@@ -49,6 +54,7 @@ public final class BatteryUsageBroadcastReceiverTest {
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mContext = spy(RuntimeEnvironment.application);
        mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
        mBatteryUsageBroadcastReceiver = new BatteryUsageBroadcastReceiver();
        doReturn(mPackageManager).when(mContext).getPackageManager();
    }
@@ -62,6 +68,8 @@ public final class BatteryUsageBroadcastReceiverTest {

    @Test
    public void onReceive_actionBatteryLevelChanged_notFetchUsageData_notFullCharged() {
        when(mFakeFeatureFactory.powerUsageFeatureProvider.getFullChargeIntentAction())
                .thenReturn(Intent.ACTION_BATTERY_LEVEL_CHANGED);
        doReturn(getBatteryIntent(/*level=*/ 20, BatteryManager.BATTERY_STATUS_UNKNOWN))
                .when(mContext).registerReceiver(any(), any());

@@ -72,7 +80,9 @@ public final class BatteryUsageBroadcastReceiverTest {
    }

    @Test
    public void onReceive_actionBatteryLevelChanged_cancelFetchUsageData() {
    public void onReceive_actionBatteryLevelChanged_notFetchUsageData_nearBooting() {
        when(mFakeFeatureFactory.powerUsageFeatureProvider.getFullChargeIntentAction())
                .thenReturn(Intent.ACTION_BATTERY_LEVEL_CHANGED);
        // Make sure isCharged returns true.
        doReturn(getBatteryIntent(/*level=*/ 100, BatteryManager.BATTERY_STATUS_FULL))
                .when(mContext).registerReceiver(any(), any());
@@ -87,7 +97,25 @@ public final class BatteryUsageBroadcastReceiverTest {
    }

    @Test
    public void onReceive_actionBatteryLevelChanged_notFetchUsageData() {
    public void onReceive_actionBatteryLevelChanged_notFetchUsageData_wrongAction() {
        when(mFakeFeatureFactory.powerUsageFeatureProvider.getFullChargeIntentAction())
                .thenReturn(Intent.ACTION_POWER_DISCONNECTED);
        // Make sure isCharged returns true.
        doReturn(getBatteryIntent(/*level=*/ 100, BatteryManager.BATTERY_STATUS_UNKNOWN))
                .when(mContext).registerReceiver(any(), any());
        BatteryUsageBroadcastReceiver.sBroadcastDelayFromBoot =
                SystemClock.elapsedRealtime() - 5 * DateUtils.MINUTE_IN_MILLIS;

        mBatteryUsageBroadcastReceiver.onReceive(mContext,
                new Intent(Intent.ACTION_BATTERY_LEVEL_CHANGED));

        assertThat(mBatteryUsageBroadcastReceiver.mFetchBatteryUsageData).isFalse();
    }

    @Test
    public void onReceive_actionBatteryLevelChanged_fetchUsageData() {
        when(mFakeFeatureFactory.powerUsageFeatureProvider.getFullChargeIntentAction())
                .thenReturn(Intent.ACTION_BATTERY_LEVEL_CHANGED);
        // Make sure isCharged returns true.
        doReturn(getBatteryIntent(/*level=*/ 100, BatteryManager.BATTERY_STATUS_UNKNOWN))
                .when(mContext).registerReceiver(any(), any());
@@ -100,6 +128,67 @@ public final class BatteryUsageBroadcastReceiverTest {
        assertThat(mBatteryUsageBroadcastReceiver.mFetchBatteryUsageData).isTrue();
    }

    @Test
    public void onReceive_actionBatteryUnplugging_notFetchUsageData_notFullCharged() {
        when(mFakeFeatureFactory.powerUsageFeatureProvider.getFullChargeIntentAction())
                .thenReturn(Intent.ACTION_POWER_DISCONNECTED);
        doReturn(getBatteryIntent(/*level=*/ 20, BatteryManager.BATTERY_STATUS_UNKNOWN))
                .when(mContext).registerReceiver(any(), any());

        mBatteryUsageBroadcastReceiver.onReceive(mContext,
                new Intent(BatteryUsageBroadcastReceiver.ACTION_BATTERY_UNPLUGGING));

        assertThat(mBatteryUsageBroadcastReceiver.mFetchBatteryUsageData).isFalse();
    }

    @Test
    public void onReceive_actionBatteryUnplugging_notFetchUsageData_nearBooting() {
        when(mFakeFeatureFactory.powerUsageFeatureProvider.getFullChargeIntentAction())
                .thenReturn(Intent.ACTION_POWER_DISCONNECTED);
        // Make sure isCharged returns true.
        doReturn(getBatteryIntent(/*level=*/ 100, BatteryManager.BATTERY_STATUS_FULL))
                .when(mContext).registerReceiver(any(), any());
        // Make sure broadcast will be sent with delay.
        BatteryUsageBroadcastReceiver.sBroadcastDelayFromBoot =
                SystemClock.elapsedRealtime() + 5 * DateUtils.MINUTE_IN_MILLIS;

        mBatteryUsageBroadcastReceiver.onReceive(mContext,
                new Intent(BatteryUsageBroadcastReceiver.ACTION_BATTERY_UNPLUGGING));

        assertThat(mBatteryUsageBroadcastReceiver.mFetchBatteryUsageData).isFalse();
    }

    @Test
    public void onReceive_actionBatteryUnplugging_notFetchUsageData_wrongAction() {
        when(mFakeFeatureFactory.powerUsageFeatureProvider.getFullChargeIntentAction())
                .thenReturn(Intent.ACTION_BATTERY_LEVEL_CHANGED);
        // Make sure isCharged returns true.
        doReturn(getBatteryIntent(/*level=*/ 100, BatteryManager.BATTERY_STATUS_UNKNOWN))
                .when(mContext).registerReceiver(any(), any());
        BatteryUsageBroadcastReceiver.sBroadcastDelayFromBoot =
                SystemClock.elapsedRealtime() - 5 * DateUtils.MINUTE_IN_MILLIS;

        mBatteryUsageBroadcastReceiver.onReceive(mContext,
                new Intent(BatteryUsageBroadcastReceiver.ACTION_BATTERY_UNPLUGGING));

        assertThat(mBatteryUsageBroadcastReceiver.mFetchBatteryUsageData).isFalse();
    }

    @Test
    public void onReceive_actionBatteryUnplugging_fetchUsageData() {
        when(mFakeFeatureFactory.powerUsageFeatureProvider.getFullChargeIntentAction())
                .thenReturn(Intent.ACTION_POWER_DISCONNECTED);
        // Make sure isCharged returns true.
        doReturn(getBatteryIntent(/*level=*/ 100, BatteryManager.BATTERY_STATUS_UNKNOWN))
                .when(mContext).registerReceiver(any(), any());
        BatteryUsageBroadcastReceiver.sBroadcastDelayFromBoot =
                SystemClock.elapsedRealtime() - 5 * DateUtils.MINUTE_IN_MILLIS;

        mBatteryUsageBroadcastReceiver.onReceive(mContext,
                new Intent(BatteryUsageBroadcastReceiver.ACTION_BATTERY_UNPLUGGING));

        assertThat(mBatteryUsageBroadcastReceiver.mFetchBatteryUsageData).isTrue();
    }

    @Test
    public void onReceive_clearCacheIntentInDebugMode_clearBatteryCacheData() {