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.settings.fuelgauge.datasaver; 18 19 import static android.net.NetworkPolicyManager.POLICY_NONE; 20 import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND; 21 22 import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME; 23 import static com.android.settings.fuelgauge.datasaver.DynamicDenylistManager.PREF_KEY_MANUAL_DENYLIST_SYNCED; 24 25 import static com.google.common.truth.Truth.assertThat; 26 27 import static org.junit.Assert.assertFalse; 28 import static org.junit.Assert.assertTrue; 29 import static org.mockito.ArgumentMatchers.anyInt; 30 import static org.mockito.ArgumentMatchers.eq; 31 import static org.mockito.Mockito.never; 32 import static org.mockito.Mockito.spy; 33 import static org.mockito.Mockito.times; 34 import static org.mockito.Mockito.verify; 35 import static org.mockito.Mockito.when; 36 37 import android.content.Context; 38 import android.content.SharedPreferences; 39 import android.content.pm.PackageManager; 40 import android.net.NetworkPolicyManager; 41 import android.util.ArraySet; 42 43 import org.junit.After; 44 import org.junit.Before; 45 import org.junit.Test; 46 import org.junit.runner.RunWith; 47 import org.mockito.Mock; 48 import org.mockito.MockitoAnnotations; 49 import org.robolectric.RobolectricTestRunner; 50 import org.robolectric.RuntimeEnvironment; 51 52 import java.io.PrintWriter; 53 import java.io.StringWriter; 54 import java.util.Collections; 55 import java.util.List; 56 import java.util.Set; 57 58 @RunWith(RobolectricTestRunner.class) 59 public class DynamicDenylistManagerTest { 60 61 private static final int[] EMPTY_ARRAY = new int[] {}; 62 private static final String FAKE_UID_1 = "1001"; 63 private static final String FAKE_UID_2 = "1002"; 64 private static final int FAKE_UID_1_INT = Integer.parseInt(FAKE_UID_1); 65 private static final int FAKE_UID_2_INT = Integer.parseInt(FAKE_UID_2); 66 67 private SharedPreferences mManualDenyListPref; 68 private SharedPreferences mDynamicDenyListPref; 69 private DynamicDenylistManager mDynamicDenylistManager; 70 71 @Mock 72 private NetworkPolicyManager mNetworkPolicyManager; 73 @Mock 74 private PackageManager mPackageManager; 75 76 @Before setUp()77 public void setUp() { 78 MockitoAnnotations.initMocks(this); 79 } 80 81 @After tearDown()82 public void tearDown() { 83 mDynamicDenylistManager.clearSharedPreferences(); 84 } 85 86 @Test init_withoutExistedRejectPolicy_createWithExpectedValue()87 public void init_withoutExistedRejectPolicy_createWithExpectedValue() { 88 initDynamicDenylistManager(EMPTY_ARRAY); 89 90 assertThat(mManualDenyListPref.getAll()).hasSize(1); 91 assertTrue(mManualDenyListPref.contains(PREF_KEY_MANUAL_DENYLIST_SYNCED)); 92 } 93 94 @Test init_withExistedRejectPolicy_createWithExpectedValue()95 public void init_withExistedRejectPolicy_createWithExpectedValue() { 96 initDynamicDenylistManager(new int[] {FAKE_UID_1_INT, FAKE_UID_2_INT}); 97 98 assertThat(mManualDenyListPref.getAll()).hasSize(3); 99 assertTrue(mManualDenyListPref.contains(PREF_KEY_MANUAL_DENYLIST_SYNCED)); 100 assertTrue(mManualDenyListPref.contains(FAKE_UID_1)); 101 assertTrue(mManualDenyListPref.contains(FAKE_UID_2)); 102 } 103 104 @Test getManualDenylistPref_initiated_containsExpectedValue()105 public void getManualDenylistPref_initiated_containsExpectedValue() { 106 initDynamicDenylistManager(EMPTY_ARRAY); 107 108 setupPreference(mManualDenyListPref, FAKE_UID_1); 109 110 assertTrue(mManualDenyListPref.contains(FAKE_UID_1)); 111 } 112 113 @Test getDynamicDenylistPref_initiated_containsExpectedValue()114 public void getDynamicDenylistPref_initiated_containsExpectedValue() { 115 initDynamicDenylistManager(EMPTY_ARRAY); 116 117 setupPreference(mDynamicDenyListPref, FAKE_UID_1); 118 119 assertTrue(mDynamicDenyListPref.contains(FAKE_UID_1)); 120 } 121 122 @Test updateManualDenylist_policyReject_addsUid()123 public void updateManualDenylist_policyReject_addsUid() { 124 initDynamicDenylistManager(EMPTY_ARRAY); 125 126 mDynamicDenylistManager.updateDenylistPref(FAKE_UID_1_INT, 127 POLICY_REJECT_METERED_BACKGROUND); 128 129 assertTrue(mManualDenyListPref.contains(FAKE_UID_1)); 130 } 131 132 @Test updateManualDenylist_policyNone_removesUid()133 public void updateManualDenylist_policyNone_removesUid() { 134 initDynamicDenylistManager(EMPTY_ARRAY); 135 setupPreference(mManualDenyListPref, FAKE_UID_1); 136 assertTrue(mManualDenyListPref.contains(FAKE_UID_1)); 137 138 mDynamicDenylistManager.updateDenylistPref(FAKE_UID_1_INT, POLICY_NONE); 139 140 assertFalse(mManualDenyListPref.contains(FAKE_UID_1)); 141 } 142 143 @Test updateManualDenylist_samePolicy_doNothing()144 public void updateManualDenylist_samePolicy_doNothing() { 145 initDynamicDenylistManager(EMPTY_ARRAY); 146 setupPreference(mManualDenyListPref, FAKE_UID_1); 147 assertTrue(mManualDenyListPref.contains(FAKE_UID_1)); 148 assertThat(mManualDenyListPref.getAll()).hasSize(2); 149 150 mDynamicDenylistManager.updateDenylistPref(FAKE_UID_1_INT, 151 POLICY_REJECT_METERED_BACKGROUND); 152 153 assertThat(mManualDenyListPref.getAll()).hasSize(2); 154 } 155 156 @Test setUidPolicyLocked_invokeSetUidPolicy()157 public void setUidPolicyLocked_invokeSetUidPolicy() { 158 initDynamicDenylistManager(EMPTY_ARRAY); 159 160 mDynamicDenylistManager.setUidPolicyLocked(FAKE_UID_1_INT, 161 POLICY_REJECT_METERED_BACKGROUND); 162 163 assertTrue(mManualDenyListPref.contains(FAKE_UID_1)); 164 verify(mNetworkPolicyManager).setUidPolicy(eq(FAKE_UID_1_INT), 165 eq(POLICY_REJECT_METERED_BACKGROUND)); 166 } 167 168 @Test setDenylist_emptyListAndNoData_doNothing()169 public void setDenylist_emptyListAndNoData_doNothing() { 170 initDynamicDenylistManager(EMPTY_ARRAY); 171 172 setDenylist(Collections.emptySet()); 173 174 verify(mNetworkPolicyManager, never()).setUidPolicy(anyInt(), anyInt()); 175 } 176 177 @Test setDenylist_uidDeniedAlready_doNothing()178 public void setDenylist_uidDeniedAlready_doNothing() { 179 initDynamicDenylistManager(new int[] {FAKE_UID_1_INT}); 180 final ArraySet uids = new ArraySet<>(); 181 uids.add(FAKE_UID_1_INT); 182 uids.add(null); 183 184 setDenylist(uids); 185 186 verify(mNetworkPolicyManager, never()).setUidPolicy(anyInt(), anyInt()); 187 } 188 189 @Test setDenylist_sameList_doNothing()190 public void setDenylist_sameList_doNothing() { 191 initDynamicDenylistManager(EMPTY_ARRAY); 192 setupPreference(mDynamicDenyListPref, FAKE_UID_2, FAKE_UID_1); 193 194 setDenylist(new ArraySet<>(List.of(FAKE_UID_1_INT, FAKE_UID_2_INT))); 195 196 verify(mNetworkPolicyManager, never()).setUidPolicy(anyInt(), anyInt()); 197 } 198 199 @Test setDenylist_newListWithOldData_modifyPolicyNoneAndReject()200 public void setDenylist_newListWithOldData_modifyPolicyNoneAndReject() { 201 initDynamicDenylistManager(EMPTY_ARRAY); 202 setupPreference(mDynamicDenyListPref, FAKE_UID_2); 203 204 setDenylist(new ArraySet<>(List.of(FAKE_UID_1_INT))); 205 206 verify(mNetworkPolicyManager).setUidPolicy(FAKE_UID_2_INT, POLICY_NONE); 207 verify(mNetworkPolicyManager).setUidPolicy(FAKE_UID_1_INT, 208 POLICY_REJECT_METERED_BACKGROUND); 209 assertThat(mDynamicDenyListPref.getAll()).hasSize(1); 210 assertTrue(mDynamicDenyListPref.contains(FAKE_UID_1)); 211 } 212 213 @Test setDenylist_newListWithoutOldData_modifyPolicyReject()214 public void setDenylist_newListWithoutOldData_modifyPolicyReject() { 215 initDynamicDenylistManager(EMPTY_ARRAY); 216 217 setDenylist(new ArraySet<>(List.of(FAKE_UID_1_INT))); 218 219 verify(mNetworkPolicyManager, never()).setUidPolicy(anyInt(), eq(POLICY_NONE)); 220 verify(mNetworkPolicyManager).setUidPolicy(FAKE_UID_1_INT, 221 POLICY_REJECT_METERED_BACKGROUND); 222 assertThat(mDynamicDenyListPref.getAll()).hasSize(1); 223 assertTrue(mDynamicDenyListPref.contains(FAKE_UID_1)); 224 } 225 226 @Test setDenylist_emptyListWithOldData_modifyPolicyNone()227 public void setDenylist_emptyListWithOldData_modifyPolicyNone() { 228 initDynamicDenylistManager(EMPTY_ARRAY); 229 setupPreference(mDynamicDenyListPref, FAKE_UID_2); 230 231 setDenylist(Collections.emptySet()); 232 233 verify(mNetworkPolicyManager).setUidPolicy(FAKE_UID_2_INT, POLICY_NONE); 234 verify(mNetworkPolicyManager, never()).setUidPolicy(anyInt(), 235 eq(POLICY_REJECT_METERED_BACKGROUND)); 236 assertThat(mDynamicDenyListPref.getAll()).isEmpty(); 237 } 238 239 @Test isInManualDenylist_returnsFalse()240 public void isInManualDenylist_returnsFalse() { 241 initDynamicDenylistManager(EMPTY_ARRAY); 242 243 assertFalse(mDynamicDenylistManager.isInManualDenylist(FAKE_UID_1_INT)); 244 } 245 246 @Test isInManualDenylist_incorrectUid_returnsFalse()247 public void isInManualDenylist_incorrectUid_returnsFalse() { 248 initDynamicDenylistManager(EMPTY_ARRAY); 249 250 mManualDenyListPref.edit().putInt(FAKE_UID_2, POLICY_REJECT_METERED_BACKGROUND).apply(); 251 252 assertFalse(mDynamicDenylistManager.isInManualDenylist(FAKE_UID_1_INT)); 253 } 254 255 @Test isInManualDenylist_initiated_returnsTrue()256 public void isInManualDenylist_initiated_returnsTrue() { 257 initDynamicDenylistManager(EMPTY_ARRAY); 258 259 mManualDenyListPref.edit().putInt(FAKE_UID_1, POLICY_REJECT_METERED_BACKGROUND).apply(); 260 261 assertTrue(mDynamicDenylistManager.isInManualDenylist(FAKE_UID_1_INT)); 262 } 263 264 @Test resetDenylistIfNeeded_nullPackageName_doNothing()265 public void resetDenylistIfNeeded_nullPackageName_doNothing() { 266 initDynamicDenylistManager(new int[0], new int[] {FAKE_UID_1_INT, FAKE_UID_2_INT}); 267 268 mDynamicDenylistManager.resetDenylistIfNeeded(null, false); 269 270 assertThat(mManualDenyListPref.getAll()).hasSize(1); 271 verify(mNetworkPolicyManager, never()).setUidPolicy(anyInt(), eq(POLICY_NONE)); 272 } 273 274 @Test resetDenylistIfNeeded_invalidPackageName_doNothing()275 public void resetDenylistIfNeeded_invalidPackageName_doNothing() { 276 initDynamicDenylistManager(new int[0], new int[] {FAKE_UID_1_INT, FAKE_UID_2_INT}); 277 278 mDynamicDenylistManager.resetDenylistIfNeeded("invalid_package_name", false); 279 280 assertThat(mManualDenyListPref.getAll()).hasSize(1); 281 verify(mNetworkPolicyManager, never()).setUidPolicy(anyInt(), eq(POLICY_NONE)); 282 } 283 284 @Test resetDenylistIfNeeded_denylistUnchanged_doNothingWithPolicy()285 public void resetDenylistIfNeeded_denylistUnchanged_doNothingWithPolicy() { 286 initDynamicDenylistManager(new int[] {FAKE_UID_1_INT, FAKE_UID_2_INT}); 287 288 mDynamicDenylistManager.resetDenylistIfNeeded(SETTINGS_PACKAGE_NAME, false); 289 290 verify(mNetworkPolicyManager, never()).setUidPolicy(anyInt(), eq(POLICY_NONE)); 291 } 292 293 @Test resetDenylistIfNeeded_denylistChanged_resetAndClear()294 public void resetDenylistIfNeeded_denylistChanged_resetAndClear() { 295 initDynamicDenylistManager(new int[0], new int[] {FAKE_UID_1_INT, FAKE_UID_2_INT}); 296 297 mDynamicDenylistManager.resetDenylistIfNeeded(SETTINGS_PACKAGE_NAME, false); 298 299 assertThat(mManualDenyListPref.getAll()).isEmpty(); 300 verify(mNetworkPolicyManager, times(2)).setUidPolicy(anyInt(), eq(POLICY_NONE)); 301 } 302 303 @Test resetDenylistIfNeeded_forceResetWithNullPackageName_resetAndClear()304 public void resetDenylistIfNeeded_forceResetWithNullPackageName_resetAndClear() { 305 initDynamicDenylistManager(new int[0], new int[] {FAKE_UID_2_INT}); 306 307 mDynamicDenylistManager.resetDenylistIfNeeded(null, true); 308 309 assertThat(mManualDenyListPref.getAll()).isEmpty(); 310 verify(mNetworkPolicyManager).setUidPolicy(eq(FAKE_UID_2_INT), eq(POLICY_NONE)); 311 } 312 313 @Test resetDenylistIfNeeded_forceResetWithInvalidPackageName_resetAndClear()314 public void resetDenylistIfNeeded_forceResetWithInvalidPackageName_resetAndClear() { 315 initDynamicDenylistManager(new int[0], new int[] {FAKE_UID_1_INT, FAKE_UID_2_INT}); 316 317 mDynamicDenylistManager.resetDenylistIfNeeded("invalid_package_name", true); 318 319 assertThat(mManualDenyListPref.getAll()).isEmpty(); 320 verify(mNetworkPolicyManager, times(2)).setUidPolicy(anyInt(), eq(POLICY_NONE)); 321 } 322 323 @Test resetDenylistIfNeeded_forceResetButDenylistUnchanged_doNothingWithPolicy()324 public void resetDenylistIfNeeded_forceResetButDenylistUnchanged_doNothingWithPolicy() { 325 initDynamicDenylistManager(new int[] {FAKE_UID_1_INT}); 326 327 mDynamicDenylistManager.resetDenylistIfNeeded(SETTINGS_PACKAGE_NAME, true); 328 329 assertThat(mManualDenyListPref.getAll()).isEmpty(); 330 verify(mNetworkPolicyManager, never()).setUidPolicy(anyInt(), eq(POLICY_NONE)); 331 } 332 333 @Test resetDenylistIfNeeded_forceResetWithDenylistChanged_resetAndClear()334 public void resetDenylistIfNeeded_forceResetWithDenylistChanged_resetAndClear() { 335 initDynamicDenylistManager(new int[0], new int[] {FAKE_UID_1_INT, FAKE_UID_2_INT}); 336 337 mDynamicDenylistManager.resetDenylistIfNeeded(SETTINGS_PACKAGE_NAME, true); 338 339 assertThat(mManualDenyListPref.getAll()).isEmpty(); 340 verify(mNetworkPolicyManager, times(2)).setUidPolicy(anyInt(), eq(POLICY_NONE)); 341 } 342 343 @Test clearSharedPreferences_manualDenyListPrefIsEmpty()344 public void clearSharedPreferences_manualDenyListPrefIsEmpty() { 345 initDynamicDenylistManager(EMPTY_ARRAY); 346 mManualDenyListPref.edit().putInt(FAKE_UID_1, POLICY_REJECT_METERED_BACKGROUND).apply(); 347 assertThat(mManualDenyListPref.getAll()).hasSize(2); 348 assertTrue(mManualDenyListPref.contains(FAKE_UID_1)); 349 assertTrue(mManualDenyListPref.contains(PREF_KEY_MANUAL_DENYLIST_SYNCED)); 350 351 mDynamicDenylistManager.clearSharedPreferences(); 352 353 assertThat(mManualDenyListPref.getAll()).isEmpty(); 354 } 355 356 @Test clearSharedPreferences_dynamicDenyListPrefIsEmpty()357 public void clearSharedPreferences_dynamicDenyListPrefIsEmpty() { 358 initDynamicDenylistManager(EMPTY_ARRAY); 359 mDynamicDenyListPref.edit().putInt(FAKE_UID_1, POLICY_REJECT_METERED_BACKGROUND).apply(); 360 assertThat(mDynamicDenyListPref.getAll()).hasSize(1); 361 assertTrue(mDynamicDenyListPref.contains(FAKE_UID_1)); 362 363 mDynamicDenylistManager.clearSharedPreferences(); 364 365 assertThat(mDynamicDenyListPref.getAll()).isEmpty(); 366 } 367 368 @Test dump_dumpExpectedResult()369 public void dump_dumpExpectedResult() { 370 initDynamicDenylistManager(EMPTY_ARRAY); 371 setupPreference(mManualDenyListPref, FAKE_UID_1); 372 setupPreference(mDynamicDenyListPref, FAKE_UID_2); 373 final StringWriter stringWriter = new StringWriter(); 374 final PrintWriter printWriter = new PrintWriter(stringWriter); 375 when(mPackageManager.getNameForUid(FAKE_UID_1_INT)).thenReturn("app1"); 376 when(mPackageManager.getNameForUid(FAKE_UID_2_INT)).thenReturn("app2"); 377 378 mDynamicDenylistManager.dump(printWriter); 379 380 final String dumpResults = stringWriter.toString(); 381 assertThat(dumpResults.contains("\tManualDenylist:\n\t\tapp1")).isTrue(); 382 assertThat(dumpResults.contains("\tDynamicDenylist:\n\t\tapp2")).isTrue(); 383 } 384 385 @Test dump_withEmptySharedPreferences_dumpExpectedResult()386 public void dump_withEmptySharedPreferences_dumpExpectedResult() { 387 initDynamicDenylistManager(EMPTY_ARRAY, EMPTY_ARRAY); 388 mDynamicDenylistManager.clearSharedPreferences(); 389 final StringWriter stringWriter = new StringWriter(); 390 final PrintWriter printWriter = new PrintWriter(stringWriter); 391 392 mDynamicDenylistManager.dump(printWriter); 393 394 final String dumpResults = stringWriter.toString(); 395 assertThat(dumpResults.contains("Dump of DynamicDenylistManager:")).isTrue(); 396 assertThat(dumpResults.contains("\tManualDenylist:\n\tDynamicDenylist:")).isTrue(); 397 } 398 399 @Test onBootComplete_resetIntoManualMode()400 public void onBootComplete_resetIntoManualMode() { 401 initDynamicDenylistManager(new int[] {FAKE_UID_1_INT}); 402 setDenylist(new ArraySet<>(List.of(FAKE_UID_2_INT))); 403 // Ensure the testing environment for manual denylist. 404 assertThat(mManualDenyListPref.getAll()).hasSize(2); 405 assertTrue(mManualDenyListPref.contains(PREF_KEY_MANUAL_DENYLIST_SYNCED)); 406 assertTrue(mManualDenyListPref.contains(FAKE_UID_1)); 407 // Ensure the testing environment for dynamic denylist. 408 assertThat(mDynamicDenyListPref.getAll()).hasSize(1); 409 410 mDynamicDenylistManager.onBootComplete(); 411 412 // Keep the users set uids in the manual denylist. 413 assertThat(mManualDenyListPref.getAll()).hasSize(2); 414 assertTrue(mManualDenyListPref.contains(PREF_KEY_MANUAL_DENYLIST_SYNCED)); 415 assertTrue(mManualDenyListPref.contains(FAKE_UID_1)); 416 // Clear the uids in the dynamic denylist. 417 assertThat(mDynamicDenyListPref.getAll()).isEmpty(); 418 } 419 initDynamicDenylistManager(int[] preload)420 private void initDynamicDenylistManager(int[] preload) { 421 initDynamicDenylistManager(preload, preload); 422 } 423 initDynamicDenylistManager(int[] preload1, int[] preload2)424 private void initDynamicDenylistManager(int[] preload1, int[] preload2) { 425 final Context context = spy(RuntimeEnvironment.application.getApplicationContext()); 426 when(context.getApplicationContext()).thenReturn(context); 427 when(context.getPackageManager()).thenReturn(mPackageManager); 428 when(mNetworkPolicyManager.getUidsWithPolicy(anyInt())) 429 .thenReturn(preload1).thenReturn(preload2); 430 mDynamicDenylistManager = new DynamicDenylistManager(context, mNetworkPolicyManager); 431 mManualDenyListPref = mDynamicDenylistManager.getManualDenylistPref(); 432 mDynamicDenyListPref = mDynamicDenylistManager.getDynamicDenylistPref(); 433 } 434 setDenylist(Set<Integer> packageNameList)435 private void setDenylist(Set<Integer> packageNameList) { 436 mDynamicDenylistManager.setDenylist(packageNameList); 437 } 438 setupPreference(SharedPreferences sharedPreferences, String... uids)439 private void setupPreference(SharedPreferences sharedPreferences, String... uids) { 440 final SharedPreferences.Editor editor = sharedPreferences.edit(); 441 for (String uid : uids) { 442 editor.putInt(uid, POLICY_REJECT_METERED_BACKGROUND); 443 } 444 editor.apply(); 445 } 446 } 447