1 /* 2 * Copyright (C) 2016 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.server.telecom.tests; 18 19 import static android.provider.CallLog.Calls.MISSED_REASON_NOT_MISSED; 20 import static android.provider.CallLog.Calls.USER_MISSED_CALL_FILTERS_TIMEOUT; 21 import static android.provider.CallLog.Calls.USER_MISSED_NO_VIBRATE; 22 23 import static org.junit.Assert.assertEquals; 24 import static org.junit.Assert.assertFalse; 25 import static org.junit.Assert.assertNotNull; 26 import static org.junit.Assert.assertNull; 27 import static org.junit.Assert.assertTrue; 28 import static org.mockito.ArgumentMatchers.any; 29 import static org.mockito.ArgumentMatchers.anyInt; 30 import static org.mockito.Mockito.doAnswer; 31 import static org.mockito.Mockito.mock; 32 import static org.mockito.Mockito.when; 33 34 import android.content.ContentResolver; 35 import android.content.Context; 36 import android.os.Build; 37 import android.telecom.CallAudioState; 38 import android.telecom.Connection; 39 import android.telecom.DisconnectCause; 40 import android.telecom.InCallService; 41 import android.telecom.Log; 42 import android.telecom.Logging.EventManager; 43 import android.telecom.ParcelableCallAnalytics; 44 import android.telecom.TelecomAnalytics; 45 import android.telecom.TelecomManager; 46 import android.telecom.VideoCallImpl; 47 import android.telecom.VideoProfile; 48 import android.telephony.SubscriptionInfo; 49 import android.telephony.SubscriptionManager; 50 import android.util.Base64; 51 52 import androidx.test.filters.FlakyTest; 53 import androidx.test.filters.MediumTest; 54 import androidx.test.filters.SmallTest; 55 56 import com.android.internal.util.IndentingPrintWriter; 57 import com.android.server.telecom.Analytics; 58 import com.android.server.telecom.CallAudioRouteStateMachine; 59 import com.android.server.telecom.LogUtils; 60 import com.android.server.telecom.nano.TelecomLogClass; 61 62 import org.junit.After; 63 import org.junit.Before; 64 import org.junit.Test; 65 import org.junit.runner.RunWith; 66 import org.junit.runners.JUnit4; 67 68 import java.io.PrintWriter; 69 import java.io.StringWriter; 70 import java.util.Arrays; 71 import java.util.Collections; 72 import java.util.HashSet; 73 import java.util.LinkedList; 74 import java.util.List; 75 import java.util.Map; 76 import java.util.Set; 77 import java.util.concurrent.CountDownLatch; 78 import java.util.concurrent.TimeUnit; 79 80 @RunWith(JUnit4.class) 81 public class AnalyticsTests extends TelecomSystemTest { 82 private SubscriptionManager mSubscriptionManager; 83 84 @Override 85 @Before setUp()86 public void setUp() throws Exception { 87 super.setUp(); 88 // this is a mock 89 mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class); 90 when(mSubscriptionManager.createForAllUserProfiles()).thenReturn(mSubscriptionManager); 91 when(mSubscriptionManager.getActiveSubscriptionInfoList()) 92 .thenReturn(Collections.emptyList()); 93 } 94 95 @Override 96 @After tearDown()97 public void tearDown() throws Exception { 98 super.tearDown(); 99 } 100 101 @MediumTest 102 @Test testAnalyticsSingleCall()103 public void testAnalyticsSingleCall() throws Exception { 104 IdPair testCall = startAndMakeActiveIncomingCall( 105 "650-555-1212", 106 mPhoneAccountA0.getAccountHandle(), 107 mConnectionServiceFixtureA); 108 109 Map<String, Analytics.CallInfoImpl> analyticsMap = Analytics.cloneData(); 110 111 assertTrue(analyticsMap.containsKey(testCall.mCallId)); 112 113 Analytics.CallInfoImpl callAnalytics = analyticsMap.get(testCall.mCallId); 114 assertTrue(callAnalytics.startTime > 0); 115 assertEquals(0, callAnalytics.endTime); 116 assertEquals(Analytics.INCOMING_DIRECTION, callAnalytics.callDirection); 117 assertFalse(callAnalytics.isInterrupted); 118 assertNull(callAnalytics.callTerminationReason); 119 assertEquals(mConnectionServiceComponentNameA.flattenToShortString(), 120 callAnalytics.connectionService); 121 122 mConnectionServiceFixtureA. 123 sendSetDisconnected(testCall.mConnectionId, DisconnectCause.ERROR); 124 125 analyticsMap = Analytics.cloneData(); 126 callAnalytics = analyticsMap.get(testCall.mCallId); 127 assertTrue(callAnalytics.endTime > 0); 128 assertNotNull(callAnalytics.callTerminationReason); 129 assertEquals(DisconnectCause.ERROR, callAnalytics.callTerminationReason.getCode()); 130 131 StringWriter sr = new StringWriter(); 132 IndentingPrintWriter ip = new IndentingPrintWriter(sr, " "); 133 Analytics.dump(ip); 134 String dumpResult = sr.toString(); 135 String[] expectedFields = {"startTime", "endTime", "direction", "isAdditionalCall", 136 "isInterrupted", "callTechnologies", "callTerminationReason", "connectionService", 137 "missedReason"}; 138 for (String field : expectedFields) { 139 assertTrue(dumpResult.contains(field)); 140 } 141 } 142 143 @FlakyTest 144 @MediumTest 145 @Test testAnalyticsDumping()146 public void testAnalyticsDumping() throws Exception { 147 Analytics.reset(); 148 IdPair testCall = startAndMakeActiveIncomingCall( 149 "650-555-1212", 150 mPhoneAccountA0.getAccountHandle(), 151 mConnectionServiceFixtureA); 152 153 mConnectionServiceFixtureA. 154 sendSetDisconnected(testCall.mConnectionId, DisconnectCause.ERROR); 155 Analytics.CallInfoImpl expectedAnalytics = Analytics.cloneData().get(testCall.mCallId); 156 157 TelecomManager tm = (TelecomManager) mSpyContext.getSystemService(Context.TELECOM_SERVICE); 158 List<ParcelableCallAnalytics> analyticsList = tm.dumpAnalytics().getCallAnalytics(); 159 160 assertEquals(1, analyticsList.size()); 161 ParcelableCallAnalytics pCA = analyticsList.get(0); 162 163 assertTrue(Math.abs(expectedAnalytics.startTime - pCA.getStartTimeMillis()) < 164 ParcelableCallAnalytics.MILLIS_IN_5_MINUTES); 165 assertEquals(0, pCA.getStartTimeMillis() % ParcelableCallAnalytics.MILLIS_IN_5_MINUTES); 166 assertTrue(Math.abs((expectedAnalytics.endTime - expectedAnalytics.startTime) - 167 pCA.getCallDurationMillis()) < ParcelableCallAnalytics.MILLIS_IN_1_SECOND); 168 assertEquals(0, pCA.getCallDurationMillis() % ParcelableCallAnalytics.MILLIS_IN_1_SECOND); 169 170 assertEquals(expectedAnalytics.callDirection, pCA.getCallType()); 171 assertEquals(expectedAnalytics.isAdditionalCall, pCA.isAdditionalCall()); 172 assertEquals(expectedAnalytics.isInterrupted, pCA.isInterrupted()); 173 assertEquals(expectedAnalytics.callTechnologies, pCA.getCallTechnologies()); 174 assertEquals(expectedAnalytics.callTerminationReason.getCode(), 175 pCA.getCallTerminationCode()); 176 assertEquals(expectedAnalytics.connectionService, pCA.getConnectionService()); 177 List<ParcelableCallAnalytics.AnalyticsEvent> analyticsEvents = pCA.analyticsEvents(); 178 Set<Integer> capturedEvents = new HashSet<>(); 179 for (ParcelableCallAnalytics.AnalyticsEvent e : analyticsEvents) { 180 capturedEvents.add(e.getEventName()); 181 assertIsRoundedToOneSigFig(e.getTimeSinceLastEvent()); 182 } 183 assertTrue(capturedEvents.contains(ParcelableCallAnalytics.AnalyticsEvent.SET_ACTIVE)); 184 assertTrue(capturedEvents.contains( 185 ParcelableCallAnalytics.AnalyticsEvent.FILTERING_INITIATED)); 186 } 187 188 @MediumTest 189 @Test 190 public void testAnalyticsTwoCalls() throws Exception { 191 when(mTimeoutsAdapter.getCallScreeningTimeoutMillis(any(ContentResolver.class))) 192 .thenReturn((long) TEST_TIMEOUT); 193 IdPair testCall1 = startAndMakeActiveIncomingCall( 194 "650-555-1212", 195 mPhoneAccountA0.getAccountHandle(), 196 mConnectionServiceFixtureA); 197 IdPair testCall2 = startAndMakeActiveOutgoingCall( 198 "650-555-1213", 199 mPhoneAccountA0.getAccountHandle(), 200 mConnectionServiceFixtureA); 201 202 Map<String, Analytics.CallInfoImpl> analyticsMap = Analytics.cloneData(); 203 assertTrue(analyticsMap.containsKey(testCall1.mCallId)); 204 assertTrue(analyticsMap.containsKey(testCall2.mCallId)); 205 206 Analytics.CallInfoImpl callAnalytics1 = analyticsMap.get(testCall1.mCallId); 207 Analytics.CallInfoImpl callAnalytics2 = analyticsMap.get(testCall2.mCallId); 208 assertTrue(callAnalytics1.startTime > 0); 209 assertTrue(callAnalytics2.startTime > 0); 210 assertEquals(0, callAnalytics1.endTime); 211 assertEquals(0, callAnalytics2.endTime); 212 long missedReason1 = callAnalytics1.missedReason; 213 assertTrue(missedReason1 == MISSED_REASON_NOT_MISSED 214 || ((missedReason1 & USER_MISSED_CALL_FILTERS_TIMEOUT) > 0) 215 || ((missedReason1 & USER_MISSED_NO_VIBRATE) > 0)); 216 assertEquals(MISSED_REASON_NOT_MISSED, callAnalytics2.missedReason); 217 218 assertEquals(Analytics.INCOMING_DIRECTION, callAnalytics1.callDirection); 219 assertEquals(Analytics.OUTGOING_DIRECTION, callAnalytics2.callDirection); 220 221 assertTrue(callAnalytics1.isInterrupted); 222 assertTrue(callAnalytics2.isAdditionalCall); 223 224 assertNull(callAnalytics1.callTerminationReason); 225 assertNull(callAnalytics2.callTerminationReason); 226 227 assertEquals(mConnectionServiceComponentNameA.flattenToShortString(), 228 callAnalytics1.connectionService); 229 assertEquals(mConnectionServiceComponentNameA.flattenToShortString(), 230 callAnalytics1.connectionService); 231 232 mConnectionServiceFixtureA. 233 sendSetDisconnected(testCall2.mConnectionId, DisconnectCause.REMOTE); 234 mConnectionServiceFixtureA. 235 sendSetDisconnected(testCall1.mConnectionId, DisconnectCause.ERROR); 236 237 analyticsMap = Analytics.cloneData(); 238 callAnalytics1 = analyticsMap.get(testCall1.mCallId); 239 callAnalytics2 = analyticsMap.get(testCall2.mCallId); 240 assertTrue(callAnalytics1.endTime > 0); 241 assertTrue(callAnalytics2.endTime > 0); 242 assertNotNull(callAnalytics1.callTerminationReason); 243 assertNotNull(callAnalytics2.callTerminationReason); 244 assertEquals(DisconnectCause.ERROR, callAnalytics1.callTerminationReason.getCode()); 245 assertEquals(DisconnectCause.REMOTE, callAnalytics2.callTerminationReason.getCode()); 246 } 247 248 @MediumTest 249 @Test testAnalyticsVideo()250 public void testAnalyticsVideo() throws Exception { 251 Analytics.reset(); 252 IdPair callIds = startAndMakeActiveOutgoingCall( 253 "650-555-1212", 254 mPhoneAccountA0.getAccountHandle(), 255 mConnectionServiceFixtureA); 256 257 CountDownLatch counter = new CountDownLatch(1); 258 InCallService.VideoCall.Callback callback = mock(InCallService.VideoCall.Callback.class); 259 260 doAnswer(invocation -> { 261 counter.countDown(); 262 return null; 263 }).when(callback) 264 .onSessionModifyResponseReceived(anyInt(), any(VideoProfile.class), 265 any(VideoProfile.class)); 266 267 mConnectionServiceFixtureA.sendSetVideoProvider( 268 mConnectionServiceFixtureA.mLatestConnectionId); 269 InCallService.VideoCall videoCall = 270 mInCallServiceFixtureX.getCall(callIds.mCallId).getVideoCallImpl( 271 mInCallServiceComponentNameX.getPackageName(), Build.VERSION.SDK_INT); 272 videoCall.registerCallback(callback); 273 ((VideoCallImpl) videoCall).setVideoState(VideoProfile.STATE_BIDIRECTIONAL); 274 275 videoCall.sendSessionModifyRequest(new VideoProfile(VideoProfile.STATE_RX_ENABLED)); 276 counter.await(10000, TimeUnit.MILLISECONDS); 277 278 StringWriter sw = new StringWriter(); 279 PrintWriter pw = new PrintWriter(sw); 280 Analytics.dumpToEncodedProto(mContext, pw, new String[]{}); 281 TelecomLogClass.TelecomLog analyticsProto = 282 TelecomLogClass.TelecomLog.parseFrom(Base64.decode(sw.toString(), Base64.DEFAULT)); 283 284 assertEquals(1, analyticsProto.callLogs.length); 285 TelecomLogClass.VideoEvent[] videoEvents = analyticsProto.callLogs[0].videoEvents; 286 assertEquals(2, videoEvents.length); 287 288 assertEquals(Analytics.SEND_LOCAL_SESSION_MODIFY_REQUEST, videoEvents[0].getEventName()); 289 assertEquals(VideoProfile.STATE_RX_ENABLED, videoEvents[0].getVideoState()); 290 assertEquals(-1, videoEvents[0].getTimeSinceLastEventMillis()); 291 292 assertEquals(Analytics.RECEIVE_REMOTE_SESSION_MODIFY_RESPONSE, 293 videoEvents[1].getEventName()); 294 assertEquals(VideoProfile.STATE_RX_ENABLED, videoEvents[1].getVideoState()); 295 assertIsRoundedToOneSigFig(videoEvents[1].getTimeSinceLastEventMillis()); 296 } 297 298 @SmallTest 299 @Test testAnalyticsRounding()300 public void testAnalyticsRounding() { 301 long[] testVals = {0, -1, -10, -100, -57836, 1, 10, 100, 1000, 458457}; 302 long[] expected = {0, -1, -10, -100, -60000, 1, 10, 100, 1000, 500000}; 303 for (int i = 0; i < testVals.length; i++) { 304 assertEquals(expected[i], Analytics.roundToOneSigFig(testVals[i])); 305 } 306 } 307 308 @SmallTest 309 @Test testAnalyticsLogSessionTiming()310 public void testAnalyticsLogSessionTiming() throws Exception { 311 long minTime = 50; 312 Log.startSession(LogUtils.Sessions.CSW_ADD_CONFERENCE_CALL); 313 Thread.sleep(minTime); 314 Log.endSession(); 315 TelecomManager tm = (TelecomManager) mSpyContext.getSystemService(Context.TELECOM_SERVICE); 316 List<TelecomAnalytics.SessionTiming> sessions = tm.dumpAnalytics().getSessionTimings(); 317 sessions.stream() 318 .filter(s -> LogUtils.Sessions.CSW_ADD_CONFERENCE_CALL.equals( 319 Analytics.sSessionIdToLogSession.get(s.getKey()))) 320 .forEach(s -> assertTrue(s.getTime() >= minTime)); 321 } 322 323 @MediumTest 324 @Test testAnalyticsDumpToProto()325 public void testAnalyticsDumpToProto() throws Exception { 326 Analytics.reset(); 327 setupCarrierIds(); 328 IdPair testCall = startAndMakeActiveIncomingCall( 329 "650-555-1212", 330 mPhoneAccountA0.getAccountHandle(), 331 mConnectionServiceFixtureA); 332 333 mConnectionServiceFixtureA. 334 sendSetDisconnected(testCall.mConnectionId, DisconnectCause.ERROR); 335 Analytics.CallInfoImpl expectedAnalytics = Analytics.cloneData().get(testCall.mCallId); 336 337 StringWriter sw = new StringWriter(); 338 PrintWriter pw = new PrintWriter(sw); 339 Analytics.dumpToEncodedProto(mContext, pw, new String[]{}); 340 TelecomLogClass.TelecomLog analyticsProto = 341 TelecomLogClass.TelecomLog.parseFrom(Base64.decode(sw.toString(), Base64.DEFAULT)); 342 343 assertEquals(1, analyticsProto.getCarrierId()); 344 assertEquals(1, analyticsProto.callLogs.length); 345 TelecomLogClass.CallLog callLog = analyticsProto.callLogs[0]; 346 347 assertTrue(Math.abs(expectedAnalytics.startTime - callLog.getStartTime5Min()) < 348 ParcelableCallAnalytics.MILLIS_IN_5_MINUTES); 349 assertEquals(0, callLog.getStartTime5Min() % ParcelableCallAnalytics.MILLIS_IN_5_MINUTES); 350 assertTrue(Math.abs((expectedAnalytics.endTime - expectedAnalytics.startTime) - 351 callLog.getCallDurationMillis()) < ParcelableCallAnalytics.MILLIS_IN_1_SECOND); 352 assertEquals(0, 353 callLog.getCallDurationMillis() % ParcelableCallAnalytics.MILLIS_IN_1_SECOND); 354 355 assertEquals(expectedAnalytics.callDirection, callLog.getType()); 356 assertEquals(expectedAnalytics.isAdditionalCall, callLog.getIsAdditionalCall()); 357 assertEquals(expectedAnalytics.isInterrupted, callLog.getIsInterrupted()); 358 assertEquals(expectedAnalytics.callTechnologies, callLog.getCallTechnologies()); 359 assertEquals(expectedAnalytics.callTerminationReason.getCode(), 360 callLog.getCallTerminationCode()); 361 assertEquals(expectedAnalytics.connectionService, callLog.connectionService[0]); 362 TelecomLogClass.Event[] analyticsEvents = callLog.callEvents; 363 Set<Integer> capturedEvents = new HashSet<>(); 364 for (TelecomLogClass.Event e : analyticsEvents) { 365 capturedEvents.add(e.getEventName()); 366 assertIsRoundedToOneSigFig(e.getTimeSinceLastEventMillis()); 367 } 368 assertTrue(capturedEvents.contains(ParcelableCallAnalytics.AnalyticsEvent.SET_ACTIVE)); 369 assertTrue(capturedEvents.contains( 370 ParcelableCallAnalytics.AnalyticsEvent.FILTERING_INITIATED)); 371 } 372 373 @MediumTest 374 @Test 375 public void testAnalyticsAudioRoutes() throws Exception { 376 Analytics.reset(); 377 IdPair testCall = startAndMakeActiveIncomingCall( 378 "650-555-1212", 379 mPhoneAccountA0.getAccountHandle(), 380 mConnectionServiceFixtureA); 381 List<Integer> audioRoutes = new LinkedList<>(); 382 383 waitForHandlerAction( 384 mTelecomSystem.getCallsManager().getCallAudioManager() 385 .getCallAudioRouteAdapter().getAdapterHandler(), 386 TEST_TIMEOUT); 387 waitForHandlerAction( 388 mTelecomSystem.getCallsManager().getCallAudioManager() 389 .getCallAudioModeStateMachine().getHandler(), 390 TEST_TIMEOUT); 391 audioRoutes.add(mInCallServiceFixtureX.mCallAudioState.getRoute()); 392 mInCallServiceFixtureX.getInCallAdapter().setAudioRoute(CallAudioState.ROUTE_SPEAKER, null); 393 waitForHandlerAction( 394 mTelecomSystem.getCallsManager().getCallAudioManager() 395 .getCallAudioRouteAdapter().getAdapterHandler(), 396 TEST_TIMEOUT); 397 waitForHandlerAction( 398 mTelecomSystem.getCallsManager().getCallAudioManager() 399 .getCallAudioModeStateMachine().getHandler(), 400 TEST_TIMEOUT); 401 audioRoutes.add(CallAudioState.ROUTE_SPEAKER); 402 403 Map<String, Analytics.CallInfoImpl> analyticsMap = Analytics.cloneData(); 404 assertTrue(analyticsMap.containsKey(testCall.mCallId)); 405 406 Analytics.CallInfoImpl callAnalytics = analyticsMap.get(testCall.mCallId); 407 List<EventManager.Event> events = callAnalytics.callEvents.getEvents(); 408 for (int route : audioRoutes) { 409 String logEvent = CallAudioRouteStateMachine.AUDIO_ROUTE_TO_LOG_EVENT.get(route); 410 assertTrue(events.stream().anyMatch(event -> event.eventId.equals(logEvent))); 411 } 412 } 413 414 @MediumTest 415 @Test 416 public void testAnalyticsConnectionProperties() throws Exception { 417 Analytics.reset(); 418 IdPair testCall = startAndMakeActiveIncomingCall( 419 "650-555-1212", 420 mPhoneAccountA0.getAccountHandle(), 421 mConnectionServiceFixtureA); 422 423 int properties1 = Connection.PROPERTY_IS_DOWNGRADED_CONFERENCE 424 | Connection.PROPERTY_WIFI 425 | Connection.PROPERTY_EMERGENCY_CALLBACK_MODE; 426 int properties2 = Connection.PROPERTY_HIGH_DEF_AUDIO 427 | Connection.PROPERTY_WIFI; 428 int expectedProperties = properties1 | properties2; 429 430 mConnectionServiceFixtureA.mConnectionById.get(testCall.mConnectionId).properties = 431 properties1; 432 mConnectionServiceFixtureA.sendSetConnectionProperties(testCall.mConnectionId); 433 mConnectionServiceFixtureA.mConnectionById.get(testCall.mConnectionId).properties = 434 properties2; 435 mConnectionServiceFixtureA.sendSetConnectionProperties(testCall.mConnectionId); 436 437 mConnectionServiceFixtureA. 438 sendSetDisconnected(testCall.mConnectionId, DisconnectCause.ERROR); 439 440 StringWriter sw = new StringWriter(); 441 PrintWriter pw = new PrintWriter(sw); 442 Analytics.dumpToEncodedProto(mContext, pw, new String[]{}); 443 TelecomLogClass.TelecomLog analyticsProto = 444 TelecomLogClass.TelecomLog.parseFrom(Base64.decode(sw.toString(), Base64.DEFAULT)); 445 446 assertEquals(expectedProperties, 447 analyticsProto.callLogs[0].getConnectionProperties() & expectedProperties); 448 } 449 450 @SmallTest 451 @Test 452 public void testAnalyticsMaxSize() throws Exception { 453 Analytics.reset(); 454 for (int i = 0; i < Analytics.MAX_NUM_CALLS_TO_STORE * 2; i++) { 455 Analytics.initiateCallAnalytics(String.valueOf(i), Analytics.INCOMING_DIRECTION) 456 .addCallTechnology(i); 457 } 458 459 StringWriter sw = new StringWriter(); 460 PrintWriter pw = new PrintWriter(sw); 461 Analytics.dumpToEncodedProto(mContext, pw, new String[]{}); 462 TelecomLogClass.TelecomLog analyticsProto = 463 TelecomLogClass.TelecomLog.parseFrom(Base64.decode(sw.toString(), Base64.DEFAULT)); 464 465 assertEquals(Analytics.MAX_NUM_CALLS_TO_STORE, analyticsProto.callLogs.length); 466 assertEquals(Arrays.stream(analyticsProto.callLogs) 467 .filter(x -> x.getCallTechnologies() < 100) 468 .count(), 0); 469 } 470 471 private void assertIsRoundedToOneSigFig(long x) { 472 assertEquals(x, Analytics.roundToOneSigFig(x)); 473 } 474 475 private void setupCarrierIds() { 476 SubscriptionInfo subInfo1 = mock(SubscriptionInfo.class); 477 SubscriptionInfo subInfo2 = mock(SubscriptionInfo.class); 478 when(subInfo1.getCarrierId()).thenReturn(1); 479 when(subInfo2.getCarrierId()).thenReturn(2); 480 when(subInfo1.isOpportunistic()).thenReturn(false); 481 when(subInfo2.isOpportunistic()).thenReturn(true); 482 when(subInfo1.getSimSlotIndex()).thenReturn(0); 483 when(subInfo2.getSimSlotIndex()).thenReturn(1); 484 when(mSubscriptionManager.getActiveSubscriptionInfoList()) 485 .thenReturn(Arrays.asList(subInfo2, subInfo1)); 486 } 487 } 488