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