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.systemui.shade.carrier; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.junit.Assert.assertEquals; 22 import static org.junit.Assert.assertFalse; 23 import static org.mockito.ArgumentMatchers.any; 24 import static org.mockito.ArgumentMatchers.anyBoolean; 25 import static org.mockito.ArgumentMatchers.anyInt; 26 import static org.mockito.ArgumentMatchers.anyString; 27 import static org.mockito.ArgumentMatchers.eq; 28 import static org.mockito.Mockito.doAnswer; 29 import static org.mockito.Mockito.mock; 30 import static org.mockito.Mockito.never; 31 import static org.mockito.Mockito.reset; 32 import static org.mockito.Mockito.times; 33 import static org.mockito.Mockito.verify; 34 import static org.mockito.Mockito.verifyZeroInteractions; 35 import static org.mockito.Mockito.when; 36 37 import android.content.Context; 38 import android.content.Intent; 39 import android.os.Handler; 40 import android.provider.Settings; 41 import android.testing.AndroidTestingRunner; 42 import android.testing.TestableLooper; 43 import android.view.View; 44 import android.widget.TextView; 45 46 import androidx.test.filters.SmallTest; 47 48 import com.android.keyguard.CarrierTextManager; 49 import com.android.systemui.log.core.FakeLogBuffer; 50 import com.android.systemui.plugins.ActivityStarter; 51 import com.android.systemui.statusbar.connectivity.IconState; 52 import com.android.systemui.statusbar.connectivity.MobileDataIndicators; 53 import com.android.systemui.statusbar.connectivity.NetworkController; 54 import com.android.systemui.statusbar.connectivity.SignalCallback; 55 import com.android.systemui.statusbar.connectivity.ui.MobileContextProvider; 56 import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags; 57 import com.android.systemui.statusbar.pipeline.mobile.ui.MobileUiAdapter; 58 import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger; 59 import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel; 60 import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.ShadeCarrierGroupMobileIconViewModel; 61 import com.android.systemui.util.CarrierConfigTracker; 62 import com.android.systemui.util.kotlin.FlowProviderKt; 63 import com.android.systemui.utils.leaks.LeakCheckedTest; 64 import com.android.systemui.utils.os.FakeHandler; 65 66 import kotlinx.coroutines.flow.MutableStateFlow; 67 68 import org.junit.Before; 69 import org.junit.Test; 70 import org.junit.runner.RunWith; 71 import org.mockito.ArgumentCaptor; 72 import org.mockito.Mock; 73 import org.mockito.MockitoAnnotations; 74 75 import java.util.ArrayList; 76 import java.util.Arrays; 77 import java.util.List; 78 79 @RunWith(AndroidTestingRunner.class) 80 @TestableLooper.RunWithLooper 81 @SmallTest 82 public class ShadeCarrierGroupControllerTest extends LeakCheckedTest { 83 84 private static final String SINGLE_CARRIER_TEXT = "singleCarrierText"; 85 private static final String MULTI_CARRIER_TEXT = "multiCarrierText"; 86 private static final String FIRST_CARRIER_NAME = "carrier1"; 87 private static final String SECOND_CARRIER_NAME = "carrier2"; 88 89 private ShadeCarrierGroupController mShadeCarrierGroupController; 90 private SignalCallback mSignalCallback; 91 private CarrierTextManager.CarrierTextCallback mCallback; 92 @Mock 93 private ShadeCarrierGroup mShadeCarrierGroup; 94 @Mock 95 private ActivityStarter mActivityStarter; 96 @Mock 97 private NetworkController mNetworkController; 98 @Mock 99 private CarrierTextManager.Builder mCarrierTextControllerBuilder; 100 @Mock 101 private CarrierTextManager mCarrierTextManager; 102 @Mock 103 private CarrierConfigTracker mCarrierConfigTracker; 104 @Mock 105 private ShadeCarrier mShadeCarrier1; 106 @Mock 107 private ShadeCarrier mShadeCarrier2; 108 @Mock 109 private ShadeCarrier mShadeCarrier3; 110 private TestableLooper mTestableLooper; 111 @Mock 112 private ShadeCarrierGroupController.OnSingleCarrierChangedListener 113 mOnSingleCarrierChangedListener; 114 @Mock 115 private MobileUiAdapter mMobileUiAdapter; 116 @Mock 117 private MobileIconsViewModel mMobileIconsViewModel; 118 @Mock 119 private ShadeCarrierGroupMobileIconViewModel mShadeCarrierGroupMobileIconViewModel; 120 @Mock 121 private MobileViewLogger mMobileViewLogger; 122 @Mock 123 private MobileContextProvider mMobileContextProvider; 124 @Mock 125 private StatusBarPipelineFlags mStatusBarPipelineFlags; 126 127 private final MutableStateFlow<Boolean> mIsVisibleFlow = 128 FlowProviderKt.getMutableStateFlow(true); 129 130 private FakeSlotIndexResolver mSlotIndexResolver; 131 private ClickListenerTextView mNoCarrierTextView; 132 133 @Before setup()134 public void setup() throws Exception { 135 MockitoAnnotations.initMocks(this); 136 injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES); 137 mTestableLooper = TestableLooper.get(this); 138 Handler handler = new FakeHandler(TestableLooper.get(this).getLooper()); 139 140 when(mNetworkController.hasVoiceCallingFeature()).thenReturn(true); 141 doAnswer(invocation -> mSignalCallback = invocation.getArgument(0)) 142 .when(mNetworkController) 143 .addCallback(any(SignalCallback.class)); 144 145 when(mCarrierTextControllerBuilder.setShowAirplaneMode(anyBoolean())) 146 .thenReturn(mCarrierTextControllerBuilder); 147 when(mCarrierTextControllerBuilder.setShowMissingSim(anyBoolean())) 148 .thenReturn(mCarrierTextControllerBuilder); 149 when(mCarrierTextControllerBuilder.setDebugLocationString(anyString())) 150 .thenReturn(mCarrierTextControllerBuilder); 151 when(mCarrierTextControllerBuilder.build()).thenReturn(mCarrierTextManager); 152 153 doAnswer(invocation -> mCallback = invocation.getArgument(0)) 154 .when(mCarrierTextManager) 155 .setListening(any(CarrierTextManager.CarrierTextCallback.class)); 156 157 mNoCarrierTextView = new ClickListenerTextView(mContext); 158 when(mShadeCarrierGroup.getNoSimTextView()).thenReturn(mNoCarrierTextView); 159 when(mShadeCarrierGroup.getCarrier1View()).thenReturn(mShadeCarrier1); 160 when(mShadeCarrierGroup.getCarrier2View()).thenReturn(mShadeCarrier2); 161 when(mShadeCarrierGroup.getCarrier3View()).thenReturn(mShadeCarrier3); 162 when(mShadeCarrierGroup.getCarrierDivider1()).thenReturn(new View(mContext)); 163 when(mShadeCarrierGroup.getCarrierDivider2()).thenReturn(new View(mContext)); 164 165 mSlotIndexResolver = new FakeSlotIndexResolver(); 166 167 when(mMobileUiAdapter.getMobileIconsViewModel()).thenReturn(mMobileIconsViewModel); 168 169 mShadeCarrierGroupController = new ShadeCarrierGroupController.Builder( 170 mActivityStarter, 171 handler, 172 TestableLooper.get(this).getLooper(), 173 new ShadeCarrierGroupControllerLogger(FakeLogBuffer.Factory.Companion.create()), 174 mNetworkController, 175 mCarrierTextControllerBuilder, 176 mContext, 177 mCarrierConfigTracker, 178 mSlotIndexResolver, 179 mMobileUiAdapter, 180 mMobileContextProvider, 181 mStatusBarPipelineFlags 182 ) 183 .setShadeCarrierGroup(mShadeCarrierGroup) 184 .build(); 185 186 mShadeCarrierGroupController.setListening(true); 187 } 188 setupWithNewPipeline()189 private void setupWithNewPipeline() { 190 when(mStatusBarPipelineFlags.useNewShadeCarrierGroupMobileIcons()).thenReturn(true); 191 when(mMobileContextProvider.getMobileContextForSub(anyInt(), any())).thenReturn(mContext); 192 when(mMobileIconsViewModel.getLogger()).thenReturn(mMobileViewLogger); 193 when(mShadeCarrierGroupMobileIconViewModel.isVisible()).thenReturn(mIsVisibleFlow); 194 when(mMobileIconsViewModel.viewModelForSub(anyInt(), any())) 195 .thenReturn(mShadeCarrierGroupMobileIconViewModel); 196 } 197 198 @Test testInitiallyMultiCarrier()199 public void testInitiallyMultiCarrier() { 200 assertFalse(mShadeCarrierGroupController.isSingleCarrier()); 201 } 202 203 @Test // throws no Exception testUpdateCarrierText_sameLengths()204 public void testUpdateCarrierText_sameLengths() { 205 // listOfCarriers length 1, subscriptionIds length 1, anySims false 206 CarrierTextManager.CarrierTextCallbackInfo 207 c1 = new CarrierTextManager.CarrierTextCallbackInfo( 208 SINGLE_CARRIER_TEXT, 209 new CharSequence[]{FIRST_CARRIER_NAME}, 210 false, 211 new int[]{0}); 212 mCallback.updateCarrierInfo(c1); 213 214 // listOfCarriers length 1, subscriptionIds length 1, anySims true 215 CarrierTextManager.CarrierTextCallbackInfo 216 c2 = new CarrierTextManager.CarrierTextCallbackInfo( 217 SINGLE_CARRIER_TEXT, 218 new CharSequence[]{FIRST_CARRIER_NAME}, 219 true, 220 new int[]{0}); 221 mCallback.updateCarrierInfo(c2); 222 223 // listOfCarriers length 2, subscriptionIds length 2, anySims false 224 CarrierTextManager.CarrierTextCallbackInfo 225 c3 = new CarrierTextManager.CarrierTextCallbackInfo( 226 MULTI_CARRIER_TEXT, 227 new CharSequence[]{FIRST_CARRIER_NAME, SECOND_CARRIER_NAME}, 228 false, 229 new int[]{0, 1}); 230 mCallback.updateCarrierInfo(c3); 231 232 // listOfCarriers length 2, subscriptionIds length 2, anySims true 233 CarrierTextManager.CarrierTextCallbackInfo 234 c4 = new CarrierTextManager.CarrierTextCallbackInfo( 235 MULTI_CARRIER_TEXT, 236 new CharSequence[]{FIRST_CARRIER_NAME, SECOND_CARRIER_NAME}, 237 true, 238 new int[]{0, 1}); 239 mCallback.updateCarrierInfo(c4); 240 241 mTestableLooper.processAllMessages(); 242 } 243 244 @Test // throws no Exception testUpdateCarrierText_differentLength()245 public void testUpdateCarrierText_differentLength() { 246 // listOfCarriers length 2, subscriptionIds length 1, anySims false 247 CarrierTextManager.CarrierTextCallbackInfo 248 c1 = new CarrierTextManager.CarrierTextCallbackInfo( 249 MULTI_CARRIER_TEXT, 250 new CharSequence[]{FIRST_CARRIER_NAME, SECOND_CARRIER_NAME}, 251 false, 252 new int[]{0}); 253 mCallback.updateCarrierInfo(c1); 254 255 // listOfCarriers length 2, subscriptionIds length 1, anySims true 256 CarrierTextManager.CarrierTextCallbackInfo 257 c2 = new CarrierTextManager.CarrierTextCallbackInfo( 258 MULTI_CARRIER_TEXT, 259 new CharSequence[]{FIRST_CARRIER_NAME, SECOND_CARRIER_NAME}, 260 true, 261 new int[]{0}); 262 mCallback.updateCarrierInfo(c2); 263 264 // listOfCarriers length 1, subscriptionIds length 2, anySims false 265 CarrierTextManager.CarrierTextCallbackInfo 266 c3 = new CarrierTextManager.CarrierTextCallbackInfo( 267 SINGLE_CARRIER_TEXT, 268 new CharSequence[]{FIRST_CARRIER_NAME}, 269 false, 270 new int[]{0, 1}); 271 mCallback.updateCarrierInfo(c3); 272 273 // listOfCarriers length 1, subscriptionIds length 2, anySims true 274 CarrierTextManager.CarrierTextCallbackInfo 275 c4 = new CarrierTextManager.CarrierTextCallbackInfo( 276 SINGLE_CARRIER_TEXT, 277 new CharSequence[]{FIRST_CARRIER_NAME}, 278 true, 279 new int[]{0, 1}); 280 mCallback.updateCarrierInfo(c4); 281 mTestableLooper.processAllMessages(); 282 } 283 284 @Test // throws no Exception testUpdateCarrierText_invalidSim()285 public void testUpdateCarrierText_invalidSim() { 286 mSlotIndexResolver.overrideInvalid = true; 287 288 CarrierTextManager.CarrierTextCallbackInfo 289 c4 = new CarrierTextManager.CarrierTextCallbackInfo( 290 MULTI_CARRIER_TEXT, 291 new CharSequence[]{FIRST_CARRIER_NAME, SECOND_CARRIER_NAME}, 292 true, 293 new int[]{0, 1}); 294 mCallback.updateCarrierInfo(c4); 295 mTestableLooper.processAllMessages(); 296 } 297 298 @Test // throws no Exception testSetMobileDataIndicators_invalidSim()299 public void testSetMobileDataIndicators_invalidSim() { 300 mSlotIndexResolver.overrideInvalid = true; 301 302 MobileDataIndicators indicators = new MobileDataIndicators( 303 mock(IconState.class), 304 mock(IconState.class), 305 0, 0, true, true, "", "", "", 0, true, true); 306 mSignalCallback.setMobileDataIndicators(indicators); 307 } 308 309 @Test testNoEmptyVisibleView_airplaneMode()310 public void testNoEmptyVisibleView_airplaneMode() { 311 CarrierTextManager.CarrierTextCallbackInfo 312 info = new CarrierTextManager.CarrierTextCallbackInfo( 313 "", 314 new CharSequence[]{""}, 315 /* anySimReady= */ true, 316 /* isInSatelliteMode= */ false, 317 new int[]{0}, 318 /* airplaneMode= */ true); 319 mCallback.updateCarrierInfo(info); 320 mTestableLooper.processAllMessages(); 321 assertEquals(View.GONE, mShadeCarrierGroup.getNoSimTextView().getVisibility()); 322 } 323 324 @Test testVisibleView_airplaneMode_WFCOn()325 public void testVisibleView_airplaneMode_WFCOn() { 326 CarrierTextManager.CarrierTextCallbackInfo 327 info = new CarrierTextManager.CarrierTextCallbackInfo( 328 "", 329 new CharSequence[]{FIRST_CARRIER_NAME, ""}, 330 /* anySimReady= */ true, 331 /* isInSatelliteMode= */ false, 332 new int[]{0, 1}, 333 /* airplaneMode= */ false); 334 mCallback.updateCarrierInfo(info); 335 mTestableLooper.processAllMessages(); 336 assertEquals(View.VISIBLE, mShadeCarrierGroupController.getShadeCarrierVisibility(0)); 337 } 338 339 @Test isInSatelliteMode_true_noSimViewShownWithText()340 public void isInSatelliteMode_true_noSimViewShownWithText() { 341 CarrierTextManager.CarrierTextCallbackInfo 342 info = new CarrierTextManager.CarrierTextCallbackInfo( 343 "Satellite Mode Test", 344 new CharSequence[]{FIRST_CARRIER_NAME}, 345 /* anySimReady= */ true, 346 /* isInSatelliteMode= */ true, 347 new int[]{1}, 348 /* airplaneMode= */ false); 349 350 mCallback.updateCarrierInfo(info); 351 mTestableLooper.processAllMessages(); 352 353 assertThat(mShadeCarrierGroup.getNoSimTextView().getVisibility()).isEqualTo(View.VISIBLE); 354 assertThat(mShadeCarrierGroup.getNoSimTextView().getText()).isEqualTo( 355 "Satellite Mode Test"); 356 357 verify(mShadeCarrier1).setVisibility(View.GONE); 358 verify(mShadeCarrier2).setVisibility(View.GONE); 359 verify(mShadeCarrier3).setVisibility(View.GONE); 360 } 361 362 @Test isInSatelliteMode_false_normalSimViewsShown()363 public void isInSatelliteMode_false_normalSimViewsShown() { 364 CarrierTextManager.CarrierTextCallbackInfo 365 info = new CarrierTextManager.CarrierTextCallbackInfo( 366 "Satellite Mode Test", 367 new CharSequence[]{FIRST_CARRIER_NAME, SECOND_CARRIER_NAME}, 368 /* anySimReady= */ true, 369 /* isInSatelliteMode= */ false, 370 new int[]{0, 1}, 371 /* airplaneMode= */ false); 372 373 mCallback.updateCarrierInfo(info); 374 mTestableLooper.processAllMessages(); 375 376 assertThat(mShadeCarrierGroup.getNoSimTextView().getVisibility()).isEqualTo(View.GONE); 377 378 verify(mShadeCarrier1).setVisibility(View.VISIBLE); 379 verify(mShadeCarrier2).setVisibility(View.VISIBLE); 380 } 381 382 @Test testListenerNotCalledOnRegistreation()383 public void testListenerNotCalledOnRegistreation() { 384 mShadeCarrierGroupController 385 .setOnSingleCarrierChangedListener(mOnSingleCarrierChangedListener); 386 387 verify(mOnSingleCarrierChangedListener, never()).onSingleCarrierChanged(anyBoolean()); 388 } 389 390 @Test testSingleCarrier()391 public void testSingleCarrier() { 392 // Only one element in the info 393 CarrierTextManager.CarrierTextCallbackInfo 394 info = new CarrierTextManager.CarrierTextCallbackInfo( 395 SINGLE_CARRIER_TEXT, 396 new CharSequence[]{SINGLE_CARRIER_TEXT}, 397 true, 398 new int[]{0}); 399 400 mCallback.updateCarrierInfo(info); 401 mTestableLooper.processAllMessages(); 402 403 verify(mShadeCarrier1).updateState(any(), eq(true)); 404 verify(mShadeCarrier2).updateState(any(), eq(true)); 405 verify(mShadeCarrier3).updateState(any(), eq(true)); 406 } 407 408 @Test testMultiCarrier()409 public void testMultiCarrier() { 410 // More than one element in the info 411 CarrierTextManager.CarrierTextCallbackInfo 412 info = new CarrierTextManager.CarrierTextCallbackInfo( 413 MULTI_CARRIER_TEXT, 414 new CharSequence[]{FIRST_CARRIER_NAME, SECOND_CARRIER_NAME}, 415 true, 416 new int[]{0, 1}); 417 418 mCallback.updateCarrierInfo(info); 419 mTestableLooper.processAllMessages(); 420 421 verify(mShadeCarrier1).updateState(any(), eq(false)); 422 verify(mShadeCarrier2).updateState(any(), eq(false)); 423 verify(mShadeCarrier3).updateState(any(), eq(false)); 424 } 425 426 @Test testSingleMultiCarrierSwitch()427 public void testSingleMultiCarrierSwitch() { 428 CarrierTextManager.CarrierTextCallbackInfo 429 singleCarrierInfo = new CarrierTextManager.CarrierTextCallbackInfo( 430 SINGLE_CARRIER_TEXT, 431 new CharSequence[]{FIRST_CARRIER_NAME}, 432 true, 433 new int[]{0}); 434 435 CarrierTextManager.CarrierTextCallbackInfo 436 multiCarrierInfo = new CarrierTextManager.CarrierTextCallbackInfo( 437 MULTI_CARRIER_TEXT, 438 new CharSequence[]{FIRST_CARRIER_NAME, SECOND_CARRIER_NAME}, 439 true, 440 new int[]{0, 1}); 441 442 mCallback.updateCarrierInfo(singleCarrierInfo); 443 mTestableLooper.processAllMessages(); 444 445 mShadeCarrierGroupController 446 .setOnSingleCarrierChangedListener(mOnSingleCarrierChangedListener); 447 reset(mOnSingleCarrierChangedListener); 448 449 mCallback.updateCarrierInfo(multiCarrierInfo); 450 mTestableLooper.processAllMessages(); 451 verify(mOnSingleCarrierChangedListener).onSingleCarrierChanged(false); 452 453 mCallback.updateCarrierInfo(singleCarrierInfo); 454 mTestableLooper.processAllMessages(); 455 verify(mOnSingleCarrierChangedListener).onSingleCarrierChanged(true); 456 } 457 458 @Test testNoCallbackIfSingleCarrierDoesntChange()459 public void testNoCallbackIfSingleCarrierDoesntChange() { 460 CarrierTextManager.CarrierTextCallbackInfo 461 singleCarrierInfo = new CarrierTextManager.CarrierTextCallbackInfo( 462 SINGLE_CARRIER_TEXT, 463 new CharSequence[]{FIRST_CARRIER_NAME}, 464 true, 465 new int[]{0}); 466 467 mCallback.updateCarrierInfo(singleCarrierInfo); 468 mTestableLooper.processAllMessages(); 469 470 mShadeCarrierGroupController 471 .setOnSingleCarrierChangedListener(mOnSingleCarrierChangedListener); 472 473 mCallback.updateCarrierInfo(singleCarrierInfo); 474 mTestableLooper.processAllMessages(); 475 476 verify(mOnSingleCarrierChangedListener, never()).onSingleCarrierChanged(anyBoolean()); 477 } 478 479 @Test testNoCallbackIfMultiCarrierDoesntChange()480 public void testNoCallbackIfMultiCarrierDoesntChange() { 481 CarrierTextManager.CarrierTextCallbackInfo 482 multiCarrierInfo = new CarrierTextManager.CarrierTextCallbackInfo( 483 MULTI_CARRIER_TEXT, 484 new CharSequence[]{FIRST_CARRIER_NAME, SECOND_CARRIER_NAME}, 485 true, 486 new int[]{0, 1}); 487 488 mCallback.updateCarrierInfo(multiCarrierInfo); 489 mTestableLooper.processAllMessages(); 490 491 mShadeCarrierGroupController 492 .setOnSingleCarrierChangedListener(mOnSingleCarrierChangedListener); 493 494 mCallback.updateCarrierInfo(multiCarrierInfo); 495 mTestableLooper.processAllMessages(); 496 497 verify(mOnSingleCarrierChangedListener, never()).onSingleCarrierChanged(anyBoolean()); 498 } 499 500 @TestableLooper.RunWithLooper(setAsMainLooper = true) 501 @Test testUpdateModernMobileIcons_addSubscription()502 public void testUpdateModernMobileIcons_addSubscription() { 503 setupWithNewPipeline(); 504 505 mShadeCarrier1.setVisibility(View.GONE); 506 mShadeCarrier2.setVisibility(View.GONE); 507 mShadeCarrier3.setVisibility(View.GONE); 508 509 List<Integer> subIds = new ArrayList<>(); 510 subIds.add(0); 511 mShadeCarrierGroupController.updateModernMobileIcons(subIds); 512 513 verify(mShadeCarrier1).addModernMobileView(any()); 514 verify(mShadeCarrier2, never()).addModernMobileView(any()); 515 verify(mShadeCarrier3, never()).addModernMobileView(any()); 516 517 resetShadeCarriers(); 518 519 subIds.add(1); 520 mShadeCarrierGroupController.updateModernMobileIcons(subIds); 521 522 verify(mShadeCarrier1, times(1)).removeModernMobileView(); 523 524 verify(mShadeCarrier1).addModernMobileView(any()); 525 verify(mShadeCarrier2).addModernMobileView(any()); 526 verify(mShadeCarrier3, never()).addModernMobileView(any()); 527 } 528 529 @TestableLooper.RunWithLooper(setAsMainLooper = true) 530 @Test testUpdateModernMobileIcons_removeSubscription()531 public void testUpdateModernMobileIcons_removeSubscription() { 532 setupWithNewPipeline(); 533 534 List<Integer> subIds = new ArrayList<>(); 535 subIds.add(0); 536 subIds.add(1); 537 mShadeCarrierGroupController.updateModernMobileIcons(subIds); 538 539 verify(mShadeCarrier1).addModernMobileView(any()); 540 verify(mShadeCarrier2).addModernMobileView(any()); 541 verify(mShadeCarrier3, never()).addModernMobileView(any()); 542 543 resetShadeCarriers(); 544 545 subIds.remove(1); 546 mShadeCarrierGroupController.updateModernMobileIcons(subIds); 547 548 verify(mShadeCarrier1, times(1)).removeModernMobileView(); 549 verify(mShadeCarrier2, times(1)).removeModernMobileView(); 550 551 verify(mShadeCarrier1).addModernMobileView(any()); 552 verify(mShadeCarrier2, never()).addModernMobileView(any()); 553 verify(mShadeCarrier3, never()).addModernMobileView(any()); 554 } 555 556 @TestableLooper.RunWithLooper(setAsMainLooper = true) 557 @Test testUpdateModernMobileIcons_removeSubscriptionOutOfOrder()558 public void testUpdateModernMobileIcons_removeSubscriptionOutOfOrder() { 559 setupWithNewPipeline(); 560 561 List<Integer> subIds = new ArrayList<>(); 562 subIds.add(0); 563 subIds.add(1); 564 subIds.add(2); 565 mShadeCarrierGroupController.updateModernMobileIcons(subIds); 566 567 verify(mShadeCarrier1).addModernMobileView(any()); 568 verify(mShadeCarrier2).addModernMobileView(any()); 569 verify(mShadeCarrier3).addModernMobileView(any()); 570 571 resetShadeCarriers(); 572 573 subIds.remove(1); 574 mShadeCarrierGroupController.updateModernMobileIcons(subIds); 575 576 verify(mShadeCarrier1).removeModernMobileView(); 577 verify(mShadeCarrier2).removeModernMobileView(); 578 verify(mShadeCarrier3).removeModernMobileView(); 579 580 verify(mShadeCarrier1).addModernMobileView(any()); 581 verify(mShadeCarrier2, never()).addModernMobileView(any()); 582 verify(mShadeCarrier3).addModernMobileView(any()); 583 } 584 585 @TestableLooper.RunWithLooper(setAsMainLooper = true) 586 @Test testProcessSubIdList_moreSubsThanSimSlots_listLimitedToMax()587 public void testProcessSubIdList_moreSubsThanSimSlots_listLimitedToMax() { 588 setupWithNewPipeline(); 589 590 List<Integer> subIds = Arrays.asList(0, 1, 2, 2); 591 592 assertThat(mShadeCarrierGroupController.processSubIdList(subIds).size()).isEqualTo(3); 593 } 594 595 @TestableLooper.RunWithLooper(setAsMainLooper = true) 596 @Test testProcessSubIdList_invalidSimSlotIndexFilteredOut()597 public void testProcessSubIdList_invalidSimSlotIndexFilteredOut() { 598 setupWithNewPipeline(); 599 600 List<Integer> subIds = Arrays.asList(0, 1, -1); 601 602 List<ShadeCarrierGroupController.IconData> processedSubs = 603 mShadeCarrierGroupController.processSubIdList(subIds); 604 assertThat(processedSubs).hasSize(2); 605 assertThat(processedSubs.get(0).subId).isNotEqualTo(-1); 606 assertThat(processedSubs.get(1).subId).isNotEqualTo(-1); 607 } 608 609 @TestableLooper.RunWithLooper(setAsMainLooper = true) 610 @Test testProcessSubIdList_indexGreaterThanSimSlotsFilteredOut()611 public void testProcessSubIdList_indexGreaterThanSimSlotsFilteredOut() { 612 setupWithNewPipeline(); 613 614 List<Integer> subIds = Arrays.asList(0, 4); 615 616 List<ShadeCarrierGroupController.IconData> processedSubs = 617 mShadeCarrierGroupController.processSubIdList(subIds); 618 assertThat(processedSubs).hasSize(1); 619 assertThat(processedSubs.get(0).subId).isNotEqualTo(4); 620 } 621 622 623 @Test testOnlyInternalViewsHaveClickableListener()624 public void testOnlyInternalViewsHaveClickableListener() { 625 ArgumentCaptor<View.OnClickListener> captor = 626 ArgumentCaptor.forClass(View.OnClickListener.class); 627 628 verify(mShadeCarrier1).setOnClickListener(captor.capture()); 629 verify(mShadeCarrier2).setOnClickListener(captor.getValue()); 630 verify(mShadeCarrier3).setOnClickListener(captor.getValue()); 631 632 assertThat(mNoCarrierTextView.getOnClickListener()).isSameInstanceAs(captor.getValue()); 633 verify(mShadeCarrierGroup, never()).setOnClickListener(any()); 634 } 635 636 @Test testOnClickListenerDoesntStartActivityIfViewNotVisible()637 public void testOnClickListenerDoesntStartActivityIfViewNotVisible() { 638 ArgumentCaptor<View.OnClickListener> captor = 639 ArgumentCaptor.forClass(View.OnClickListener.class); 640 641 verify(mShadeCarrier1).setOnClickListener(captor.capture()); 642 when(mShadeCarrier1.isVisibleToUser()).thenReturn(false); 643 644 captor.getValue().onClick(mShadeCarrier1); 645 verifyZeroInteractions(mActivityStarter); 646 } 647 648 @Test testOnClickListenerLaunchesActivityIfViewVisible()649 public void testOnClickListenerLaunchesActivityIfViewVisible() { 650 ArgumentCaptor<View.OnClickListener> listenerCaptor = 651 ArgumentCaptor.forClass(View.OnClickListener.class); 652 ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); 653 654 verify(mShadeCarrier1).setOnClickListener(listenerCaptor.capture()); 655 when(mShadeCarrier1.isVisibleToUser()).thenReturn(true); 656 657 listenerCaptor.getValue().onClick(mShadeCarrier1); 658 verify(mActivityStarter) 659 .postStartActivityDismissingKeyguard(intentCaptor.capture(), anyInt()); 660 assertThat(intentCaptor.getValue().getAction()) 661 .isEqualTo(Settings.ACTION_WIRELESS_SETTINGS); 662 } 663 resetShadeCarriers()664 private void resetShadeCarriers() { 665 reset(mShadeCarrier1); 666 reset(mShadeCarrier2); 667 reset(mShadeCarrier3); 668 } 669 670 private class FakeSlotIndexResolver implements ShadeCarrierGroupController.SlotIndexResolver { 671 public boolean overrideInvalid; 672 673 @Override getSlotIndex(int subscriptionId)674 public int getSlotIndex(int subscriptionId) { 675 return overrideInvalid ? -1 : subscriptionId; 676 } 677 } 678 679 private class ClickListenerTextView extends TextView { 680 View.OnClickListener mListener = null; 681 ClickListenerTextView(Context context)682 ClickListenerTextView(Context context) { 683 super(context); 684 } 685 686 @Override setOnClickListener(OnClickListener l)687 public void setOnClickListener(OnClickListener l) { 688 super.setOnClickListener(l); 689 mListener = l; 690 } 691 getOnClickListener()692 View.OnClickListener getOnClickListener() { 693 return mListener; 694 } 695 } 696 } 697