From 06339350295c18d0ec2465d1cf08e36bb3803b6d Mon Sep 17 00:00:00 2001 From: pajacechen Date: Fri, 4 Aug 2023 22:50:14 +0800 Subject: [PATCH] [BatteryEventFramework] Implement static util function in BatteryStatus - Implements some static util function for BatteryStatus - Add test case to improve code quality Bug: 284890860 Bug: 292884081 Test: atest BatteryStatusTest.kt Change-Id: I12b62eafdd691316e84d10d26b43f01580da8717 --- .../settingslib/fuelgauge/BatteryStatus.java | 78 +++++- .../fuelgague/BatteryStatusTest.kt | 222 ++++++++++++++++++ 2 files changed, 297 insertions(+), 3 deletions(-) create mode 100644 packages/SettingsLib/tests/unit/src/com/android/settingslib/fuelgague/BatteryStatusTest.kt diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java index 1251b0dc306a9..d0cf144929bc8 100644 --- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java +++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java @@ -40,6 +40,8 @@ import java.util.Optional; */ public class BatteryStatus { private static final int LOW_BATTERY_THRESHOLD = 20; + private static final int SEVERE_LOW_BATTERY_THRESHOLD = 10; + private static final int EXTREME_LOW_BATTERY_THRESHOLD = 3; private static final int DEFAULT_CHARGING_VOLTAGE_MICRO_VOLT = 5000000; public static final int CHARGING_UNKNOWN = -1; @@ -140,15 +142,15 @@ public class BatteryStatus { /** Whether battery is low and needs to be charged. */ public boolean isBatteryLow() { - return level < LOW_BATTERY_THRESHOLD; + return isLowBattery(level); } /** Whether battery defender is enabled. */ public boolean isBatteryDefender() { - return chargingStatus == CHARGING_POLICY_ADAPTIVE_LONGLIFE; + return isBatteryDefender(chargingStatus); } - /** Return current chargin speed is fast, slow or normal. */ + /** Return current charging speed is fast, slow or normal. */ public final int getChargingSpeed(Context context) { final int slowThreshold = context.getResources().getInteger( R.integer.config_chargingSlowlyThreshold); @@ -218,4 +220,74 @@ public class BatteryStatus { || plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS || plugged == BatteryManager.BATTERY_PLUGGED_DOCK; } + + /** + * Whether the battery is low or not. + * + * @param batteryChangedIntent the {@link ACTION_BATTERY_CHANGED} intent + * @return {@code true} if the battery level is less or equal to {@link LOW_BATTERY_THRESHOLD} + */ + public static boolean isLowBattery(Intent batteryChangedIntent) { + int level = getBatteryLevel(batteryChangedIntent); + return isLowBattery(level); + } + + /** + * Whether the battery is low or not. + * + * @param batteryLevel the battery level + * @return {@code true} if the battery level is less or equal to {@link LOW_BATTERY_THRESHOLD} + */ + public static boolean isLowBattery(int batteryLevel) { + return batteryLevel <= LOW_BATTERY_THRESHOLD; + } + + /** + * Whether the battery is severe low or not. + * + * @param batteryChangedIntent the ACTION_BATTERY_CHANGED intent + * @return {@code true} if the battery level is less or equal to {@link + * SEVERE_LOW_BATTERY_THRESHOLD} + */ + public static boolean isSevereLowBattery(Intent batteryChangedIntent) { + int level = getBatteryLevel(batteryChangedIntent); + return level <= SEVERE_LOW_BATTERY_THRESHOLD; + } + + /** + * Whether the battery is extreme low or not. + * + * @param batteryChangedIntent the ACTION_BATTERY_CHANGED intent + * @return {@code true} if the battery level is less or equal to {@link + * EXTREME_LOW_BATTERY_THRESHOLD} + */ + public static boolean isExtremeLowBattery(Intent batteryChangedIntent) { + int level = getBatteryLevel(batteryChangedIntent); + return level <= EXTREME_LOW_BATTERY_THRESHOLD; + } + + /** + * Whether the battery defender is enabled or not. + * + * @param batteryChangedIntent the ACTION_BATTERY_CHANGED intent + * @return {@code true} if the battery defender is enabled. It could be dock defend, dwell + * defend, or temp defend + */ + public static boolean isBatteryDefender(Intent batteryChangedIntent) { + int chargingStatus = + batteryChangedIntent.getIntExtra(EXTRA_CHARGING_STATUS, CHARGING_POLICY_DEFAULT); + return isBatteryDefender(chargingStatus); + } + + /** + * Whether the battery defender is enabled or not. + * + * @param chargingStatus for {@link EXTRA_CHARGING_STATUS} field in the ACTION_BATTERY_CHANGED + * intent + * @return {@code true} if the battery defender is enabled. It could be dock defend, dwell + * defend, or temp defend + */ + public static boolean isBatteryDefender(int chargingStatus) { + return chargingStatus == CHARGING_POLICY_ADAPTIVE_LONGLIFE; + } } diff --git a/packages/SettingsLib/tests/unit/src/com/android/settingslib/fuelgague/BatteryStatusTest.kt b/packages/SettingsLib/tests/unit/src/com/android/settingslib/fuelgague/BatteryStatusTest.kt new file mode 100644 index 0000000000000..9d4306ee6161f --- /dev/null +++ b/packages/SettingsLib/tests/unit/src/com/android/settingslib/fuelgague/BatteryStatusTest.kt @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.fuelgague + +import android.content.Intent +import android.os.BatteryManager +import android.os.BatteryManager.BATTERY_PLUGGED_AC +import android.os.BatteryManager.BATTERY_PLUGGED_DOCK +import android.os.BatteryManager.BATTERY_PLUGGED_USB +import android.os.BatteryManager.BATTERY_PLUGGED_WIRELESS +import android.os.BatteryManager.BATTERY_STATUS_FULL +import android.os.BatteryManager.BATTERY_STATUS_UNKNOWN +import android.os.BatteryManager.CHARGING_POLICY_ADAPTIVE_LONGLIFE +import android.os.BatteryManager.CHARGING_POLICY_DEFAULT +import android.os.BatteryManager.EXTRA_CHARGING_STATUS +import android.os.OsProtoEnums.BATTERY_PLUGGED_NONE +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.settingslib.fuelgauge.BatteryStatus +import com.android.settingslib.fuelgauge.BatteryStatus.isBatteryDefender +import com.google.common.truth.Truth.assertThat +import com.google.common.truth.Truth.assertWithMessage +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.Parameterized +import org.junit.runners.Suite +import org.junit.runners.Suite.SuiteClasses + +@RunWith(Suite::class) +@SuiteClasses( + BatteryStatusTest.NonParameterizedTest::class, + BatteryStatusTest.IsPluggedInTest::class, + BatteryStatusTest.IsChargedTest::class, +) +class BatteryStatusTest { + + @RunWith(AndroidJUnit4::class) + class NonParameterizedTest { + @Test + fun isLowBattery_20Percent_returnsTrue() { + val level = 20 + val intent = createIntent(batteryLevel = level) + + assertWithMessage("failed by isLowBattery(Intent), level=$level") + .that(BatteryStatus.isLowBattery(intent)) + .isTrue() + assertWithMessage("failed by isLowBattery($level)") + .that(BatteryStatus.isLowBattery(level)) + .isTrue() + } + + @Test + fun isLowBattery_21Percent_returnsFalse() { + val level = 21 + val intent = createIntent(batteryLevel = level) + + assertWithMessage("failed by isLowBattery(intent), level=$level") + .that(BatteryStatus.isLowBattery(intent)) + .isFalse() + assertWithMessage("failed by isLowBattery($level)") + .that(BatteryStatus.isLowBattery(intent)) + .isFalse() + } + + @Test + fun isSevereLowBattery_10Percent_returnsTrue() { + val batteryChangedIntent = createIntent(batteryLevel = 10) + + assertThat(BatteryStatus.isSevereLowBattery(batteryChangedIntent)).isTrue() + } + + @Test + fun isSevereLowBattery_11Percent_returnFalse() { + val batteryChangedIntent = createIntent(batteryLevel = 11) + + assertThat(BatteryStatus.isSevereLowBattery(batteryChangedIntent)).isFalse() + } + + @Test + fun isExtremeLowBattery_3Percent_returnsTrue() { + val batteryChangedIntent = createIntent(batteryLevel = 3) + + assertThat(BatteryStatus.isExtremeLowBattery(batteryChangedIntent)).isTrue() + } + + @Test + fun isExtremeLowBattery_4Percent_returnsFalse() { + val batteryChangedIntent = createIntent(batteryLevel = 4) + + assertThat(BatteryStatus.isExtremeLowBattery(batteryChangedIntent)).isFalse() + } + + @Test + fun isBatteryDefender_chargingLongLife_returnsTrue() { + val chargingStatus = CHARGING_POLICY_ADAPTIVE_LONGLIFE + val batteryChangedIntent = createIntent(chargingStatus = chargingStatus) + + assertIsBatteryDefender(chargingStatus, batteryChangedIntent).isTrue() + } + + @Test + fun isBatteryDefender_nonChargingLongLife_returnsFalse() { + val chargingStatus = CHARGING_POLICY_DEFAULT + val batteryChangedIntent = createIntent(chargingStatus = chargingStatus) + + assertIsBatteryDefender(chargingStatus, batteryChangedIntent).isFalse() + } + + private fun assertIsBatteryDefender(chargingStatus: Int, batteryChangedIntent: Intent) = + object { + val assertions = + listOf( + "failed by isBatteryDefender(Intent), chargingStatus=$chargingStatus".let { + assertWithMessage(it).that(isBatteryDefender(batteryChangedIntent)) + }, + "failed by isBatteryDefender($chargingStatus)".let { + assertWithMessage(it).that(isBatteryDefender(chargingStatus)) + }, + ) + + fun isTrue() = assertions.forEach { it.isTrue() } + + fun isFalse() = assertions.forEach { it.isFalse() } + } + + private fun createIntent( + batteryLevel: Int = 50, + chargingStatus: Int = CHARGING_POLICY_DEFAULT + ): Intent = + Intent().apply { + putExtra(BatteryManager.EXTRA_LEVEL, batteryLevel) + putExtra(BatteryManager.EXTRA_SCALE, 100) + putExtra(EXTRA_CHARGING_STATUS, chargingStatus) + } + } + + @RunWith(Parameterized::class) + class IsPluggedInTest( + private val name: String, + private val plugged: Int, + val expected: Boolean + ) { + + @Test + fun isPluggedIn_() { + val batteryChangedIntent = + Intent().apply { putExtra(BatteryManager.EXTRA_PLUGGED, plugged) } + + assertWithMessage("failed by isPluggedIn(plugged=$plugged)") + .that(BatteryStatus.isPluggedIn(plugged)) + .isEqualTo(expected) + assertWithMessage("failed by isPlugged(Intent), which plugged=$plugged") + .that(BatteryStatus.isPluggedIn(batteryChangedIntent)) + .isEqualTo(expected) + } + + companion object { + @Parameterized.Parameters(name = "{0}") + @JvmStatic + fun parameters() = + arrayListOf( + arrayOf("withAC_returnsTrue", BATTERY_PLUGGED_AC, true), + arrayOf("withDock_returnsTrue", BATTERY_PLUGGED_DOCK, true), + arrayOf("withUSB_returnsTrue", BATTERY_PLUGGED_USB, true), + arrayOf("withWireless_returnsTrue", BATTERY_PLUGGED_WIRELESS, true), + arrayOf("pluggedNone_returnsTrue", BATTERY_PLUGGED_NONE, false), + ) + } + } + + @RunWith(Parameterized::class) + class IsChargedTest( + private val status: Int, + private val batteryLevel: Int, + private val expected: Boolean + ) { + + @Test + fun isCharged_() { + val batteryChangedIntent = + Intent().apply { + putExtra(BatteryManager.EXTRA_STATUS, status) + putExtra(BatteryManager.EXTRA_SCALE, 100) + putExtra(BatteryManager.EXTRA_LEVEL, batteryLevel) + } + + assertWithMessage( + "failed by isCharged(Intent), status=$status, batteryLevel=$batteryLevel" + ) + .that(BatteryStatus.isCharged(batteryChangedIntent)) + .isEqualTo(expected) + assertWithMessage("failed by isCharged($status, $batteryLevel)") + .that(BatteryStatus.isCharged(status, batteryLevel)) + .isEqualTo(expected) + } + + companion object { + @Parameterized.Parameters(name = "status{0}_level{1}_returns-{2}") + @JvmStatic + fun parameters() = + arrayListOf( + arrayOf(BATTERY_STATUS_FULL, 99, true), + arrayOf(BATTERY_STATUS_UNKNOWN, 100, true), + arrayOf(BATTERY_STATUS_FULL, 100, true), + arrayOf(BATTERY_STATUS_UNKNOWN, 99, false), + ) + } + } +}