• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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 com.android.server.telecom.tests.ConnectionServiceFixture.STATUS_HINTS_EXTRA;
20 
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertFalse;
23 import static org.junit.Assert.assertNotNull;
24 import static org.junit.Assert.assertNull;
25 import static org.junit.Assert.assertTrue;
26 import static org.mockito.ArgumentMatchers.nullable;
27 import static org.mockito.Matchers.any;
28 import static org.mockito.Matchers.anyInt;
29 import static org.mockito.Matchers.anyString;
30 import static org.mockito.Matchers.eq;
31 import static org.mockito.Matchers.isNull;
32 import static org.mockito.Mockito.doReturn;
33 import static org.mockito.Mockito.never;
34 import static org.mockito.Mockito.timeout;
35 import static org.mockito.Mockito.times;
36 import static org.mockito.Mockito.verify;
37 import static org.mockito.Mockito.verifyZeroInteractions;
38 import static org.mockito.Mockito.when;
39 
40 import android.content.Context;
41 import android.content.IContentProvider;
42 import android.content.pm.PackageManager;
43 import android.media.AudioDeviceInfo;
44 import android.content.Intent;
45 import android.graphics.drawable.Icon;
46 import android.media.AudioManager;
47 import android.net.Uri;
48 import android.os.Binder;
49 import android.os.Bundle;
50 import android.os.Handler;
51 import android.os.Looper;
52 import android.os.Process;
53 import android.os.UserHandle;
54 import android.provider.BlockedNumberContract;
55 import android.telecom.Call;
56 import android.telecom.CallAudioState;
57 import android.telecom.Connection;
58 import android.telecom.ConnectionRequest;
59 import android.telecom.DisconnectCause;
60 import android.telecom.Log;
61 import android.telecom.ParcelableCall;
62 import android.telecom.PhoneAccount;
63 import android.telecom.PhoneAccountHandle;
64 import android.telecom.StatusHints;
65 import android.telecom.TelecomManager;
66 import android.telecom.VideoProfile;
67 import android.test.suitebuilder.annotation.LargeTest;
68 import android.test.suitebuilder.annotation.MediumTest;
69 
70 import androidx.test.filters.FlakyTest;
71 import androidx.test.filters.SmallTest;
72 
73 import com.android.internal.telecom.IInCallAdapter;
74 import android.telecom.CallerInfo;
75 
76 import com.google.common.base.Predicate;
77 
78 import org.junit.After;
79 import org.junit.Before;
80 import org.junit.Ignore;
81 import org.junit.Test;
82 import org.junit.runner.RunWith;
83 import org.junit.runners.JUnit4;
84 import org.mockito.ArgumentCaptor;
85 import org.mockito.invocation.InvocationOnMock;
86 import org.mockito.stubbing.Answer;
87 
88 import java.util.List;
89 import java.util.concurrent.BrokenBarrierException;
90 import java.util.concurrent.CountDownLatch;
91 import java.util.concurrent.CyclicBarrier;
92 import java.util.concurrent.TimeUnit;
93 
94 /**
95  * Performs various basic call tests in Telecom.
96  */
97 @RunWith(JUnit4.class)
98 public class BasicCallTests extends TelecomSystemTest {
99     private static final String TEST_BUNDLE_KEY = "android.telecom.extra.TEST";
100     private static final String TEST_EVENT = "android.telecom.event.TEST";
101 
102     private PackageManager mPackageManager;
103 
104     @Override
105     @Before
setUp()106     public void setUp() throws Exception {
107         super.setUp();
108         doReturn(mContext).when(mContext).createContextAsUser(any(UserHandle.class), anyInt());
109         mPackageManager = mContext.getPackageManager();
110         when(mPackageManager.getPackageUid(anyString(), eq(0))).thenReturn(Binder.getCallingUid());
111     }
112 
113     @Override
114     @After
tearDown()115     public void tearDown() throws Exception {
116         super.tearDown();
117     }
118 
119     @LargeTest
120     @Test
testSingleOutgoingCallLocalDisconnect()121     public void testSingleOutgoingCallLocalDisconnect() throws Exception {
122         IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
123                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
124 
125         mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
126         assertEquals(Call.STATE_DISCONNECTING,
127                 mInCallServiceFixtureX.getCall(ids.mCallId).getState());
128         assertEquals(Call.STATE_DISCONNECTING,
129                 mInCallServiceFixtureY.getCall(ids.mCallId).getState());
130 
131         when(mClockProxy.currentTimeMillis()).thenReturn(TEST_DISCONNECT_TIME);
132         when(mClockProxy.elapsedRealtime()).thenReturn(TEST_DISCONNECT_ELAPSED_TIME);
133         mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
134         assertEquals(Call.STATE_DISCONNECTED,
135                 mInCallServiceFixtureX.getCall(ids.mCallId).getState());
136         assertEquals(Call.STATE_DISCONNECTED,
137                 mInCallServiceFixtureY.getCall(ids.mCallId).getState());
138         assertEquals(TEST_CONNECT_TIME,
139                 mInCallServiceFixtureX.getCall(ids.mCallId).getConnectTimeMillis());
140         assertEquals(TEST_CONNECT_TIME,
141                 mInCallServiceFixtureY.getCall(ids.mCallId).getConnectTimeMillis());
142         assertEquals(TEST_CREATE_TIME,
143                 mInCallServiceFixtureX.getCall(ids.mCallId).getCreationTimeMillis());
144         assertEquals(TEST_CREATE_TIME,
145                 mInCallServiceFixtureY.getCall(ids.mCallId).getCreationTimeMillis());
146 
147         verifyNoBlockChecks();
148     }
149 
150     @LargeTest
151     @Test
testSingleOutgoingCallRemoteDisconnect()152     public void testSingleOutgoingCallRemoteDisconnect() throws Exception {
153         IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
154                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
155 
156         when(mClockProxy.currentTimeMillis()).thenReturn(TEST_DISCONNECT_TIME);
157         when(mClockProxy.elapsedRealtime()).thenReturn(TEST_DISCONNECT_ELAPSED_TIME);
158         mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
159         assertEquals(Call.STATE_DISCONNECTED,
160                 mInCallServiceFixtureX.getCall(ids.mCallId).getState());
161         assertEquals(Call.STATE_DISCONNECTED,
162                 mInCallServiceFixtureY.getCall(ids.mCallId).getState());
163         verifyNoBlockChecks();
164     }
165 
166     /**
167      * Tests the {@link TelecomManager#acceptRingingCall()} API.  Tests simple case of an incoming
168      * audio-only call.
169      *
170      * @throws Exception
171      */
172     @LargeTest
173     @Test
testTelecomManagerAcceptRingingCall()174     public void testTelecomManagerAcceptRingingCall() throws Exception {
175         IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
176                 mConnectionServiceFixtureA);
177 
178         assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
179         assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
180 
181         // Use TelecomManager API to answer the ringing call.
182         TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble()
183                 .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
184         telecomManager.acceptRingingCall();
185 
186         waitForHandlerAction(mTelecomSystem.getCallsManager()
187                 .getConnectionServiceFocusManager().getHandler(), TEST_TIMEOUT);
188 
189         verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
190                 .answer(eq(ids.mConnectionId), any());
191         mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);
192 
193         mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
194     }
195 
196     /**
197      * Tests the {@link TelecomManager#acceptRingingCall()} API.  Tests simple case of an incoming
198      * video call, which should be answered as video.
199      *
200      * @throws Exception
201      */
202     @LargeTest
203     @Test
testTelecomManagerAcceptRingingVideoCall()204     public void testTelecomManagerAcceptRingingVideoCall() throws Exception {
205         IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
206                 VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA, null);
207 
208         assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
209         assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
210 
211         // Use TelecomManager API to answer the ringing call; the default expected behavior is to
212         // answer using whatever video state the ringing call requests.
213         TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble()
214                 .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
215         telecomManager.acceptRingingCall();
216 
217         // Answer video API should be called
218         verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
219                 .answerVideo(eq(ids.mConnectionId), eq(VideoProfile.STATE_BIDIRECTIONAL), any());
220         mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);
221 
222         mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
223     }
224 
225     /**
226      * Tests the {@link TelecomManager#acceptRingingCall(int)} API.  Tests answering a video call
227      * as an audio call.
228      *
229      * @throws Exception
230      */
231     @LargeTest
232     @Test
testTelecomManagerAcceptRingingVideoCallAsAudio()233     public void testTelecomManagerAcceptRingingVideoCallAsAudio() throws Exception {
234         IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
235                 VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA, null);
236 
237         assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
238         assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
239 
240         // Use TelecomManager API to answer the ringing call.
241         TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble()
242                 .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
243         telecomManager.acceptRingingCall(VideoProfile.STATE_AUDIO_ONLY);
244 
245         waitForHandlerAction(mTelecomSystem.getCallsManager()
246                 .getConnectionServiceFocusManager().getHandler(), TEST_TIMEOUT);
247 
248         // The generic answer method on the ConnectionService is used to answer audio-only calls.
249         verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
250                 .answer(eq(ids.mConnectionId), any());
251         mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);
252 
253         mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
254     }
255 
256     /**
257      * Tests the {@link TelecomManager#acceptRingingCall()} API.  Tests simple case of an incoming
258      * video call, where an attempt is made to answer with an invalid video state.
259      *
260      * @throws Exception
261      */
262     @LargeTest
263     @Test
testTelecomManagerAcceptRingingInvalidVideoState()264     public void testTelecomManagerAcceptRingingInvalidVideoState() throws Exception {
265         IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
266                 VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA, null);
267 
268         assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
269         assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
270 
271         // Use TelecomManager API to answer the ringing call; the default expected behavior is to
272         // answer using whatever video state the ringing call requests.
273         TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble()
274                 .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
275         telecomManager.acceptRingingCall(999 /* invalid videostate */);
276 
277         waitForHandlerAction(mTelecomSystem.getCallsManager()
278                 .getConnectionServiceFocusManager().getHandler(), TEST_TIMEOUT);
279 
280         // Answer video API should be called
281         verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
282                 .answerVideo(eq(ids.mConnectionId), eq(VideoProfile.STATE_BIDIRECTIONAL), any());
283         mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);
284         mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
285     }
286 
287     @LargeTest
288     @Test
testSingleIncomingCallLocalDisconnect()289     public void testSingleIncomingCallLocalDisconnect() throws Exception {
290         IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
291                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
292         mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
293         assertEquals(Call.STATE_DISCONNECTING,
294                 mInCallServiceFixtureX.getCall(ids.mCallId).getState());
295         assertEquals(Call.STATE_DISCONNECTING,
296                 mInCallServiceFixtureY.getCall(ids.mCallId).getState());
297 
298         when(mClockProxy.currentTimeMillis()).thenReturn(TEST_DISCONNECT_TIME);
299         when(mClockProxy.elapsedRealtime()).thenReturn(TEST_DISCONNECT_ELAPSED_TIME);
300         mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
301 
302         assertEquals(Call.STATE_DISCONNECTED,
303                 mInCallServiceFixtureX.getCall(ids.mCallId).getState());
304         assertEquals(Call.STATE_DISCONNECTED,
305                 mInCallServiceFixtureY.getCall(ids.mCallId).getState());
306     }
307 
308     @LargeTest
309     @Test
testSingleIncomingCallRemoteDisconnect()310     public void testSingleIncomingCallRemoteDisconnect() throws Exception {
311         IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
312                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
313 
314         when(mClockProxy.currentTimeMillis()).thenReturn(TEST_DISCONNECT_TIME);
315         when(mClockProxy.elapsedRealtime()).thenReturn(TEST_DISCONNECT_ELAPSED_TIME);
316         mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
317         assertEquals(Call.STATE_DISCONNECTED,
318                 mInCallServiceFixtureX.getCall(ids.mCallId).getState());
319         assertEquals(Call.STATE_DISCONNECTED,
320                 mInCallServiceFixtureY.getCall(ids.mCallId).getState());
321     }
322 
323     @LargeTest
324     @Test
testIncomingEmergencyCallback()325     public void testIncomingEmergencyCallback() throws Exception {
326         // Make an outgoing emergency call
327         String phoneNumber = "650-555-1212";
328         IdPair ids = startAndMakeDialingEmergencyCall(phoneNumber,
329                 mPhoneAccountE0.getAccountHandle(), mConnectionServiceFixtureA);
330         mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
331         mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
332 
333         // Incoming call should be marked as a potential emergency callback
334         Bundle extras = new Bundle();
335         extras.putParcelable(
336                 TelecomManager.EXTRA_INCOMING_CALL_ADDRESS,
337                 Uri.fromParts(PhoneAccount.SCHEME_TEL, phoneNumber, null));
338         mTelecomSystem.getTelecomServiceImpl().getBinder()
339                 .addNewIncomingCall(mPhoneAccountA0.getAccountHandle(), extras);
340 
341         waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
342                 TEST_TIMEOUT);
343         ArgumentCaptor<ConnectionRequest> connectionRequestCaptor
344             = ArgumentCaptor.forClass(ConnectionRequest.class);
345         verify(mConnectionServiceFixtureA.getTestDouble())
346                 .createConnection(any(PhoneAccountHandle.class), anyString(),
347                         connectionRequestCaptor.capture(), eq(true), eq(false), any());
348 
349         assertTrue(connectionRequestCaptor.getValue().getExtras().containsKey(
350             android.telecom.Call.EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS));
351         assertTrue(connectionRequestCaptor.getValue().getExtras().getLong(
352             android.telecom.Call.EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS, 0) > 0);
353         assertTrue(connectionRequestCaptor.getValue().getExtras().containsKey(
354             TelecomManager.EXTRA_INCOMING_CALL_ADDRESS));
355     }
356 
357     @LargeTest
358     @Test
testOutgoingCallAndSelectPhoneAccount()359     public void testOutgoingCallAndSelectPhoneAccount() throws Exception {
360         // Remove default PhoneAccount so that the Call moves into the correct
361         // SELECT_PHONE_ACCOUNT state.
362         mTelecomSystem.getPhoneAccountRegistrar().setUserSelectedOutgoingPhoneAccount(
363                 null, Process.myUserHandle());
364         int startingNumConnections = mConnectionServiceFixtureA.mConnectionById.size();
365         int startingNumCalls = mInCallServiceFixtureX.mCallById.size();
366         String callId = startOutgoingPhoneCallWithNoPhoneAccount("650-555-1212",
367                 mConnectionServiceFixtureA);
368         mTelecomSystem.getCallsManager().getLatestPreAccountSelectionFuture().join();
369         waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
370                 TEST_TIMEOUT);
371         assertEquals(Call.STATE_SELECT_PHONE_ACCOUNT,
372                 mInCallServiceFixtureX.getCall(callId).getState());
373         assertEquals(Call.STATE_SELECT_PHONE_ACCOUNT,
374                 mInCallServiceFixtureY.getCall(callId).getState());
375         mInCallServiceFixtureX.mInCallAdapter.phoneAccountSelected(callId,
376                 mPhoneAccountA0.getAccountHandle(), false);
377         waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
378                 TEST_TIMEOUT);
379         waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
380                 TEST_TIMEOUT);
381         verifyAndProcessOutgoingCallBroadcast(mPhoneAccountA0.getAccountHandle());
382 
383         IdPair ids = outgoingCallPhoneAccountSelected(mPhoneAccountA0.getAccountHandle(),
384                 startingNumConnections, startingNumCalls, mConnectionServiceFixtureA);
385 
386         when(mClockProxy.currentTimeMillis()).thenReturn(TEST_DISCONNECT_TIME);
387         when(mClockProxy.elapsedRealtime()).thenReturn(TEST_DISCONNECT_ELAPSED_TIME);
388         mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
389         assertEquals(Call.STATE_DISCONNECTED,
390                 mInCallServiceFixtureX.getCall(ids.mCallId).getState());
391         assertEquals(Call.STATE_DISCONNECTED,
392                 mInCallServiceFixtureY.getCall(ids.mCallId).getState());
393     }
394 
395     @FlakyTest
396     @LargeTest
397     @Test
testIncomingCallFromContactWithSendToVoicemailIsRejected()398     public void testIncomingCallFromContactWithSendToVoicemailIsRejected() throws Exception {
399         Bundle extras = new Bundle();
400         extras.putParcelable(
401                 TelecomManager.EXTRA_INCOMING_CALL_ADDRESS,
402                 Uri.fromParts(PhoneAccount.SCHEME_TEL, "650-555-1212", null));
403         mTelecomSystem.getTelecomServiceImpl().getBinder()
404                 .addNewIncomingCall(mPhoneAccountA0.getAccountHandle(), extras);
405 
406         waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
407                 TEST_TIMEOUT);
408         verify(mConnectionServiceFixtureA.getTestDouble())
409                 .createConnection(any(PhoneAccountHandle.class), anyString(),
410                         any(ConnectionRequest.class), eq(true), eq(false), any());
411 
412         waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
413                 TEST_TIMEOUT);
414         assertEquals(1, mCallerInfoAsyncQueryFactoryFixture.mRequests.size());
415 
416         CallerInfo sendToVoicemailCallerInfo = new CallerInfo();
417         sendToVoicemailCallerInfo.shouldSendToVoicemail = true;
418         sendToVoicemailCallerInfo.contactExists = true;
419         mCallerInfoAsyncQueryFactoryFixture.setResponse(sendToVoicemailCallerInfo);
420         for (CallerInfoAsyncQueryFactoryFixture.Request request :
421                 mCallerInfoAsyncQueryFactoryFixture.mRequests) {
422             request.replyWithCallerInfo(sendToVoicemailCallerInfo);
423         }
424 
425         assertTrueWithTimeout(new Predicate<Void>() {
426             @Override
427             public boolean apply(Void aVoid) {
428                 return mConnectionServiceFixtureA.mConnectionService.rejectedCallIds.size() == 1;
429             }
430         });
431         assertTrueWithTimeout(new Predicate<Void>() {
432             @Override
433             public boolean apply(Void aVoid) {
434                 return mMissedCallNotifier.missedCallsNotified.size() == 1;
435             }
436         });
437 
438         verify(mInCallServiceFixtureX.getTestDouble(), never())
439                 .setInCallAdapter(any(IInCallAdapter.class));
440         verify(mInCallServiceFixtureY.getTestDouble(), never())
441                 .setInCallAdapter(any(IInCallAdapter.class));
442     }
443 
444     @LargeTest
445     @Test
testIncomingCallCallerInfoLookupTimesOutIsAllowed()446     public void testIncomingCallCallerInfoLookupTimesOutIsAllowed() throws Exception {
447         when(mClockProxy.currentTimeMillis()).thenReturn(TEST_CREATE_TIME);
448         when(mClockProxy.elapsedRealtime()).thenReturn(TEST_CREATE_ELAPSED_TIME);
449         Bundle extras = new Bundle();
450         extras.putParcelable(
451                 TelecomManager.EXTRA_INCOMING_CALL_ADDRESS,
452                 Uri.fromParts(PhoneAccount.SCHEME_TEL, "650-555-1212", null));
453         mTelecomSystem.getTelecomServiceImpl().getBinder()
454                 .addNewIncomingCall(mPhoneAccountA0.getAccountHandle(), extras);
455 
456         waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
457                 TEST_TIMEOUT);
458         verify(mConnectionServiceFixtureA.getTestDouble())
459                 .createConnection(any(PhoneAccountHandle.class), anyString(),
460                         any(ConnectionRequest.class), eq(true), eq(false), any());
461 
462         waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
463                 TEST_TIMEOUT);
464         // Never reply to the caller info lookup.
465         assertEquals(1, mCallerInfoAsyncQueryFactoryFixture.mRequests.size());
466 
467         verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT))
468                 .setInCallAdapter(any(IInCallAdapter.class));
469         verify(mInCallServiceFixtureY.getTestDouble(), timeout(TEST_TIMEOUT))
470                 .setInCallAdapter(any(IInCallAdapter.class));
471 
472         assertEquals(0, mConnectionServiceFixtureA.mConnectionService.rejectedCallIds.size());
473         assertEquals(0, mMissedCallNotifier.missedCallsNotified.size());
474 
475         assertTrueWithTimeout(new Predicate<Void>() {
476             @Override
477             public boolean apply(Void v) {
478                 return mInCallServiceFixtureX.mInCallAdapter != null;
479             }
480         });
481 
482         verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT))
483                 .addCall(any(ParcelableCall.class));
484         verify(mInCallServiceFixtureY.getTestDouble(), timeout(TEST_TIMEOUT))
485                 .addCall(any(ParcelableCall.class));
486 
487         when(mClockProxy.currentTimeMillis()).thenReturn(TEST_CONNECT_TIME);
488         when(mClockProxy.elapsedRealtime()).thenReturn(TEST_CONNECT_ELAPSED_TIME);
489         disconnectCall(mInCallServiceFixtureX.mLatestCallId,
490                 mConnectionServiceFixtureA.mLatestConnectionId);
491     }
492 
493     @LargeTest
494     @Test
495     @FlakyTest
496     @Ignore("b/189904580")
testIncomingCallFromBlockedNumberIsRejected()497     public void testIncomingCallFromBlockedNumberIsRejected() throws Exception {
498         String phoneNumber = "650-555-1212";
499         blockNumber(phoneNumber);
500 
501         Bundle extras = new Bundle();
502         extras.putParcelable(
503                 TelecomManager.EXTRA_INCOMING_CALL_ADDRESS,
504                 Uri.fromParts(PhoneAccount.SCHEME_TEL, phoneNumber, null));
505         mTelecomSystem.getTelecomServiceImpl().getBinder()
506                 .addNewIncomingCall(mPhoneAccountA0.getAccountHandle(), extras);
507 
508         waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
509                 TEST_TIMEOUT);
510         verify(mConnectionServiceFixtureA.getTestDouble())
511                 .createConnection(any(PhoneAccountHandle.class), anyString(),
512                         any(ConnectionRequest.class), eq(true), eq(false), any());
513 
514         waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
515                 TEST_TIMEOUT);
516 
517         assertEquals(1, mCallerInfoAsyncQueryFactoryFixture.mRequests.size());
518         for (CallerInfoAsyncQueryFactoryFixture.Request request :
519                 mCallerInfoAsyncQueryFactoryFixture.mRequests) {
520             request.reply();
521         }
522 
523         assertTrueWithTimeout(new Predicate<Void>() {
524             @Override
525             public boolean apply(Void aVoid) {
526                 return mConnectionServiceFixtureA.mConnectionService.rejectedCallIds.size() == 1;
527             }
528         });
529         assertEquals(0, mMissedCallNotifier.missedCallsNotified.size());
530 
531         verify(mInCallServiceFixtureX.getTestDouble(), never())
532                 .setInCallAdapter(any(IInCallAdapter.class));
533         verify(mInCallServiceFixtureY.getTestDouble(), never())
534                 .setInCallAdapter(any(IInCallAdapter.class));
535     }
536 
537     @LargeTest
538     @Test
testIncomingCallBlockCheckTimesoutIsAllowed()539     public void testIncomingCallBlockCheckTimesoutIsAllowed() throws Exception {
540         final CountDownLatch latch = new CountDownLatch(1);
541         String phoneNumber = "650-555-1212";
542         blockNumberWithAnswer(phoneNumber, new Answer<Bundle>() {
543             @Override
544             public Bundle answer(InvocationOnMock invocation) throws Throwable {
545                 latch.await(TEST_TIMEOUT * 2, TimeUnit.MILLISECONDS);
546                 Bundle bundle = new Bundle();
547                 bundle.putBoolean(BlockedNumberContract.RES_NUMBER_IS_BLOCKED, true);
548                 return bundle;
549             }
550         });
551 
552         IdPair ids = startAndMakeActiveIncomingCall(
553                 phoneNumber, mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
554         latch.countDown();
555 
556         assertEquals(0, mConnectionServiceFixtureA.mConnectionService.rejectedCallIds.size());
557         assertEquals(0, mMissedCallNotifier.missedCallsNotified.size());
558         disconnectCall(ids.mCallId, ids.mConnectionId);
559     }
560 
do_testDeadlockOnOutgoingCall()561     public void do_testDeadlockOnOutgoingCall() throws Exception {
562         final IdPair ids = startOutgoingPhoneCall("650-555-1212",
563                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA,
564                 Process.myUserHandle());
565         rapidFire(
566                 new Runnable() {
567                     @Override
568                     public void run() {
569                         while (mCallerInfoAsyncQueryFactoryFixture.mRequests.size() > 0) {
570                             mCallerInfoAsyncQueryFactoryFixture.mRequests.remove(0).reply();
571                         }
572                     }
573                 },
574                 new Runnable() {
575                     @Override
576                     public void run() {
577                         try {
578                             mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);
579                         } catch (Exception e) {
580                             Log.e(this, e, "");
581                         }
582                     }
583                 });
584     }
585 
586     @LargeTest
587     @Test
testIncomingThenOutgoingCalls()588     public void testIncomingThenOutgoingCalls() throws Exception {
589         // TODO: We have to use the same PhoneAccount for both; see http://b/18461539
590         IdPair incoming = startAndMakeActiveIncomingCall("650-555-2323",
591                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
592         IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1212",
593                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
594 
595         mInCallServiceFixtureX.mInCallAdapter.disconnectCall(incoming.mCallId);
596         mInCallServiceFixtureX.mInCallAdapter.disconnectCall(outgoing.mCallId);
597     }
598 
599     @LargeTest
600     @Test
testOutgoingThenIncomingCalls()601     public void testOutgoingThenIncomingCalls() throws Exception {
602         // TODO: We have to use the same PhoneAccount for both; see http://b/18461539
603         IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1212",
604                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
605         waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
606                 TEST_TIMEOUT);
607         IdPair incoming = startAndMakeActiveIncomingCall("650-555-2323",
608                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
609         waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
610                 TEST_TIMEOUT);
611         verify(mConnectionServiceFixtureA.getTestDouble())
612                 .hold(eq(outgoing.mConnectionId), any());
613         mConnectionServiceFixtureA.mConnectionById.get(outgoing.mConnectionId).state =
614                 Connection.STATE_HOLDING;
615         mConnectionServiceFixtureA.sendSetOnHold(outgoing.mConnectionId);
616         assertEquals(Call.STATE_HOLDING,
617                 mInCallServiceFixtureX.getCall(outgoing.mCallId).getState());
618         assertEquals(Call.STATE_HOLDING,
619                 mInCallServiceFixtureY.getCall(outgoing.mCallId).getState());
620 
621         mInCallServiceFixtureX.mInCallAdapter.disconnectCall(incoming.mCallId);
622         mInCallServiceFixtureX.mInCallAdapter.disconnectCall(outgoing.mCallId);
623     }
624 
625     @LargeTest
626     @Test
testAudioManagerOperations()627     public void testAudioManagerOperations() throws Exception {
628         AudioManager audioManager = (AudioManager) mComponentContextFixture.getTestDouble()
629                 .getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
630 
631         IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1212",
632                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
633 
634         verify(audioManager, timeout(TEST_TIMEOUT)).requestAudioFocusForCall(anyInt(), anyInt());
635         verify(audioManager, timeout(TEST_TIMEOUT).atLeastOnce())
636                 .setMode(AudioManager.MODE_IN_CALL);
637 
638         mInCallServiceFixtureX.mInCallAdapter.mute(true);
639         verify(mAudioService, timeout(TEST_TIMEOUT))
640                 .setMicrophoneMute(eq(true), any(String.class), any(Integer.class),
641                         nullable(String.class));
642         mInCallServiceFixtureX.mInCallAdapter.mute(false);
643         verify(mAudioService, timeout(TEST_TIMEOUT))
644                 .setMicrophoneMute(eq(false), any(String.class), any(Integer.class),
645                         nullable(String.class));
646 
647         mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_SPEAKER, null);
648         waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager()
649                 .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT);
650         ArgumentCaptor<AudioDeviceInfo> infoArgumentCaptor =
651                 ArgumentCaptor.forClass(AudioDeviceInfo.class);
652         verify(audioManager, timeout(TEST_TIMEOUT)).setCommunicationDevice(
653                 infoArgumentCaptor.capture());
654         assertEquals(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, infoArgumentCaptor.getValue().getType());
655         mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_EARPIECE, null);
656         waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager()
657                 .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT);
658         // setSpeakerPhoneOn(false) gets called once during the call initiation phase
659         verify(audioManager, timeout(TEST_TIMEOUT).atLeast(1))
660                 .clearCommunicationDevice();
661 
662         mConnectionServiceFixtureA.
663                 sendSetDisconnected(outgoing.mConnectionId, DisconnectCause.REMOTE);
664 
665         waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager()
666                 .getCallAudioModeStateMachine().getHandler(), TEST_TIMEOUT);
667         waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager()
668                 .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT);
669         verify(audioManager, timeout(TEST_TIMEOUT))
670                 .abandonAudioFocusForCall();
671         verify(audioManager, timeout(TEST_TIMEOUT).atLeastOnce())
672                 .setMode(AudioManager.MODE_NORMAL);
673     }
674 
rapidFire(Runnable... tasks)675     private void rapidFire(Runnable... tasks) {
676         final CyclicBarrier barrier = new CyclicBarrier(tasks.length);
677         final CountDownLatch latch = new CountDownLatch(tasks.length);
678         for (int i = 0; i < tasks.length; i++) {
679             final Runnable task = tasks[i];
680             new Thread(new Runnable() {
681                 @Override
682                 public void run() {
683                     try {
684                         barrier.await();
685                         task.run();
686                     } catch (InterruptedException | BrokenBarrierException e){
687                         Log.e(BasicCallTests.this, e, "Unexpectedly interrupted");
688                     } finally {
689                         latch.countDown();
690                     }
691                 }
692             }).start();
693         }
694         try {
695             latch.await();
696         } catch (InterruptedException e) {
697             Log.e(BasicCallTests.this, e, "Unexpectedly interrupted");
698         }
699     }
700 
701     @MediumTest
702     @Test
testBasicConferenceCall()703     public void testBasicConferenceCall() throws Exception {
704         makeConferenceCall(null, null);
705     }
706 
707     @MediumTest
708     @Test
testAddCallToConference1()709     public void testAddCallToConference1() throws Exception {
710         ParcelableCall conferenceCall = makeConferenceCall(null, null);
711         IdPair callId3 = startAndMakeActiveOutgoingCall("650-555-1214",
712                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
713         // testAddCallToConference{1,2} differ in the order of arguments to InCallAdapter#conference
714         mInCallServiceFixtureX.getInCallAdapter().conference(
715                 conferenceCall.getId(), callId3.mCallId);
716         Thread.sleep(200);
717 
718         ParcelableCall call3 = mInCallServiceFixtureX.getCall(callId3.mCallId);
719         ParcelableCall updatedConference = mInCallServiceFixtureX.getCall(conferenceCall.getId());
720         assertEquals(conferenceCall.getId(), call3.getParentCallId());
721         assertEquals(3, updatedConference.getChildCallIds().size());
722         assertTrue(updatedConference.getChildCallIds().contains(callId3.mCallId));
723     }
724 
725     @MediumTest
726     @Test
testAddCallToConference2()727     public void testAddCallToConference2() throws Exception {
728         ParcelableCall conferenceCall = makeConferenceCall(null, null);
729         IdPair callId3 = startAndMakeActiveOutgoingCall("650-555-1214",
730                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
731         mInCallServiceFixtureX.getInCallAdapter()
732                 .conference(callId3.mCallId, conferenceCall.getId());
733         Thread.sleep(200);
734 
735         ParcelableCall call3 = mInCallServiceFixtureX.getCall(callId3.mCallId);
736         ParcelableCall updatedConference = mInCallServiceFixtureX.getCall(conferenceCall.getId());
737         assertEquals(conferenceCall.getId(), call3.getParentCallId());
738         assertEquals(3, updatedConference.getChildCallIds().size());
739         assertTrue(updatedConference.getChildCallIds().contains(callId3.mCallId));
740     }
741 
742     /**
743      * Tests the {@link Call#pullExternalCall()} API.  Verifies that if a call is not an external
744      * call, no pull call request is made to the connection service.
745      *
746      * @throws Exception
747      */
748     @MediumTest
749     @Test
testPullNonExternalCall()750     public void testPullNonExternalCall() throws Exception {
751         // TODO: Revisit this unit test once telecom support for filtering external calls from
752         // InCall services is implemented.
753         IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
754                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
755         assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
756 
757         // Attempt to pull the call and verify the API call makes it through
758         mInCallServiceFixtureX.mInCallAdapter.pullExternalCall(ids.mCallId);
759         Thread.sleep(TEST_TIMEOUT);
760         verify(mConnectionServiceFixtureA.getTestDouble(), never())
761                 .pullExternalCall(eq(ids.mCallId), any());
762     }
763 
764     /**
765      * Tests the {@link Connection#sendConnectionEvent(String, Bundle)} API.
766      *
767      * @throws Exception
768      */
769     @MediumTest
770     @Test
testSendConnectionEventNull()771     public void testSendConnectionEventNull() throws Exception {
772         IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
773                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
774         assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
775         mConnectionServiceFixtureA.sendConnectionEvent(ids.mConnectionId, TEST_EVENT, null);
776         verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT))
777                 .onConnectionEvent(ids.mCallId, TEST_EVENT, null);
778     }
779 
780     /**
781      * Tests the {@link Connection#sendConnectionEvent(String, Bundle)} API.
782      *
783      * @throws Exception
784      */
785     @MediumTest
786     @Test
testSendConnectionEventNotNull()787     public void testSendConnectionEventNotNull() throws Exception {
788         IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
789                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
790         assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
791 
792         Bundle testBundle = new Bundle();
793         testBundle.putString(TEST_BUNDLE_KEY, "TEST");
794 
795         ArgumentCaptor<Bundle> bundleArgumentCaptor = ArgumentCaptor.forClass(Bundle.class);
796         mConnectionServiceFixtureA.sendConnectionEvent(ids.mConnectionId, TEST_EVENT, testBundle);
797         verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT))
798                 .onConnectionEvent(eq(ids.mCallId), eq(TEST_EVENT), bundleArgumentCaptor.capture());
799         assert (bundleArgumentCaptor.getValue().containsKey(TEST_BUNDLE_KEY));
800     }
801 
802     /**
803      * Tests the {@link Call#sendCallEvent(String, Bundle)} API.
804      *
805      * @throws Exception
806      */
807     @MediumTest
808     @Test
testSendCallEventNull()809     public void testSendCallEventNull() throws Exception {
810         IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
811                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
812         assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
813 
814         mInCallServiceFixtureX.mInCallAdapter.sendCallEvent(ids.mCallId, TEST_EVENT, 26, null);
815         verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
816                 .sendCallEvent(eq(ids.mConnectionId), eq(TEST_EVENT), isNull(Bundle.class), any());
817     }
818 
819     /**
820      * Tests the {@link Call#sendCallEvent(String, Bundle)} API.
821      *
822      * @throws Exception
823      */
824     @MediumTest
825     @Test
testSendCallEventNonNull()826     public void testSendCallEventNonNull() throws Exception {
827         IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
828                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
829         assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
830 
831         Bundle testBundle = new Bundle();
832         testBundle.putString(TEST_BUNDLE_KEY, "TEST");
833 
834         ArgumentCaptor<Bundle> bundleArgumentCaptor = ArgumentCaptor.forClass(Bundle.class);
835         mInCallServiceFixtureX.mInCallAdapter.sendCallEvent(ids.mCallId, TEST_EVENT, 26,
836                 testBundle);
837         verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
838                 .sendCallEvent(eq(ids.mConnectionId), eq(TEST_EVENT),
839                         bundleArgumentCaptor.capture(), any());
840         assert (bundleArgumentCaptor.getValue().containsKey(TEST_BUNDLE_KEY));
841     }
842 
blockNumber(String phoneNumber)843     private void blockNumber(String phoneNumber) throws Exception {
844         blockNumberWithAnswer(phoneNumber, new Answer<Bundle>() {
845             @Override
846             public Bundle answer(InvocationOnMock invocation) throws Throwable {
847                 Bundle bundle = new Bundle();
848                 bundle.putInt(BlockedNumberContract.RES_BLOCK_STATUS,
849                         BlockedNumberContract.STATUS_BLOCKED_IN_LIST);
850                 return bundle;
851             }
852         });
853     }
854 
blockNumberWithAnswer(String phoneNumber, Answer answer)855     private void blockNumberWithAnswer(String phoneNumber, Answer answer) throws Exception {
856         when(getBlockedNumberProvider().call(
857                 any(),
858                 anyString(),
859                 eq(BlockedNumberContract.SystemContract.METHOD_SHOULD_SYSTEM_BLOCK_NUMBER),
860                 eq(phoneNumber),
861                 nullable(Bundle.class))).thenAnswer(answer);
862     }
863 
verifyNoBlockChecks()864     private void verifyNoBlockChecks() {
865         verifyZeroInteractions(getBlockedNumberProvider());
866     }
867 
getBlockedNumberProvider()868     private IContentProvider getBlockedNumberProvider() {
869         return mSpyContext.getContentResolver().acquireProvider(BlockedNumberContract.AUTHORITY);
870     }
871 
disconnectCall(String callId, String connectionId)872     private void disconnectCall(String callId, String connectionId) throws Exception {
873         when(mClockProxy.currentTimeMillis()).thenReturn(TEST_DISCONNECT_TIME);
874         when(mClockProxy.elapsedRealtime()).thenReturn(TEST_DISCONNECT_ELAPSED_TIME);
875         mConnectionServiceFixtureA.sendSetDisconnected(connectionId, DisconnectCause.LOCAL);
876         assertEquals(Call.STATE_DISCONNECTED, mInCallServiceFixtureX.getCall(callId).getState());
877         assertEquals(Call.STATE_DISCONNECTED, mInCallServiceFixtureY.getCall(callId).getState());
878         assertEquals(TEST_CREATE_TIME,
879                 mInCallServiceFixtureX.getCall(callId).getCreationTimeMillis());
880         assertEquals(TEST_CREATE_TIME,
881                 mInCallServiceFixtureY.getCall(callId).getCreationTimeMillis());
882     }
883 
884     /**
885      * Tests to make sure that the Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY property is set on a
886      * Call that is based on a Connection with the Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY
887      * property set.
888      */
889     @MediumTest
890     @Test
testCdmaEnhancedPrivacyVoiceCall()891     public void testCdmaEnhancedPrivacyVoiceCall() throws Exception {
892         mConnectionServiceFixtureA.mConnectionServiceDelegate.mProperties =
893                 Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY;
894 
895         IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
896                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
897         assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
898 
899         assertTrue(Call.Details.hasProperty(
900                 mInCallServiceFixtureX.getCall(ids.mCallId).getProperties(),
901                 Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY));
902     }
903 
904     /**
905      * Tests to make sure that Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY is dropped
906      * when the Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY property is removed from the Connection.
907      */
908     @MediumTest
909     @Test
testDropCdmaEnhancedPrivacyVoiceCall()910     public void testDropCdmaEnhancedPrivacyVoiceCall() throws Exception {
911         mConnectionServiceFixtureA.mConnectionServiceDelegate.mProperties =
912                 Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY;
913 
914         IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
915                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
916         assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
917         mConnectionServiceFixtureA.mLatestConnection.setConnectionProperties(0);
918 
919         assertFalse(Call.Details.hasProperty(
920                 mInCallServiceFixtureX.getCall(ids.mCallId).getProperties(),
921                 Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY));
922     }
923 
924     /**
925      * Tests the {@link Call#pullExternalCall()} API.  Ensures that an external call which is
926      * pullable can be pulled.
927      *
928      * @throws Exception
929      */
930     @LargeTest
931     @Test
testPullExternalCall()932     public void testPullExternalCall() throws Exception {
933         // TODO: Revisit this unit test once telecom support for filtering external calls from
934         // InCall services is implemented.
935         mConnectionServiceFixtureA.mConnectionServiceDelegate.mCapabilities =
936                 Connection.CAPABILITY_CAN_PULL_CALL;
937         mConnectionServiceFixtureA.mConnectionServiceDelegate.mProperties =
938                 Connection.PROPERTY_IS_EXTERNAL_CALL;
939 
940         IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
941                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
942         assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
943 
944         // Attempt to pull the call and verify the API call makes it through
945         mInCallServiceFixtureX.mInCallAdapter.pullExternalCall(ids.mCallId);
946         verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
947                 .pullExternalCall(eq(ids.mConnectionId), any());
948     }
949 
950     /**
951      * Tests the {@link Call#pullExternalCall()} API.  Verifies that if an external call is not
952      * marked as pullable that the connection service does not get an API call to pull the external
953      * call.
954      *
955      * @throws Exception
956      */
957     @LargeTest
958     @Test
testPullNonPullableExternalCall()959     public void testPullNonPullableExternalCall() throws Exception {
960         // TODO: Revisit this unit test once telecom support for filtering external calls from
961         // InCall services is implemented.
962         mConnectionServiceFixtureA.mConnectionServiceDelegate.mProperties =
963                 Connection.PROPERTY_IS_EXTERNAL_CALL;
964 
965         IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
966                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
967         assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
968 
969         // Attempt to pull the call and verify the API call makes it through
970         mInCallServiceFixtureX.mInCallAdapter.pullExternalCall(ids.mCallId);
971         Thread.sleep(TEST_TIMEOUT);
972         verify(mConnectionServiceFixtureA.getTestDouble(), never())
973                 .pullExternalCall(eq(ids.mConnectionId), any());
974     }
975 
976     /**
977      * Test scenario where the user starts an outgoing video call with no selected PhoneAccount, and
978      * then subsequently selects a PhoneAccount which supports video calling.
979      * @throws Exception
980      */
981     @LargeTest
982     @Test
testOutgoingCallSelectPhoneAccountVideo()983     public void testOutgoingCallSelectPhoneAccountVideo() throws Exception {
984         startOutgoingPhoneCallPendingCreateConnection("650-555-1212",
985                 null, mConnectionServiceFixtureA,
986                 Process.myUserHandle(), VideoProfile.STATE_BIDIRECTIONAL, null);
987         com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
988                 .iterator().next();
989         assert(call.isVideoCallingSupportedByPhoneAccount());
990         assertEquals(VideoProfile.STATE_BIDIRECTIONAL, call.getVideoState());
991 
992         // Change the phone account to one which supports video calling.
993         call.setTargetPhoneAccount(mPhoneAccountA1.getAccountHandle());
994         assert(call.isVideoCallingSupportedByPhoneAccount());
995         assertEquals(VideoProfile.STATE_BIDIRECTIONAL, call.getVideoState());
996     }
997 
998     /**
999      * Test scenario where the user starts an outgoing video call with no selected PhoneAccount, and
1000      * then subsequently selects a PhoneAccount which does not support video calling.
1001      * @throws Exception
1002      */
1003     @FlakyTest
1004     @LargeTest
1005     @Test
testOutgoingCallSelectPhoneAccountNoVideo()1006     public void testOutgoingCallSelectPhoneAccountNoVideo() throws Exception {
1007         startOutgoingPhoneCallPendingCreateConnection("650-555-1212",
1008                 null, mConnectionServiceFixtureA,
1009                 Process.myUserHandle(), VideoProfile.STATE_BIDIRECTIONAL, null);
1010         com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
1011                 .iterator().next();
1012         assert(call.isVideoCallingSupportedByPhoneAccount());
1013         assertEquals(VideoProfile.STATE_BIDIRECTIONAL, call.getVideoState());
1014 
1015         // Change the phone account to one which does not support video calling.
1016         call.setTargetPhoneAccount(mPhoneAccountA2.getAccountHandle());
1017         assert(!call.isVideoCallingSupportedByPhoneAccount());
1018         assertEquals(VideoProfile.STATE_AUDIO_ONLY, call.getVideoState());
1019     }
1020 
1021     /**
1022      * Basic test to ensure that a self-managed ConnectionService can place a call.
1023      * @throws Exception
1024      */
1025     @LargeTest
1026     @Test
testSelfManagedOutgoing()1027     public void testSelfManagedOutgoing() throws Exception {
1028         PhoneAccountHandle phoneAccountHandle = mPhoneAccountSelfManaged.getAccountHandle();
1029         IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212", phoneAccountHandle,
1030                 mConnectionServiceFixtureA);
1031 
1032         // The InCallService should not know about the call since its self-managed.
1033         assertNull(mInCallServiceFixtureX.getCall(ids.mCallId));
1034     }
1035 
1036     /**
1037      * Basic test to ensure that a self-managed ConnectionService can add an incoming call.
1038      * @throws Exception
1039      */
1040     @LargeTest
1041     @Test
testSelfManagedIncoming()1042     public void testSelfManagedIncoming() throws Exception {
1043         PhoneAccountHandle phoneAccountHandle = mPhoneAccountSelfManaged.getAccountHandle();
1044         IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", phoneAccountHandle,
1045                 mConnectionServiceFixtureA);
1046 
1047         // The InCallService should not know about the call since its self-managed.
1048         assertNull(mInCallServiceFixtureX.getCall(ids.mCallId));
1049     }
1050 
1051     /**
1052      * Basic test to ensure that when there are no calls, we permit outgoing calls by a self managed
1053      * CS.
1054      * @throws Exception
1055      */
1056     @LargeTest
1057     @Test
testIsOutgoingCallPermitted()1058     public void testIsOutgoingCallPermitted() throws Exception {
1059         assertTrue(mTelecomSystem.getTelecomServiceImpl().getBinder()
1060                 .isOutgoingCallPermitted(mPhoneAccountSelfManaged.getAccountHandle(),
1061                         mPhoneAccountSelfManaged.getAccountHandle().getComponentName()
1062                                 .getPackageName()));
1063     }
1064 
1065     /**
1066      * Ensure if there is a holdable call ongoing we'll be able to place another call.
1067      * @throws Exception
1068      */
1069     @LargeTest
1070     @Test
testIsOutgoingCallPermittedOngoingHoldable()1071     public void testIsOutgoingCallPermittedOngoingHoldable() throws Exception {
1072         // Start a regular call; the self-managed CS can make a call now since ongoing call can be
1073         // held
1074         IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
1075                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
1076         assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
1077 
1078         assertTrue(mTelecomSystem.getTelecomServiceImpl().getBinder()
1079                 .isOutgoingCallPermitted(mPhoneAccountSelfManaged.getAccountHandle(),
1080                         mPhoneAccountSelfManaged.getAccountHandle().getComponentName()
1081                                 .getPackageName()));
1082     }
1083 
1084     /**
1085      * Ensure if there is an unholdable call we can't place another call.
1086      * @throws Exception
1087      */
1088     @LargeTest
1089     @Test
testIsOutgoingCallPermittedOngoingUnHoldable()1090     public void testIsOutgoingCallPermittedOngoingUnHoldable() throws Exception {
1091         // Start a regular call; the self-managed CS can't make a call now because the ongoing call
1092         // can't be held.
1093         mConnectionServiceFixtureA.mConnectionServiceDelegate.mCapabilities = 0;
1094         IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
1095                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
1096         assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
1097 
1098         assertTrue(mTelecomSystem.getTelecomServiceImpl().getBinder()
1099                 .isOutgoingCallPermitted(mPhoneAccountSelfManaged.getAccountHandle(),
1100                         mPhoneAccountSelfManaged.getAccountHandle().getComponentName()
1101                                 .getPackageName()));
1102     }
1103 
1104     /**
1105      * Basic to verify audio route gets reset to baseline when emergency call placed while a
1106      * self-managed call is underway.
1107      * @throws Exception
1108      */
1109     @LargeTest
1110     @Test
1111     @FlakyTest
testDisconnectSelfManaged()1112     public void testDisconnectSelfManaged() throws Exception {
1113         // Add a self-managed call.
1114         PhoneAccountHandle phoneAccountHandle = mPhoneAccountSelfManaged.getAccountHandle();
1115         startAndMakeActiveIncomingCall("650-555-1212", phoneAccountHandle,
1116                 mConnectionServiceFixtureA);
1117         Connection connection = mConnectionServiceFixtureA.mLatestConnection;
1118 
1119         // Route self-managed call to speaker.
1120         connection.setAudioRoute(CallAudioState.ROUTE_SPEAKER);
1121         waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
1122                 TEST_TIMEOUT);
1123 
1124         // Place an emergency call.
1125         startAndMakeDialingEmergencyCall("650-555-1212", mPhoneAccountE0.getAccountHandle(),
1126                 mConnectionServiceFixtureA);
1127 
1128         // Should have reverted back to earpiece.
1129         assertTrueWithTimeout(new Predicate<Void>() {
1130             @Override
1131             public boolean apply(Void aVoid) {
1132                 return mInCallServiceFixtureX.mCallAudioState.getRoute()
1133                         == CallAudioState.ROUTE_EARPIECE;
1134             }
1135         });
1136     }
1137 
1138     /**
1139      * Tests the {@link Call#deflect} API.  Verifies that if a call is incoming,
1140      * and deflect API is called, then request is made to the connection service.
1141      *
1142      * @throws Exception
1143      */
1144     @LargeTest
1145     @Test
testDeflectCallWhenIncoming()1146     public void testDeflectCallWhenIncoming() throws Exception {
1147         Uri deflectAddress = Uri.parse("tel:650-555-1214");
1148         IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
1149                 mConnectionServiceFixtureA);
1150 
1151         assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
1152         assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
1153         // Attempt to deflect the call and verify the API call makes it through
1154         mInCallServiceFixtureX.mInCallAdapter.deflectCall(ids.mCallId, deflectAddress);
1155         verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
1156                 .deflect(eq(ids.mConnectionId), eq(deflectAddress), any());
1157         mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
1158     }
1159 
1160     /**
1161      * Tests the {@link Call#deflect} API.  Verifies that if a call is outgoing,
1162      * and deflect API is called, then request is not made to the connection service.
1163      * Ideally, deflect option should be displayed only if call is incoming/waiting.
1164      *
1165      * @throws Exception
1166      */
1167     @LargeTest
1168     @Test
testDeflectCallWhenOutgoing()1169     public void testDeflectCallWhenOutgoing() throws Exception {
1170         Uri deflectAddress = Uri.parse("tel:650-555-1214");
1171         IdPair ids = startOutgoingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
1172                 mConnectionServiceFixtureA, Process.myUserHandle());
1173         // Attempt to deflect the call and verify the API call does not make it through
1174         mInCallServiceFixtureX.mInCallAdapter.deflectCall(ids.mCallId, deflectAddress);
1175         verify(mConnectionServiceFixtureA.getTestDouble(), never())
1176                 .deflect(eq(ids.mConnectionId), eq(deflectAddress), any());
1177         mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
1178     }
1179 
1180     /**
1181      * Test to make sure to unmute automatically when making an emergency call and keep unmute
1182      * during the emergency call.
1183      * @throws Exception
1184      */
1185     @LargeTest
1186     @Test
1187     @FlakyTest
testUnmuteDuringEmergencyCall()1188     public void testUnmuteDuringEmergencyCall() throws Exception {
1189         // Make an outgoing call and turn ON mute.
1190         IdPair outgoingCall = startAndMakeActiveOutgoingCall("650-555-1212",
1191                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
1192         assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(outgoingCall.mCallId)
1193                 .getState());
1194         mInCallServiceFixtureX.mInCallAdapter.mute(true);
1195         waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager()
1196                 .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT);
1197         assertTrue(mTelecomSystem.getCallsManager().getAudioState().isMuted());
1198 
1199         // Make an emergency call.
1200         IdPair emergencyCall = startAndMakeDialingEmergencyCall("650-555-1213",
1201                 mPhoneAccountE0.getAccountHandle(), mConnectionServiceFixtureA);
1202         assertEquals(Call.STATE_DIALING, mInCallServiceFixtureX.getCall(emergencyCall.mCallId)
1203                 .getState());
1204         waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager()
1205                 .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT);
1206         // Should be unmute automatically.
1207         assertFalse(mTelecomSystem.getCallsManager().getAudioState().isMuted());
1208 
1209         // Toggle mute during an emergency call.
1210         mTelecomSystem.getCallsManager().getCallAudioManager().toggleMute();
1211         waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager()
1212                 .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT);
1213         // Should keep unmute.
1214         assertFalse(mTelecomSystem.getCallsManager().getAudioState().isMuted());
1215 
1216         ArgumentCaptor<Boolean> muteValueCaptor = ArgumentCaptor.forClass(Boolean.class);
1217         verify(mAudioService, times(2)).setMicrophoneMute(muteValueCaptor.capture(),
1218                 any(String.class), any(Integer.class), nullable(String.class));
1219         List<Boolean> muteValues = muteValueCaptor.getAllValues();
1220         // Check mute status was changed twice with true and false.
1221         assertTrue(muteValues.get(0));
1222         assertFalse(muteValues.get(1));
1223     }
1224 
1225     /**
1226      * Verifies that StatusHints image is validated in ConnectionServiceWrapper#addConferenceCall
1227      * when the image doesn't belong to the calling user. Simulates a scenario where an app
1228      * could manipulate the contents of the bundle and send it via the binder to upload an image
1229      * from another user.
1230      *
1231      * @throws Exception
1232      */
1233     @SmallTest
1234     @Test
testValidateStatusHintsImage_addConferenceCall()1235     public void testValidateStatusHintsImage_addConferenceCall() throws Exception {
1236         Intent callIntent1 = new Intent();
1237         // Stub intent for call2
1238         Intent callIntent2 = new Intent();
1239         Bundle callExtras1 = new Bundle();
1240         Icon icon = Icon.createWithContentUri("content://10@media/external/images/media/");
1241         // Load StatusHints extra into TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS to be processed
1242         // as the call extras. This will be leveraged in ConnectionServiceFixture to set the
1243         // StatusHints for the given connection.
1244         StatusHints statusHints = new StatusHints(icon);
1245         assertNotNull(statusHints.getIcon());
1246         callExtras1.putParcelable(STATUS_HINTS_EXTRA, statusHints);
1247         callIntent1.putExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, callExtras1);
1248 
1249         // Start conference call to invoke ConnectionServiceWrapper#addConferenceCall.
1250         // Note that the calling user would be User 0.
1251         ParcelableCall conferenceCall = makeConferenceCall(callIntent1, callIntent2);
1252 
1253         // Ensure that StatusHints was set.
1254         assertNotNull(mInCallServiceFixtureX.getCall(mInCallServiceFixtureX.mLatestCallId)
1255                 .getStatusHints());
1256         // Ensure that the StatusHints image icon was disregarded.
1257         assertNull(mInCallServiceFixtureX.getCall(mInCallServiceFixtureX.mLatestCallId)
1258                 .getStatusHints().getIcon());
1259     }
1260 
1261     /**
1262      * Verifies that StatusHints image is validated in
1263      * ConnectionServiceWrapper#handleCreateConnectionComplete when the image doesn't belong to the
1264      * calling user. Simulates a scenario where an app could manipulate the contents of the
1265      * bundle and send it via the binder to upload an image from another user.
1266      *
1267      * @throws Exception
1268      */
1269     @SmallTest
1270     @Test
testValidateStatusHintsImage_handleCreateConnectionComplete()1271     public void testValidateStatusHintsImage_handleCreateConnectionComplete() throws Exception {
1272         Bundle extras = new Bundle();
1273         Icon icon = Icon.createWithContentUri("content://10@media/external/images/media/");
1274         // Load the bundle with the test extra in order to simulate an app directly invoking the
1275         // binder on ConnectionServiceWrapper#handleCreateConnectionComplete.
1276         StatusHints statusHints = new StatusHints(icon);
1277         assertNotNull(statusHints.getIcon());
1278         extras.putParcelable(STATUS_HINTS_EXTRA, statusHints);
1279 
1280         // Start incoming call with StatusHints extras
1281         // Note that the calling user in ConnectionServiceWrapper#handleCreateConnectionComplete
1282         // would be User 0.
1283         IdPair ids = startIncomingPhoneCallWithExtras("650-555-1212",
1284                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA, extras);
1285 
1286         // Ensure that StatusHints was set.
1287         assertNotNull(mInCallServiceFixtureX.getCall(ids.mCallId).getStatusHints());
1288         // Ensure that the StatusHints image icon was disregarded.
1289         assertNull(mInCallServiceFixtureX.getCall(ids.mCallId).getStatusHints().getIcon());
1290     }
1291 
1292     /**
1293      * Verifies that StatusHints image is validated in ConnectionServiceWrapper#setStatusHints
1294      * when the image doesn't belong to the calling user. Simulates a scenario where an app
1295      * could manipulate the contents of the bundle and send it via the binder to upload an image
1296      * from another user.
1297      *
1298      * @throws Exception
1299      */
1300     @SmallTest
1301     @Test
testValidateStatusHintsImage_setStatusHints()1302     public void testValidateStatusHintsImage_setStatusHints() throws Exception {
1303         IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1214",
1304                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
1305 
1306         // Modify existing connection with StatusHints image exploit
1307         Icon icon = Icon.createWithContentUri("content://10@media/external/images/media/");
1308         StatusHints statusHints = new StatusHints(icon);
1309         assertNotNull(statusHints.getIcon());
1310         ConnectionServiceFixture.ConnectionInfo connectionInfo = mConnectionServiceFixtureA
1311                 .mConnectionById.get(outgoing.mConnectionId);
1312         connectionInfo.statusHints = statusHints;
1313 
1314         // Invoke ConnectionServiceWrapper#setStatusHints.
1315         // Note that the calling user would be User 0.
1316         mConnectionServiceFixtureA.sendSetStatusHints(outgoing.mConnectionId);
1317         waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
1318                 TEST_TIMEOUT);
1319 
1320         // Ensure that StatusHints was set.
1321         assertNotNull(mInCallServiceFixtureX.getCall(outgoing.mCallId).getStatusHints());
1322         // Ensure that the StatusHints image icon was disregarded.
1323         assertNull(mInCallServiceFixtureX.getCall(outgoing.mCallId)
1324                 .getStatusHints().getIcon());
1325     }
1326 
1327     /**
1328      * Verifies that StatusHints image is validated in
1329      * ConnectionServiceWrapper#addExistingConnection when the image doesn't belong to the calling
1330      * user. Simulates a scenario where an app could manipulate the contents of the bundle and
1331      * send it via the binder to upload an image from another user.
1332      *
1333      * @throws Exception
1334      */
1335     @SmallTest
1336     @Test
testValidateStatusHintsImage_addExistingConnection()1337     public void testValidateStatusHintsImage_addExistingConnection() throws Exception {
1338         IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1214",
1339                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
1340         Connection existingConnection = mConnectionServiceFixtureA.mLatestConnection;
1341 
1342         // Modify existing connection with StatusHints image exploit
1343         Icon icon = Icon.createWithContentUri("content://10@media/external/images/media/");
1344         StatusHints modifiedStatusHints = new StatusHints(icon);
1345         assertNotNull(modifiedStatusHints.getIcon());
1346         ConnectionServiceFixture.ConnectionInfo connectionInfo = mConnectionServiceFixtureA
1347                 .mConnectionById.get(outgoing.mConnectionId);
1348         connectionInfo.statusHints = modifiedStatusHints;
1349 
1350         // Invoke ConnectionServiceWrapper#addExistingConnection.
1351         // Note that the calling user would be User 0.
1352         mConnectionServiceFixtureA.sendAddExistingConnection(outgoing.mConnectionId);
1353         waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
1354                 TEST_TIMEOUT);
1355 
1356         // Ensure that StatusHints was set. Due to test setup, the ParcelableConnection object that
1357         // is passed into sendAddExistingConnection is instantiated on invocation. The call's
1358         // StatusHints are not updated at the time of completion, so instead, we can verify that
1359         // the ParcelableConnection object was modified.
1360         assertNotNull(mConnectionServiceFixtureA.mLatestParcelableConnection.getStatusHints());
1361         // Ensure that the StatusHints image icon was disregarded.
1362         assertNull(mConnectionServiceFixtureA.mLatestParcelableConnection
1363                 .getStatusHints().getIcon());
1364     }
1365 }
1366