1 /* <lambda>null2 * Copyright (C) 2024 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.settings.fuelgauge.batteryusage 18 19 import android.content.Context 20 import androidx.test.core.app.ApplicationProvider 21 import androidx.test.ext.junit.runners.AndroidJUnit4 22 import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action 23 import com.android.settings.fuelgauge.BatteryOptimizeUtils 24 import com.android.settings.fuelgauge.BatteryOptimizeUtils.MODE_OPTIMIZED 25 import com.android.settings.fuelgauge.BatteryOptimizeUtils.MODE_RESTRICTED 26 import com.android.settings.fuelgauge.BatteryOptimizeUtils.MODE_UNKNOWN 27 import com.android.settings.fuelgauge.BatteryOptimizeUtils.MODE_UNRESTRICTED 28 import com.android.settings.fuelgauge.batteryusage.AppOptModeSharedPreferencesUtils.UNLIMITED_EXPIRE_TIME 29 import com.android.settings.testutils.FakeFeatureFactory 30 import com.google.common.truth.Truth.assertThat 31 import org.junit.After 32 import org.junit.Before 33 import org.junit.Rule 34 import org.junit.Test 35 import org.junit.runner.RunWith 36 import org.mockito.ArgumentMatchers.any 37 import org.mockito.Mockito.anyInt 38 import org.mockito.Mockito.never 39 import org.mockito.Mockito.spy 40 import org.mockito.Mockito.verify 41 import org.mockito.Mockito.`when` as whenever 42 import org.mockito.Spy 43 import org.mockito.junit.MockitoJUnit 44 import org.mockito.junit.MockitoRule 45 46 @RunWith(AndroidJUnit4::class) 47 class AppOptModeSharedPreferencesUtilsTest { 48 @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule() 49 50 @Spy private var context: Context = ApplicationProvider.getApplicationContext() 51 52 @Spy 53 private var testBatteryOptimizeUtils = spy(BatteryOptimizeUtils(context, UID, PACKAGE_NAME)) 54 55 private lateinit var featureFactory: FakeFeatureFactory 56 57 @Before 58 fun setup() { 59 AppOptModeSharedPreferencesUtils.clearAll(context) 60 featureFactory = FakeFeatureFactory.setupForTest() 61 whenever(featureFactory.powerUsageFeatureProvider.isForceExpireAppOptimizationModeEnabled) 62 .thenReturn(false) 63 } 64 65 @After 66 fun tearDown() { 67 AppOptModeSharedPreferencesUtils.clearAll(context) 68 } 69 70 @Test 71 fun getAllEvents_emptyData_verifyEmptyList() { 72 assertThat(AppOptModeSharedPreferencesUtils.getAllEvents(context)).isEmpty() 73 } 74 75 @Test 76 fun clearAll_withData_verifyCleared() { 77 insertAppOptModeEventForTest(expirationTime = 1000L) 78 assertThat(AppOptModeSharedPreferencesUtils.getAllEvents(context)).hasSize(1) 79 80 AppOptModeSharedPreferencesUtils.clearAll(context) 81 82 assertThat(AppOptModeSharedPreferencesUtils.getAllEvents(context)).isEmpty() 83 } 84 85 @Test 86 fun updateAppOptModeExpirationInternal_withoutExpirationTime_verifyEmptyList() { 87 insertAppOptModeEventForTest(expirationTime = UNLIMITED_EXPIRE_TIME) 88 89 assertThat(AppOptModeSharedPreferencesUtils.getAllEvents(context)).isEmpty() 90 } 91 92 @Test 93 fun updateAppOptModeExpirationInternal_setOptimizedModeWithFlagEnabled_verifyData() { 94 whenever(featureFactory.powerUsageFeatureProvider.isRestrictedModeOverwriteEnabled) 95 .thenReturn(true) 96 insertAppOptModeEventForTest(expirationTime = 1000L, mode = MODE_OPTIMIZED) 97 98 val events = AppOptModeSharedPreferencesUtils.getAllEvents(context) 99 100 assertThat(events).hasSize(1) 101 assertAppOptimizationModeEventInfo( 102 events[0], 103 UID, 104 PACKAGE_NAME, 105 MODE_OPTIMIZED, 106 expirationTime = 1000L 107 ) 108 } 109 110 @Test 111 fun updateAppOptModeExpirationInternal_setOptimizedModeWithFlagDisabled_verifyData() { 112 whenever(featureFactory.powerUsageFeatureProvider.isRestrictedModeOverwriteEnabled) 113 .thenReturn(false) 114 insertAppOptModeEventForTest(expirationTime = 1000L, mode = MODE_OPTIMIZED) 115 116 val events = AppOptModeSharedPreferencesUtils.getAllEvents(context) 117 118 assertThat(events).hasSize(1) 119 assertAppOptimizationModeEventInfo( 120 events[0], 121 UID, 122 PACKAGE_NAME, 123 MODE_OPTIMIZED, 124 expirationTime = 1000L 125 ) 126 } 127 128 @Test 129 fun updateAppOptModeExpirationInternal_setRestrictedModeWithFlagEnabled_verifyData() { 130 whenever(featureFactory.powerUsageFeatureProvider.isRestrictedModeOverwriteEnabled) 131 .thenReturn(true) 132 insertAppOptModeEventForTest(expirationTime = 1000L, mode = MODE_RESTRICTED) 133 134 val events = AppOptModeSharedPreferencesUtils.getAllEvents(context) 135 136 assertThat(events).hasSize(1) 137 assertAppOptimizationModeEventInfo( 138 events[0], 139 UID, 140 PACKAGE_NAME, 141 MODE_RESTRICTED, 142 expirationTime = 1000L 143 ) 144 } 145 146 @Test 147 fun updateAppOptModeExpirationInternal_setRestrictedModeWithFlagDisabled_verifyEmptyList() { 148 whenever(featureFactory.powerUsageFeatureProvider.isRestrictedModeOverwriteEnabled) 149 .thenReturn(false) 150 insertAppOptModeEventForTest(expirationTime = 1000L, mode = MODE_RESTRICTED) 151 152 assertThat(AppOptModeSharedPreferencesUtils.getAllEvents(context)).isEmpty() 153 } 154 155 @Test 156 fun deleteAppOptimizationModeEventByUid_uidNotContained_verifyData() { 157 insertAppOptModeEventForTest(expirationTime = 1000L) 158 assertThat(AppOptModeSharedPreferencesUtils.getAllEvents(context)).hasSize(1) 159 160 AppOptModeSharedPreferencesUtils.deleteAppOptimizationModeEventByUid(context, UNSET_UID) 161 val events = AppOptModeSharedPreferencesUtils.getAllEvents(context) 162 163 assertThat(events).hasSize(1) 164 assertAppOptimizationModeEventInfo( 165 events[0], 166 UID, 167 PACKAGE_NAME, 168 MODE_OPTIMIZED, 169 expirationTime = 1000L 170 ) 171 } 172 173 @Test 174 fun deleteAppOptimizationModeEventByUid_uidExisting_verifyData() { 175 insertAppOptModeEventForTest(expirationTime = 1000L) 176 177 AppOptModeSharedPreferencesUtils.deleteAppOptimizationModeEventByUid(context, UID) 178 179 assertThat(AppOptModeSharedPreferencesUtils.getAllEvents(context)).isEmpty() 180 } 181 182 @Test 183 fun resetExpiredAppOptModeBeforeTimestamp_forceExpiredData_verifyEmptyList() { 184 whenever(featureFactory.powerUsageFeatureProvider.isForceExpireAppOptimizationModeEnabled) 185 .thenReturn(true) 186 insertAppOptModeEventForTest(expirationTime = 1000L) 187 188 AppOptModeSharedPreferencesUtils.resetExpiredAppOptModeBeforeTimestamp( 189 context, 190 queryTimestampMs = 999L 191 ) 192 193 assertThat(AppOptModeSharedPreferencesUtils.getAllEvents(context)).isEmpty() 194 } 195 196 @Test 197 fun resetExpiredAppOptModeBeforeTimestamp_noExpiredData_verifyData() { 198 insertAppOptModeEventForTest(expirationTime = 1000L) 199 200 AppOptModeSharedPreferencesUtils.resetExpiredAppOptModeBeforeTimestamp( 201 context, 202 queryTimestampMs = 999L 203 ) 204 val events = AppOptModeSharedPreferencesUtils.getAllEvents(context) 205 206 assertThat(events).hasSize(1) 207 assertAppOptimizationModeEventInfo( 208 events[0], 209 UID, 210 PACKAGE_NAME, 211 MODE_OPTIMIZED, 212 expirationTime = 1000L 213 ) 214 } 215 216 @Test 217 fun resetExpiredAppOptModeBeforeTimestamp_hasExpiredData_verifyEmptyList() { 218 insertAppOptModeEventForTest(expirationTime = 1000L) 219 220 AppOptModeSharedPreferencesUtils.resetExpiredAppOptModeBeforeTimestamp( 221 context, 222 queryTimestampMs = 1001L 223 ) 224 225 assertThat(AppOptModeSharedPreferencesUtils.getAllEvents(context)).isEmpty() 226 } 227 228 @Test 229 fun updateBatteryOptimizationMode_updateToOptimizedMode_verifyAction() { 230 whenever(testBatteryOptimizeUtils?.isOptimizeModeMutable).thenReturn(true) 231 whenever(testBatteryOptimizeUtils?.getAppOptimizationMode()) 232 .thenReturn(MODE_UNRESTRICTED) 233 234 val currentOptMode = 235 AppOptModeSharedPreferencesUtils.updateBatteryOptimizationMode( 236 context, 237 UID, 238 PACKAGE_NAME, 239 MODE_OPTIMIZED, 240 Action.EXTERNAL_UPDATE, 241 testBatteryOptimizeUtils 242 ) 243 244 verify(testBatteryOptimizeUtils)?.setAppUsageState(MODE_OPTIMIZED, Action.EXTERNAL_UPDATE) 245 assertThat(currentOptMode).isEqualTo(MODE_UNRESTRICTED) 246 } 247 248 @Test 249 fun updateBatteryOptimizationMode_optimizationModeImmutable_verifyAction() { 250 whenever(testBatteryOptimizeUtils?.isOptimizeModeMutable).thenReturn(false) 251 whenever(testBatteryOptimizeUtils?.appOptimizationMode) 252 .thenReturn(MODE_UNRESTRICTED) 253 254 val currentOptMode = 255 AppOptModeSharedPreferencesUtils.updateBatteryOptimizationMode( 256 context, 257 UID, 258 PACKAGE_NAME, 259 MODE_OPTIMIZED, 260 Action.EXTERNAL_UPDATE, 261 testBatteryOptimizeUtils 262 ) 263 264 verify(testBatteryOptimizeUtils, never())?.setAppUsageState(anyInt(), any()) 265 assertThat(currentOptMode).isEqualTo(MODE_UNKNOWN) 266 } 267 268 @Test 269 fun updateBatteryOptimizationMode_updateToSameOptimizationMode_verifyAction() { 270 whenever(testBatteryOptimizeUtils?.isOptimizeModeMutable).thenReturn(true) 271 whenever(testBatteryOptimizeUtils?.appOptimizationMode).thenReturn(MODE_RESTRICTED) 272 273 val currentOptMode = 274 AppOptModeSharedPreferencesUtils.updateBatteryOptimizationMode( 275 context, 276 UID, 277 PACKAGE_NAME, 278 MODE_RESTRICTED, 279 Action.EXTERNAL_UPDATE, 280 testBatteryOptimizeUtils 281 ) 282 283 verify(testBatteryOptimizeUtils)?.setAppUsageState(MODE_RESTRICTED, Action.EXTERNAL_UPDATE) 284 assertThat(currentOptMode).isEqualTo(MODE_RESTRICTED) 285 } 286 287 private fun insertAppOptModeEventForTest(expirationTime: Long, mode: Int = MODE_OPTIMIZED) { 288 whenever(testBatteryOptimizeUtils?.isOptimizeModeMutable).thenReturn(true) 289 whenever(testBatteryOptimizeUtils?.appOptimizationMode).thenReturn(mode) 290 AppOptModeSharedPreferencesUtils.updateAppOptModeExpirationInternal( 291 context, 292 mutableListOf(UID), 293 mutableListOf(PACKAGE_NAME), 294 mutableListOf(mode), 295 longArrayOf(expirationTime), 296 ) { _: Int, _: String -> 297 testBatteryOptimizeUtils 298 } 299 } 300 301 companion object { 302 const val UID: Int = 12345 303 const val UNSET_UID: Int = 15432 304 const val PACKAGE_NAME: String = "com.android.app" 305 306 private fun assertAppOptimizationModeEventInfo( 307 event: AppOptimizationModeEvent, 308 uid: Int, 309 packageName: String, 310 resetOptimizationMode: Int, 311 expirationTime: Long 312 ) { 313 assertThat(event.uid).isEqualTo(uid) 314 assertThat(event.packageName).isEqualTo(packageName) 315 assertThat(event.resetOptimizationMode).isEqualTo(resetOptimizationMode) 316 assertThat(event.expirationTime).isEqualTo(expirationTime) 317 } 318 } 319 } 320