1 /*
2  * Copyright (C) 2021 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.phone;
18 
19 import static android.telephony.ims.ImsStateCallback.REASON_IMS_SERVICE_DISCONNECTED;
20 import static android.telephony.ims.ImsStateCallback.REASON_IMS_SERVICE_NOT_READY;
21 import static android.telephony.ims.ImsStateCallback.REASON_NO_IMS_SERVICE_CONFIGURED;
22 import static android.telephony.ims.ImsStateCallback.REASON_SUBSCRIPTION_INACTIVE;
23 import static android.telephony.ims.feature.ImsFeature.FEATURE_MMTEL;
24 import static android.telephony.ims.feature.ImsFeature.FEATURE_RCS;
25 
26 import static com.android.ims.FeatureConnector.UNAVAILABLE_REASON_DISCONNECTED;
27 import static com.android.ims.FeatureConnector.UNAVAILABLE_REASON_IMS_UNSUPPORTED;
28 import static com.android.ims.FeatureConnector.UNAVAILABLE_REASON_NOT_READY;
29 
30 import static junit.framework.Assert.assertFalse;
31 import static junit.framework.Assert.assertNotNull;
32 import static junit.framework.Assert.assertNull;
33 import static junit.framework.Assert.assertTrue;
34 
35 import static org.mockito.Matchers.any;
36 import static org.mockito.Matchers.anyInt;
37 import static org.mockito.Matchers.eq;
38 import static org.mockito.Mockito.atLeastOnce;
39 import static org.mockito.Mockito.doAnswer;
40 import static org.mockito.Mockito.times;
41 import static org.mockito.Mockito.verify;
42 import static org.mockito.Mockito.when;
43 
44 import android.content.Context;
45 import android.os.Handler;
46 import android.os.HandlerThread;
47 import android.os.IBinder;
48 import android.os.Looper;
49 import android.telephony.SubscriptionManager;
50 import android.telephony.TelephonyRegistryManager;
51 import android.testing.TestableLooper;
52 import android.util.Log;
53 
54 import androidx.test.filters.SmallTest;
55 
56 import com.android.TelephonyTestBase;
57 import com.android.ims.FeatureConnector;
58 import com.android.ims.ImsManager;
59 import com.android.ims.RcsFeatureManager;
60 import com.android.internal.telephony.IImsStateCallback;
61 import com.android.internal.telephony.ITelephony;
62 import com.android.internal.telephony.Phone;
63 import com.android.internal.telephony.ims.ImsResolver;
64 
65 import org.junit.After;
66 import org.junit.Before;
67 import org.junit.Test;
68 import org.mockito.ArgumentCaptor;
69 import org.mockito.Captor;
70 import org.mockito.Mock;
71 import org.mockito.MockitoAnnotations;
72 import org.mockito.invocation.InvocationOnMock;
73 import org.mockito.stubbing.Answer;
74 
75 import java.util.concurrent.Executor;
76 
77 /**
78  * Unit tests for RcsProvisioningMonitor
79  */
80 public class ImsStateCallbackControllerTest extends TelephonyTestBase {
81     private static final String TAG = "ImsStateCallbackControllerTest";
82     private static final int FAKE_SUB_ID_BASE = 0x0FFFFFF0;
83 
84     private static final int SLOT_0 = 0;
85     private static final int SLOT_1 = 1;
86 
87     private static final int SLOT_0_SUB_ID = 1;
88     private static final int SLOT_1_SUB_ID = 2;
89     private static final int SLOT_2_SUB_ID = 3;
90 
91     private ImsStateCallbackController mImsStateCallbackController;
92     private Handler mHandler;
93     private HandlerThread mHandlerThread;
94     private TestableLooper mLooper;
95     @Mock private SubscriptionManager mSubscriptionManager;
96     private SubscriptionManager.OnSubscriptionsChangedListener mSubChangedListener;
97     @Mock private TelephonyRegistryManager mTelephonyRegistryManager;
98     @Mock private ITelephony.Stub mITelephony;
99     @Mock private RcsFeatureManager mRcsFeatureManager;
100     @Mock private ImsManager mMmTelFeatureManager;
101     @Mock private ImsStateCallbackController.MmTelFeatureConnectorFactory mMmTelFeatureFactory;
102     @Mock private ImsStateCallbackController.RcsFeatureConnectorFactory mRcsFeatureFactory;
103     @Mock private FeatureConnector<ImsManager> mMmTelFeatureConnectorSlot0;
104     @Mock private FeatureConnector<ImsManager> mMmTelFeatureConnectorSlot1;
105     @Mock private FeatureConnector<RcsFeatureManager> mRcsFeatureConnectorSlot0;
106     @Mock private FeatureConnector<RcsFeatureManager> mRcsFeatureConnectorSlot1;
107     @Captor ArgumentCaptor<FeatureConnector.Listener<ImsManager>> mMmTelConnectorListenerSlot0;
108     @Captor ArgumentCaptor<FeatureConnector.Listener<ImsManager>> mMmTelConnectorListenerSlot1;
109     @Captor ArgumentCaptor<FeatureConnector.Listener<RcsFeatureManager>> mRcsConnectorListenerSlot0;
110     @Captor ArgumentCaptor<FeatureConnector.Listener<RcsFeatureManager>> mRcsConnectorListenerSlot1;
111     @Mock private PhoneGlobals mPhone;
112     @Mock ImsStateCallbackController.PhoneFactoryProxy mPhoneFactoryProxy;
113     @Mock Phone mPhoneSlot0;
114     @Mock Phone mPhoneSlot1;
115     @Mock private IBinder mBinder0;
116     @Mock private IBinder mBinder1;
117     @Mock private IBinder mBinder2;
118     @Mock private IBinder mBinder3;
119     @Mock private IImsStateCallback mCallback0;
120     @Mock private IImsStateCallback mCallback1;
121     @Mock private IImsStateCallback mCallback2;
122     @Mock private IImsStateCallback mCallback3;
123     @Mock private ImsResolver mImsResolver;
124 
125     private Executor mExecutor = new Executor() {
126         @Override
127         public void execute(Runnable r) {
128             r.run();
129         }
130     };
131 
132     @Before
setUp()133     public void setUp() throws Exception {
134         MockitoAnnotations.initMocks(this);
135 
136         when(mPhone.getMainExecutor()).thenReturn(mExecutor);
137         when(mPhone.getSystemServiceName(eq(SubscriptionManager.class)))
138                 .thenReturn(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
139         when(mPhone.getSystemService(eq(Context.TELEPHONY_SUBSCRIPTION_SERVICE)))
140                 .thenReturn(mSubscriptionManager);
141         when(mPhone.getSystemServiceName(eq(TelephonyRegistryManager.class)))
142                 .thenReturn(Context.TELEPHONY_REGISTRY_SERVICE);
143         when(mPhone.getSystemService(eq(Context.TELEPHONY_REGISTRY_SERVICE)))
144                 .thenReturn(mTelephonyRegistryManager);
145         when(mPhoneFactoryProxy.getPhone(eq(0))).thenReturn(mPhoneSlot0);
146         when(mPhoneFactoryProxy.getPhone(eq(1))).thenReturn(mPhoneSlot1);
147         when(mPhoneSlot0.getSubId()).thenReturn(SLOT_0_SUB_ID);
148         when(mPhoneSlot1.getSubId()).thenReturn(SLOT_1_SUB_ID);
149 
150         when(mCallback0.asBinder()).thenReturn(mBinder0);
151         when(mCallback1.asBinder()).thenReturn(mBinder1);
152         when(mCallback2.asBinder()).thenReturn(mBinder2);
153         when(mCallback3.asBinder()).thenReturn(mBinder3);
154 
155         // slot 0
156         when(mImsResolver.isImsServiceConfiguredForFeature(eq(0), eq(FEATURE_MMTEL)))
157                 .thenReturn(true);
158         when(mImsResolver.isImsServiceConfiguredForFeature(eq(0), eq(FEATURE_RCS)))
159                 .thenReturn(true);
160 
161         // slot 1
162         when(mImsResolver.isImsServiceConfiguredForFeature(eq(1), eq(FEATURE_MMTEL)))
163                 .thenReturn(true);
164         when(mImsResolver.isImsServiceConfiguredForFeature(eq(1), eq(FEATURE_RCS)))
165                 .thenReturn(true);
166 
167         doAnswer(new Answer<Void>() {
168             @Override
169             public Void answer(InvocationOnMock invocation) throws Throwable {
170                 mSubChangedListener = (SubscriptionManager.OnSubscriptionsChangedListener)
171                         invocation.getArguments()[0];
172                 return null;
173             }
174         }).when(mTelephonyRegistryManager).addOnSubscriptionsChangedListener(
175                 any(SubscriptionManager.OnSubscriptionsChangedListener.class),
176                 any());
177 
178         mHandlerThread = new HandlerThread("ImsStateCallbackControllerTest");
179         mHandlerThread.start();
180     }
181 
182     @After
tearDown()183     public void tearDown() throws Exception {
184         if (mImsStateCallbackController != null) {
185             mImsStateCallbackController.destroy();
186             mImsStateCallbackController = null;
187         }
188 
189         if (mLooper != null) {
190             mLooper.destroy();
191             mLooper = null;
192         }
193         super.tearDown();
194     }
195 
196     @Test
197     @SmallTest
testMmTelRegisterThenUnregisterCallback()198     public void testMmTelRegisterThenUnregisterCallback() throws Exception {
199         createController(1);
200 
201         mImsStateCallbackController
202                 .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_MMTEL, mCallback0, "callback0");
203         processAllMessages();
204         assertTrue(mImsStateCallbackController.isRegistered(mCallback0));
205         verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
206 
207         mImsStateCallbackController.unregisterImsStateCallback(mCallback0);
208         processAllMessages();
209         assertFalse(mImsStateCallbackController.isRegistered(mCallback0));
210     }
211 
212     @Test
213     @SmallTest
testMmTelConnectionUnavailable()214     public void testMmTelConnectionUnavailable() throws Exception {
215         createController(1);
216 
217         mImsStateCallbackController
218                 .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_MMTEL, mCallback0, "callback0");
219         processAllMessages();
220         assertTrue(mImsStateCallbackController.isRegistered(mCallback0));
221         verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
222 
223         mMmTelConnectorListenerSlot0.getValue()
224                 .connectionUnavailable(UNAVAILABLE_REASON_NOT_READY);
225         processAllMessages();
226         verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_NOT_READY);
227 
228         mMmTelConnectorListenerSlot0.getValue()
229                 .connectionUnavailable(UNAVAILABLE_REASON_IMS_UNSUPPORTED);
230         processAllMessages();
231         verify(mCallback0, times(1)).onUnavailable(REASON_NO_IMS_SERVICE_CONFIGURED);
232 
233         mImsStateCallbackController.unregisterImsStateCallback(mCallback0);
234         processAllMessages();
235         assertFalse(mImsStateCallbackController.isRegistered(mCallback0));
236     }
237 
238     @Test
239     @SmallTest
testMmTelConnectionReady()240     public void testMmTelConnectionReady() throws Exception {
241         createController(1);
242 
243         mImsStateCallbackController
244                 .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_MMTEL, mCallback0, "callback0");
245         processAllMessages();
246         assertTrue(mImsStateCallbackController.isRegistered(mCallback0));
247         verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
248         verify(mCallback0, times(0)).onAvailable();
249 
250         mMmTelConnectorListenerSlot0.getValue().connectionReady(null, SLOT_0_SUB_ID);
251         processAllMessages();
252         verify(mCallback0, atLeastOnce()).onAvailable();
253 
254         mImsStateCallbackController.unregisterImsStateCallback(mCallback0);
255         processAllMessages();
256         assertFalse(mImsStateCallbackController.isRegistered(mCallback0));
257     }
258 
259     @Test
260     @SmallTest
testMmTelIgnoreDuplicatedConsecutiveReason()261     public void testMmTelIgnoreDuplicatedConsecutiveReason() throws Exception {
262         createController(1);
263 
264         mImsStateCallbackController
265                 .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_MMTEL, mCallback0, "callback0");
266         processAllMessages();
267         assertTrue(mImsStateCallbackController.isRegistered(mCallback0));
268         verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
269 
270         mMmTelConnectorListenerSlot0.getValue()
271                 .connectionUnavailable(UNAVAILABLE_REASON_IMS_UNSUPPORTED);
272         processAllMessages();
273         verify(mCallback0, times(1)).onUnavailable(REASON_NO_IMS_SERVICE_CONFIGURED);
274 
275         mMmTelConnectorListenerSlot0.getValue()
276                 .connectionUnavailable(UNAVAILABLE_REASON_IMS_UNSUPPORTED);
277         processAllMessages();
278         verify(mCallback0, times(1)).onUnavailable(REASON_NO_IMS_SERVICE_CONFIGURED);
279 
280         mImsStateCallbackController.unregisterImsStateCallback(mCallback0);
281         processAllMessages();
282         assertFalse(mImsStateCallbackController.isRegistered(mCallback0));
283     }
284 
285     @Test
286     @SmallTest
testRcsRegisterThenUnregisterCallback()287     public void testRcsRegisterThenUnregisterCallback() throws Exception {
288         createController(1);
289 
290         mImsStateCallbackController
291                 .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_RCS, mCallback0, "callback0");
292         processAllMessages();
293         assertTrue(mImsStateCallbackController.isRegistered(mCallback0));
294         verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
295 
296         mImsStateCallbackController.unregisterImsStateCallback(mCallback0);
297         processAllMessages();
298         assertFalse(mImsStateCallbackController.isRegistered(mCallback0));
299     }
300 
301     @Test
302     @SmallTest
testRcsConnectionUnavailable()303     public void testRcsConnectionUnavailable() throws Exception {
304         createController(1);
305 
306         mImsStateCallbackController
307                 .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_RCS, mCallback0, "callback0");
308         processAllMessages();
309         assertTrue(mImsStateCallbackController.isRegistered(mCallback0));
310         verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
311 
312         // TelephonyRcsService notifying active features
313         mImsStateCallbackController.notifyExternalRcsStateChanged(SLOT_0, false, true);
314         processAllMessages();
315 
316         mRcsConnectorListenerSlot0.getValue()
317                 .connectionUnavailable(UNAVAILABLE_REASON_NOT_READY);
318         processAllMessages();
319         verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_NOT_READY);
320 
321         mRcsConnectorListenerSlot0.getValue()
322                 .connectionUnavailable(UNAVAILABLE_REASON_IMS_UNSUPPORTED);
323         processAllMessages();
324         verify(mCallback0, times(1)).onUnavailable(REASON_NO_IMS_SERVICE_CONFIGURED);
325 
326         mImsStateCallbackController.unregisterImsStateCallback(mCallback0);
327         processAllMessages();
328         assertFalse(mImsStateCallbackController.isRegistered(mCallback0));
329     }
330 
331     @Test
332     @SmallTest
testRcsConnectionReady()333     public void testRcsConnectionReady() throws Exception {
334         createController(1);
335 
336         mImsStateCallbackController
337                 .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_RCS, mCallback0, "callback0");
338         processAllMessages();
339         assertTrue(mImsStateCallbackController.isRegistered(mCallback0));
340         verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
341 
342         // TelephonyRcsService notifying active features
343         mImsStateCallbackController.notifyExternalRcsStateChanged(SLOT_0, false, true);
344         processAllMessages();
345 
346         mRcsConnectorListenerSlot0.getValue()
347                 .connectionUnavailable(UNAVAILABLE_REASON_NOT_READY);
348         processAllMessages();
349         verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_NOT_READY);
350 
351         mRcsConnectorListenerSlot0.getValue().connectionReady(null, SLOT_0_SUB_ID);
352         processAllMessages();
353         verify(mCallback0, times(0)).onAvailable();
354 
355         // RcsFeatureController notifying STATE_READY
356         mImsStateCallbackController.notifyExternalRcsStateChanged(SLOT_0, true, true);
357         processAllMessages();
358         verify(mCallback0, times(1)).onAvailable();
359 
360         mRcsConnectorListenerSlot0.getValue()
361                 .connectionUnavailable(UNAVAILABLE_REASON_DISCONNECTED);
362         processAllMessages();
363         verify(mCallback0, times(2)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
364 
365         mRcsConnectorListenerSlot0.getValue()
366                 .connectionUnavailable(UNAVAILABLE_REASON_NOT_READY);
367         processAllMessages();
368         verify(mCallback0, times(2)).onUnavailable(REASON_IMS_SERVICE_NOT_READY);
369 
370         // RcsFeatureController notifying STATE_READY
371         mImsStateCallbackController.notifyExternalRcsStateChanged(SLOT_0, true, true);
372         processAllMessages();
373         verify(mCallback0, times(1)).onAvailable();
374 
375         mRcsConnectorListenerSlot0.getValue().connectionReady(null, SLOT_0_SUB_ID);
376         processAllMessages();
377         verify(mCallback0, times(2)).onAvailable();
378 
379         mImsStateCallbackController.unregisterImsStateCallback(mCallback0);
380         processAllMessages();
381         assertFalse(mImsStateCallbackController.isRegistered(mCallback0));
382     }
383 
384     @Test
385     @SmallTest
testRcsHasNoActiveFeature()386     public void testRcsHasNoActiveFeature() throws Exception {
387         createController(1);
388 
389         mImsStateCallbackController
390                 .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_RCS, mCallback0, "callback0");
391         processAllMessages();
392         assertTrue(mImsStateCallbackController.isRegistered(mCallback0));
393         verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
394 
395         // TelephonyRcsService notifying NO active feature
396         mImsStateCallbackController.notifyExternalRcsStateChanged(SLOT_0, false, false);
397         processAllMessages();
398         verify(mCallback0, times(1)).onUnavailable(REASON_NO_IMS_SERVICE_CONFIGURED);
399 
400         mRcsConnectorListenerSlot0.getValue()
401                 .connectionUnavailable(UNAVAILABLE_REASON_NOT_READY);
402         processAllMessages();
403         verify(mCallback0, times(0)).onUnavailable(REASON_IMS_SERVICE_NOT_READY);
404 
405         mRcsConnectorListenerSlot0.getValue().connectionReady(null, SLOT_0_SUB_ID);
406         processAllMessages();
407         verify(mCallback0, times(0)).onAvailable();
408 
409         mImsStateCallbackController.unregisterImsStateCallback(mCallback0);
410         processAllMessages();
411         assertFalse(mImsStateCallbackController.isRegistered(mCallback0));
412     }
413 
414     @Test
415     @SmallTest
testRcsIgnoreDuplicatedConsecutiveReason()416     public void testRcsIgnoreDuplicatedConsecutiveReason() throws Exception {
417         createController(1);
418 
419         mImsStateCallbackController
420                 .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_RCS, mCallback0, "callback0");
421         processAllMessages();
422         assertTrue(mImsStateCallbackController.isRegistered(mCallback0));
423         verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
424 
425         // TelephonyRcsService notifying active features
426         mImsStateCallbackController.notifyExternalRcsStateChanged(SLOT_0, false, true);
427         processAllMessages();
428 
429         mRcsConnectorListenerSlot0.getValue()
430                 .connectionUnavailable(UNAVAILABLE_REASON_NOT_READY);
431         processAllMessages();
432         verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_NOT_READY);
433 
434         mRcsConnectorListenerSlot0.getValue()
435                 .connectionUnavailable(UNAVAILABLE_REASON_NOT_READY);
436         processAllMessages();
437         verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_NOT_READY);
438 
439         mImsStateCallbackController.unregisterImsStateCallback(mCallback0);
440         processAllMessages();
441         assertFalse(mImsStateCallbackController.isRegistered(mCallback0));
442     }
443 
444     @Test
445     @SmallTest
testCallbackRemovedWhenSubInfoChanged()446     public void testCallbackRemovedWhenSubInfoChanged() throws Exception {
447         createController(2);
448 
449         mImsStateCallbackController
450                 .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_MMTEL, mCallback0, "callback0");
451         mImsStateCallbackController
452                 .registerImsStateCallback(SLOT_1_SUB_ID, FEATURE_RCS, mCallback1, "callback1");
453         processAllMessages();
454         assertTrue(mImsStateCallbackController.isRegistered(mCallback0));
455         assertTrue(mImsStateCallbackController.isRegistered(mCallback1));
456 
457         verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
458         verify(mCallback1, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
459 
460         makeFakeActiveSubIds(0);
461         mExecutor.execute(() -> mSubChangedListener.onSubscriptionsChanged());
462         processAllMessages();
463 
464         verify(mCallback0, times(1)).onUnavailable(REASON_SUBSCRIPTION_INACTIVE);
465         verify(mCallback1, times(1)).onUnavailable(REASON_SUBSCRIPTION_INACTIVE);
466 
467         assertFalse(mImsStateCallbackController.isRegistered(mCallback0));
468         assertFalse(mImsStateCallbackController.isRegistered(mCallback1));
469     }
470 
471     @Test
472     @SmallTest
testCarrierConfigurationChanged()473     public void testCarrierConfigurationChanged() throws Exception {
474         createController(2);
475 
476         when(mImsResolver.isImsServiceConfiguredForFeature(eq(1), eq(FEATURE_MMTEL)))
477                 .thenReturn(false);
478 
479         mImsStateCallbackController
480                 .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_MMTEL, mCallback0, "callback0");
481         mImsStateCallbackController
482                 .registerImsStateCallback(SLOT_1_SUB_ID, FEATURE_MMTEL, mCallback1, "callback1");
483         mImsStateCallbackController
484                 .registerImsStateCallback(SLOT_1_SUB_ID, FEATURE_RCS, mCallback2, "callback2");
485         processAllMessages();
486         assertTrue(mImsStateCallbackController.isRegistered(mCallback0));
487         assertTrue(mImsStateCallbackController.isRegistered(mCallback1));
488         assertTrue(mImsStateCallbackController.isRegistered(mCallback2));
489 
490         // check initial reason
491         verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
492         verify(mCallback1, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
493         verify(mCallback2, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
494 
495         verify(mCallback0, times(0)).onUnavailable(REASON_NO_IMS_SERVICE_CONFIGURED);
496         verify(mCallback1, times(0)).onUnavailable(REASON_NO_IMS_SERVICE_CONFIGURED);
497         verify(mCallback2, times(0)).onUnavailable(REASON_NO_IMS_SERVICE_CONFIGURED);
498 
499         // ensure only one reason reported until now
500         verify(mCallback0, times(1)).onUnavailable(anyInt());
501         verify(mCallback1, times(1)).onUnavailable(anyInt());
502         verify(mCallback2, times(1)).onUnavailable(anyInt());
503 
504         // state change in RCS for slot 0
505         mRcsConnectorListenerSlot0.getValue()
506                 .connectionUnavailable(UNAVAILABLE_REASON_NOT_READY);
507 
508         // ensure there is no change, since callbacks are not interested RCS on slot 0
509         verify(mCallback0, times(1)).onUnavailable(anyInt());
510         verify(mCallback1, times(1)).onUnavailable(anyInt());
511         verify(mCallback2, times(1)).onUnavailable(anyInt());
512 
513         // carrier config changed, no MMTEL package for slot 1
514         mImsStateCallbackController.notifyCarrierConfigChanged(SLOT_1);
515         processAllMessages();
516 
517         // only the callback for MMTEL of slot 1 received the reason
518         verify(mCallback0, times(0)).onUnavailable(REASON_NO_IMS_SERVICE_CONFIGURED);
519         verify(mCallback1, times(1)).onUnavailable(REASON_NO_IMS_SERVICE_CONFIGURED);
520         verify(mCallback2, times(0)).onUnavailable(REASON_NO_IMS_SERVICE_CONFIGURED);
521 
522         // ensure no other callbacks
523         verify(mCallback0, times(1)).onUnavailable(anyInt());
524         verify(mCallback1, times(2)).onUnavailable(anyInt());
525         verify(mCallback2, times(1)).onUnavailable(anyInt());
526 
527         mMmTelConnectorListenerSlot1.getValue()
528                 .connectionUnavailable(UNAVAILABLE_REASON_NOT_READY);
529         mMmTelConnectorListenerSlot1.getValue()
530                 .connectionUnavailable(UNAVAILABLE_REASON_DISCONNECTED);
531 
532         // resons except REASON_NO_IMS_SERVICE_CONFIGURED are discared
533         verify(mCallback0, times(1)).onUnavailable(anyInt());
534         verify(mCallback1, times(2)).onUnavailable(anyInt());
535         verify(mCallback2, times(1)).onUnavailable(anyInt());
536 
537         // IMS package for MMTEL of slot 1 is added
538         when(mImsResolver.isImsServiceConfiguredForFeature(eq(1), eq(FEATURE_MMTEL)))
539                 .thenReturn(true);
540         mImsStateCallbackController.notifyCarrierConfigChanged(SLOT_1);
541         processAllMessages();
542 
543         // ensure the callback to MMTEL of slot 1 only received REASON_IMS_SERVICE_DISCONNECTED
544         verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
545         verify(mCallback1, times(2)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
546         verify(mCallback2, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
547 
548         // ensure no other reason repored
549         verify(mCallback0, times(1)).onUnavailable(anyInt());
550         verify(mCallback1, times(3)).onUnavailable(anyInt());
551         verify(mCallback2, times(1)).onUnavailable(anyInt());
552 
553         // carrier config changed, no MMTEL package for slot 1
554         when(mImsResolver.isImsServiceConfiguredForFeature(eq(1), eq(FEATURE_MMTEL)))
555                 .thenReturn(false);
556         mImsStateCallbackController.notifyCarrierConfigChanged(SLOT_1);
557         mImsStateCallbackController.notifyCarrierConfigChanged(SLOT_1);
558         processAllMessages();
559         // only the callback for MMTEL of slot 1 received the reason
560         verify(mCallback0, times(0)).onUnavailable(REASON_NO_IMS_SERVICE_CONFIGURED);
561         verify(mCallback1, times(2)).onUnavailable(REASON_NO_IMS_SERVICE_CONFIGURED);
562         verify(mCallback2, times(0)).onUnavailable(REASON_NO_IMS_SERVICE_CONFIGURED);
563 
564         // ensure no other reason repored
565         verify(mCallback0, times(1)).onUnavailable(anyInt());
566         verify(mCallback1, times(4)).onUnavailable(anyInt());
567         verify(mCallback2, times(1)).onUnavailable(anyInt());
568 
569         mMmTelConnectorListenerSlot1.getValue()
570                 .connectionUnavailable(UNAVAILABLE_REASON_NOT_READY);
571 
572         // resons except REASON_NO_IMS_SERVICE_CONFIGURED are discared
573         verify(mCallback0, times(1)).onUnavailable(anyInt());
574         verify(mCallback1, times(4)).onUnavailable(anyInt());
575         verify(mCallback2, times(1)).onUnavailable(anyInt());
576 
577         // IMS package for MMTEL of slot 1 is added
578         when(mImsResolver.isImsServiceConfiguredForFeature(eq(1), eq(FEATURE_MMTEL)))
579                 .thenReturn(true);
580         mImsStateCallbackController.notifyCarrierConfigChanged(SLOT_1);
581         processAllMessages();
582 
583         // ensure the callback to MMTEL of slot 1
584         // there is a pending reason UNAVAILABLE_REASON_NOT_READY
585         verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
586         verify(mCallback1, times(2)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
587         verify(mCallback1, times(1)).onUnavailable(REASON_IMS_SERVICE_NOT_READY);
588         verify(mCallback2, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
589 
590         // ensure no other reason repored
591         verify(mCallback0, times(1)).onUnavailable(anyInt());
592         verify(mCallback1, times(5)).onUnavailable(anyInt());
593         verify(mCallback2, times(1)).onUnavailable(anyInt());
594 
595         assertTrue(mImsStateCallbackController.isRegistered(mCallback0));
596         assertTrue(mImsStateCallbackController.isRegistered(mCallback1));
597         assertTrue(mImsStateCallbackController.isRegistered(mCallback2));
598 
599         mImsStateCallbackController.unregisterImsStateCallback(mCallback0);
600         mImsStateCallbackController.unregisterImsStateCallback(mCallback1);
601         mImsStateCallbackController.unregisterImsStateCallback(mCallback2);
602         processAllMessages();
603 
604         assertFalse(mImsStateCallbackController.isRegistered(mCallback0));
605         assertFalse(mImsStateCallbackController.isRegistered(mCallback1));
606         assertFalse(mImsStateCallbackController.isRegistered(mCallback2));
607     }
608 
609     @Test
610     @SmallTest
testMultiSubscriptions()611     public void testMultiSubscriptions() throws Exception {
612         createController(2);
613 
614         // registration
615         mImsStateCallbackController
616                 .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_MMTEL, mCallback0, "callback0");
617         mImsStateCallbackController
618                 .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_RCS, mCallback1, "callback1");
619         mImsStateCallbackController
620                 .registerImsStateCallback(SLOT_1_SUB_ID, FEATURE_MMTEL, mCallback2, "callback2");
621         mImsStateCallbackController
622                 .registerImsStateCallback(SLOT_1_SUB_ID, FEATURE_RCS, mCallback3, "callback3");
623         processAllMessages();
624         assertTrue(mImsStateCallbackController.isRegistered(mCallback0));
625         assertTrue(mImsStateCallbackController.isRegistered(mCallback1));
626         assertTrue(mImsStateCallbackController.isRegistered(mCallback2));
627         assertTrue(mImsStateCallbackController.isRegistered(mCallback3));
628         verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
629         verify(mCallback1, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
630         verify(mCallback2, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
631         verify(mCallback3, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
632 
633         // TelephonyRcsService notifying active features
634         // slot 0
635         mImsStateCallbackController.notifyExternalRcsStateChanged(SLOT_0, false, true);
636         // slot 1
637         mImsStateCallbackController.notifyExternalRcsStateChanged(SLOT_1, false, true);
638         processAllMessages();
639 
640         verify(mCallback0, times(1)).onUnavailable(anyInt());
641         verify(mCallback1, times(1)).onUnavailable(anyInt());
642         verify(mCallback2, times(1)).onUnavailable(anyInt());
643         verify(mCallback3, times(1)).onUnavailable(anyInt());
644 
645         verify(mCallback0, times(0)).onAvailable();
646         verify(mCallback1, times(0)).onAvailable();
647         verify(mCallback2, times(0)).onAvailable();
648         verify(mCallback3, times(0)).onAvailable();
649 
650         // connectionUnavailable
651         mMmTelConnectorListenerSlot0.getValue()
652                 .connectionUnavailable(UNAVAILABLE_REASON_NOT_READY);
653         processAllMessages();
654         verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_NOT_READY);
655         verify(mCallback0, times(2)).onUnavailable(anyInt());
656         verify(mCallback1, times(1)).onUnavailable(anyInt());
657         verify(mCallback1, times(1)).onUnavailable(anyInt());
658         verify(mCallback2, times(1)).onUnavailable(anyInt());
659         verify(mCallback2, times(1)).onUnavailable(anyInt());
660         verify(mCallback3, times(1)).onUnavailable(anyInt());
661         verify(mCallback3, times(1)).onUnavailable(anyInt());
662 
663         mRcsConnectorListenerSlot0.getValue()
664                 .connectionUnavailable(UNAVAILABLE_REASON_NOT_READY);
665         processAllMessages();
666         verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_NOT_READY);
667         verify(mCallback0, times(2)).onUnavailable(anyInt());
668         verify(mCallback1, times(1)).onUnavailable(REASON_IMS_SERVICE_NOT_READY);
669         verify(mCallback1, times(2)).onUnavailable(anyInt());
670         verify(mCallback2, times(1)).onUnavailable(anyInt());
671         verify(mCallback2, times(1)).onUnavailable(anyInt());
672         verify(mCallback3, times(1)).onUnavailable(anyInt());
673         verify(mCallback3, times(1)).onUnavailable(anyInt());
674 
675         mMmTelConnectorListenerSlot1.getValue()
676                 .connectionUnavailable(UNAVAILABLE_REASON_NOT_READY);
677         processAllMessages();
678         verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_NOT_READY);
679         verify(mCallback0, times(2)).onUnavailable(anyInt());
680         verify(mCallback1, times(1)).onUnavailable(REASON_IMS_SERVICE_NOT_READY);
681         verify(mCallback1, times(2)).onUnavailable(anyInt());
682         verify(mCallback2, times(1)).onUnavailable(REASON_IMS_SERVICE_NOT_READY);
683         verify(mCallback2, times(2)).onUnavailable(anyInt());
684         verify(mCallback3, times(1)).onUnavailable(anyInt());
685         verify(mCallback3, times(1)).onUnavailable(anyInt());
686 
687         mRcsConnectorListenerSlot1.getValue()
688                 .connectionUnavailable(UNAVAILABLE_REASON_NOT_READY);
689         processAllMessages();
690         verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_NOT_READY);
691         verify(mCallback0, times(2)).onUnavailable(anyInt());
692         verify(mCallback1, times(1)).onUnavailable(REASON_IMS_SERVICE_NOT_READY);
693         verify(mCallback1, times(2)).onUnavailable(anyInt());
694         verify(mCallback2, times(1)).onUnavailable(REASON_IMS_SERVICE_NOT_READY);
695         verify(mCallback2, times(2)).onUnavailable(anyInt());
696         verify(mCallback3, times(1)).onUnavailable(REASON_IMS_SERVICE_NOT_READY);
697         verify(mCallback3, times(2)).onUnavailable(anyInt());
698 
699         // connectionReady
700         mMmTelConnectorListenerSlot0.getValue().connectionReady(null, SLOT_0_SUB_ID);
701         processAllMessages();
702         verify(mCallback0, times(1)).onAvailable();
703         verify(mCallback1, times(0)).onAvailable();
704         verify(mCallback2, times(0)).onAvailable();
705         verify(mCallback3, times(0)).onAvailable();
706         verify(mCallback0, times(2)).onUnavailable(anyInt());
707         verify(mCallback1, times(2)).onUnavailable(anyInt());
708         verify(mCallback2, times(2)).onUnavailable(anyInt());
709         verify(mCallback3, times(2)).onUnavailable(anyInt());
710 
711         mRcsConnectorListenerSlot0.getValue().connectionReady(null, SLOT_0_SUB_ID);
712         processAllMessages();
713         verify(mCallback0, times(1)).onAvailable();
714         verify(mCallback1, times(0)).onAvailable();
715         verify(mCallback2, times(0)).onAvailable();
716         verify(mCallback3, times(0)).onAvailable();
717         verify(mCallback0, times(2)).onUnavailable(anyInt());
718         verify(mCallback1, times(2)).onUnavailable(anyInt());
719         verify(mCallback2, times(2)).onUnavailable(anyInt());
720         verify(mCallback3, times(2)).onUnavailable(anyInt());
721 
722         mImsStateCallbackController.notifyExternalRcsStateChanged(SLOT_0, true, true);
723         processAllMessages();
724         verify(mCallback0, times(1)).onAvailable();
725         verify(mCallback1, times(1)).onAvailable();
726         verify(mCallback2, times(0)).onAvailable();
727         verify(mCallback3, times(0)).onAvailable();
728         verify(mCallback0, times(2)).onUnavailable(anyInt());
729         verify(mCallback1, times(2)).onUnavailable(anyInt());
730         verify(mCallback2, times(2)).onUnavailable(anyInt());
731         verify(mCallback3, times(2)).onUnavailable(anyInt());
732 
733         mMmTelConnectorListenerSlot1.getValue().connectionReady(null, SLOT_1_SUB_ID);
734         processAllMessages();
735         verify(mCallback0, times(1)).onAvailable();
736         verify(mCallback1, times(1)).onAvailable();
737         verify(mCallback2, times(1)).onAvailable();
738         verify(mCallback3, times(0)).onAvailable();
739         verify(mCallback0, times(2)).onUnavailable(anyInt());
740         verify(mCallback1, times(2)).onUnavailable(anyInt());
741         verify(mCallback2, times(2)).onUnavailable(anyInt());
742         verify(mCallback3, times(2)).onUnavailable(anyInt());
743 
744         mRcsConnectorListenerSlot1.getValue().connectionReady(null, SLOT_1_SUB_ID);
745         processAllMessages();
746         verify(mCallback0, times(1)).onAvailable();
747         verify(mCallback1, times(1)).onAvailable();
748         verify(mCallback2, times(1)).onAvailable();
749         verify(mCallback3, times(0)).onAvailable();
750         verify(mCallback0, times(2)).onUnavailable(anyInt());
751         verify(mCallback1, times(2)).onUnavailable(anyInt());
752         verify(mCallback2, times(2)).onUnavailable(anyInt());
753         verify(mCallback3, times(2)).onUnavailable(anyInt());
754 
755         mImsStateCallbackController.notifyExternalRcsStateChanged(SLOT_1, true, true);
756         processAllMessages();
757         verify(mCallback0, times(1)).onAvailable();
758         verify(mCallback1, times(1)).onAvailable();
759         verify(mCallback2, times(1)).onAvailable();
760         verify(mCallback3, times(1)).onAvailable();
761         verify(mCallback0, times(2)).onUnavailable(anyInt());
762         verify(mCallback1, times(2)).onUnavailable(anyInt());
763         verify(mCallback2, times(2)).onUnavailable(anyInt());
764         verify(mCallback3, times(2)).onUnavailable(anyInt());
765 
766         // unregistration
767         mImsStateCallbackController.unregisterImsStateCallback(mCallback0);
768         processAllMessages();
769         assertFalse(mImsStateCallbackController.isRegistered(mCallback0));
770         assertTrue(mImsStateCallbackController.isRegistered(mCallback1));
771         assertTrue(mImsStateCallbackController.isRegistered(mCallback2));
772         assertTrue(mImsStateCallbackController.isRegistered(mCallback3));
773 
774         mImsStateCallbackController.unregisterImsStateCallback(mCallback1);
775         processAllMessages();
776         assertFalse(mImsStateCallbackController.isRegistered(mCallback0));
777         assertFalse(mImsStateCallbackController.isRegistered(mCallback1));
778         assertTrue(mImsStateCallbackController.isRegistered(mCallback2));
779         assertTrue(mImsStateCallbackController.isRegistered(mCallback3));
780 
781         mImsStateCallbackController.unregisterImsStateCallback(mCallback2);
782         processAllMessages();
783         assertFalse(mImsStateCallbackController.isRegistered(mCallback0));
784         assertFalse(mImsStateCallbackController.isRegistered(mCallback1));
785         assertFalse(mImsStateCallbackController.isRegistered(mCallback2));
786         assertTrue(mImsStateCallbackController.isRegistered(mCallback3));
787 
788         mImsStateCallbackController.unregisterImsStateCallback(mCallback3);
789         processAllMessages();
790         assertFalse(mImsStateCallbackController.isRegistered(mCallback0));
791         assertFalse(mImsStateCallbackController.isRegistered(mCallback1));
792         assertFalse(mImsStateCallbackController.isRegistered(mCallback2));
793         assertFalse(mImsStateCallbackController.isRegistered(mCallback3));
794     }
795 
796     @Test
797     @SmallTest
testSlotUpdates()798     public void testSlotUpdates() throws Exception {
799         createController(1);
800 
801         verify(mMmTelFeatureConnectorSlot0, times(1)).connect();
802         verify(mRcsFeatureConnectorSlot0, times(1)).connect();
803         verify(mMmTelFeatureConnectorSlot0, times(0)).disconnect();
804         verify(mRcsFeatureConnectorSlot0, times(0)).disconnect();
805 
806         // Add a new slot.
807         mImsStateCallbackController.updateFeatureControllerSize(2);
808 
809         // connect in slot 1
810         verify(mMmTelFeatureConnectorSlot1, times(1)).connect();
811         verify(mRcsFeatureConnectorSlot1, times(1)).connect();
812 
813         // no change in slot 0
814         verify(mMmTelFeatureConnectorSlot0, times(1)).connect();
815         verify(mRcsFeatureConnectorSlot0, times(1)).connect();
816 
817         // Remove a slot.
818         mImsStateCallbackController.updateFeatureControllerSize(1);
819 
820         // destroy in slot 1
821         verify(mMmTelFeatureConnectorSlot1, times(1)).disconnect();
822         verify(mRcsFeatureConnectorSlot1, times(1)).disconnect();
823 
824         // no change in slot 0
825         verify(mMmTelFeatureConnectorSlot0, times(0)).disconnect();
826         verify(mRcsFeatureConnectorSlot0, times(0)).disconnect();
827     }
828 
829     @Test
830     @SmallTest
testMmTelConnectionReadyWhenReEnableSim()831     public void testMmTelConnectionReadyWhenReEnableSim() throws Exception {
832         createController(1);
833 
834         // MMTEL feature
835         mMmTelConnectorListenerSlot0.getValue().connectionReady(null, SLOT_0_SUB_ID);
836         processAllMessages();
837         mMmTelConnectorListenerSlot0.getValue()
838                 .connectionUnavailable(UNAVAILABLE_REASON_DISCONNECTED);
839         processAllMessages();
840         mMmTelConnectorListenerSlot0.getValue().connectionReady(null,
841                 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
842         processAllMessages();
843         mImsStateCallbackController
844                 .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_MMTEL, mCallback0, "callback0");
845         processAllMessages();
846 
847         assertTrue(mImsStateCallbackController.isRegistered(mCallback0));
848         verify(mCallback0, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
849         verify(mCallback0, times(0)).onAvailable();
850 
851         mImsStateCallbackController.unregisterImsStateCallback(mCallback0);
852         processAllMessages();
853         assertFalse(mImsStateCallbackController.isRegistered(mCallback0));
854 
855         // RCS feature
856         // TelephonyRcsService notifying active features
857         mImsStateCallbackController.notifyExternalRcsStateChanged(SLOT_0, false, true);
858         processAllMessages();
859         // RcsFeatureController notifying STATE_READY
860         mImsStateCallbackController.notifyExternalRcsStateChanged(SLOT_0, true, true);
861         processAllMessages();
862         mRcsConnectorListenerSlot0.getValue()
863                 .connectionUnavailable(UNAVAILABLE_REASON_DISCONNECTED);
864         processAllMessages();
865         mRcsConnectorListenerSlot0.getValue().connectionReady(null,
866                 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
867         processAllMessages();
868         mImsStateCallbackController
869                 .registerImsStateCallback(SLOT_0_SUB_ID, FEATURE_RCS, mCallback1, "callback1");
870         processAllMessages();
871 
872         assertTrue(mImsStateCallbackController.isRegistered(mCallback1));
873         verify(mCallback1, times(1)).onUnavailable(REASON_IMS_SERVICE_DISCONNECTED);
874         verify(mCallback1, times(0)).onAvailable();
875 
876         mImsStateCallbackController.unregisterImsStateCallback(mCallback1);
877         processAllMessages();
878         assertFalse(mImsStateCallbackController.isRegistered(mCallback1));
879     }
880 
881     @Test
882     @SmallTest
testImsManagerInstance()883     public void testImsManagerInstance() throws Exception {
884         createController(1);
885 
886         // MmTelConnection not ready
887         // check ImsManager instance
888         ImsManager imsManager = mImsStateCallbackController.getImsManager(SLOT_0_SUB_ID);
889         assertNull(imsManager);
890 
891         // MmTelConnection ready
892         mMmTelConnectorListenerSlot0.getValue()
893                 .connectionReady(mMmTelFeatureManager, SLOT_0_SUB_ID);
894         processAllMessages();
895 
896         // check ImsManager instance
897         imsManager = mImsStateCallbackController.getImsManager(SLOT_0_SUB_ID);
898         assertNotNull(imsManager);
899 
900         // MmTelConnection unavailable
901         mMmTelConnectorListenerSlot0.getValue()
902                 .connectionUnavailable(UNAVAILABLE_REASON_NOT_READY);
903         processAllMessages();
904 
905         // MmTelConnection unavailable
906         // check ImsManager instance
907         imsManager = mImsStateCallbackController.getImsManager(SLOT_0_SUB_ID);
908         assertNull(imsManager);
909     }
910 
createController(int slotCount)911     private void createController(int slotCount) throws Exception {
912         if (Looper.myLooper() == null) {
913             Looper.prepare();
914         }
915         makeFakeActiveSubIds(slotCount);
916 
917         when(mMmTelFeatureFactory
918                 .create(any(), eq(0), any(), mMmTelConnectorListenerSlot0.capture(), any()))
919                 .thenReturn(mMmTelFeatureConnectorSlot0);
920         when(mMmTelFeatureFactory
921                 .create(any(), eq(1), any(), mMmTelConnectorListenerSlot1.capture(), any()))
922                 .thenReturn(mMmTelFeatureConnectorSlot1);
923         when(mRcsFeatureFactory
924                 .create(any(), eq(0), mRcsConnectorListenerSlot0.capture(), any(), any()))
925                 .thenReturn(mRcsFeatureConnectorSlot0);
926         when(mRcsFeatureFactory
927                 .create(any(), eq(1), mRcsConnectorListenerSlot1.capture(), any(), any()))
928                 .thenReturn(mRcsFeatureConnectorSlot1);
929 
930         mImsStateCallbackController =
931                 new ImsStateCallbackController(mPhone, mHandlerThread.getLooper(),
932                         slotCount, mMmTelFeatureFactory, mRcsFeatureFactory, mImsResolver);
933 
934         replaceInstance(ImsStateCallbackController.class,
935                 "mPhoneFactoryProxy", mImsStateCallbackController, mPhoneFactoryProxy);
936         mImsStateCallbackController.onSubChanged();
937 
938         mHandler = mImsStateCallbackController.getHandler();
939         try {
940             mLooper = new TestableLooper(mHandler.getLooper());
941         } catch (Exception e) {
942             logd("Unable to create looper from handler.");
943         }
944 
945         verify(mRcsFeatureConnectorSlot0, atLeastOnce()).connect();
946         verify(mMmTelFeatureConnectorSlot0, atLeastOnce()).connect();
947 
948         if (slotCount == 1) {
949             verify(mRcsFeatureConnectorSlot1, times(0)).connect();
950             verify(mMmTelFeatureConnectorSlot1, times(0)).connect();
951         } else {
952             verify(mRcsFeatureConnectorSlot1, atLeastOnce()).connect();
953             verify(mMmTelFeatureConnectorSlot1, atLeastOnce()).connect();
954         }
955     }
956 
makeFakeActiveSubIds(int count)957     private void makeFakeActiveSubIds(int count) {
958         final int[] subIds = new int[count];
959         for (int i = 0; i < count; i++) {
960             subIds[i] = FAKE_SUB_ID_BASE + i;
961         }
962         when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(subIds);
963     }
964 
processAllMessages()965     private void processAllMessages() {
966         while (!mLooper.getLooper().getQueue().isIdle()) {
967             mLooper.processAllMessages();
968         }
969     }
970 
logd(String str)971     private static void logd(String str) {
972         Log.d(TAG, str);
973     }
974 }
975