1 /* 2 * Copyright (C) 2022 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.localepicker; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.mockito.ArgumentMatchers.any; 22 import static org.mockito.ArgumentMatchers.eq; 23 import static org.mockito.Mockito.mock; 24 import static org.mockito.Mockito.spy; 25 import static org.mockito.Mockito.times; 26 import static org.mockito.Mockito.verify; 27 import static org.mockito.Mockito.when; 28 29 import android.app.Activity; 30 import android.app.ApplicationPackageManager; 31 import android.app.LocaleConfig; 32 import android.app.settings.SettingsEnums; 33 import android.content.Context; 34 import android.content.Intent; 35 import android.content.pm.ApplicationInfo; 36 import android.content.pm.InstallSourceInfo; 37 import android.content.pm.PackageInfo; 38 import android.content.pm.PackageManager.NameNotFoundException; 39 import android.content.pm.ResolveInfo; 40 import android.content.res.Resources; 41 import android.net.Uri; 42 import android.os.LocaleList; 43 import android.os.Process; 44 import android.os.SystemClock; 45 import android.os.UserHandle; 46 import android.platform.test.annotations.RequiresFlagsEnabled; 47 import android.platform.test.flag.junit.CheckFlagsRule; 48 import android.platform.test.flag.junit.DeviceFlagsValueProvider; 49 import android.telephony.TelephonyManager; 50 51 import androidx.annotation.ArrayRes; 52 53 import com.android.internal.app.LocaleStore; 54 import com.android.settings.applications.AppInfoBase; 55 import com.android.settings.applications.AppLocaleUtil; 56 import com.android.settings.flags.Flags; 57 import com.android.settings.testutils.FakeFeatureFactory; 58 59 import org.junit.After; 60 import org.junit.Before; 61 import org.junit.Rule; 62 import org.junit.Test; 63 import org.junit.runner.RunWith; 64 import org.mockito.Mock; 65 import org.mockito.junit.MockitoJUnit; 66 import org.mockito.junit.MockitoRule; 67 import org.robolectric.Robolectric; 68 import org.robolectric.RobolectricTestRunner; 69 import org.robolectric.RuntimeEnvironment; 70 import org.robolectric.Shadows; 71 import org.robolectric.android.controller.ActivityController; 72 import org.robolectric.annotation.Config; 73 import org.robolectric.annotation.Implementation; 74 import org.robolectric.annotation.Implements; 75 import org.robolectric.shadows.ShadowPackageManager; 76 import org.robolectric.shadows.ShadowTelephonyManager; 77 import org.robolectric.util.ReflectionHelpers; 78 79 import java.util.ArrayList; 80 import java.util.Calendar; 81 import java.util.List; 82 import java.util.Locale; 83 import java.util.Set; 84 85 @RunWith(RobolectricTestRunner.class) 86 @Config( 87 shadows = { 88 AppLocalePickerActivityTest.ShadowApplicationPackageManager.class, 89 AppLocalePickerActivityTest.ShadowResources.class, 90 }) 91 public class AppLocalePickerActivityTest { 92 private static final String TEST_PACKAGE_NAME = "com.android.settings"; 93 private static final Uri TEST_PACKAGE_URI = Uri.parse("package:" + TEST_PACKAGE_NAME); 94 private static final String EN_CA = "en-CA"; 95 private static final String EN_US = "en-US"; 96 private static int sUid; 97 98 private FakeFeatureFactory mFeatureFactory; 99 private LocaleNotificationDataManager mDataManager; 100 private AppLocalePickerActivity mActivity; 101 102 @Mock 103 LocaleStore.LocaleInfo mLocaleInfo; 104 @Mock 105 private LocaleConfig mLocaleConfig; 106 107 @Rule 108 public MockitoRule rule = MockitoJUnit.rule(); 109 @Rule 110 public final CheckFlagsRule mCheckFlagsRule = 111 DeviceFlagsValueProvider.createCheckFlagsRule(); 112 113 private Context mContext; 114 private ShadowPackageManager mPackageManager; 115 116 @Before setUp()117 public void setUp() { 118 mContext = spy(RuntimeEnvironment.application); 119 mPackageManager = Shadows.shadowOf(mContext.getPackageManager()); 120 mLocaleConfig = mock(LocaleConfig.class); 121 when(mLocaleConfig.getStatus()).thenReturn(LocaleConfig.STATUS_SUCCESS); 122 when(mLocaleConfig.getSupportedLocales()).thenReturn(LocaleList.forLanguageTags("en-US")); 123 ReflectionHelpers.setStaticField(AppLocaleUtil.class, "sLocaleConfig", mLocaleConfig); 124 sUid = Process.myUid(); 125 mFeatureFactory = FakeFeatureFactory.setupForTest(); 126 } 127 128 @After tearDown()129 public void tearDown() throws Exception { 130 mPackageManager.removePackage(TEST_PACKAGE_NAME); 131 ReflectionHelpers.setStaticField(AppLocaleUtil.class, "sLocaleConfig", null); 132 ShadowResources.setDisAllowPackage(false); 133 ShadowApplicationPackageManager.setNoLaunchEntry(false); 134 } 135 136 @Test launchAppLocalePickerActivity_hasPackageName_success()137 public void launchAppLocalePickerActivity_hasPackageName_success() { 138 ActivityController<TestAppLocalePickerActivity> controller = 139 initActivityController(true); 140 controller.create(); 141 142 assertThat(controller.get().isFinishing()).isFalse(); 143 } 144 145 @Test launchAppLocalePickerActivity_appNoLocaleConfig_failed()146 public void launchAppLocalePickerActivity_appNoLocaleConfig_failed() { 147 when(mLocaleConfig.getStatus()).thenReturn(LocaleConfig.STATUS_NOT_SPECIFIED); 148 149 ActivityController<TestAppLocalePickerActivity> controller = 150 initActivityController(true); 151 controller.create(); 152 153 assertThat(controller.get().isFinishing()).isTrue(); 154 } 155 156 @Test launchAppLocalePickerActivity_appSignPlatformKey_failed()157 public void launchAppLocalePickerActivity_appSignPlatformKey_failed() { 158 final ApplicationInfo applicationInfo = new ApplicationInfo(); 159 applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY; 160 applicationInfo.packageName = TEST_PACKAGE_NAME; 161 162 final PackageInfo packageInfo = new PackageInfo(); 163 packageInfo.packageName = TEST_PACKAGE_NAME; 164 packageInfo.applicationInfo = applicationInfo; 165 mPackageManager.installPackage(packageInfo); 166 167 ActivityController<TestAppLocalePickerActivity> controller = 168 initActivityController(true); 169 controller.create(); 170 171 assertThat(controller.get().isFinishing()).isTrue(); 172 } 173 174 @Test launchAppLocalePickerActivity_appMatchDisallowedPackage_failed()175 public void launchAppLocalePickerActivity_appMatchDisallowedPackage_failed() { 176 ShadowResources.setDisAllowPackage(true); 177 178 ActivityController<TestAppLocalePickerActivity> controller = 179 initActivityController(true); 180 controller.create(); 181 182 assertThat(controller.get().isFinishing()).isTrue(); 183 } 184 185 @Test launchAppLocalePickerActivity_appNoLaunchEntry_failed()186 public void launchAppLocalePickerActivity_appNoLaunchEntry_failed() { 187 ShadowApplicationPackageManager.setNoLaunchEntry(true); 188 189 ActivityController<TestAppLocalePickerActivity> controller = 190 initActivityController(true); 191 controller.create(); 192 193 assertThat(controller.get().isFinishing()).isTrue(); 194 } 195 196 @Test launchAppLocalePickerActivity_intentWithoutPackageName_failed()197 public void launchAppLocalePickerActivity_intentWithoutPackageName_failed() { 198 ActivityController<TestAppLocalePickerActivity> controller = 199 initActivityController(false); 200 controller.create(); 201 202 assertThat(controller.get().isFinishing()).isTrue(); 203 } 204 205 @Test onLocaleSelected_getLocaleNotNull_getLanguageTag()206 public void onLocaleSelected_getLocaleNotNull_getLanguageTag() { 207 ActivityController<TestAppLocalePickerActivity> controller = 208 initActivityController(true); 209 Locale locale = new Locale("en", "US"); 210 when(mLocaleInfo.getLocale()).thenReturn(locale); 211 when(mLocaleInfo.isSystemLocale()).thenReturn(false); 212 213 controller.create(); 214 AppLocalePickerActivity mActivity = controller.get(); 215 mActivity.onLocaleSelected(mLocaleInfo); 216 217 // 1st for getLocale()!= null 218 // 2nd for setAppDefaultLocale(getLocale()) 219 // 3rd for broadcastAppLocaleChange() 220 verify(mLocaleInfo, times(3)).getLocale(); 221 assertThat(mLocaleInfo.getLocale().toLanguageTag()).isEqualTo("en-US"); 222 assertThat(controller.get().isFinishing()).isTrue(); 223 } 224 225 @Test onLocaleSelected_getLocaleNull_getEmptyLanguageTag()226 public void onLocaleSelected_getLocaleNull_getEmptyLanguageTag() { 227 ActivityController<TestAppLocalePickerActivity> controller = 228 initActivityController(true); 229 when(mLocaleInfo.getLocale()).thenReturn(null); 230 when(mLocaleInfo.isSystemLocale()).thenReturn(false); 231 232 controller.create(); 233 AppLocalePickerActivity mActivity = controller.get(); 234 mActivity.onLocaleSelected(mLocaleInfo); 235 236 verify(mLocaleInfo, times(1)).getLocale(); 237 assertThat(controller.get().isFinishing()).isTrue(); 238 } 239 240 @Test onLocaleSelected_logLocaleSource()241 public void onLocaleSelected_logLocaleSource() { 242 ActivityController<TestAppLocalePickerActivity> controller = 243 initActivityController(true); 244 LocaleList.setDefault(LocaleList.forLanguageTags("ja-JP,en-CA,en-US")); 245 Locale locale = new Locale("en", "US"); 246 when(mLocaleInfo.getLocale()).thenReturn(locale); 247 when(mLocaleInfo.isSystemLocale()).thenReturn(false); 248 when(mLocaleInfo.isSuggested()).thenReturn(true); 249 when(mLocaleInfo.isSuggestionOfType(LocaleStore.LocaleInfo.SUGGESTION_TYPE_SIM)).thenReturn( 250 true); 251 when(mLocaleInfo.isSuggestionOfType( 252 LocaleStore.LocaleInfo.SUGGESTION_TYPE_SYSTEM_AVAILABLE_LANGUAGE)).thenReturn( 253 true); 254 when(mLocaleInfo.isSuggestionOfType( 255 LocaleStore.LocaleInfo.SUGGESTION_TYPE_OTHER_APP_LANGUAGE)).thenReturn( 256 true); 257 when(mLocaleInfo.isSuggestionOfType( 258 LocaleStore.LocaleInfo.SUGGESTION_TYPE_IME_LANGUAGE)).thenReturn( 259 true); 260 261 controller.create(); 262 AppLocalePickerActivity mActivity = controller.get(); 263 mActivity.onLocaleSelected(mLocaleInfo); 264 265 int localeSource = 15; // SIM_LOCALE | SYSTEM_LOCALE |IME_LOCALE|APP_LOCALE 266 verify(mFeatureFactory.metricsFeatureProvider).action( 267 any(), eq(SettingsEnums.ACTION_CHANGE_APP_LANGUAGE_FROM_SUGGESTED), 268 eq(localeSource)); 269 } 270 271 @Test 272 @RequiresFlagsEnabled(Flags.FLAG_LOCALE_NOTIFICATION_ENABLED) onLocaleSelected_evaluateNotification_simpleLocaleUpdate_localeCreatedWithUid()273 public void onLocaleSelected_evaluateNotification_simpleLocaleUpdate_localeCreatedWithUid() 274 throws Exception { 275 sUid = 100; 276 initLocaleNotificationEnvironment(); 277 ActivityController<TestAppLocalePickerActivity> controller = initActivityController(true); 278 controller.create(); 279 AppLocalePickerActivity mActivity = controller.get(); 280 LocaleNotificationDataManager dataManager = 281 NotificationController.getInstance(mActivity).getDataManager(); 282 283 mActivity.onLocaleSelected(mLocaleInfo); 284 285 // Notification is not triggered. 286 // In the sharedpreference, en-US's uid list contains uid1 and the notificationCount 287 // equals 0. 288 NotificationInfo info = dataManager.getNotificationInfo(EN_US); 289 assertThat(info.getUidCollection().contains(sUid)).isTrue(); 290 assertThat(info.getNotificationCount()).isEqualTo(0); 291 assertThat(info.getDismissCount()).isEqualTo(0); 292 assertThat(info.getLastNotificationTimeMs()).isEqualTo(0); 293 294 mDataManager.clearLocaleNotificationMap(); 295 } 296 297 @Test 298 @RequiresFlagsEnabled(Flags.FLAG_LOCALE_NOTIFICATION_ENABLED) onLocaleSelected_evaluateNotification_twoLocaleUpdate_triggerNotification()299 public void onLocaleSelected_evaluateNotification_twoLocaleUpdate_triggerNotification() 300 throws Exception { 301 // App with uid 101 changed its locale from System to en-US. 302 sUid = 101; 303 initLocaleNotificationEnvironment(); 304 // Initialize the proto to contain en-US locale. Its uid list includes 100. 305 Set<Integer> uidSet = Set.of(100); 306 initSharedPreference(EN_US, uidSet, 0, 0, 0, 0); 307 308 mActivity.onLocaleSelected(mLocaleInfo); 309 310 // Notification is triggered. 311 // In the proto file, en-US's uid list contains 101, the notificationCount equals 1, and 312 // LastNotificationTime > 0. 313 NotificationInfo info = mDataManager.getNotificationInfo(EN_US); 314 assertThat(info.getUidCollection()).contains(sUid); 315 assertThat(info.getNotificationCount()).isEqualTo(1); 316 assertThat(info.getDismissCount()).isEqualTo(0); 317 assertThat(info.getLastNotificationTimeMs()).isNotEqualTo(0); 318 verify(mFeatureFactory.metricsFeatureProvider).action( 319 any(), eq(SettingsEnums.ACTION_NOTIFICATION_FOR_SYSTEM_LOCALE)); 320 321 mDataManager.clearLocaleNotificationMap(); 322 } 323 324 @Test 325 @RequiresFlagsEnabled(Flags.FLAG_LOCALE_NOTIFICATION_ENABLED) onLocaleSelected_evaluateNotification_oddLocaleUpdate_uidAddedWithoutNotification()326 public void onLocaleSelected_evaluateNotification_oddLocaleUpdate_uidAddedWithoutNotification() 327 throws Exception { 328 // App with uid 102 changed its locale from System to en-US. 329 sUid = 102; 330 initLocaleNotificationEnvironment(); 331 // Initialize the proto to include en-US locale. Its uid list includes 100,101 and 332 // the notification count equals 1. 333 int notificationId = (int) SystemClock.uptimeMillis(); 334 Set<Integer> uidSet = Set.of(100, 101); 335 initSharedPreference(EN_US, uidSet, 0, 1, 336 Calendar.getInstance().getTimeInMillis(), notificationId); 337 338 mActivity.onLocaleSelected(mLocaleInfo); 339 340 // Notification is not triggered because count % 2 != 0. 341 // In the proto file, en-US's uid list contains 102, the notificationCount equals 1, and 342 // LastNotificationTime > 0. 343 NotificationInfo info = mDataManager.getNotificationInfo(EN_US); 344 assertThat(info.getUidCollection()).contains(sUid); 345 assertThat(info.getNotificationCount()).isEqualTo(1); 346 assertThat(info.getDismissCount()).isEqualTo(0); 347 assertThat(info.getLastNotificationTimeMs()).isNotEqualTo(0); 348 assertThat(info.getNotificationId()).isEqualTo(notificationId); 349 350 mDataManager.clearLocaleNotificationMap(); 351 } 352 353 @Test 354 @RequiresFlagsEnabled(Flags.FLAG_LOCALE_NOTIFICATION_ENABLED) onLocaleSelected_evaluateNotification_frequentLocaleUpdate_uidAddedNoNotification()355 public void onLocaleSelected_evaluateNotification_frequentLocaleUpdate_uidAddedNoNotification() 356 throws Exception { 357 // App with uid 103 changed its locale from System to en-US. 358 sUid = 103; 359 initLocaleNotificationEnvironment(); 360 // Initialize the proto to include en-US locale. Its uid list includes 100,101,102 and 361 // the notification count equals 1. 362 int notificationId = (int) SystemClock.uptimeMillis(); 363 Set<Integer> uidSet = Set.of(100, 101, 102); 364 initSharedPreference(EN_US, uidSet, 0, 1, 365 Calendar.getInstance().getTimeInMillis(), notificationId); 366 367 mActivity.onLocaleSelected(mLocaleInfo); 368 369 // Notification is not triggered because the duration is less than the threshold. 370 // In the proto file, en-US's uid list contains 103, the notificationCount equals 1, and 371 // LastNotificationTime > 0. 372 NotificationInfo info = mDataManager.getNotificationInfo(EN_US); 373 assertThat(info.getUidCollection()).contains(sUid); 374 assertThat(info.getNotificationCount()).isEqualTo(1); 375 assertThat(info.getDismissCount()).isEqualTo(0); 376 assertThat(info.getLastNotificationTimeMs()).isNotEqualTo(0); 377 assertThat(info.getNotificationId()).isEqualTo(notificationId); 378 379 mDataManager.clearLocaleNotificationMap(); 380 } 381 382 @Test 383 @RequiresFlagsEnabled(Flags.FLAG_LOCALE_NOTIFICATION_ENABLED) onLocaleSelected_evaluateNotification_2ndOddLocaleUpdate_uidAddedNoNotification()384 public void onLocaleSelected_evaluateNotification_2ndOddLocaleUpdate_uidAddedNoNotification() 385 throws Exception { 386 // App with uid 104 changed its locale from System to en-US. 387 sUid = 104; 388 initLocaleNotificationEnvironment(); 389 390 // Initialize the proto to include en-US locale. Its uid list includes 100,101,102,103 and 391 // the notification count equals 1. 392 int notificationId = (int) SystemClock.uptimeMillis(); 393 Set<Integer> uidSet = Set.of(100, 101, 102, 103); 394 initSharedPreference(EN_US, uidSet, 0, 1, Calendar.getInstance().getTimeInMillis(), 395 notificationId); 396 397 mActivity.onLocaleSelected(mLocaleInfo); 398 399 // Notification is not triggered because uid count % 2 != 0 400 // In the proto file, en-US's uid list contains uid4, the notificationCount equals 1, and 401 // LastNotificationTime > 0. 402 NotificationInfo info = mDataManager.getNotificationInfo(EN_US); 403 assertThat(info.getUidCollection()).contains(sUid); 404 assertThat(info.getNotificationCount()).isEqualTo(1); 405 assertThat(info.getDismissCount()).isEqualTo(0); 406 assertThat(info.getLastNotificationTimeMs()).isNotEqualTo(0); 407 408 mDataManager.clearLocaleNotificationMap(); 409 } 410 411 @Test 412 @RequiresFlagsEnabled(Flags.FLAG_LOCALE_NOTIFICATION_ENABLED) testEvaluateLocaleNotification_evenLocaleUpdate_trigger2ndNotification()413 public void testEvaluateLocaleNotification_evenLocaleUpdate_trigger2ndNotification() 414 throws Exception { 415 sUid = 105; 416 initLocaleNotificationEnvironment(); 417 418 // Initialize the proto to include en-US locale. Its uid list includes 100,101,102,103,104 419 // and the notification count equals 1. 420 // Eight days later, App with uid 105 changed its locale from System to en-US 421 int notificationId = (int) SystemClock.uptimeMillis(); 422 Set<Integer> uidSet = Set.of(100, 101, 102, 103, 104); 423 Calendar now = Calendar.getInstance(); 424 now.add(Calendar.DAY_OF_MONTH, -8); // Set the lastNotificationTime to eight days ago. 425 long lastNotificationTime = now.getTimeInMillis(); 426 initSharedPreference(EN_US, uidSet, 0, 1, lastNotificationTime, notificationId); 427 428 mActivity.onLocaleSelected(mLocaleInfo); 429 430 // Notification is triggered. 431 // In the proto file, en-US's uid list contains 105, the notificationCount equals 2, and 432 // LastNotificationTime is updated. 433 NotificationInfo info = mDataManager.getNotificationInfo(EN_US); 434 assertThat(info.getUidCollection()).contains(sUid); 435 assertThat(info.getNotificationCount()).isEqualTo(2); 436 assertThat(info.getDismissCount()).isEqualTo(0); 437 assertThat(info.getLastNotificationTimeMs()).isGreaterThan(lastNotificationTime); 438 439 mDataManager.clearLocaleNotificationMap(); 440 } 441 442 @Test 443 @RequiresFlagsEnabled(Flags.FLAG_LOCALE_NOTIFICATION_ENABLED) testEvaluateLocaleNotification_localeUpdateReachThreshold_noUidNorNotification()444 public void testEvaluateLocaleNotification_localeUpdateReachThreshold_noUidNorNotification() 445 throws Exception { 446 // App with uid 106 changed its locale from System to en-US. 447 sUid = 106; 448 initLocaleNotificationEnvironment(); 449 // Initialize the proto to include en-US locale. Its uid list includes 450 // 100,101,102,103,104,105 and the notification count equals 2. 451 int notificationId = (int) SystemClock.uptimeMillis(); 452 Set<Integer> uidSet = Set.of(100, 101, 102, 103, 104, 105); 453 Calendar now = Calendar.getInstance(); 454 now.add(Calendar.DAY_OF_MONTH, -8); 455 long lastNotificationTime = now.getTimeInMillis(); 456 initSharedPreference(EN_US, uidSet, 0, 2, lastNotificationTime, notificationId); 457 458 mActivity.onLocaleSelected(mLocaleInfo); 459 460 // Notification is not triggered because the notification count threshold, 2, is reached. 461 // In the proto file, en-US's uid list contains 106, the notificationCount equals 2, and 462 // LastNotificationTime > 0. 463 NotificationInfo info = mDataManager.getNotificationInfo(EN_US); 464 assertThat(info.getUidCollection().contains(sUid)).isFalse(); 465 assertThat(info.getNotificationCount()).isEqualTo(2); 466 assertThat(info.getDismissCount()).isEqualTo(0); 467 assertThat(info.getLastNotificationTimeMs()).isEqualTo(lastNotificationTime); 468 469 mDataManager.clearLocaleNotificationMap(); 470 } 471 472 @Test 473 @RequiresFlagsEnabled(Flags.FLAG_LOCALE_NOTIFICATION_ENABLED) testEvaluateLocaleNotification_appChangedLocales_newLocaleCreated()474 public void testEvaluateLocaleNotification_appChangedLocales_newLocaleCreated() 475 throws Exception { 476 sUid = 100; 477 initLocaleNotificationEnvironment(); 478 // App with uid 100 changed its locale from en-US to ja-JP. 479 Locale locale = Locale.forLanguageTag("ja-JP"); 480 when(mLocaleInfo.getLocale()).thenReturn(locale); 481 // Initialize the proto to include en-US locale. Its uid list includes 482 // 100,101,102,103,104,105,106 and the notification count equals 2. 483 int notificationId = (int) SystemClock.uptimeMillis(); 484 Set<Integer> uidSet = Set.of(100, 101, 102, 103, 104, 105, 106); 485 Calendar now = Calendar.getInstance(); 486 now.add(Calendar.DAY_OF_MONTH, -8); 487 initSharedPreference(EN_US, uidSet, 0, 2, now.getTimeInMillis(), 488 notificationId); 489 490 mActivity.onLocaleSelected(mLocaleInfo); 491 492 // Notification is not triggered 493 // In the proto file, a map for ja-JP is created. Its uid list contains uid1. 494 NotificationInfo info = mDataManager.getNotificationInfo("ja-JP"); 495 assertThat(info.getUidCollection()).contains(sUid); 496 assertThat(info.getNotificationCount()).isEqualTo(0); 497 assertThat(info.getDismissCount()).isEqualTo(0); 498 assertThat(info.getLastNotificationTimeMs()).isEqualTo(0); 499 500 mDataManager.clearLocaleNotificationMap(); 501 } 502 initLocaleNotificationEnvironment()503 private void initLocaleNotificationEnvironment() throws Exception { 504 LocaleList.setDefault(LocaleList.forLanguageTags(EN_CA)); 505 506 Locale locale = Locale.forLanguageTag("en-US"); 507 when(mLocaleInfo.getLocale()).thenReturn(locale); 508 when(mLocaleInfo.isSystemLocale()).thenReturn(false); 509 when(mLocaleInfo.isAppCurrentLocale()).thenReturn(false); 510 511 ActivityController<TestAppLocalePickerActivity> controller = initActivityController(true); 512 controller.create(); 513 mActivity = controller.get(); 514 mDataManager = NotificationController.getInstance(mActivity).getDataManager(); 515 } 516 initSharedPreference(String locale, Set<Integer> uidSet, int dismissCount, int notificationCount, long lastNotificationTime, int notificationId)517 private void initSharedPreference(String locale, Set<Integer> uidSet, int dismissCount, 518 int notificationCount, long lastNotificationTime, int notificationId) 519 throws Exception { 520 NotificationInfo info = new NotificationInfo(uidSet, notificationCount, dismissCount, 521 lastNotificationTime, notificationId); 522 mDataManager.putNotificationInfo(locale, info); 523 } 524 initActivityController( boolean hasPackageName)525 private ActivityController<TestAppLocalePickerActivity> initActivityController( 526 boolean hasPackageName) { 527 Intent data = new Intent(); 528 if (hasPackageName) { 529 data.setData(TEST_PACKAGE_URI); 530 } 531 data.putExtra(AppInfoBase.ARG_PACKAGE_UID, sUid); 532 ActivityController<TestAppLocalePickerActivity> activityController = 533 Robolectric.buildActivity(TestAppLocalePickerActivity.class, data); 534 Activity activity = activityController.get(); 535 536 ShadowTelephonyManager shadowTelephonyManager = Shadows.shadowOf( 537 activity.getSystemService(TelephonyManager.class)); 538 shadowTelephonyManager.setSimCountryIso("US"); 539 shadowTelephonyManager.setNetworkCountryIso("US"); 540 541 return activityController; 542 } 543 544 private static class TestAppLocalePickerActivity extends AppLocalePickerActivity { 545 @Override createContextAsUser(UserHandle user, int flags)546 public Context createContextAsUser(UserHandle user, int flags) { 547 // return the current context as a work profile 548 return this; 549 } 550 } 551 552 @Implements(ApplicationPackageManager.class) 553 public static class ShadowApplicationPackageManager extends 554 org.robolectric.shadows.ShadowApplicationPackageManager { 555 private static boolean sNoLaunchEntry = false; 556 557 @Implementation getInstallSourceInfo(String packageName)558 protected Object getInstallSourceInfo(String packageName) { 559 return new InstallSourceInfo("", null, null, ""); 560 } 561 562 @Implementation queryIntentActivities(Intent intent, int flags)563 protected List<ResolveInfo> queryIntentActivities(Intent intent, int flags) { 564 if (sNoLaunchEntry) { 565 return new ArrayList(); 566 } else { 567 return super.queryIntentActivities(intent, flags); 568 } 569 } 570 setNoLaunchEntry(boolean noLaunchEntry)571 private static void setNoLaunchEntry(boolean noLaunchEntry) { 572 sNoLaunchEntry = noLaunchEntry; 573 } 574 575 @Implementation getApplicationInfo(String packageName, int flags)576 protected ApplicationInfo getApplicationInfo(String packageName, int flags) 577 throws NameNotFoundException { 578 if (packageName.equals(TEST_PACKAGE_NAME)) { 579 ApplicationInfo applicationInfo = new ApplicationInfo(); 580 applicationInfo.packageName = TEST_PACKAGE_NAME; 581 applicationInfo.uid = sUid; 582 return applicationInfo; 583 } else { 584 return super.getApplicationInfo(packageName, flags); 585 } 586 } 587 } 588 589 @Implements(Resources.class) 590 public static class ShadowResources extends 591 org.robolectric.shadows.ShadowResources { 592 private static boolean sDisAllowPackage = false; 593 594 @Implementation getStringArray(@rrayRes int id)595 public String[] getStringArray(@ArrayRes int id) { 596 if (sDisAllowPackage) { 597 return new String[]{TEST_PACKAGE_NAME}; 598 } else { 599 return new String[0]; 600 } 601 } 602 setDisAllowPackage(boolean disAllowPackage)603 private static void setDisAllowPackage(boolean disAllowPackage) { 604 sDisAllowPackage = disAllowPackage; 605 } 606 } 607 } 608