Loading src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java +16 −12 Original line number Diff line number Diff line Loading @@ -78,25 +78,29 @@ public class BatteryHeaderPreferenceController extends BasePreferenceController } private CharSequence generateLabel(BatteryInfo info) { if (info.pluggedStatus == BatteryManager.BATTERY_PLUGGED_WIRELESS) { final CharSequence wirelessChargingLabel = mBatterySettingsFeatureProvider.getWirelessChargingLabel(mContext, info); if (wirelessChargingLabel != null) { return wirelessChargingLabel; } } if (Utils.containsIncompatibleChargers(mContext, TAG)) { return mContext.getString( com.android.settingslib.R.string.battery_info_status_not_charging); } else if (BatteryUtils.isBatteryDefenderOn(info)) { } if (BatteryUtils.isBatteryDefenderOn(info)) { return mContext.getString( com.android.settingslib.R.string.battery_info_status_charging_on_hold); } else if (info.remainingLabel == null } if (info.remainingLabel == null || info.batteryStatus == BatteryManager.BATTERY_STATUS_NOT_CHARGING) { // Present status only if no remaining time or status anomalous return info.statusLabel; } else if (info.statusLabel != null && !info.discharging) { } if (mBatterySettingsFeatureProvider.isChargingOptimizationMode(mContext)) { return info.remainingLabel; } if (info.pluggedStatus == BatteryManager.BATTERY_PLUGGED_WIRELESS) { final CharSequence wirelessChargingLabel = mBatterySettingsFeatureProvider.getWirelessChargingLabel(mContext, info); if (wirelessChargingLabel != null) { return wirelessChargingLabel; } } if (info.statusLabel != null && !info.discharging) { // Charging state if (com.android.settingslib.fuelgauge.BatteryUtils.isChargingStringV2Enabled()) { return info.isFastCharging Loading src/com/android/settings/fuelgauge/BatteryInfo.java +32 −7 Original line number Diff line number Diff line Loading @@ -319,6 +319,12 @@ public class BatteryInfo { info.isFastCharging = BatteryStatus.getChargingSpeed(context, batteryBroadcast) == BatteryStatus.CHARGING_FAST; if (info.isBatteryDefender) { info.isBatteryDefender = FeatureFactory.getFeatureFactory() .getPowerUsageFeatureProvider() .isBatteryDefend(info); } if (!info.mCharging) { updateBatteryInfoDischarging(context, shortString, estimate, info); } else { Loading Loading @@ -388,9 +394,10 @@ public class BatteryInfo { && status != BatteryManager.BATTERY_STATUS_FULL && dockDefenderMode == BatteryUtils.DockDefenderMode.DISABLED) || dockDefenderMode == BatteryUtils.DockDefenderMode.TEMPORARILY_BYPASSED) { final BatterySettingsFeatureProvider featureProvider = FeatureFactory.getFeatureFactory().getBatterySettingsFeatureProvider(); // Battery is charging to full info.remainingTimeUs = PowerUtil.convertMsToUs(chargeTimeMs); int resId = getChargingDurationResId(info.isFastCharging); info.remainingLabel = chargeTimeMs <= 0 Loading @@ -400,7 +407,8 @@ public class BatteryInfo { chargeTimeMs, info.isFastCharging, info.pluggedStatus, currentTimeMs); currentTimeMs, featureProvider); info.chargeLabel = chargeTimeMs <= 0 Loading @@ -411,7 +419,8 @@ public class BatteryInfo { info.batteryPercentString, chargeTimeMs, info.isFastCharging, currentTimeMs); currentTimeMs, featureProvider); } else if (dockDefenderMode == BatteryUtils.DockDefenderMode.FUTURE_BYPASS) { // Dock defender will be triggered in the future, charging will be optimized. info.chargeLabel = Loading @@ -436,10 +445,17 @@ public class BatteryInfo { long chargeRemainingTimeMs, boolean isFastCharging, int pluggedStatus, long currentTimeMs) { long currentTimeMs, BatterySettingsFeatureProvider featureProvider) { if (featureProvider.isChargingOptimizationMode(context)) { final CharSequence chargingOptimizationRemainingLabel = featureProvider.getChargingOptimizationRemainingLabel( context, chargeRemainingTimeMs, currentTimeMs); if (chargingOptimizationRemainingLabel != null) { return chargingOptimizationRemainingLabel; } } if (pluggedStatus == BatteryManager.BATTERY_PLUGGED_WIRELESS) { BatterySettingsFeatureProvider featureProvider = FeatureFactory.getFeatureFactory().getBatterySettingsFeatureProvider(); final CharSequence wirelessChargingRemainingLabel = featureProvider.getWirelessChargingRemainingLabel( context, chargeRemainingTimeMs, currentTimeMs); Loading Loading @@ -472,7 +488,16 @@ public class BatteryInfo { String batteryPercentString, long chargeTimeMs, boolean isFastCharging, long currentTimeMs) { long currentTimeMs, BatterySettingsFeatureProvider featureProvider) { if (featureProvider.isChargingOptimizationMode(context)) { final CharSequence chargingOptimizationChargeLabel = featureProvider.getChargingOptimizationChargeLabel( context, batteryPercentString, chargeTimeMs, currentTimeMs); if (chargingOptimizationChargeLabel != null) { return chargingOptimizationChargeLabel; } } if (com.android.settingslib.fuelgauge.BatteryUtils.isChargingStringV2Enabled()) { var timeString = PowerUtil.getTargetTimeShortString(context, chargeTimeMs, currentTimeMs); Loading src/com/android/settings/fuelgauge/BatterySettingsFeatureProvider.java +16 −0 Original line number Diff line number Diff line Loading @@ -53,4 +53,20 @@ public interface BatterySettingsFeatureProvider { @Nullable CharSequence getWirelessChargingRemainingLabel( @NonNull Context context, long remainingTimeMs, long currentTimeMs); /** Return true if it's in the charging optimization mode. */ boolean isChargingOptimizationMode(@NonNull Context context); /** Return a charging remaining time label for charging optimization mode. */ @Nullable CharSequence getChargingOptimizationRemainingLabel( @NonNull Context context, long chargeRemainingTimeMs, long currentTimeMs); /** Return a charge label for charging optimization mode. */ @Nullable CharSequence getChargingOptimizationChargeLabel( @NonNull Context context, @NonNull String batteryPercentageString, long chargeRemainingTimeMs, long currentTimeMs); } src/com/android/settings/fuelgauge/BatterySettingsFeatureProviderImpl.java +22 −0 Original line number Diff line number Diff line Loading @@ -67,4 +67,26 @@ public class BatterySettingsFeatureProviderImpl implements BatterySettingsFeatur @NonNull Context context, long remainingTimeMs, long currentTimeMs) { return null; } @Override public boolean isChargingOptimizationMode(@NonNull Context context) { return false; } @Nullable @Override public CharSequence getChargingOptimizationRemainingLabel( @NonNull Context context, long chargeRemainingTimeMs, long currentTimeMs) { return null; } @Nullable @Override public CharSequence getChargingOptimizationChargeLabel( @NonNull Context context, @NonNull String batteryPercentageString, long chargeRemainingTimeMs, long currentTimeMs) { return null; } } tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java +80 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertWithMessage; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doAnswer; Loading Loading @@ -307,6 +308,9 @@ public class BatteryInfoTest { @Test public void getBatteryInfo_chargingWithDefender_updateChargeLabel() { doReturn(TEST_CHARGE_TIME_REMAINING).when(mBatteryUsageStats).getChargeTimeRemainingMs(); doReturn(true) .when(mFeatureFactory.powerUsageFeatureProvider) .isBatteryDefend(any(BatteryInfo.class)); mChargingBatteryBroadcast.putExtra( BatteryManager.EXTRA_CHARGING_STATUS, BatteryManager.CHARGING_POLICY_ADAPTIVE_LONGLIFE); Loading Loading @@ -363,6 +367,9 @@ public class BatteryInfoTest { .when(mBatteryUsageStats) .getChargeTimeRemainingMs(); doReturn(true).when(mFeatureFactory.powerUsageFeatureProvider).isExtraDefend(); doReturn(true) .when(mFeatureFactory.powerUsageFeatureProvider) .isBatteryDefend(any(BatteryInfo.class)); Intent intent = createBatteryIntent( BatteryManager.BATTERY_PLUGGED_DOCK, Loading Loading @@ -709,6 +716,79 @@ public class BatteryInfoTest { expectedChargeLabel); } @Test public void getBatteryInfo_chargeOptimizationMode_updateRemainingAndStatusLabel() { prepareTestGetBatteryInfoEnvironment( /* remainingTimeMs= */ Duration.ofMinutes(130).toMillis(), /* chargingStringV2Enabled= */ false); Intent batteryIntent = createIntentForGetBatteryInfoTest( ChargingType.WIRED, ChargingSpeed.REGULAR, /* batteryLevel= */ 65); var expectedRemainingLabel = "Done charging by"; var expectedChargeLabel = "65% - " + expectedRemainingLabel; when(mFeatureFactory.batterySettingsFeatureProvider.isChargingOptimizationMode(mContext)) .thenReturn(true); when(mFeatureFactory.batterySettingsFeatureProvider.getChargingOptimizationRemainingLabel( eq(mContext), anyLong(), anyLong())) .thenReturn(expectedRemainingLabel); when(mFeatureFactory.batterySettingsFeatureProvider.getChargingOptimizationChargeLabel( eq(mContext), anyString(), anyLong(), anyLong())) .thenReturn(expectedChargeLabel); var expectedStatusLabel = "Charging"; assertGetBatteryInfo( batteryIntent, /* currentTimeMillis= */ UNUSED_TIME_MS, expectedStatusLabel, expectedRemainingLabel, expectedChargeLabel); } @Test public void getBatteryInfo_notChargeOptimizationModeWithV1_updateRemainingAndStatusLabel() { prepareTestGetBatteryInfoEnvironment( /* remainingTimeMs= */ Duration.ofMinutes(130).toMillis(), /* chargingStringV2Enabled= */ false); Intent batteryIntent = createIntentForGetBatteryInfoTest( ChargingType.WIRED, ChargingSpeed.REGULAR, /* batteryLevel= */ 65); when(mFeatureFactory.batterySettingsFeatureProvider.isChargingOptimizationMode(mContext)) .thenReturn(false); var expectedStatusLabel = "Charging"; var expectedRemainingLabel = "2 hr, 10 min left until full"; var expectedChargeLabel = "65% - " + expectedRemainingLabel; assertGetBatteryInfo( batteryIntent, /* currentTimeMillis= */ UNUSED_TIME_MS, expectedStatusLabel, expectedRemainingLabel, expectedChargeLabel); } @Test public void getBatteryInfo_notChargeOptimizationModeWithV2_updateRemainingAndStatusLabel() { prepareTestGetBatteryInfoEnvironment( /* remainingTimeMs= */ Duration.ofMinutes(130).toMillis(), /* chargingStringV2Enabled= */ true); Intent batteryIntent = createIntentForGetBatteryInfoTest( ChargingType.WIRED, ChargingSpeed.REGULAR, /* batteryLevel= */ 65); when(mFeatureFactory.batterySettingsFeatureProvider.isChargingOptimizationMode(mContext)) .thenReturn(false); var expectedStatusLabel = "Charging"; var expectedRemainingLabel = "Fully charged by"; var expectedChargeLabel = "65% - " + expectedRemainingLabel; var currentTimeMillis = Instant.parse("2024-04-01T15:00:00Z").toEpochMilli(); assertGetBatteryInfo( batteryIntent, currentTimeMillis, expectedStatusLabel, expectedRemainingLabel, expectedChargeLabel); } private enum ChargingSpeed { FAST, REGULAR, Loading Loading
src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java +16 −12 Original line number Diff line number Diff line Loading @@ -78,25 +78,29 @@ public class BatteryHeaderPreferenceController extends BasePreferenceController } private CharSequence generateLabel(BatteryInfo info) { if (info.pluggedStatus == BatteryManager.BATTERY_PLUGGED_WIRELESS) { final CharSequence wirelessChargingLabel = mBatterySettingsFeatureProvider.getWirelessChargingLabel(mContext, info); if (wirelessChargingLabel != null) { return wirelessChargingLabel; } } if (Utils.containsIncompatibleChargers(mContext, TAG)) { return mContext.getString( com.android.settingslib.R.string.battery_info_status_not_charging); } else if (BatteryUtils.isBatteryDefenderOn(info)) { } if (BatteryUtils.isBatteryDefenderOn(info)) { return mContext.getString( com.android.settingslib.R.string.battery_info_status_charging_on_hold); } else if (info.remainingLabel == null } if (info.remainingLabel == null || info.batteryStatus == BatteryManager.BATTERY_STATUS_NOT_CHARGING) { // Present status only if no remaining time or status anomalous return info.statusLabel; } else if (info.statusLabel != null && !info.discharging) { } if (mBatterySettingsFeatureProvider.isChargingOptimizationMode(mContext)) { return info.remainingLabel; } if (info.pluggedStatus == BatteryManager.BATTERY_PLUGGED_WIRELESS) { final CharSequence wirelessChargingLabel = mBatterySettingsFeatureProvider.getWirelessChargingLabel(mContext, info); if (wirelessChargingLabel != null) { return wirelessChargingLabel; } } if (info.statusLabel != null && !info.discharging) { // Charging state if (com.android.settingslib.fuelgauge.BatteryUtils.isChargingStringV2Enabled()) { return info.isFastCharging Loading
src/com/android/settings/fuelgauge/BatteryInfo.java +32 −7 Original line number Diff line number Diff line Loading @@ -319,6 +319,12 @@ public class BatteryInfo { info.isFastCharging = BatteryStatus.getChargingSpeed(context, batteryBroadcast) == BatteryStatus.CHARGING_FAST; if (info.isBatteryDefender) { info.isBatteryDefender = FeatureFactory.getFeatureFactory() .getPowerUsageFeatureProvider() .isBatteryDefend(info); } if (!info.mCharging) { updateBatteryInfoDischarging(context, shortString, estimate, info); } else { Loading Loading @@ -388,9 +394,10 @@ public class BatteryInfo { && status != BatteryManager.BATTERY_STATUS_FULL && dockDefenderMode == BatteryUtils.DockDefenderMode.DISABLED) || dockDefenderMode == BatteryUtils.DockDefenderMode.TEMPORARILY_BYPASSED) { final BatterySettingsFeatureProvider featureProvider = FeatureFactory.getFeatureFactory().getBatterySettingsFeatureProvider(); // Battery is charging to full info.remainingTimeUs = PowerUtil.convertMsToUs(chargeTimeMs); int resId = getChargingDurationResId(info.isFastCharging); info.remainingLabel = chargeTimeMs <= 0 Loading @@ -400,7 +407,8 @@ public class BatteryInfo { chargeTimeMs, info.isFastCharging, info.pluggedStatus, currentTimeMs); currentTimeMs, featureProvider); info.chargeLabel = chargeTimeMs <= 0 Loading @@ -411,7 +419,8 @@ public class BatteryInfo { info.batteryPercentString, chargeTimeMs, info.isFastCharging, currentTimeMs); currentTimeMs, featureProvider); } else if (dockDefenderMode == BatteryUtils.DockDefenderMode.FUTURE_BYPASS) { // Dock defender will be triggered in the future, charging will be optimized. info.chargeLabel = Loading @@ -436,10 +445,17 @@ public class BatteryInfo { long chargeRemainingTimeMs, boolean isFastCharging, int pluggedStatus, long currentTimeMs) { long currentTimeMs, BatterySettingsFeatureProvider featureProvider) { if (featureProvider.isChargingOptimizationMode(context)) { final CharSequence chargingOptimizationRemainingLabel = featureProvider.getChargingOptimizationRemainingLabel( context, chargeRemainingTimeMs, currentTimeMs); if (chargingOptimizationRemainingLabel != null) { return chargingOptimizationRemainingLabel; } } if (pluggedStatus == BatteryManager.BATTERY_PLUGGED_WIRELESS) { BatterySettingsFeatureProvider featureProvider = FeatureFactory.getFeatureFactory().getBatterySettingsFeatureProvider(); final CharSequence wirelessChargingRemainingLabel = featureProvider.getWirelessChargingRemainingLabel( context, chargeRemainingTimeMs, currentTimeMs); Loading Loading @@ -472,7 +488,16 @@ public class BatteryInfo { String batteryPercentString, long chargeTimeMs, boolean isFastCharging, long currentTimeMs) { long currentTimeMs, BatterySettingsFeatureProvider featureProvider) { if (featureProvider.isChargingOptimizationMode(context)) { final CharSequence chargingOptimizationChargeLabel = featureProvider.getChargingOptimizationChargeLabel( context, batteryPercentString, chargeTimeMs, currentTimeMs); if (chargingOptimizationChargeLabel != null) { return chargingOptimizationChargeLabel; } } if (com.android.settingslib.fuelgauge.BatteryUtils.isChargingStringV2Enabled()) { var timeString = PowerUtil.getTargetTimeShortString(context, chargeTimeMs, currentTimeMs); Loading
src/com/android/settings/fuelgauge/BatterySettingsFeatureProvider.java +16 −0 Original line number Diff line number Diff line Loading @@ -53,4 +53,20 @@ public interface BatterySettingsFeatureProvider { @Nullable CharSequence getWirelessChargingRemainingLabel( @NonNull Context context, long remainingTimeMs, long currentTimeMs); /** Return true if it's in the charging optimization mode. */ boolean isChargingOptimizationMode(@NonNull Context context); /** Return a charging remaining time label for charging optimization mode. */ @Nullable CharSequence getChargingOptimizationRemainingLabel( @NonNull Context context, long chargeRemainingTimeMs, long currentTimeMs); /** Return a charge label for charging optimization mode. */ @Nullable CharSequence getChargingOptimizationChargeLabel( @NonNull Context context, @NonNull String batteryPercentageString, long chargeRemainingTimeMs, long currentTimeMs); }
src/com/android/settings/fuelgauge/BatterySettingsFeatureProviderImpl.java +22 −0 Original line number Diff line number Diff line Loading @@ -67,4 +67,26 @@ public class BatterySettingsFeatureProviderImpl implements BatterySettingsFeatur @NonNull Context context, long remainingTimeMs, long currentTimeMs) { return null; } @Override public boolean isChargingOptimizationMode(@NonNull Context context) { return false; } @Nullable @Override public CharSequence getChargingOptimizationRemainingLabel( @NonNull Context context, long chargeRemainingTimeMs, long currentTimeMs) { return null; } @Nullable @Override public CharSequence getChargingOptimizationChargeLabel( @NonNull Context context, @NonNull String batteryPercentageString, long chargeRemainingTimeMs, long currentTimeMs) { return null; } }
tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java +80 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertWithMessage; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doAnswer; Loading Loading @@ -307,6 +308,9 @@ public class BatteryInfoTest { @Test public void getBatteryInfo_chargingWithDefender_updateChargeLabel() { doReturn(TEST_CHARGE_TIME_REMAINING).when(mBatteryUsageStats).getChargeTimeRemainingMs(); doReturn(true) .when(mFeatureFactory.powerUsageFeatureProvider) .isBatteryDefend(any(BatteryInfo.class)); mChargingBatteryBroadcast.putExtra( BatteryManager.EXTRA_CHARGING_STATUS, BatteryManager.CHARGING_POLICY_ADAPTIVE_LONGLIFE); Loading Loading @@ -363,6 +367,9 @@ public class BatteryInfoTest { .when(mBatteryUsageStats) .getChargeTimeRemainingMs(); doReturn(true).when(mFeatureFactory.powerUsageFeatureProvider).isExtraDefend(); doReturn(true) .when(mFeatureFactory.powerUsageFeatureProvider) .isBatteryDefend(any(BatteryInfo.class)); Intent intent = createBatteryIntent( BatteryManager.BATTERY_PLUGGED_DOCK, Loading Loading @@ -709,6 +716,79 @@ public class BatteryInfoTest { expectedChargeLabel); } @Test public void getBatteryInfo_chargeOptimizationMode_updateRemainingAndStatusLabel() { prepareTestGetBatteryInfoEnvironment( /* remainingTimeMs= */ Duration.ofMinutes(130).toMillis(), /* chargingStringV2Enabled= */ false); Intent batteryIntent = createIntentForGetBatteryInfoTest( ChargingType.WIRED, ChargingSpeed.REGULAR, /* batteryLevel= */ 65); var expectedRemainingLabel = "Done charging by"; var expectedChargeLabel = "65% - " + expectedRemainingLabel; when(mFeatureFactory.batterySettingsFeatureProvider.isChargingOptimizationMode(mContext)) .thenReturn(true); when(mFeatureFactory.batterySettingsFeatureProvider.getChargingOptimizationRemainingLabel( eq(mContext), anyLong(), anyLong())) .thenReturn(expectedRemainingLabel); when(mFeatureFactory.batterySettingsFeatureProvider.getChargingOptimizationChargeLabel( eq(mContext), anyString(), anyLong(), anyLong())) .thenReturn(expectedChargeLabel); var expectedStatusLabel = "Charging"; assertGetBatteryInfo( batteryIntent, /* currentTimeMillis= */ UNUSED_TIME_MS, expectedStatusLabel, expectedRemainingLabel, expectedChargeLabel); } @Test public void getBatteryInfo_notChargeOptimizationModeWithV1_updateRemainingAndStatusLabel() { prepareTestGetBatteryInfoEnvironment( /* remainingTimeMs= */ Duration.ofMinutes(130).toMillis(), /* chargingStringV2Enabled= */ false); Intent batteryIntent = createIntentForGetBatteryInfoTest( ChargingType.WIRED, ChargingSpeed.REGULAR, /* batteryLevel= */ 65); when(mFeatureFactory.batterySettingsFeatureProvider.isChargingOptimizationMode(mContext)) .thenReturn(false); var expectedStatusLabel = "Charging"; var expectedRemainingLabel = "2 hr, 10 min left until full"; var expectedChargeLabel = "65% - " + expectedRemainingLabel; assertGetBatteryInfo( batteryIntent, /* currentTimeMillis= */ UNUSED_TIME_MS, expectedStatusLabel, expectedRemainingLabel, expectedChargeLabel); } @Test public void getBatteryInfo_notChargeOptimizationModeWithV2_updateRemainingAndStatusLabel() { prepareTestGetBatteryInfoEnvironment( /* remainingTimeMs= */ Duration.ofMinutes(130).toMillis(), /* chargingStringV2Enabled= */ true); Intent batteryIntent = createIntentForGetBatteryInfoTest( ChargingType.WIRED, ChargingSpeed.REGULAR, /* batteryLevel= */ 65); when(mFeatureFactory.batterySettingsFeatureProvider.isChargingOptimizationMode(mContext)) .thenReturn(false); var expectedStatusLabel = "Charging"; var expectedRemainingLabel = "Fully charged by"; var expectedChargeLabel = "65% - " + expectedRemainingLabel; var currentTimeMillis = Instant.parse("2024-04-01T15:00:00Z").toEpochMilli(); assertGetBatteryInfo( batteryIntent, currentTimeMillis, expectedStatusLabel, expectedRemainingLabel, expectedChargeLabel); } private enum ChargingSpeed { FAST, REGULAR, Loading