Merge changes from topic "event-framework" into udc-qpr-dev
* changes:
[BatteryEventFramework] Implement getChargingSpeed function
[BatteryEventFramework] Implement static util function in BatteryStatus
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java
index 1251b0d..9ab84d2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java
@@ -26,6 +26,7 @@
import static android.os.BatteryManager.EXTRA_PLUGGED;
import static android.os.BatteryManager.EXTRA_PRESENT;
import static android.os.BatteryManager.EXTRA_STATUS;
+import static android.os.OsProtoEnums.BATTERY_PLUGGED_NONE;
import android.content.Context;
import android.content.Intent;
@@ -40,6 +41,8 @@
*/
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;
@@ -90,21 +93,7 @@
present = batteryChangedIntent.getBooleanExtra(EXTRA_PRESENT, true);
this.incompatibleCharger = incompatibleCharger;
- final int maxChargingMicroAmp = batteryChangedIntent.getIntExtra(EXTRA_MAX_CHARGING_CURRENT,
- -1);
- int maxChargingMicroVolt = batteryChangedIntent.getIntExtra(EXTRA_MAX_CHARGING_VOLTAGE, -1);
-
- if (maxChargingMicroVolt <= 0) {
- maxChargingMicroVolt = DEFAULT_CHARGING_VOLTAGE_MICRO_VOLT;
- }
- if (maxChargingMicroAmp > 0) {
- // Calculating muW = muA * muV / (10^6 mu^2 / mu); splitting up the divisor
- // to maintain precision equally on both factors.
- maxChargingWattage = (maxChargingMicroAmp / 1000)
- * (maxChargingMicroVolt / 1000);
- } else {
- maxChargingWattage = -1;
- }
+ maxChargingWattage = calculateMaxChargingMicroWatt(batteryChangedIntent);
}
/** Determine whether the device is plugged. */
@@ -126,7 +115,7 @@
/** Determine whether the device is plugged in dock. */
public boolean isPluggedInDock() {
- return plugged == BatteryManager.BATTERY_PLUGGED_DOCK;
+ return isPluggedInDock(plugged);
}
/**
@@ -140,15 +129,15 @@
/** 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 +207,126 @@
|| plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS
|| plugged == BatteryManager.BATTERY_PLUGGED_DOCK;
}
+
+ /** Determine whether the device is plugged in dock. */
+ public static boolean isPluggedInDock(Intent batteryChangedIntent) {
+ return isPluggedInDock(
+ batteryChangedIntent.getIntExtra(EXTRA_PLUGGED, BATTERY_PLUGGED_NONE));
+ }
+
+ /** Determine whether the device is plugged in dock. */
+ public static boolean isPluggedInDock(int plugged) {
+ return 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;
+ }
+
+ /**
+ * Gets the max charging current and max charging voltage form {@link
+ * Intent.ACTION_BATTERY_CHANGED} and calculates the charging speed based on the {@link
+ * R.integer.config_chargingSlowlyThreshold} and {@link R.integer.config_chargingFastThreshold}.
+ *
+ * @param context the application context
+ * @param batteryChangedIntent the intent from {@link Intent.ACTION_BATTERY_CHANGED}
+ * @return the charging speed. {@link CHARGING_REGULAR}, {@link CHARGING_FAST}, {@link
+ * CHARGING_SLOWLY} or {@link CHARGING_UNKNOWN}
+ */
+ public static int getChargingSpeed(Context context, Intent batteryChangedIntent) {
+ final int maxChargingMicroWatt = calculateMaxChargingMicroWatt(batteryChangedIntent);
+ if (maxChargingMicroWatt <= 0) {
+ return CHARGING_UNKNOWN;
+ } else if (maxChargingMicroWatt
+ < context.getResources().getInteger(R.integer.config_chargingSlowlyThreshold)) {
+ return CHARGING_SLOWLY;
+ } else if (maxChargingMicroWatt
+ > context.getResources().getInteger(R.integer.config_chargingFastThreshold)) {
+ return CHARGING_FAST;
+ } else {
+ return CHARGING_REGULAR;
+ }
+ }
+
+ private static int calculateMaxChargingMicroWatt(Intent batteryChangedIntent) {
+ final int maxChargingMicroAmp =
+ batteryChangedIntent.getIntExtra(EXTRA_MAX_CHARGING_CURRENT, -1);
+ int maxChargingMicroVolt = batteryChangedIntent.getIntExtra(EXTRA_MAX_CHARGING_VOLTAGE, -1);
+ if (maxChargingMicroVolt <= 0) {
+ maxChargingMicroVolt = DEFAULT_CHARGING_VOLTAGE_MICRO_VOLT;
+ }
+
+ if (maxChargingMicroAmp > 0) {
+ // Calculating µW = mA * mV
+ return (int) Math.round(maxChargingMicroAmp * 0.001 * maxChargingMicroVolt * 0.001);
+ } else {
+ return -1;
+ }
+ }
}
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 0000000..6c0c1a7
--- /dev/null
+++ b/packages/SettingsLib/tests/unit/src/com/android/settingslib/fuelgague/BatteryStatusTest.kt
@@ -0,0 +1,330 @@
+/*
+ * 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.Context
+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_MAX_CHARGING_CURRENT
+import android.os.BatteryManager.EXTRA_MAX_CHARGING_VOLTAGE
+import android.os.OsProtoEnums.BATTERY_PLUGGED_NONE
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settingslib.fuelgauge.BatteryStatus
+import com.android.settingslib.fuelgauge.BatteryStatus.CHARGING_FAST
+import com.android.settingslib.fuelgauge.BatteryStatus.CHARGING_REGULAR
+import com.android.settingslib.fuelgauge.BatteryStatus.CHARGING_SLOWLY
+import com.android.settingslib.fuelgauge.BatteryStatus.CHARGING_UNKNOWN
+import com.android.settingslib.fuelgauge.BatteryStatus.isBatteryDefender
+import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
+import java.util.Optional
+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,
+ BatteryStatusTest.GetChargingSpeedTest::class,
+ BatteryStatusTest.IsPluggedInDockTest::class,
+)
+open class BatteryStatusTest {
+
+ @RunWith(AndroidJUnit4::class)
+ class NonParameterizedTest : BatteryStatusTest() {
+ @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() }
+ }
+ }
+
+ @RunWith(Parameterized::class)
+ class IsPluggedInTest(
+ private val name: String,
+ private val plugged: Int,
+ val expected: Boolean
+ ) : BatteryStatusTest() {
+
+ @Test
+ fun isPluggedIn_() {
+ val batteryChangedIntent = createIntent(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 IsPluggedInDockTest(
+ private val name: String,
+ private val plugged: Int,
+ val expected: Boolean
+ ) : BatteryStatusTest() {
+
+ @Test
+ fun isPluggedDockIn_() {
+ val batteryChangedIntent = createIntent(plugged = plugged)
+
+ assertWithMessage("failed by isPluggedInDock(plugged=$plugged)")
+ .that(BatteryStatus.isPluggedInDock(plugged))
+ .isEqualTo(expected)
+ assertWithMessage("failed by isPluggedInDock(Intent), which plugged=$plugged")
+ .that(BatteryStatus.isPluggedInDock(batteryChangedIntent))
+ .isEqualTo(expected)
+ }
+
+ companion object {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun parameters() =
+ arrayListOf(
+ arrayOf("withAC_returnsTrue", BATTERY_PLUGGED_AC, false),
+ arrayOf("withDock_returnsTrue", BATTERY_PLUGGED_DOCK, true),
+ arrayOf("withUSB_returnsTrue", BATTERY_PLUGGED_USB, false),
+ arrayOf("withWireless_returnsTrue", BATTERY_PLUGGED_WIRELESS, false),
+ arrayOf("pluggedNone_returnsTrue", BATTERY_PLUGGED_NONE, false),
+ )
+ }
+ }
+
+ @RunWith(Parameterized::class)
+ class IsChargedTest(
+ private val status: Int,
+ private val batteryLevel: Int,
+ private val expected: Boolean
+ ) : BatteryStatusTest() {
+
+ @Test
+ fun isCharged_() {
+ val batteryChangedIntent = createIntent(batteryLevel = batteryLevel, status = status)
+
+ 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),
+ )
+ }
+ }
+
+ @RunWith(Parameterized::class)
+ class GetChargingSpeedTest(
+ private val name: String,
+ private val maxChargingCurrent: Optional<Int>,
+ private val maxChargingVoltage: Optional<Int>,
+ private val expectedChargingSpeed: Int,
+ ) {
+
+ val context: Context = ApplicationProvider.getApplicationContext()
+
+ @Test
+ fun getChargingSpeed_() {
+ val batteryChangedIntent =
+ Intent(Intent.ACTION_BATTERY_CHANGED).apply {
+ maxChargingCurrent.ifPresent { putExtra(EXTRA_MAX_CHARGING_CURRENT, it) }
+ maxChargingVoltage.ifPresent { putExtra(EXTRA_MAX_CHARGING_VOLTAGE, it) }
+ }
+
+ assertThat(BatteryStatus.getChargingSpeed(context, batteryChangedIntent))
+ .isEqualTo(expectedChargingSpeed)
+ }
+
+ companion object {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun parameters() =
+ arrayListOf(
+ arrayOf(
+ "maxCurrent=n/a, maxVoltage=n/a -> UNKNOWN",
+ Optional.empty<Int>(),
+ Optional.empty<Int>(),
+ CHARGING_UNKNOWN
+ ),
+ arrayOf(
+ "maxCurrent=0, maxVoltage=9000000 -> UNKNOWN",
+ Optional.of(0),
+ Optional.of(0),
+ CHARGING_UNKNOWN
+ ),
+ arrayOf(
+ "maxCurrent=1500000, maxVoltage=5000000 -> CHARGING_REGULAR",
+ Optional.of(1500000),
+ Optional.of(5000000),
+ CHARGING_REGULAR
+ ),
+ arrayOf(
+ "maxCurrent=1000000, maxVoltage=5000000 -> CHARGING_REGULAR",
+ Optional.of(1000000),
+ Optional.of(5000000),
+ CHARGING_REGULAR
+ ),
+ arrayOf(
+ "maxCurrent=1500001, maxVoltage=5000000 -> CHARGING_FAST",
+ Optional.of(1501000),
+ Optional.of(5000000),
+ CHARGING_FAST
+ ),
+ arrayOf(
+ "maxCurrent=999999, maxVoltage=5000000 -> CHARGING_SLOWLY",
+ Optional.of(999999),
+ Optional.of(5000000),
+ CHARGING_SLOWLY
+ ),
+ )
+ }
+ }
+
+ protected fun createIntent(
+ batteryLevel: Int = 50,
+ chargingStatus: Int = CHARGING_POLICY_DEFAULT,
+ plugged: Int = BATTERY_PLUGGED_NONE,
+ status: Int = BatteryManager.BATTERY_STATUS_CHARGING,
+ ): Intent =
+ Intent(Intent.ACTION_BATTERY_CHANGED).apply {
+ putExtra(BatteryManager.EXTRA_STATUS, status)
+ putExtra(BatteryManager.EXTRA_LEVEL, batteryLevel)
+ putExtra(BatteryManager.EXTRA_SCALE, 100)
+ putExtra(BatteryManager.EXTRA_CHARGING_STATUS, chargingStatus)
+ putExtra(BatteryManager.EXTRA_PLUGGED, plugged)
+ }
+}