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 android.telecom.cts;
18 
19 import static android.telecom.cts.TestUtils.*;
20 
21 import android.content.ContentValues;
22 import android.content.Context;
23 import android.net.Uri;
24 import android.os.Bundle;
25 import android.provider.BlockedNumberContract;
26 import android.telecom.CallAudioState;
27 import android.telecom.Call;
28 import android.telecom.Connection;
29 import android.telecom.ConnectionService;
30 import android.telecom.InCallService;
31 import android.telecom.TelecomManager;
32 import android.telecom.VideoProfile;
33 
34 import java.util.List;
35 
36 /**
37  * Extended suite of tests that use {@link CtsConnectionService} and {@link MockInCallService} to
38  * verify the functionality of the Telecom service.
39  */
40 public class ExtendedInCallServiceTest extends BaseTelecomTestWithMockServices {
41 
42     @Override
setUp()43     protected void setUp() throws Exception {
44         super.setUp();
45         if (mShouldTestTelecom) {
46             setupConnectionService(null, FLAG_REGISTER | FLAG_ENABLE);
47         }
48     }
49 
testAddNewOutgoingCallAndThenDisconnect()50     public void testAddNewOutgoingCallAndThenDisconnect() {
51         if (!mShouldTestTelecom) {
52             return;
53         }
54 
55         placeAndVerifyCall();
56         verifyConnectionForOutgoingCall();
57 
58         final MockInCallService inCallService = mInCallCallbacks.getService();
59         inCallService.disconnectLastCall();
60 
61         assertNumCalls(inCallService, 0);
62     }
63 
testMuteAndUnmutePhone()64     public void testMuteAndUnmutePhone() {
65         if (!mShouldTestTelecom) {
66             return;
67         }
68 
69         placeAndVerifyCall();
70         final MockConnection connection = verifyConnectionForOutgoingCall();
71 
72         final MockInCallService inCallService = mInCallCallbacks.getService();
73 
74         final Call call = inCallService.getLastCall();
75 
76         assertCallState(call, Call.STATE_DIALING);
77 
78         assertMuteState(connection, false);
79 
80         // Explicitly call super implementation to enable detection of CTS coverage
81         ((InCallService) inCallService).setMuted(true);
82 
83         assertMuteState(connection, true);
84         assertMuteState(inCallService, true);
85 
86         inCallService.setMuted(false);
87         assertMuteState(connection, false);
88         assertMuteState(inCallService, false);
89     }
90 
testSwitchAudioRoutes()91     public void testSwitchAudioRoutes() {
92         if (!mShouldTestTelecom) {
93             return;
94         }
95 
96         placeAndVerifyCall();
97         final MockConnection connection = verifyConnectionForOutgoingCall();
98 
99         final MockInCallService inCallService = mInCallCallbacks.getService();
100 
101         final Call call = inCallService.getLastCall();
102         assertCallState(call, Call.STATE_DIALING);
103 
104         final int currentInvokeCount = mOnCallAudioStateChangedCounter.getInvokeCount();
105 
106 
107         // We need to check what audio routes are available. If speaker and either headset or
108         // earpiece aren't available, then we should skip this test.
109         int availableRoutes = connection.getCallAudioState().getSupportedRouteMask();
110         if ((availableRoutes & CallAudioState.ROUTE_SPEAKER) == 0) {
111             return;
112         }
113         if ((availableRoutes & CallAudioState.ROUTE_WIRED_OR_EARPIECE) == 0) {
114             return;
115         }
116         // Determine what the second route to go to after SPEAKER should be, depending on what's
117         // supported.
118         int secondRoute = (availableRoutes & CallAudioState.ROUTE_EARPIECE) == 0 ?
119                 CallAudioState.ROUTE_WIRED_HEADSET : CallAudioState.ROUTE_EARPIECE;
120 
121         // Explicitly call super implementation to enable detection of CTS coverage
122         ((InCallService) inCallService).setAudioRoute(CallAudioState.ROUTE_SPEAKER);
123         mOnCallAudioStateChangedCounter.waitForCount(currentInvokeCount + 1,
124                 WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
125         assertAudioRoute(connection, CallAudioState.ROUTE_SPEAKER);
126         assertAudioRoute(inCallService, CallAudioState.ROUTE_SPEAKER);
127 
128         inCallService.setAudioRoute(secondRoute);
129         mOnCallAudioStateChangedCounter.waitForCount(currentInvokeCount + 2,
130                 WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
131         assertAudioRoute(connection, secondRoute);
132         assertAudioRoute(inCallService, secondRoute);
133     }
134 
135     /**
136      * Tests that DTMF Tones are sent from the {@link InCallService} to the
137      * {@link ConnectionService} in the correct sequence.
138      *
139      * @see {@link Call#playDtmfTone(char)}
140      * @see {@link Call#stopDtmfTone()}
141      */
testPlayAndStopDtmfTones()142     public void testPlayAndStopDtmfTones() {
143         if (!mShouldTestTelecom) {
144             return;
145         }
146 
147         placeAndVerifyCall();
148         final MockConnection connection = verifyConnectionForOutgoingCall();
149 
150         final MockInCallService inCallService = mInCallCallbacks.getService();
151 
152         final Call call = inCallService.getLastCall();
153         assertCallState(call, Call.STATE_DIALING);
154 
155         assertDtmfString(connection, "");
156 
157         call.playDtmfTone('1');
158         assertDtmfString(connection, "1");
159 
160         call.playDtmfTone('2');
161         assertDtmfString(connection, "12");
162 
163         call.stopDtmfTone();
164         assertDtmfString(connection, "12.");
165 
166         call.playDtmfTone('3');
167         call.playDtmfTone('4');
168         call.playDtmfTone('5');
169         assertDtmfString(connection, "12.345");
170 
171         call.stopDtmfTone();
172         assertDtmfString(connection, "12.345.");
173     }
174 
testHoldAndUnholdCall()175     public void testHoldAndUnholdCall() {
176         if (!mShouldTestTelecom) {
177             return;
178         }
179 
180         placeAndVerifyCall();
181         final MockConnection connection = verifyConnectionForOutgoingCall();
182 
183         final MockInCallService inCallService = mInCallCallbacks.getService();
184 
185         final Call call = inCallService.getLastCall();
186 
187         assertCallState(call, Call.STATE_DIALING);
188 
189         connection.setActive();
190 
191         assertCallState(call, Call.STATE_ACTIVE);
192 
193         call.hold();
194         assertCallState(call, Call.STATE_HOLDING);
195         assertEquals(Connection.STATE_HOLDING, connection.getState());
196 
197         call.unhold();
198         assertCallState(call, Call.STATE_ACTIVE);
199         assertEquals(Connection.STATE_ACTIVE, connection.getState());
200     }
201 
testAnswerIncomingCallAudioOnly()202     public void testAnswerIncomingCallAudioOnly() {
203         if (!mShouldTestTelecom) {
204             return;
205         }
206 
207         addAndVerifyNewIncomingCall(createTestNumber(), null);
208         final MockConnection connection = verifyConnectionForIncomingCall();
209 
210         final MockInCallService inCallService = mInCallCallbacks.getService();
211 
212         final Call call = inCallService.getLastCall();
213 
214         assertCallState(call, Call.STATE_RINGING);
215         assertConnectionState(connection, Connection.STATE_RINGING);
216 
217         call.answer(VideoProfile.STATE_AUDIO_ONLY);
218 
219         assertCallState(call, Call.STATE_ACTIVE);
220         assertConnectionState(connection, Connection.STATE_ACTIVE);
221     }
222 
testIncomingCallFromBlockedNumber_IsRejected()223     public void testIncomingCallFromBlockedNumber_IsRejected() throws Exception {
224         if (!mShouldTestTelecom) {
225             return;
226         }
227 
228         Uri blockedUri = null;
229 
230         try {
231             Uri testNumberUri = createTestNumber();
232             blockedUri = blockNumber(testNumberUri);
233 
234             final Bundle extras = new Bundle();
235             extras.putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, testNumberUri);
236             mTelecomManager.addNewIncomingCall(TEST_PHONE_ACCOUNT_HANDLE, extras);
237 
238             final MockConnection connection = verifyConnectionForIncomingCall();
239             assertConnectionState(connection, Connection.STATE_DISCONNECTED);
240             assertNull(mInCallCallbacks.getService());
241         } finally {
242             if (blockedUri != null) {
243                 mContext.getContentResolver().delete(blockedUri, null, null);
244             }
245         }
246     }
247 
blockNumber(Uri phoneNumberUri)248     private Uri blockNumber(Uri phoneNumberUri) {
249         ContentValues cv = new ContentValues();
250         cv.put(BlockedNumberContract.BlockedNumbers.COLUMN_ORIGINAL_NUMBER,
251                 phoneNumberUri.getSchemeSpecificPart());
252         return mContext.getContentResolver().insert(
253                 BlockedNumberContract.BlockedNumbers.CONTENT_URI, cv);
254     }
255 
testAnswerIncomingCallAsVideo_SendsCorrectVideoState()256     public void testAnswerIncomingCallAsVideo_SendsCorrectVideoState() {
257         if (!mShouldTestTelecom) {
258             return;
259         }
260 
261         addAndVerifyNewIncomingCall(createTestNumber(), null);
262         final MockConnection connection = verifyConnectionForIncomingCall();
263 
264         final MockInCallService inCallService = mInCallCallbacks.getService();
265 
266         final Call call = inCallService.getLastCall();
267 
268         assertCallState(call, Call.STATE_RINGING);
269         assertConnectionState(connection, Connection.STATE_RINGING);
270 
271         call.answer(VideoProfile.STATE_BIDIRECTIONAL);
272 
273         assertCallState(call, Call.STATE_ACTIVE);
274         assertConnectionState(connection, Connection.STATE_ACTIVE);
275         assertEquals("Connection did not receive VideoState for answered call",
276                 VideoProfile.STATE_BIDIRECTIONAL, connection.videoState);
277     }
278 
testRejectIncomingCall()279     public void testRejectIncomingCall() {
280         if (!mShouldTestTelecom) {
281             return;
282         }
283 
284         addAndVerifyNewIncomingCall(createTestNumber(), null);
285         final MockConnection connection = verifyConnectionForIncomingCall();
286 
287         final MockInCallService inCallService = mInCallCallbacks.getService();
288 
289         final Call call = inCallService.getLastCall();
290 
291         assertCallState(call, Call.STATE_RINGING);
292         assertConnectionState(connection, Connection.STATE_RINGING);
293 
294         call.reject(false, null);
295 
296         assertCallState(call, Call.STATE_DISCONNECTED);
297         assertConnectionState(connection, Connection.STATE_DISCONNECTED);
298     }
299 
testRejectIncomingCallWithMessage()300     public void testRejectIncomingCallWithMessage() {
301         if (!mShouldTestTelecom) {
302             return;
303         }
304         String disconnectReason = "Test reason for disconnect";
305 
306         addAndVerifyNewIncomingCall(createTestNumber(), null);
307         final MockConnection connection = verifyConnectionForIncomingCall();
308 
309         final MockInCallService inCallService = mInCallCallbacks.getService();
310 
311         final Call call = inCallService.getLastCall();
312 
313         assertCallState(call, Call.STATE_RINGING);
314         assertConnectionState(connection, Connection.STATE_RINGING);
315 
316         call.reject(true, disconnectReason);
317 
318         assertCallState(call, Call.STATE_DISCONNECTED);
319         assertConnectionState(connection, Connection.STATE_DISCONNECTED);
320         assertDisconnectReason(connection, disconnectReason);
321     }
322 
testCanAddCall_CannotAddForExistingDialingCall()323     public void testCanAddCall_CannotAddForExistingDialingCall() {
324         if (!mShouldTestTelecom) {
325             return;
326         }
327 
328         placeAndVerifyCall();
329         verifyConnectionForOutgoingCall();
330 
331         final MockInCallService inCallService = mInCallCallbacks.getService();
332 
333         final Call call = inCallService.getLastCall();
334         assertCallState(call, Call.STATE_DIALING);
335 
336         assertCanAddCall(inCallService, false,
337                 "Should not be able to add call with existing dialing call");
338     }
339 
testCanAddCall_CanAddForExistingActiveCall()340     public void testCanAddCall_CanAddForExistingActiveCall() {
341         if (!mShouldTestTelecom) {
342             return;
343         }
344 
345         placeAndVerifyCall();
346         final MockConnection connection = verifyConnectionForOutgoingCall();
347 
348         final MockInCallService inCallService = mInCallCallbacks.getService();
349 
350         final Call call = inCallService.getLastCall();
351         assertCallState(call, Call.STATE_DIALING);
352 
353         connection.setActive();
354 
355         assertCallState(call, Call.STATE_ACTIVE);
356 
357         assertCanAddCall(inCallService, true,
358                 "Should be able to add call with only one active call");
359     }
360 
testCanAddCall_CannotAddIfTooManyCalls()361     public void testCanAddCall_CannotAddIfTooManyCalls() {
362         if (!mShouldTestTelecom) {
363             return;
364         }
365 
366         placeAndVerifyCall();
367         final MockConnection connection1 = verifyConnectionForOutgoingCall(0);
368         final MockInCallService inCallService = mInCallCallbacks.getService();
369         final Call call1 = inCallService.getLastCall();
370         assertCallState(call1, Call.STATE_DIALING);
371 
372         connection1.setActive();
373 
374         assertCallState(call1, Call.STATE_ACTIVE);
375 
376         placeAndVerifyCall();
377         final MockConnection connection2 = verifyConnectionForOutgoingCall(1);
378 
379         final Call call2 = inCallService.getLastCall();
380         assertCallState(call2, Call.STATE_DIALING);
381         connection2.setActive();
382         assertCallState(call2, Call.STATE_ACTIVE);
383 
384         assertEquals("InCallService should have 2 calls", 2, inCallService.getCallCount());
385 
386         assertCanAddCall(inCallService, false,
387                 "Should not be able to add call with two calls already present");
388 
389         call1.hold();
390         assertCallState(call1, Call.STATE_HOLDING);
391 
392         assertCanAddCall(inCallService, false,
393                 "Should not be able to add call with two calls already present");
394     }
395 
testOnBringToForeground()396     public void testOnBringToForeground() {
397         if (!mShouldTestTelecom) {
398             return;
399         }
400 
401         placeAndVerifyCall();
402         verifyConnectionForOutgoingCall();
403 
404         final MockInCallService inCallService = mInCallCallbacks.getService();
405 
406         final Call call = inCallService.getLastCall();
407 
408         assertCallState(call, Call.STATE_DIALING);
409 
410         assertEquals(0, mOnBringToForegroundCounter.getInvokeCount());
411 
412         final TelecomManager tm =
413             (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
414 
415         tm.showInCallScreen(false);
416 
417         mOnBringToForegroundCounter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
418 
419         assertFalse((Boolean) mOnBringToForegroundCounter.getArgs(0)[0]);
420 
421         tm.showInCallScreen(true);
422 
423         mOnBringToForegroundCounter.waitForCount(2, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
424 
425         assertTrue((Boolean) mOnBringToForegroundCounter.getArgs(1)[0]);
426     }
427 
testSilenceRinger()428     public void testSilenceRinger() {
429         if (!mShouldTestTelecom) {
430             return;
431         }
432 
433         addAndVerifyNewIncomingCall(createTestNumber(), null);
434         final MockConnection connection = verifyConnectionForIncomingCall();
435         final MockInCallService inCallService = mInCallCallbacks.getService();
436 
437         final TelecomManager telecomManager =
438             (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
439         telecomManager.silenceRinger();
440         mOnSilenceRingerCounter.waitForCount(1);
441     }
442 
testOnPostDialWaitAndContinue()443     public void testOnPostDialWaitAndContinue() {
444         if (!mShouldTestTelecom) {
445             return;
446         }
447 
448         placeAndVerifyCall();
449         final MockConnection connection = verifyConnectionForOutgoingCall();
450         final MockInCallService inCallService = mInCallCallbacks.getService();
451         final Call call = inCallService.getLastCall();
452         assertCallState(call, Call.STATE_DIALING);
453 
454         connection.setActive();
455         assertCallState(call, Call.STATE_ACTIVE);
456 
457         final String postDialString = "12345";
458         ((Connection) connection).setPostDialWait(postDialString);
459         mOnPostDialWaitCounter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
460 
461         assertEquals(postDialString, mOnPostDialWaitCounter.getArgs(0)[1]);
462         assertEquals(postDialString, call.getRemainingPostDialSequence());
463 
464         final InvokeCounter counter = connection.getInvokeCounter(MockConnection.ON_POST_DIAL_WAIT);
465 
466         call.postDialContinue(true);
467         counter.waitForCount(1);
468         assertTrue((Boolean) counter.getArgs(0)[0]);
469 
470         call.postDialContinue(false);
471         counter.waitForCount(2);
472         assertFalse((Boolean) counter.getArgs(1)[0]);
473     }
474 
testOnCannedTextResponsesLoaded()475     public void testOnCannedTextResponsesLoaded() {
476         if (!mShouldTestTelecom) {
477             return;
478         }
479 
480         addAndVerifyNewIncomingCall(createTestNumber(), null);
481         verifyConnectionForIncomingCall();
482         final MockInCallService inCallService = mInCallCallbacks.getService();
483 
484         final Call call = inCallService.getLastCall();
485 
486         assertCallState(call, Call.STATE_RINGING);
487 
488         // We can't do much to enforce the number and type of responses that are preloaded on
489         // device, so the best we can do is to make sure that the call back is called and
490         // that the returned list is non-empty.
491 
492         // This test should also verify that the callback is called as well, but unfortunately it
493         // is never called right now (b/22952515).
494         // mOnCannedTextResponsesLoadedCounter.waitForCount(1);
495 
496         assertGetCannedTextResponsesNotEmpty(call);
497     }
498 
testGetCalls()499     public void testGetCalls() {
500         if (!mShouldTestTelecom) {
501             return;
502         }
503 
504         placeAndVerifyCall();
505         final MockConnection connection1 = verifyConnectionForOutgoingCall(0);
506         final MockInCallService inCallService = mInCallCallbacks.getService();
507         final Call call1 = inCallService.getLastCall();
508         assertCallState(call1, Call.STATE_DIALING);
509 
510         connection1.setActive();
511 
512         assertCallState(call1, Call.STATE_ACTIVE);
513 
514         List<Call> calls = inCallService.getCalls();
515         assertEquals("InCallService.getCalls() should return list with 1 call.", 1, calls.size());
516         assertEquals(call1, calls.get(0));
517 
518         addAndVerifyNewIncomingCall(createTestNumber(), null);
519         verifyConnectionForIncomingCall();
520 
521         final Call call2 = inCallService.getLastCall();
522         calls = inCallService.getCalls();
523         assertEquals("InCallService.getCalls() should return list with 2 calls.", 2, calls.size());
524         assertEquals(call1, calls.get(0));
525         assertEquals(call2, calls.get(1));
526     }
527 
assertGetCannedTextResponsesNotEmpty(final Call call)528     private void assertGetCannedTextResponsesNotEmpty(final Call call) {
529         waitUntilConditionIsTrueOrTimeout(
530                 new Condition() {
531                     @Override
532                     public Object expected() {
533                         return true;
534                     }
535 
536                     @Override
537                     public Object actual() {
538                         return call.getCannedTextResponses() != null
539                                 && !call.getCannedTextResponses().isEmpty();
540                     }
541 
542                 },
543                 WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
544                 "Call.getCannedTextResponses should not be empty");
545     }
546 
assertCanAddCall(final InCallService inCallService, final boolean canAddCall, String message)547     private void assertCanAddCall(final InCallService inCallService, final boolean canAddCall,
548             String message) {
549         waitUntilConditionIsTrueOrTimeout(
550                 new Condition() {
551                     @Override
552                     public Object expected() {
553                         return canAddCall;
554                     }
555 
556                     @Override
557                     public Object actual() {
558                         return inCallService.canAddCall();
559                     }
560                 },
561                 WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
562                 message
563         );
564     }
565 }
566