1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settingslib.fuelgague 18 19 import android.content.Context 20 import android.content.Intent 21 import android.os.BatteryManager 22 import android.os.BatteryManager.BATTERY_PLUGGED_AC 23 import android.os.BatteryManager.BATTERY_PLUGGED_DOCK 24 import android.os.BatteryManager.BATTERY_PLUGGED_USB 25 import android.os.BatteryManager.BATTERY_PLUGGED_WIRELESS 26 import android.os.BatteryManager.BATTERY_STATUS_FULL 27 import android.os.BatteryManager.BATTERY_STATUS_UNKNOWN 28 import android.os.BatteryManager.CHARGING_POLICY_ADAPTIVE_LONGLIFE 29 import android.os.BatteryManager.CHARGING_POLICY_DEFAULT 30 import android.os.BatteryManager.EXTRA_MAX_CHARGING_CURRENT 31 import android.os.BatteryManager.EXTRA_MAX_CHARGING_VOLTAGE 32 import android.os.OsProtoEnums.BATTERY_PLUGGED_NONE 33 import androidx.test.core.app.ApplicationProvider 34 import androidx.test.ext.junit.runners.AndroidJUnit4 35 import com.android.settingslib.fuelgauge.BatteryStatus 36 import com.android.settingslib.fuelgauge.BatteryStatus.CHARGING_FAST 37 import com.android.settingslib.fuelgauge.BatteryStatus.CHARGING_REGULAR 38 import com.android.settingslib.fuelgauge.BatteryStatus.CHARGING_SLOWLY 39 import com.android.settingslib.fuelgauge.BatteryStatus.CHARGING_UNKNOWN 40 import com.android.settingslib.fuelgauge.BatteryStatus.isBatteryDefender 41 import com.android.settingslib.fuelgauge.BatteryUtils 42 import com.google.common.truth.Truth.assertThat 43 import com.google.common.truth.Truth.assertWithMessage 44 import java.util.Optional 45 import org.junit.Test 46 import org.junit.runner.RunWith 47 import org.junit.runners.Parameterized 48 import org.junit.runners.Suite 49 import org.junit.runners.Suite.SuiteClasses 50 51 @RunWith(Suite::class) 52 @SuiteClasses( 53 BatteryStatusTest.NonParameterizedTest::class, 54 BatteryStatusTest.IsPluggedInTest::class, 55 BatteryStatusTest.IsChargedTest::class, 56 BatteryStatusTest.GetChargingSpeedTest::class, 57 BatteryStatusTest.IsPluggedInDockTest::class, 58 ) 59 open class BatteryStatusTest { 60 61 @RunWith(AndroidJUnit4::class) 62 class NonParameterizedTest : BatteryStatusTest() { 63 @Test isLowBattery_20Percent_returnsTruenull64 fun isLowBattery_20Percent_returnsTrue() { 65 val level = 20 66 val intent = createIntent(batteryLevel = level) 67 68 assertWithMessage("failed by isLowBattery(Intent), level=$level") 69 .that(BatteryStatus.isLowBattery(intent)) 70 .isTrue() 71 assertWithMessage("failed by isLowBattery($level)") 72 .that(BatteryStatus.isLowBattery(level)) 73 .isTrue() 74 } 75 76 @Test isLowBattery_21Percent_returnsFalsenull77 fun isLowBattery_21Percent_returnsFalse() { 78 val level = 21 79 val intent = createIntent(batteryLevel = level) 80 81 assertWithMessage("failed by isLowBattery(intent), level=$level") 82 .that(BatteryStatus.isLowBattery(intent)) 83 .isFalse() 84 assertWithMessage("failed by isLowBattery($level)") 85 .that(BatteryStatus.isLowBattery(intent)) 86 .isFalse() 87 } 88 89 @Test isSevereLowBattery_10Percent_returnsTruenull90 fun isSevereLowBattery_10Percent_returnsTrue() { 91 val batteryChangedIntent = createIntent(batteryLevel = 10) 92 93 assertThat(BatteryStatus.isSevereLowBattery(batteryChangedIntent)).isTrue() 94 } 95 96 @Test isSevereLowBattery_11Percent_returnFalsenull97 fun isSevereLowBattery_11Percent_returnFalse() { 98 val batteryChangedIntent = createIntent(batteryLevel = 11) 99 100 assertThat(BatteryStatus.isSevereLowBattery(batteryChangedIntent)).isFalse() 101 } 102 103 @Test isExtremeLowBattery_3Percent_returnsTruenull104 fun isExtremeLowBattery_3Percent_returnsTrue() { 105 val batteryChangedIntent = createIntent(batteryLevel = 3) 106 107 assertThat(BatteryStatus.isExtremeLowBattery(batteryChangedIntent)).isTrue() 108 } 109 110 @Test isExtremeLowBattery_4Percent_returnsFalsenull111 fun isExtremeLowBattery_4Percent_returnsFalse() { 112 val batteryChangedIntent = createIntent(batteryLevel = 4) 113 114 assertThat(BatteryStatus.isExtremeLowBattery(batteryChangedIntent)).isFalse() 115 } 116 117 @Test isBatteryDefender_chargingLongLife_returnsTruenull118 fun isBatteryDefender_chargingLongLife_returnsTrue() { 119 val chargingStatus = CHARGING_POLICY_ADAPTIVE_LONGLIFE 120 val batteryChangedIntent = createIntent(chargingStatus = chargingStatus) 121 122 assertIsBatteryDefender(chargingStatus, batteryChangedIntent).isTrue() 123 } 124 125 @Test isBatteryDefender_nonChargingLongLife_returnsFalsenull126 fun isBatteryDefender_nonChargingLongLife_returnsFalse() { 127 val chargingStatus = CHARGING_POLICY_DEFAULT 128 val batteryChangedIntent = createIntent(chargingStatus = chargingStatus) 129 130 assertIsBatteryDefender(chargingStatus, batteryChangedIntent).isFalse() 131 } 132 assertIsBatteryDefendernull133 private fun assertIsBatteryDefender(chargingStatus: Int, batteryChangedIntent: Intent) = 134 object { 135 val assertions = 136 listOf( 137 "failed by isBatteryDefender(Intent), chargingStatus=$chargingStatus".let { 138 assertWithMessage(it).that(isBatteryDefender(batteryChangedIntent)) 139 }, 140 "failed by isBatteryDefender($chargingStatus)".let { 141 assertWithMessage(it).that(isBatteryDefender(chargingStatus)) 142 }, 143 ) 144 145 fun isTrue() = assertions.forEach { it.isTrue() } 146 147 fun isFalse() = assertions.forEach { it.isFalse() } 148 } 149 } 150 151 @RunWith(Parameterized::class) 152 class IsPluggedInTest( 153 private val name: String, 154 private val plugged: Int, 155 val expected: Boolean 156 ) : BatteryStatusTest() { 157 158 @Test isPluggedIn_null159 fun isPluggedIn_() { 160 val batteryChangedIntent = createIntent(plugged = plugged) 161 162 assertWithMessage("failed by isPluggedIn(plugged=$plugged)") 163 .that(BatteryStatus.isPluggedIn(plugged)) 164 .isEqualTo(expected) 165 assertWithMessage("failed by isPlugged(Intent), which plugged=$plugged") 166 .that(BatteryStatus.isPluggedIn(batteryChangedIntent)) 167 .isEqualTo(expected) 168 } 169 170 companion object { 171 @Parameterized.Parameters(name = "{0}") 172 @JvmStatic parametersnull173 fun parameters() = 174 arrayListOf( 175 arrayOf("withAC_returnsTrue", BATTERY_PLUGGED_AC, true), 176 arrayOf("withDock_returnsTrue", BATTERY_PLUGGED_DOCK, true), 177 arrayOf("withUSB_returnsTrue", BATTERY_PLUGGED_USB, true), 178 arrayOf("withWireless_returnsTrue", BATTERY_PLUGGED_WIRELESS, true), 179 arrayOf("pluggedNone_returnsTrue", BATTERY_PLUGGED_NONE, false), 180 ) 181 } 182 } 183 184 @RunWith(Parameterized::class) 185 class IsPluggedInDockTest( 186 private val name: String, 187 private val plugged: Int, 188 val expected: Boolean 189 ) : BatteryStatusTest() { 190 191 @Test 192 fun isPluggedDockIn_() { 193 val batteryChangedIntent = createIntent(plugged = plugged) 194 195 assertWithMessage("failed by isPluggedInDock(plugged=$plugged)") 196 .that(BatteryStatus.isPluggedInDock(plugged)) 197 .isEqualTo(expected) 198 assertWithMessage("failed by isPluggedInDock(Intent), which plugged=$plugged") 199 .that(BatteryStatus.isPluggedInDock(batteryChangedIntent)) 200 .isEqualTo(expected) 201 } 202 203 companion object { 204 @Parameterized.Parameters(name = "{0}") 205 @JvmStatic 206 fun parameters() = 207 arrayListOf( 208 arrayOf("withAC_returnsTrue", BATTERY_PLUGGED_AC, false), 209 arrayOf("withDock_returnsTrue", BATTERY_PLUGGED_DOCK, true), 210 arrayOf("withUSB_returnsTrue", BATTERY_PLUGGED_USB, false), 211 arrayOf("withWireless_returnsTrue", BATTERY_PLUGGED_WIRELESS, false), 212 arrayOf("pluggedNone_returnsTrue", BATTERY_PLUGGED_NONE, false), 213 ) 214 } 215 } 216 217 @RunWith(Parameterized::class) 218 class IsChargedTest( 219 private val status: Int, 220 private val batteryLevel: Int, 221 private val expected: Boolean 222 ) : BatteryStatusTest() { 223 224 @Test isCharged_null225 fun isCharged_() { 226 val batteryChangedIntent = createIntent(batteryLevel = batteryLevel, status = status) 227 228 assertWithMessage( 229 "failed by isCharged(Intent), status=$status, batteryLevel=$batteryLevel" 230 ) 231 .that(BatteryStatus.isCharged(batteryChangedIntent)) 232 .isEqualTo(expected) 233 assertWithMessage("failed by isCharged($status, $batteryLevel)") 234 .that(BatteryStatus.isCharged(status, batteryLevel)) 235 .isEqualTo(expected) 236 } 237 238 companion object { 239 @Parameterized.Parameters(name = "status{0}_level{1}_returns-{2}") 240 @JvmStatic parametersnull241 fun parameters() = 242 arrayListOf( 243 arrayOf(BATTERY_STATUS_FULL, 99, true), 244 arrayOf(BATTERY_STATUS_UNKNOWN, 100, true), 245 arrayOf(BATTERY_STATUS_FULL, 100, true), 246 arrayOf(BATTERY_STATUS_UNKNOWN, 99, false), 247 ) 248 } 249 } 250 251 @RunWith(Parameterized::class) 252 class GetChargingSpeedTest( 253 private val name: String, 254 private val maxChargingCurrent: Optional<Int>, 255 private val maxChargingVoltage: Optional<Int>, 256 private val expectedChargingSpeed: Int, 257 private val chargingStringV2Enabled: Boolean, 258 ) { 259 260 val context: Context = ApplicationProvider.getApplicationContext() 261 262 @Test 263 fun getChargingSpeed_() { 264 BatteryUtils.setChargingStringV2Enabled( 265 chargingStringV2Enabled, 266 false /* updateProperty */ 267 ) 268 val batteryChangedIntent = 269 Intent(Intent.ACTION_BATTERY_CHANGED).apply { 270 maxChargingCurrent.ifPresent { putExtra(EXTRA_MAX_CHARGING_CURRENT, it) } 271 maxChargingVoltage.ifPresent { putExtra(EXTRA_MAX_CHARGING_VOLTAGE, it) } 272 } 273 274 assertThat(BatteryStatus.getChargingSpeed(context, batteryChangedIntent)) 275 .isEqualTo(expectedChargingSpeed) 276 } 277 278 companion object { 279 @Parameterized.Parameters(name = "{0}") 280 @JvmStatic 281 fun parameters() = 282 arrayListOf( 283 arrayOf( 284 "maxCurrent=n/a, maxVoltage=n/a -> UNKNOWN", 285 Optional.empty<Int>(), 286 Optional.empty<Int>(), 287 CHARGING_UNKNOWN, 288 false /* chargingStringV2Enabled */ 289 ), 290 arrayOf( 291 "maxCurrent=0, maxVoltage=9000000 -> UNKNOWN", 292 Optional.of(0), 293 Optional.of(0), 294 CHARGING_UNKNOWN, 295 false /* chargingStringV2Enabled */ 296 ), 297 arrayOf( 298 "maxCurrent=1500000, maxVoltage=5000000 -> CHARGING_REGULAR", 299 Optional.of(1500000), 300 Optional.of(5000000), 301 CHARGING_REGULAR, 302 false /* chargingStringV2Enabled */ 303 ), 304 arrayOf( 305 "maxCurrent=1000000, maxVoltage=5000000 -> CHARGING_REGULAR", 306 Optional.of(1000000), 307 Optional.of(5000000), 308 CHARGING_REGULAR, 309 false /* chargingStringV2Enabled */ 310 ), 311 arrayOf( 312 "maxCurrent=1500001, maxVoltage=5000000 -> CHARGING_FAST", 313 Optional.of(1501000), 314 Optional.of(5000000), 315 CHARGING_FAST, 316 false /* chargingStringV2Enabled */ 317 ), 318 arrayOf( 319 "maxCurrent=999999, maxVoltage=5000000 -> CHARGING_SLOWLY", 320 Optional.of(999999), 321 Optional.of(5000000), 322 CHARGING_SLOWLY, 323 false /* chargingStringV2Enabled */ 324 ), 325 arrayOf( 326 "maxCurrent=3000000, maxVoltage=9000000 -> CHARGING_FAST", 327 Optional.of(3000000), 328 Optional.of(9000000), 329 CHARGING_FAST, 330 true /* chargingStringV2Enabled */ 331 ), 332 arrayOf( 333 "maxCurrent=2200000, maxVoltage=9000000 -> CHARGING_REGULAR", 334 Optional.of(2200000), 335 Optional.of(9000000), 336 CHARGING_REGULAR, 337 true /* chargingStringV2Enabled */ 338 ), 339 ) 340 } 341 } 342 createIntentnull343 protected fun createIntent( 344 batteryLevel: Int = 50, 345 chargingStatus: Int = CHARGING_POLICY_DEFAULT, 346 plugged: Int = BATTERY_PLUGGED_NONE, 347 status: Int = BatteryManager.BATTERY_STATUS_CHARGING, 348 ): Intent = 349 Intent(Intent.ACTION_BATTERY_CHANGED).apply { 350 putExtra(BatteryManager.EXTRA_STATUS, status) 351 putExtra(BatteryManager.EXTRA_LEVEL, batteryLevel) 352 putExtra(BatteryManager.EXTRA_SCALE, 100) 353 putExtra(BatteryManager.EXTRA_CHARGING_STATUS, chargingStatus) 354 putExtra(BatteryManager.EXTRA_PLUGGED, plugged) 355 } 356 } 357