• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.services.telephony.domainselection;
18 
19 import static org.junit.Assert.assertNotNull;
20 import static org.mockito.ArgumentMatchers.any;
21 import static org.mockito.ArgumentMatchers.anyInt;
22 import static org.mockito.ArgumentMatchers.eq;
23 import static org.mockito.Mockito.doReturn;
24 import static org.mockito.Mockito.never;
25 import static org.mockito.Mockito.verify;
26 import static org.mockito.Mockito.verifyNoMoreInteractions;
27 import static org.mockito.Mockito.when;
28 
29 import android.annotation.NonNull;
30 import android.annotation.Nullable;
31 import android.content.Context;
32 import android.os.Handler;
33 import android.os.Looper;
34 import android.telephony.BarringInfo;
35 import android.telephony.DomainSelectionService;
36 import android.telephony.DomainSelectionService.SelectionAttributes;
37 import android.telephony.DomainSelectionService.SelectorType;
38 import android.telephony.ServiceState;
39 import android.telephony.SubscriptionInfo;
40 import android.telephony.SubscriptionManager;
41 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
42 import android.telephony.TransportSelectorCallback;
43 import android.testing.TestableLooper;
44 
45 import androidx.test.filters.SmallTest;
46 import androidx.test.runner.AndroidJUnit4;
47 
48 import com.android.TestContext;
49 import com.android.internal.telephony.flags.Flags;
50 
51 import org.junit.After;
52 import org.junit.Before;
53 import org.junit.Test;
54 import org.junit.runner.RunWith;
55 import org.mockito.ArgumentCaptor;
56 import org.mockito.Mock;
57 import org.mockito.Mockito;
58 import org.mockito.MockitoAnnotations;
59 
60 import java.util.ArrayList;
61 import java.util.List;
62 import java.util.concurrent.Executor;
63 
64 /**
65  * Unit tests for TelephonyDomainSelectionService.
66  */
67 @RunWith(AndroidJUnit4.class)
68 public class TelephonyDomainSelectionServiceTest {
69     private TelephonyDomainSelectionService.ImsStateTrackerFactory mImsStateTrackerFactory =
70             new TelephonyDomainSelectionService.ImsStateTrackerFactory() {
71                 @Override
72                 public ImsStateTracker create(Context context, int slotId,
73                         @NonNull Looper looper) {
74                     return mImsStateTracker;
75                 }
76             };
77     private TelephonyDomainSelectionService.DomainSelectorFactory mDomainSelectorFactory =
78             new TelephonyDomainSelectionService.DomainSelectorFactory() {
79                 @Override
80                 public DomainSelectorBase create(Context context, int slotId, int subId,
81                         @SelectorType int selectorType, boolean isEmergency,
82                         @NonNull Looper looper, @NonNull ImsStateTracker imsStateTracker,
83                         @NonNull DomainSelectorBase.DestroyListener listener,
84                         @NonNull CrossSimRedialingController crossSimRedialingController,
85                         @NonNull DataConnectionStateHelper dataConnectionStateHelper) {
86                     switch (selectorType) {
87                         case DomainSelectionService.SELECTOR_TYPE_CALLING: // fallthrough
88                         case DomainSelectionService.SELECTOR_TYPE_SMS:
89                             mDomainSelectorDestroyListener = listener;
90                             if (subId == SUB_1) {
91                                 return mDomainSelectorBase1;
92                             } else {
93                                 return mDomainSelectorBase2;
94                             }
95                         default:
96                             return null;
97                     }
98                 }
99             };
100     private static class TestTelephonyDomainSelectionService
101             extends TelephonyDomainSelectionService {
102         private final Context mContext;
103 
TestTelephonyDomainSelectionService(Context context, @NonNull ImsStateTrackerFactory imsStateTrackerFactory, @NonNull DomainSelectorFactory domainSelectorFactory, @Nullable DataConnectionStateHelper dataConnectionStateHelper)104         TestTelephonyDomainSelectionService(Context context,
105                 @NonNull ImsStateTrackerFactory imsStateTrackerFactory,
106                 @NonNull DomainSelectorFactory domainSelectorFactory,
107                 @Nullable DataConnectionStateHelper dataConnectionStateHelper) {
108             super(imsStateTrackerFactory, domainSelectorFactory,
109                     dataConnectionStateHelper);
110             mContext = context;
111         }
112 
113         @Override
onCreate()114         public void onCreate() {
115             // attach test context.
116             attachBaseContext(mContext);
117             super.onCreate();
118         }
119     }
120     private static final int SLOT_0 = 0;
121     private static final int SUB_1 = 1;
122     private static final int SUB_2 = 2;
123     private static final String CALL_ID = "Call_1";
124     private static final @SelectorType int TEST_SELECTOR_TYPE =
125             DomainSelectionService.SELECTOR_TYPE_CALLING;
126     private static final @SelectorType int INVALID_SELECTOR_TYPE = -1;
127 
128     @Mock private DomainSelectorBase mDomainSelectorBase1;
129     @Mock private DomainSelectorBase mDomainSelectorBase2;
130     @Mock private TransportSelectorCallback mSelectorCallback1;
131     @Mock private TransportSelectorCallback mSelectorCallback2;
132     @Mock private ImsStateTracker mImsStateTracker;
133     @Mock private DataConnectionStateHelper mDataConnectionStateHelper;
134 
135     private final ServiceState mServiceState = new ServiceState();
136     private final BarringInfo mBarringInfo = new BarringInfo();
137     private Context mContext;
138     private Handler mServiceHandler;
139     private TestableLooper mTestableLooper;
140     private SubscriptionManager mSubscriptionManager;
141     private OnSubscriptionsChangedListener mOnSubscriptionsChangedListener;
142     private DomainSelectorBase.DestroyListener mDomainSelectorDestroyListener;
143     private TelephonyDomainSelectionService mDomainSelectionService;
144 
145     @Before
setUp()146     public void setUp() throws Exception {
147         MockitoAnnotations.initMocks(this);
148 
149         if (Looper.myLooper() == null) {
150             Looper.prepare();
151         }
152 
153         mContext = new TestContext();
154         mDomainSelectionService = new TestTelephonyDomainSelectionService(mContext,
155                 mImsStateTrackerFactory, mDomainSelectorFactory,
156                 mDataConnectionStateHelper);
157         mDomainSelectionService.onCreate();
158         mServiceHandler = new Handler(mDomainSelectionService.getLooper());
159         mTestableLooper = new TestableLooper(mDomainSelectionService.getLooper());
160 
161         mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
162         if (Flags.workProfileApiSplit()) {
163             doReturn(mSubscriptionManager).when(mSubscriptionManager).createForAllUserProfiles();
164         }
165         ArgumentCaptor<OnSubscriptionsChangedListener> listenerCaptor =
166                 ArgumentCaptor.forClass(OnSubscriptionsChangedListener.class);
167         verify(mSubscriptionManager).addOnSubscriptionsChangedListener(
168                 any(Executor.class), listenerCaptor.capture());
169         mOnSubscriptionsChangedListener = listenerCaptor.getValue();
170     }
171 
172     @After
tearDown()173     public void tearDown() throws Exception {
174         if (mTestableLooper != null) {
175             mTestableLooper.destroy();
176             mTestableLooper = null;
177         }
178         mServiceHandler = null;
179 
180         if (mDomainSelectionService != null) {
181             mDomainSelectionService.onDestroy();
182             mDomainSelectionService = null;
183         }
184 
185         mDomainSelectorBase1 = null;
186         mDomainSelectorBase2 = null;
187         mSelectorCallback1 = null;
188         mSelectorCallback2 = null;
189         mImsStateTracker = null;
190         mSubscriptionManager = null;
191         mOnSubscriptionsChangedListener = null;
192         mDomainSelectorDestroyListener = null;
193     }
194 
195     @Test
196     @SmallTest
testGetExecutor()197     public void testGetExecutor() {
198         assertNotNull(mDomainSelectionService.getExecutor());
199     }
200 
201     @Test
202     @SmallTest
testOnDomainSelection()203     public void testOnDomainSelection() {
204         SelectionAttributes attr1 = new SelectionAttributes.Builder(
205                 SLOT_0, SUB_1, TEST_SELECTOR_TYPE)
206                 .setCallId(CALL_ID)
207                 .setEmergency(true)
208                 .build();
209         mDomainSelectionService.onDomainSelection(attr1, mSelectorCallback1);
210         processAllMessages();
211 
212         verify(mImsStateTracker).start(eq(SUB_1));
213         verify(mSelectorCallback1).onCreated(eq(mDomainSelectorBase1));
214         verifyNoMoreInteractions(mSelectorCallback1);
215         verify(mDomainSelectorBase1).selectDomain(eq(attr1), eq(mSelectorCallback1));
216     }
217 
218     @Test
219     @SmallTest
testOnDomainSelectionWithInvalidSelectorType()220     public void testOnDomainSelectionWithInvalidSelectorType() {
221         SelectionAttributes attr1 = new SelectionAttributes.Builder(
222                 SLOT_0, SUB_1, INVALID_SELECTOR_TYPE)
223                 .setCallId(CALL_ID)
224                 .setEmergency(true)
225                 .build();
226         mDomainSelectionService.onDomainSelection(attr1, mSelectorCallback1);
227         processAllMessages();
228 
229         verify(mImsStateTracker, never()).start(anyInt());
230         verify(mSelectorCallback1).onSelectionTerminated(anyInt());
231         verifyNoMoreInteractions(mSelectorCallback1);
232         verify(mDomainSelectorBase1, never()).selectDomain(eq(attr1), eq(mSelectorCallback1));
233     }
234 
235     @Test
236     @SmallTest
testOnDomainSelectionTwiceWithDestroy()237     public void testOnDomainSelectionTwiceWithDestroy() {
238         SelectionAttributes attr1 = new SelectionAttributes.Builder(
239                 SLOT_0, SUB_1, TEST_SELECTOR_TYPE)
240                 .setCallId(CALL_ID)
241                 .setEmergency(true)
242                 .build();
243         mDomainSelectionService.onDomainSelection(attr1, mSelectorCallback1);
244         processAllMessages();
245 
246         verify(mImsStateTracker).start(eq(SUB_1));
247         verify(mSelectorCallback1).onCreated(eq(mDomainSelectorBase1));
248         verifyNoMoreInteractions(mSelectorCallback1);
249         verify(mDomainSelectorBase1).selectDomain(eq(attr1), eq(mSelectorCallback1));
250 
251         // Notify the domain selection service that this domain selector is destroyed.
252         mDomainSelectorDestroyListener.onDomainSelectorDestroyed(mDomainSelectorBase1);
253 
254         SelectionAttributes attr2 = new SelectionAttributes.Builder(
255                 SLOT_0, SUB_2, TEST_SELECTOR_TYPE)
256                 .setCallId(CALL_ID)
257                 .setEmergency(true)
258                 .build();
259         mDomainSelectionService.onDomainSelection(attr2, mSelectorCallback2);
260         processAllMessages();
261 
262         verify(mImsStateTracker).start(eq(SUB_2));
263         verify(mSelectorCallback2).onCreated(eq(mDomainSelectorBase2));
264         verifyNoMoreInteractions(mSelectorCallback2);
265         verify(mDomainSelectorBase2).selectDomain(eq(attr2), eq(mSelectorCallback2));
266     }
267 
268     @Test
269     @SmallTest
testOnDomainSelectionTwiceWithoutDestroy()270     public void testOnDomainSelectionTwiceWithoutDestroy() {
271         SelectionAttributes attr1 = new SelectionAttributes.Builder(
272                 SLOT_0, SUB_1, TEST_SELECTOR_TYPE)
273                 .setCallId(CALL_ID)
274                 .setEmergency(true)
275                 .build();
276         mDomainSelectionService.onDomainSelection(attr1, mSelectorCallback1);
277         processAllMessages();
278 
279         verify(mImsStateTracker).start(eq(SUB_1));
280         verify(mSelectorCallback1).onCreated(eq(mDomainSelectorBase1));
281         verifyNoMoreInteractions(mSelectorCallback1);
282         verify(mDomainSelectorBase1).selectDomain(eq(attr1), eq(mSelectorCallback1));
283 
284         SelectionAttributes attr2 = new SelectionAttributes.Builder(
285                 SLOT_0, SUB_2, TEST_SELECTOR_TYPE)
286                 .setCallId(CALL_ID)
287                 .setEmergency(true)
288                 .build();
289         mDomainSelectionService.onDomainSelection(attr2, mSelectorCallback2);
290         processAllMessages();
291 
292         verify(mImsStateTracker).start(eq(SUB_2));
293         verify(mSelectorCallback2).onCreated(eq(mDomainSelectorBase2));
294         verifyNoMoreInteractions(mSelectorCallback2);
295         verify(mDomainSelectorBase2).selectDomain(eq(attr2), eq(mSelectorCallback2));
296     }
297 
298     @Test
299     @SmallTest
testOnServiceStateUpdated()300     public void testOnServiceStateUpdated() {
301         mDomainSelectionService.onServiceStateUpdated(SLOT_0, SUB_1, mServiceState);
302 
303         verify(mImsStateTracker).updateServiceState(eq(mServiceState));
304     }
305 
306     @Test
307     @SmallTest
testOnBarringInfoUpdated()308     public void testOnBarringInfoUpdated() {
309         mDomainSelectionService.onBarringInfoUpdated(SLOT_0, SUB_1, mBarringInfo);
310 
311         verify(mImsStateTracker).updateBarringInfo(eq(mBarringInfo));
312     }
313 
314     @Test
315     @SmallTest
testOnDestroy()316     public void testOnDestroy() {
317         SelectionAttributes attr1 = new SelectionAttributes.Builder(
318                 SLOT_0, SUB_1, TEST_SELECTOR_TYPE)
319                 .setCallId(CALL_ID)
320                 .setEmergency(true)
321                 .build();
322         mDomainSelectionService.onDomainSelection(attr1, mSelectorCallback1);
323         processAllMessages();
324 
325         mDomainSelectionService.onDestroy();
326 
327         verify(mImsStateTracker).destroy();
328         verify(mDomainSelectorBase1).destroy();
329         verify(mSubscriptionManager).removeOnSubscriptionsChangedListener(any());
330     }
331 
332     @Test
333     @SmallTest
testHandleSubscriptionsChangedWithEmptySubscriptionInfo()334     public void testHandleSubscriptionsChangedWithEmptySubscriptionInfo() {
335         when(mSubscriptionManager.getActiveSubscriptionInfoList())
336                 .thenReturn(null, new ArrayList<SubscriptionInfo>());
337 
338         mOnSubscriptionsChangedListener.onSubscriptionsChanged();
339         mOnSubscriptionsChangedListener.onSubscriptionsChanged();
340 
341         verify(mImsStateTracker, never()).start(anyInt());
342     }
343 
344     @Test
345     @SmallTest
testHandleSubscriptionsChangedWithActiveSubscriptionInfoAndInvalidSlotIndex()346     public void testHandleSubscriptionsChangedWithActiveSubscriptionInfoAndInvalidSlotIndex() {
347         SubscriptionInfo subsInfo = Mockito.mock(SubscriptionInfo.class);
348         List<SubscriptionInfo> subsInfoList = new ArrayList<>();
349         subsInfoList.add(subsInfo);
350         when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(subsInfoList);
351         when(subsInfo.getSimSlotIndex()).thenReturn(SubscriptionManager.INVALID_SIM_SLOT_INDEX);
352 
353         mOnSubscriptionsChangedListener.onSubscriptionsChanged();
354 
355         verify(mImsStateTracker, never()).start(anyInt());
356     }
357 
358     @Test
359     @SmallTest
testHandleSubscriptionsChangedWithActiveSubscriptionInfo()360     public void testHandleSubscriptionsChangedWithActiveSubscriptionInfo() {
361         SubscriptionInfo subsInfo = Mockito.mock(SubscriptionInfo.class);
362         List<SubscriptionInfo> subsInfoList = new ArrayList<>();
363         subsInfoList.add(subsInfo);
364         when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(subsInfoList);
365         when(subsInfo.getSubscriptionId())
366                 .thenReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID, SUB_1);
367         when(subsInfo.getSimSlotIndex()).thenReturn(SLOT_0);
368 
369         mOnSubscriptionsChangedListener.onSubscriptionsChanged();
370         mOnSubscriptionsChangedListener.onSubscriptionsChanged();
371 
372         verify(mImsStateTracker).start(eq(SubscriptionManager.INVALID_SUBSCRIPTION_ID));
373         verify(mImsStateTracker).start(eq(SUB_1));
374     }
375 
processAllMessages()376     private void processAllMessages() {
377         while (!mTestableLooper.getLooper().getQueue().isIdle()) {
378             mTestableLooper.processAllMessages();
379         }
380     }
381 }
382