1 package android.telecom.cts;
2 
3 import static android.app.role.RoleManager.ROLE_CALL_SCREENING;
4 import static android.telecom.cts.TestUtils.TEST_PHONE_ACCOUNT_HANDLE;
5 import static android.telecom.cts.TestUtils.waitOnAllHandlers;
6 
7 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
8 
9 import android.app.role.RoleManager;
10 import android.content.Context;
11 import android.content.ServiceConnection;
12 import android.media.AudioManager;
13 import android.os.Bundle;
14 import android.os.Process;
15 import android.os.UserHandle;
16 import android.provider.CallLog;
17 import android.telecom.Call;
18 import android.telecom.Call.Details;
19 import android.telecom.CallScreeningService.CallResponse;
20 import android.telecom.Connection;
21 import android.telecom.DisconnectCause;
22 import android.telecom.TelecomManager;
23 import android.telecom.VideoProfile;
24 import android.telecom.cts.MockCallScreeningService.CallScreeningServiceCallbacks;
25 import android.telecom.cts.api29incallservice.ICtsApi29InCallServiceControl;
26 import android.text.TextUtils;
27 import android.util.Pair;
28 
29 import androidx.test.InstrumentationRegistry;
30 
31 import java.util.concurrent.Executor;
32 import java.util.concurrent.LinkedBlockingQueue;
33 import java.util.concurrent.TimeUnit;
34 
35 public class BackgroundCallAudioTest extends BaseTelecomTestWithMockServices {
36     private static final String LOG_TAG = BackgroundCallAudioTest.class.getSimpleName();
37 
38     private static final int ASYNC_TIMEOUT = 10000;
39     private RoleManager mRoleManager;
40     private ServiceConnection mApiCompatControlServiceConnection;
41 
42     // copied from AudioSystem.java -- defined here because that change isn't in AOSP yet.
43     private static final int MODE_CALL_SCREENING = 4;
44 
45     // true if there's platform support for call screening in the audio stack.
46     private boolean doesAudioManagerSupportCallScreening = false;
47 
48     private String mPreviousDefaultDialer = null;
49 
50     @Override
setUp()51     protected void setUp() throws Exception {
52         super.setUp();
53         if (mShouldTestTelecom) {
54             mRoleManager = (RoleManager) mContext.getSystemService(Context.ROLE_SERVICE);
55             clearRoleHoldersAsUser(ROLE_CALL_SCREENING);
56             mPreviousDefaultDialer = TestUtils.getDefaultDialer(getInstrumentation());
57             TestUtils.setDefaultDialer(getInstrumentation(), TestUtils.PACKAGE);
58             setupConnectionService(null, FLAG_REGISTER | FLAG_ENABLE);
59             // Some of the tests expect changes in audio mode when the ringer starts, so we're
60             // going to turn up the ring stream volume.
61             AudioManager audioManager = mContext.getSystemService(AudioManager.class);
62             audioManager.adjustStreamVolume(AudioManager.STREAM_RING,
63                     AudioManager.ADJUST_UNMUTE, 0);
64             doesAudioManagerSupportCallScreening =
65                     audioManager.isCallScreeningModeSupported();
66         }
67     }
68 
69     @Override
tearDown()70     protected void tearDown() throws Exception {
71         if (mShouldTestTelecom && !TextUtils.isEmpty(mPreviousDefaultDialer)) {
72             TestUtils.setDefaultDialer(getInstrumentation(), mPreviousDefaultDialer);
73             MockCallScreeningService.disableService(mContext);
74         }
75         super.tearDown();
76     }
77 
testAudioProcessingFromCallScreeningAllow()78     public void testAudioProcessingFromCallScreeningAllow() throws Exception {
79         if (!mShouldTestTelecom) {
80             return;
81         }
82 
83         setupIncomingCallWithCallScreening();
84 
85         final MockConnection connection = verifyConnectionForIncomingCall();
86 
87         if (!mInCallCallbacks.lock.tryAcquire(TestUtils.WAIT_FOR_CALL_ADDED_TIMEOUT_S,
88                 TimeUnit.SECONDS)) {
89             fail("No call added to InCallService.");
90         }
91 
92         Call call = mInCallCallbacks.getService().getLastCall();
93         assertCallState(call, Call.STATE_AUDIO_PROCESSING);
94         assertConnectionState(connection, Connection.STATE_ACTIVE);
95 
96         AudioManager audioManager = mContext.getSystemService(AudioManager.class);
97         if (doesAudioManagerSupportCallScreening) {
98             assertAudioMode(audioManager, MODE_CALL_SCREENING);
99         }
100 
101         verifySimulateRingAndUserPickup(call, connection);
102     }
103 
testHoldAfterAudioProcessingFromCallScreening()104     public void testHoldAfterAudioProcessingFromCallScreening() throws Exception {
105         if (!mShouldTestTelecom) {
106             return;
107         }
108 
109         setupIncomingCallWithCallScreening();
110 
111         final MockConnection connection = verifyConnectionForIncomingCall();
112 
113         if (!mInCallCallbacks.lock.tryAcquire(TestUtils.WAIT_FOR_CALL_ADDED_TIMEOUT_S,
114                 TimeUnit.SECONDS)) {
115             fail("No call added to InCallService.");
116         }
117 
118         Call call = mInCallCallbacks.getService().getLastCall();
119         assertCallState(call, Call.STATE_AUDIO_PROCESSING);
120         assertConnectionState(connection, Connection.STATE_ACTIVE);
121 
122         AudioManager audioManager = mContext.getSystemService(AudioManager.class);
123         if (doesAudioManagerSupportCallScreening) {
124             assertAudioMode(audioManager, MODE_CALL_SCREENING);
125         }
126 
127         verifySimulateRingAndUserPickup(call, connection);
128 
129         call.hold();
130         assertCallState(call, Call.STATE_HOLDING);
131         call.unhold();
132         assertCallState(call, Call.STATE_ACTIVE);
133     }
134 
testAudioProcessingFromCallScreeningDisallow()135     public void testAudioProcessingFromCallScreeningDisallow() throws Exception {
136         if (!mShouldTestTelecom) {
137             return;
138         }
139 
140         setupIncomingCallWithCallScreening();
141 
142         final MockConnection connection = verifyConnectionForIncomingCall();
143 
144         if (!mInCallCallbacks.lock.tryAcquire(TestUtils.WAIT_FOR_CALL_ADDED_TIMEOUT_S,
145                 TimeUnit.SECONDS)) {
146             fail("No call added to InCallService.");
147         }
148 
149         Call call = mInCallCallbacks.getService().getLastCall();
150         assertCallState(call, Call.STATE_AUDIO_PROCESSING);
151         assertConnectionState(connection, Connection.STATE_ACTIVE);
152 
153         AudioManager audioManager = mContext.getSystemService(AudioManager.class);
154         if (doesAudioManagerSupportCallScreening) {
155             assertAudioMode(audioManager, MODE_CALL_SCREENING);
156         }
157 
158         call.disconnect();
159         assertCallState(call, Call.STATE_DISCONNECTED);
160         assertEquals(DisconnectCause.REJECTED, call.getDetails().getDisconnectCause().getCode());
161     }
162 
testAudioProcessingFromCallScreeningMissed()163     public void testAudioProcessingFromCallScreeningMissed() throws Exception {
164         if (!mShouldTestTelecom) {
165             return;
166         }
167 
168         setupIncomingCallWithCallScreening();
169 
170         final MockConnection connection = verifyConnectionForIncomingCall();
171 
172         if (!mInCallCallbacks.lock.tryAcquire(TestUtils.WAIT_FOR_CALL_ADDED_TIMEOUT_S,
173                 TimeUnit.SECONDS)) {
174             fail("No call added to InCallService.");
175         }
176 
177         Call call = mInCallCallbacks.getService().getLastCall();
178         assertCallState(call, Call.STATE_AUDIO_PROCESSING);
179         assertConnectionState(connection, Connection.STATE_ACTIVE);
180 
181         AudioManager audioManager = mContext.getSystemService(AudioManager.class);
182         if (doesAudioManagerSupportCallScreening) {
183             assertAudioMode(audioManager, MODE_CALL_SCREENING);
184         }
185 
186         verifySimulateRingAndUserMissed(call, connection);
187     }
188 
testAudioProcessingFromCallScreeningRemoteHangupDuringRing()189     public void testAudioProcessingFromCallScreeningRemoteHangupDuringRing() throws Exception {
190         if (!mShouldTestTelecom) {
191             return;
192         }
193 
194         setupIncomingCallWithCallScreening();
195 
196         final MockConnection connection = verifyConnectionForIncomingCall();
197 
198         if (!mInCallCallbacks.lock.tryAcquire(TestUtils.WAIT_FOR_CALL_ADDED_TIMEOUT_S,
199                 TimeUnit.SECONDS)) {
200             fail("No call added to InCallService.");
201         }
202 
203         Call call = mInCallCallbacks.getService().getLastCall();
204         assertCallState(call, Call.STATE_AUDIO_PROCESSING);
205         assertConnectionState(connection, Connection.STATE_ACTIVE);
206 
207         AudioManager audioManager = mContext.getSystemService(AudioManager.class);
208         if (doesAudioManagerSupportCallScreening) {
209             assertAudioMode(audioManager, MODE_CALL_SCREENING);
210         }
211 
212         call.exitBackgroundAudioProcessing(true);
213         assertCallState(call, Call.STATE_SIMULATED_RINGING);
214 
215         waitOnAllHandlers(getInstrumentation());
216         // We expect the audio mode to stay in CALL_SCREENING when going into simulated ringing.
217         if (doesAudioManagerSupportCallScreening) {
218             assertAudioMode(audioManager, MODE_CALL_SCREENING);
219         }
220         assertConnectionState(connection, Connection.STATE_ACTIVE);
221 
222         connection.setDisconnected(new DisconnectCause(DisconnectCause.REMOTE));
223         assertCallState(call, Call.STATE_DISCONNECTED);
224         assertEquals(DisconnectCause.MISSED, call.getDetails().getDisconnectCause().getCode());
225         connection.destroy();
226     }
227 
testAudioProcessingFromCallScreeningAllowPlaceEmergencyCall()228     public void testAudioProcessingFromCallScreeningAllowPlaceEmergencyCall() throws Exception {
229         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
230             return;
231         }
232         setupForEmergencyCalling(TEST_EMERGENCY_NUMBER);
233         setupIncomingCallWithCallScreening();
234 
235         final MockConnection connection = verifyConnectionForIncomingCall();
236 
237         if (!mInCallCallbacks.lock.tryAcquire(TestUtils.WAIT_FOR_CALL_ADDED_TIMEOUT_S,
238                 TimeUnit.SECONDS)) {
239             fail("No call added to InCallService.");
240         }
241 
242         Call call = mInCallCallbacks.getService().getLastCall();
243         assertCallState(call, Call.STATE_AUDIO_PROCESSING);
244         assertConnectionState(connection, Connection.STATE_ACTIVE);
245 
246         AudioManager audioManager = mContext.getSystemService(AudioManager.class);
247         if (doesAudioManagerSupportCallScreening) {
248             assertAudioMode(audioManager, MODE_CALL_SCREENING);
249         }
250 
251         call.exitBackgroundAudioProcessing(true);
252         assertCallState(call, Call.STATE_SIMULATED_RINGING);
253         waitOnAllHandlers(getInstrumentation());
254         // We expect the audio mode to stay in CALL_SCREENING when going into simulated ringing.
255         if (doesAudioManagerSupportCallScreening) {
256             assertAudioMode(audioManager, MODE_CALL_SCREENING);
257         }
258         assertConnectionState(connection, Connection.STATE_ACTIVE);
259 
260         placeAndVerifyEmergencyCall(false /*supportsHold*/);
261         waitOnAllHandlers(getInstrumentation());
262         Call eCall = getInCallService().getLastCall();
263         assertCallState(eCall, Call.STATE_DIALING);
264         // Even though the connection was technically active, it is "simulated ringing", so
265         // disconnect as you would a normal ringing call in favor of an emergency call.
266         assertCallState(call, Call.STATE_DISCONNECTED);
267         assertConnectionState(connection, Connection.STATE_DISCONNECTED);
268         // Notify as missed instead of rejected, since the user did not explicitly reject.
269         verifyCallLogging(connection.getAddress(), CallLog.Calls.MISSED_TYPE,
270                 TestUtils.TEST_PHONE_ACCOUNT_HANDLE);
271     }
272 
testAudioProcessingFromIncomingActivePlaceEmergencyCall()273     public void testAudioProcessingFromIncomingActivePlaceEmergencyCall() throws Exception {
274         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
275             return;
276         }
277         setupForEmergencyCalling(TEST_EMERGENCY_NUMBER);
278         setupIncomingCallWithCallScreening();
279 
280         final MockConnection connection = verifyConnectionForIncomingCall();
281 
282         if (!mInCallCallbacks.lock.tryAcquire(TestUtils.WAIT_FOR_CALL_ADDED_TIMEOUT_S,
283                 TimeUnit.SECONDS)) {
284             fail("No call added to InCallService.");
285         }
286 
287         Call call = mInCallCallbacks.getService().getLastCall();
288         assertCallState(call, Call.STATE_AUDIO_PROCESSING);
289         assertConnectionState(connection, Connection.STATE_ACTIVE);
290 
291         AudioManager audioManager = mContext.getSystemService(AudioManager.class);
292         if (doesAudioManagerSupportCallScreening) {
293             assertAudioMode(audioManager, MODE_CALL_SCREENING);
294         }
295 
296         verifySimulateRingAndUserPickup(call, connection);
297         // Go back into audio processing for hold case
298         call.enterBackgroundAudioProcessing();
299         assertCallState(call, Call.STATE_AUDIO_PROCESSING);
300         waitOnAllHandlers(getInstrumentation());
301 
302         placeAndVerifyEmergencyCall(false /*supportsHold*/);
303         waitOnAllHandlers(getInstrumentation());
304         Call eCall = getInCallService().getLastCall();
305         assertCallState(eCall, Call.STATE_DIALING);
306         // Even though the connection was technically active, it is "simulated ringing", so
307         // disconnect as you would a normal ringing call in favor of an emergency call.
308         assertCallState(call, Call.STATE_DISCONNECTED);
309         assertConnectionState(connection, Connection.STATE_DISCONNECTED);
310         // Notify as incoming, since the user has already answered the call.
311         verifyCallLogging(connection.getAddress(), CallLog.Calls.INCOMING_TYPE,
312                 TestUtils.TEST_PHONE_ACCOUNT_HANDLE);
313     }
314 
testAudioProcessActiveCall()315     public void testAudioProcessActiveCall() {
316         if (!mShouldTestTelecom) {
317             return;
318         }
319 
320         Connection connection = placeActiveOutgoingCall();
321         Call call = mInCallCallbacks.getService().getLastCall();
322 
323         call.enterBackgroundAudioProcessing();
324         assertCallState(call, Call.STATE_AUDIO_PROCESSING);
325 
326         waitOnAllHandlers(getInstrumentation());
327         AudioManager audioManager = mContext.getSystemService(AudioManager.class);
328         if (doesAudioManagerSupportCallScreening) {
329             assertAudioMode(audioManager, MODE_CALL_SCREENING);
330         }
331         assertConnectionState(connection, Connection.STATE_ACTIVE);
332 
333         verifySimulateRingAndUserPickup(call, connection);
334     }
335 
testAudioProcessActiveCallMissed()336     public void testAudioProcessActiveCallMissed() throws Exception {
337         if (!mShouldTestTelecom) {
338             return;
339         }
340 
341         Connection connection = placeActiveOutgoingCall();
342         Call call = mInCallCallbacks.getService().getLastCall();
343 
344         call.enterBackgroundAudioProcessing();
345         assertCallState(call, Call.STATE_AUDIO_PROCESSING);
346         assertConnectionState(connection, Connection.STATE_ACTIVE);
347 
348         waitOnAllHandlers(getInstrumentation());
349         AudioManager audioManager = mContext.getSystemService(AudioManager.class);
350         if (doesAudioManagerSupportCallScreening) {
351             assertAudioMode(audioManager, MODE_CALL_SCREENING);
352         }
353 
354         verifySimulateRingAndUserMissed(call, connection);
355     }
356 
testAudioProcessActiveCallRemoteHangup()357     public void testAudioProcessActiveCallRemoteHangup() {
358         if (!mShouldTestTelecom) {
359             return;
360         }
361 
362         Connection connection = placeActiveOutgoingCall();
363         Call call = mInCallCallbacks.getService().getLastCall();
364 
365         call.enterBackgroundAudioProcessing();
366         assertCallState(call, Call.STATE_AUDIO_PROCESSING);
367         assertConnectionState(connection, Connection.STATE_ACTIVE);
368 
369         waitOnAllHandlers(getInstrumentation());
370         AudioManager audioManager = mContext.getSystemService(AudioManager.class);
371         if (doesAudioManagerSupportCallScreening) {
372             assertAudioMode(audioManager, MODE_CALL_SCREENING);
373         }
374 
375         connection.setDisconnected(new DisconnectCause(DisconnectCause.REMOTE));
376         assertCallState(call, Call.STATE_DISCONNECTED);
377         assertEquals(DisconnectCause.REMOTE, call.getDetails().getDisconnectCause().getCode());
378         connection.destroy();
379     }
380 
testAudioProcessOutgoingActiveEmergencyCallPlaced()381     public void testAudioProcessOutgoingActiveEmergencyCallPlaced() throws Exception {
382         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
383             return;
384         }
385         setupForEmergencyCalling(TEST_EMERGENCY_NUMBER);
386 
387         Connection connection = placeActiveOutgoingCall();
388         Call call = mInCallCallbacks.getService().getLastCall();
389 
390         call.enterBackgroundAudioProcessing();
391         assertCallState(call, Call.STATE_AUDIO_PROCESSING);
392         assertConnectionState(connection, Connection.STATE_ACTIVE);
393 
394         waitOnAllHandlers(getInstrumentation());
395         AudioManager audioManager = mContext.getSystemService(AudioManager.class);
396         if (doesAudioManagerSupportCallScreening) {
397             assertAudioMode(audioManager, MODE_CALL_SCREENING);
398         }
399 
400         placeAndVerifyEmergencyCall(false /*supportsHold*/);
401         waitOnAllHandlers(getInstrumentation());
402         Call eCall = getInCallService().getLastCall();
403         // emergency call should be dialing
404         assertCallState(eCall, Call.STATE_DIALING);
405         // audio processing call should be disconnected
406         assertConnectionState(connection, Connection.STATE_DISCONNECTED);
407         assertCallState(call, Call.STATE_DISCONNECTED);
408         // If we went to AUDIO_PROCESSING from an active outgoing call, Make sure the call is
409         // marked outgoing, not missed.
410         verifyCallLogging(connection.getAddress(), CallLog.Calls.OUTGOING_TYPE,
411                 TestUtils.TEST_PHONE_ACCOUNT_HANDLE);
412     }
413 
testManualAudioCallScreenAccept()414     public void testManualAudioCallScreenAccept() {
415         if (!mShouldTestTelecom) {
416             return;
417         }
418 
419         addAndVerifyNewIncomingCall(createTestNumber(), null);
420         final MockConnection connection = verifyConnectionForIncomingCall();
421 
422         Call call = mInCallCallbacks.getService().getLastCall();
423         assertCallState(call, Call.STATE_RINGING);
424 
425         call.enterBackgroundAudioProcessing();
426         assertCallState(call, Call.STATE_AUDIO_PROCESSING);
427         assertConnectionState(connection, Connection.STATE_ACTIVE);
428 
429         waitOnAllHandlers(getInstrumentation());
430         AudioManager audioManager = mContext.getSystemService(AudioManager.class);
431         if (doesAudioManagerSupportCallScreening) {
432             assertAudioMode(audioManager, MODE_CALL_SCREENING);
433         }
434 
435         call.exitBackgroundAudioProcessing(false);
436         assertCallState(call, Call.STATE_ACTIVE);
437         waitOnAllHandlers(getInstrumentation());
438         assertAudioMode(audioManager, AudioManager.MODE_IN_CALL);
439     }
440 
testManualAudioCallScreenReject()441     public void testManualAudioCallScreenReject() {
442         if (!mShouldTestTelecom) {
443             return;
444         }
445 
446         addAndVerifyNewIncomingCall(createTestNumber(), null);
447         final MockConnection connection = verifyConnectionForIncomingCall();
448 
449         Call call = mInCallCallbacks.getService().getLastCall();
450         assertCallState(call, Call.STATE_RINGING);
451 
452         call.enterBackgroundAudioProcessing();
453         assertCallState(call, Call.STATE_AUDIO_PROCESSING);
454         assertConnectionState(connection, Connection.STATE_ACTIVE);
455 
456         waitOnAllHandlers(getInstrumentation());
457         AudioManager audioManager = mContext.getSystemService(AudioManager.class);
458         if (doesAudioManagerSupportCallScreening) {
459             assertAudioMode(audioManager, MODE_CALL_SCREENING);
460         }
461 
462         call.disconnect();
463         assertCallState(call, Call.STATE_DISCONNECTED);
464         assertEquals(DisconnectCause.REJECTED, call.getDetails().getDisconnectCause().getCode());
465     }
466 
testEnterAudioProcessingWithoutPermission()467     public void testEnterAudioProcessingWithoutPermission() {
468         if (!mShouldTestTelecom) {
469             return;
470         }
471 
472         if (true) {
473             // TODO: enable test
474             return;
475         }
476 
477         placeAndVerifyCall();
478         final MockConnection connection = verifyConnectionForOutgoingCall();
479 
480         final MockInCallService inCallService = mInCallCallbacks.getService();
481 
482         connection.setActive();
483         final Call call = inCallService.getLastCall();
484         assertCallState(call, Call.STATE_ACTIVE);
485 
486         try {
487             call.enterBackgroundAudioProcessing();
488             fail("Expected SecurityException");
489         } catch (SecurityException e) {
490             // expected
491         }
492     }
493 
testLowerApiLevelCompatibility1()494     public void testLowerApiLevelCompatibility1() throws Exception {
495         if (!mShouldTestTelecom) {
496             return;
497         }
498 
499         InstrumentationRegistry.getInstrumentation().getUiAutomation()
500                 .adoptShellPermissionIdentity("android.permission.CONTROL_INCALL_EXPERIENCE");
501         try {
502             ICtsApi29InCallServiceControl controlInterface = setUpControl();
503 
504             setupIncomingCallWithCallScreening();
505 
506             final MockConnection connection = verifyConnectionForIncomingCall();
507 
508             if (!mInCallCallbacks.lock.tryAcquire(TestUtils.WAIT_FOR_CALL_ADDED_TIMEOUT_S,
509                     TimeUnit.SECONDS)) {
510                 fail("No call added to InCallService.");
511             }
512 
513             Call call = mInCallCallbacks.getService().getLastCall();
514             assertCallState(call, Call.STATE_AUDIO_PROCESSING);
515             assertConnectionState(connection, Connection.STATE_ACTIVE);
516             // Make sure that the test app never got any calls
517             assertEquals(0, controlInterface.getHistoricalCallCount());
518 
519             call.exitBackgroundAudioProcessing(true);
520             assertCallState(call, Call.STATE_SIMULATED_RINGING);
521             waitOnAllHandlers(getInstrumentation());
522             assertConnectionState(connection, Connection.STATE_ACTIVE);
523             // Make sure that the test app sees a ringing call.
524             assertEquals(Call.STATE_RINGING,
525                     controlInterface.getCallState(call.getDetails().getTelecomCallId()));
526 
527             call.answer(VideoProfile.STATE_AUDIO_ONLY);
528             assertCallState(call, Call.STATE_ACTIVE);
529             waitOnAllHandlers(getInstrumentation());
530             assertConnectionState(connection, Connection.STATE_ACTIVE);
531             // Make sure that the test app sees an active call.
532             assertEquals(Call.STATE_ACTIVE,
533                     controlInterface.getCallState(call.getDetails().getTelecomCallId()));
534 
535             tearDownControl();
536         } finally {
537             InstrumentationRegistry.getInstrumentation().getUiAutomation()
538                     .dropShellPermissionIdentity();
539         }
540     }
541 
testLowerApiLevelCompatibility2()542     public void testLowerApiLevelCompatibility2() throws Exception {
543         if (!mShouldTestTelecom) {
544             return;
545         }
546         InstrumentationRegistry.getInstrumentation().getUiAutomation()
547                 .adoptShellPermissionIdentity("android.permission.CONTROL_INCALL_EXPERIENCE");
548         try {
549             ICtsApi29InCallServiceControl controlInterface = setUpControl();
550 
551             setupIncomingCallWithCallScreening();
552 
553             final MockConnection connection = verifyConnectionForIncomingCall();
554 
555             if (!mInCallCallbacks.lock.tryAcquire(TestUtils.WAIT_FOR_CALL_ADDED_TIMEOUT_S,
556                     TimeUnit.SECONDS)) {
557                 fail("No call added to InCallService.");
558             }
559 
560             Call call = mInCallCallbacks.getService().getLastCall();
561             assertCallState(call, Call.STATE_AUDIO_PROCESSING);
562             assertConnectionState(connection, Connection.STATE_ACTIVE);
563             // Make sure that the test app never got any calls
564             assertEquals(0, controlInterface.getHistoricalCallCount());
565 
566             call.disconnect();
567             assertCallState(call, Call.STATE_DISCONNECTED);
568             waitOnAllHandlers(getInstrumentation());
569             assertConnectionState(connection, Connection.STATE_DISCONNECTED);
570             // Under some rare circumstances, the test app might get a flash of the disconnection
571             // call, so we won't do the call count check again.
572 
573             tearDownControl();
574         } finally {
575             InstrumentationRegistry.getInstrumentation().getUiAutomation()
576                     .dropShellPermissionIdentity();
577         }
578     }
579 
placeActiveOutgoingCall()580     private Connection placeActiveOutgoingCall() {
581         placeAndVerifyCall();
582 
583         Call call = mInCallCallbacks.getService().getLastCall();
584         assertCallState(call, Call.STATE_DIALING);
585 
586         final MockConnection connection = verifyConnectionForOutgoingCall();
587         connection.setActive();
588         assertCallState(call, Call.STATE_ACTIVE);
589         return connection;
590     }
591 
verifySimulateRingAndUserPickup(Call call, Connection connection)592     private void verifySimulateRingAndUserPickup(Call call, Connection connection) {
593         AudioManager audioManager = mContext.getSystemService(AudioManager.class);
594 
595         call.exitBackgroundAudioProcessing(true);
596         assertCallState(call, Call.STATE_SIMULATED_RINGING);
597         waitOnAllHandlers(getInstrumentation());
598         // We expect the audio mode to stay in CALL_SCREENING when going into simulated ringing.
599         if (doesAudioManagerSupportCallScreening) {
600             assertAudioMode(audioManager, MODE_CALL_SCREENING);
601         }
602         assertConnectionState(connection, Connection.STATE_ACTIVE);
603 
604         call.answer(VideoProfile.STATE_AUDIO_ONLY);
605         assertCallState(call, Call.STATE_ACTIVE);
606         waitOnAllHandlers(getInstrumentation());
607         assertAudioMode(audioManager, AudioManager.MODE_IN_CALL);
608         assertConnectionState(connection, Connection.STATE_ACTIVE);
609     }
610 
verifySimulateRingAndUserMissed(Call call, Connection connection)611     private void verifySimulateRingAndUserMissed(Call call, Connection connection) {
612         AudioManager audioManager = mContext.getSystemService(AudioManager.class);
613 
614         call.exitBackgroundAudioProcessing(true);
615         assertCallState(call, Call.STATE_SIMULATED_RINGING);
616         waitOnAllHandlers(getInstrumentation());
617         // We expect the audio mode to stay in CALL_SCREENING when going into simulated ringing.
618         if (doesAudioManagerSupportCallScreening) {
619             assertAudioMode(audioManager, MODE_CALL_SCREENING);
620         }
621         assertConnectionState(connection, Connection.STATE_ACTIVE);
622         assertTrue(mTelecomManager.isRinging());
623 
624         call.disconnect();
625         assertCallState(call, Call.STATE_DISCONNECTED);
626         assertConnectionState(connection, Connection.STATE_DISCONNECTED);
627         assertEquals(DisconnectCause.MISSED, call.getDetails().getDisconnectCause().getCode());
628     }
629 
setupIncomingCallWithCallScreening()630     private void setupIncomingCallWithCallScreening() throws Exception {
631         CallScreeningServiceCallbacks callback = new CallScreeningServiceCallbacks() {
632             @Override
633             public void onScreenCall(Details callDetails) {
634                 getService().respondToCall(callDetails, new CallResponse.Builder()
635                         .setDisallowCall(false)
636                         .setShouldScreenCallViaAudioProcessing(true)
637                         .build());
638                 lock.release();
639             }
640         };
641         MockCallScreeningService.enableService(mContext);
642         MockCallScreeningService.setCallbacks(callback);
643         Bundle extras = new Bundle();
644         extras.putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, createTestNumber());
645         mTelecomManager.addNewIncomingCall(TEST_PHONE_ACCOUNT_HANDLE, extras);
646 
647         if (!callback.lock.tryAcquire(TestUtils.WAIT_FOR_CALL_ADDED_TIMEOUT_S,
648                 TimeUnit.SECONDS)) {
649             fail("Call screening service never got the call");
650         }
651 
652     }
653 
setUpControl()654     private ICtsApi29InCallServiceControl setUpControl() throws Exception {
655         Pair<ServiceConnection, ICtsApi29InCallServiceControl> setupResult =
656                 Api29InCallUtils.setupControl(mContext);
657         mApiCompatControlServiceConnection = setupResult.first;
658         return setupResult.second;
659     }
660 
tearDownControl()661     private void tearDownControl() throws Exception {
662         Api29InCallUtils.tearDownControl(mContext,
663                 mApiCompatControlServiceConnection);
664     }
665 
clearRoleHoldersAsUser(String roleName)666     private void clearRoleHoldersAsUser(String roleName)
667             throws Exception {
668         UserHandle user = Process.myUserHandle();
669         Executor executor = mContext.getMainExecutor();
670         LinkedBlockingQueue<Boolean> queue = new LinkedBlockingQueue(1);
671 
672         runWithShellPermissionIdentity(() -> mRoleManager.clearRoleHoldersAsUser(roleName,
673                 RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, user, executor,
674                 successful -> {
675                     try {
676                         queue.put(successful);
677                     } catch (InterruptedException e) {
678                         e.printStackTrace();
679                     }
680                 }));
681         boolean result = queue.poll(ASYNC_TIMEOUT, TimeUnit.MILLISECONDS);
682         assertTrue(result);
683     }
684 }
685