diff --git a/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java index 5872e814b4d..06c3ceeca14 100644 --- a/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java +++ b/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java @@ -78,6 +78,21 @@ public class BatteryHeaderPreferenceController extends BasePreferenceController } private CharSequence generateLabel(BatteryInfo info) { + if (Utils.containsIncompatibleChargers(mContext, TAG)) { + return mContext.getString( + com.android.settingslib.R.string.battery_info_status_not_charging); + } + if (BatteryUtils.isBatteryDefenderOn(info)) { + return mContext.getString( + com.android.settingslib.R.string.battery_info_status_charging_on_hold); + } + if (info.remainingLabel == null + || info.batteryStatus == BatteryManager.BATTERY_STATUS_NOT_CHARGING) { + return info.statusLabel; + } + if (mBatterySettingsFeatureProvider.isChargingOptimizationMode(mContext)) { + return info.remainingLabel; + } if (info.pluggedStatus == BatteryManager.BATTERY_PLUGGED_WIRELESS) { final CharSequence wirelessChargingLabel = mBatterySettingsFeatureProvider.getWirelessChargingLabel(mContext, info); @@ -85,18 +100,7 @@ public class BatteryHeaderPreferenceController extends BasePreferenceController 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)) { - return mContext.getString( - com.android.settingslib.R.string.battery_info_status_charging_on_hold); - } else 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 (info.statusLabel != null && !info.discharging) { // Charging state if (com.android.settingslib.fuelgauge.BatteryUtils.isChargingStringV2Enabled()) { return info.isFastCharging diff --git a/src/com/android/settings/fuelgauge/BatteryInfo.java b/src/com/android/settings/fuelgauge/BatteryInfo.java index 66ce8b82d4d..c333a33d67f 100644 --- a/src/com/android/settings/fuelgauge/BatteryInfo.java +++ b/src/com/android/settings/fuelgauge/BatteryInfo.java @@ -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 { @@ -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 @@ -400,7 +407,8 @@ public class BatteryInfo { chargeTimeMs, info.isFastCharging, info.pluggedStatus, - currentTimeMs); + currentTimeMs, + featureProvider); info.chargeLabel = chargeTimeMs <= 0 @@ -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 = @@ -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); @@ -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); diff --git a/src/com/android/settings/fuelgauge/BatterySettingsFeatureProvider.java b/src/com/android/settings/fuelgauge/BatterySettingsFeatureProvider.java index a1a220d986c..ab6d5acc1eb 100644 --- a/src/com/android/settings/fuelgauge/BatterySettingsFeatureProvider.java +++ b/src/com/android/settings/fuelgauge/BatterySettingsFeatureProvider.java @@ -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); } diff --git a/src/com/android/settings/fuelgauge/BatterySettingsFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/BatterySettingsFeatureProviderImpl.java index 49db450bc58..b2db3470fa9 100644 --- a/src/com/android/settings/fuelgauge/BatterySettingsFeatureProviderImpl.java +++ b/src/com/android/settings/fuelgauge/BatterySettingsFeatureProviderImpl.java @@ -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; + } } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java index ba17d8ec8d8..a1081f4519e 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java @@ -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; @@ -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); @@ -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, @@ -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, diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatterySettingsFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatterySettingsFeatureProviderImplTest.java index c6241abf5c2..c55a121785e 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatterySettingsFeatureProviderImplTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatterySettingsFeatureProviderImplTest.java @@ -79,4 +79,20 @@ public class BatterySettingsFeatureProviderImplTest { public void getWirelessChargingRemainingLabel_returnNull() { assertThat(mImpl.getWirelessChargingRemainingLabel(mContext, 1000L, 1000L)).isNull(); } + + @Test + public void isChargingOptimizationMode_default_returnFalse() { + assertThat(mImpl.isChargingOptimizationMode(mContext)).isFalse(); + } + + @Test + public void getChargingOptimizationRemainingLabel_default_returnNull() { + assertThat(mImpl.getChargingOptimizationRemainingLabel(mContext, 1000L, 1000L)).isNull(); + } + + @Test + public void getChargingOptimizationChargeLabel_default_returnNull() { + assertThat(mImpl.getChargingOptimizationChargeLabel(mContext, "70%", 1000L, 1000L)) + .isNull(); + } }