1 /*
2  * Copyright (C) 2017 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.media.AudioManager.MODE_IN_CALL;
20 import static android.media.AudioManager.MODE_IN_COMMUNICATION;
21 import static android.telecom.cts.TestUtils.SELF_MANAGED_ACCOUNT_LABEL;
22 import static android.telecom.cts.TestUtils.TEST_SELF_MANAGED_HANDLE_1;
23 import static android.telecom.cts.TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS;
24 import static android.telecom.cts.TestUtils.waitOnAllHandlers;
25 
26 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
27 
28 import static org.junit.Assert.assertNotEquals;
29 
30 import android.content.ComponentName;
31 import android.content.Context;
32 import android.content.Intent;
33 import android.content.ServiceConnection;
34 import android.database.Cursor;
35 import android.graphics.Color;
36 import android.media.AudioManager;
37 import android.net.Uri;
38 import android.os.Bundle;
39 import android.os.IBinder;
40 import android.os.OutcomeReceiver;
41 import android.os.UserHandle;
42 import android.provider.CallLog;
43 import android.telecom.Call;
44 import android.telecom.CallAudioState;
45 import android.telecom.CallEndpoint;
46 import android.telecom.CallEndpointException;
47 import android.telecom.Connection;
48 import android.telecom.ConnectionService;
49 import android.telecom.DisconnectCause;
50 import android.telecom.InCallService;
51 import android.telecom.PhoneAccount;
52 import android.telecom.PhoneAccountHandle;
53 import android.telecom.TelecomManager;
54 import android.telecom.VideoProfile;
55 import android.telecom.cts.selfmanagedcstestapp.ICtsSelfManagedConnectionServiceControl;
56 import android.telecom.cts.selfmanagedcstestappone.CtsSelfManagedConnectionServiceControlOne;
57 import android.util.Log;
58 
59 import androidx.test.platform.app.InstrumentationRegistry;
60 
61 import com.android.compatibility.common.util.ApiTest;
62 import com.android.compatibility.common.util.CddTest;
63 import com.android.server.telecom.flags.Flags;
64 
65 import java.util.ArrayList;
66 import java.util.List;
67 import java.util.concurrent.CountDownLatch;
68 import java.util.concurrent.Executor;
69 import java.util.concurrent.TimeUnit;
70 import java.util.function.Predicate;
71 
72 /**
73  * CTS tests for the self-managed {@link android.telecom.ConnectionService} APIs.
74  * For more information about these APIs, see {@link android.telecom}, and
75  * {@link android.telecom.PhoneAccount#CAPABILITY_SELF_MANAGED}.
76  */
77 
78 public class SelfManagedConnectionServiceTest extends BaseTelecomTestWithMockServices {
79     private static final String TAG = "SelfManagedConnectionServiceTest";
80     private static final long TIMEOUT = 3000L;
81     private Uri TEST_ADDRESS_1 = Uri.fromParts("sip", "call1@test.com", null);
82     private Uri TEST_ADDRESS_2 = Uri.fromParts("tel", "6505551212", null);
83     private Uri TEST_ADDRESS_3 = Uri.fromParts("tel", "6505551213", null);
84     private Uri TEST_ADDRESS_4 = Uri.fromParts(TestUtils.TEST_URI_SCHEME, "fizzle_schmozle", null);
85 
86     private static final String SELF_MANAGED_CS_CONTROL =
87             "android.telecom.cts.selfmanagedcstestapp.ACTION_SELF_MANAGED_CS_CONTROL";
88     private static final String SELF_MANAGED_CS_PKG_1 =
89             CtsSelfManagedConnectionServiceControlOne.class.getPackage().getName();
90     private static final ComponentName SELF_MANAGED_CS_1 = ComponentName.createRelative(
91             SELF_MANAGED_CS_PKG_1, CtsSelfManagedConnectionServiceControlOne.class.getName());
92 
93     @Override
setUp()94     protected void setUp() throws Exception {
95         super.setUp();
96         NewOutgoingCallBroadcastReceiver.reset();
97         mContext = getInstrumentation().getContext();
98         if (mShouldTestTelecom && TestUtils.hasTelephonyFeature(mContext)) {
99             // Register and enable the CTS ConnectionService; we want to be able to test a managed
100             // ConnectionService alongside a self-managed ConnectionService.
101             // Also set FLAG_SET_DEFAULT to test the case where the call is not expected to go over
102             // the self-managed ConnectionService.
103             setupConnectionService(null, FLAG_REGISTER | FLAG_ENABLE | FLAG_SET_DEFAULT);
104 
105             mTelecomManager.registerPhoneAccount(TestUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_1);
106             mTelecomManager.registerPhoneAccount(TestUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_2);
107             mTelecomManager.registerPhoneAccount(TestUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_3);
108             mTelecomManager.registerPhoneAccount(TestUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_4);
109         }
110     }
111 
112     @Override
tearDown()113     protected void tearDown() throws Exception {
114         if (mShouldTestTelecom && TestUtils.hasTelephonyFeature(mContext)) {
115             CtsSelfManagedConnectionService connectionService =
116                     CtsSelfManagedConnectionService.getConnectionService();
117             if (connectionService != null) {
118                 connectionService.tearDown();
119                 mTelecomManager.unregisterPhoneAccount(TestUtils.TEST_SELF_MANAGED_HANDLE_1);
120                 mTelecomManager.unregisterPhoneAccount(TestUtils.TEST_SELF_MANAGED_HANDLE_2);
121                 mTelecomManager.unregisterPhoneAccount(TestUtils.TEST_SELF_MANAGED_HANDLE_3);
122                 mTelecomManager.unregisterPhoneAccount(TestUtils.TEST_SELF_MANAGED_HANDLE_4);
123             }
124         }
125         super.tearDown();
126     }
127 
128     private static class TestServiceConnection implements ServiceConnection {
129         private IBinder mService;
130         private final CountDownLatch mLatch = new CountDownLatch(1);
131         private boolean mIsConnected;
132         private final PhoneAccount mAssociatedAccount;
133 
134         private ICtsSelfManagedConnectionServiceControl mControl;
135 
TestServiceConnection(PhoneAccount account)136         TestServiceConnection(PhoneAccount account) {
137             mAssociatedAccount = account;
138         }
139 
140         @Override
onServiceConnected(ComponentName componentName, IBinder service)141         public void onServiceConnected(ComponentName componentName, IBinder service) {
142             Log.i(TAG, "Service Connected: " + componentName);
143             mService = service;
144             mControl = ICtsSelfManagedConnectionServiceControl.Stub.asInterface(service);
145             mIsConnected = true;
146             mLatch.countDown();
147         }
148 
149         @Override
onServiceDisconnected(ComponentName componentName)150         public void onServiceDisconnected(ComponentName componentName) {
151             mService = null;
152         }
153 
getService()154         public IBinder getService() {
155             return mService;
156         }
157 
getInterface()158         public ICtsSelfManagedConnectionServiceControl getInterface() {
159             return mControl;
160         }
161 
getAssociatedAccount()162         public PhoneAccount getAssociatedAccount() {
163             return mAssociatedAccount;
164         }
165 
waitBind()166         public boolean waitBind() {
167             try {
168                 mLatch.await(TIMEOUT, TimeUnit.MILLISECONDS);
169                 return mIsConnected;
170             } catch (InterruptedException e) {
171                 return false;
172             }
173         }
174     }
175 
bindExternalSelfManagedServiceAndRegister( PhoneAccount account)176     private TestServiceConnection bindExternalSelfManagedServiceAndRegister(
177             PhoneAccount account) throws Exception {
178         TestServiceConnection control = setUpControl(SELF_MANAGED_CS_CONTROL, SELF_MANAGED_CS_1,
179                 account);
180         control.getInterface().init();
181         control.getInterface().registerPhoneAccount(account);
182         return control;
183     }
184 
setUpControl(String action, ComponentName componentName, PhoneAccount acct)185     private TestServiceConnection setUpControl(String action, ComponentName componentName,
186             PhoneAccount acct) {
187         Intent bindIntent = new Intent(action);
188         bindIntent.setComponent(componentName);
189 
190         TestServiceConnection serviceConnection = new TestServiceConnection(acct);
191         mContext.bindService(bindIntent, serviceConnection, Context.BIND_AUTO_CREATE);
192         if (!serviceConnection.waitBind()) {
193             fail("fail bind to service");
194         }
195         return serviceConnection;
196     }
197 
tearDownControl(TestServiceConnection c)198     private void tearDownControl(TestServiceConnection c) throws Exception {
199         c.getInterface().unregisterPhoneAccount(c.getAssociatedAccount().getAccountHandle());
200         c.getInterface().deInit();
201         mContext.unbindService(c);
202     }
203 
204     /**
205      * Tests {@link TelecomManager#getSelfManagedPhoneAccounts()} API to ensure it returns a list of
206      * the registered self-managed {@link android.telecom.PhoneAccount}s.
207      */
208     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
209     @ApiTest(apis = {"android.telecom.TelecomManager#getSelfManagedPhoneAccounts"})
testTelecomManagerGetSelfManagedPhoneAccounts()210     public void testTelecomManagerGetSelfManagedPhoneAccounts() {
211         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
212             return;
213         }
214 
215         List<PhoneAccountHandle> phoneAccountHandles =
216                 mTelecomManager.getSelfManagedPhoneAccounts();
217 
218         assertTrue(phoneAccountHandles.contains(TestUtils.TEST_SELF_MANAGED_HANDLE_1));
219         assertTrue(phoneAccountHandles.contains(TestUtils.TEST_SELF_MANAGED_HANDLE_2));
220         assertTrue(phoneAccountHandles.contains(TestUtils.TEST_SELF_MANAGED_HANDLE_3));
221         assertFalse(phoneAccountHandles.contains(TestUtils.TEST_PHONE_ACCOUNT_HANDLE));
222     }
223 
224     /**
225      * Tests the ability to successfully register a self-managed
226      * {@link android.telecom.PhoneAccount}.
227      * <p>
228      * It should be possible to register self-managed Connection Services which suppor the TEL, SIP,
229      * or other URI schemes.
230      */
231     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
232     @ApiTest(apis = {"android.telecom.TelecomManager#registerPhoneAccount",
233             "android.telecom.PhoneAccount"})
testRegisterSelfManagedConnectionService()234     public void testRegisterSelfManagedConnectionService() {
235         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
236             return;
237         }
238         verifyAccountRegistration(TestUtils.TEST_SELF_MANAGED_HANDLE_1,
239                 TestUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_1);
240         verifyAccountRegistration(TestUtils.TEST_SELF_MANAGED_HANDLE_2,
241                 TestUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_2);
242         verifyAccountRegistration(TestUtils.TEST_SELF_MANAGED_HANDLE_3,
243                 TestUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_3);
244     }
245 
246     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
247     @ApiTest(apis = {"android.telecom.TelecomManager#registerPhoneAccount",
248             "android.telecom.PhoneAccount"})
testSelfManagedConnectionServiceRegistrationUnmodifiable()249     public void testSelfManagedConnectionServiceRegistrationUnmodifiable() {
250         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
251             return;
252         }
253 
254         verifyAccountRegistration(TestUtils.TEST_SELF_MANAGED_HANDLE_1,
255                 TestUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_1);
256         PhoneAccount newPhoneAccount = PhoneAccount.builder(
257                         TEST_SELF_MANAGED_HANDLE_1, SELF_MANAGED_ACCOUNT_LABEL)
258                 .setAddress(Uri.parse("sip:test@test.com"))
259                 .setSubscriptionAddress(Uri.parse("sip:test@test.com"))
260                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER
261                         | PhoneAccount.CAPABILITY_SUPPORTS_VIDEO_CALLING
262                         | PhoneAccount.CAPABILITY_VIDEO_CALLING)
263                 .setHighlightColor(Color.BLUE)
264                 .setShortDescription(SELF_MANAGED_ACCOUNT_LABEL)
265                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
266                 .addSupportedUriScheme(PhoneAccount.SCHEME_SIP)
267                 .build();
268         try {
269             mTelecomManager.registerPhoneAccount(newPhoneAccount);
270             fail("Self-managed phone account can be replaced to a call provider phone account!");
271         } catch (IllegalArgumentException e) {
272             // expected
273         }
274     }
275 
276     /**
277      * This test ensures that a {@link android.telecom.PhoneAccount} declared as self-managed cannot
278      * but is also registered as a call provider is not permitted.
279      *
280      * A self-managed {@link android.telecom.PhoneAccount} cannot also be a call provider.
281      */
282     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
283     @ApiTest(apis = {"android.telecom.TelecomManager#registerPhoneAccount",
284             "android.telecom.PhoneAccount"})
testRegisterCallCapableSelfManagedConnectionService()285     public void testRegisterCallCapableSelfManagedConnectionService() {
286         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
287             return;
288         }
289 
290         // Attempt to register both a call provider and self-managed account.
291         PhoneAccount toRegister = TestUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_1.toBuilder()
292                 .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED |
293                         PhoneAccount.CAPABILITY_CALL_PROVIDER)
294                 .build();
295 
296         registerAndExpectFailure(toRegister);
297     }
298 
299     /**
300      * This test ensures that a {@link android.telecom.PhoneAccount} declared as self-managed cannot
301      * but is also registered as a sim subscription is not permitted.
302      *
303      * A self-managed {@link android.telecom.PhoneAccount} cannot also be a SIM subscription.
304      */
305     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
306     @ApiTest(apis = {"android.telecom.TelecomManager#registerPhoneAccount",
307             "android.telecom.PhoneAccount"})
testRegisterSimSelfManagedConnectionService()308     public void testRegisterSimSelfManagedConnectionService() {
309         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
310             return;
311         }
312 
313         // Attempt to register both a call provider and self-managed account.
314         PhoneAccount toRegister = TestUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_1.toBuilder()
315                 .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED |
316                         PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
317                 .build();
318 
319         registerAndExpectFailure(toRegister);
320     }
321 
322     /**
323      * This test ensures that a {@link android.telecom.PhoneAccount} declared as self-managed cannot
324      * but is also registered as a connection manager is not permitted.
325      *
326      * A self-managed {@link android.telecom.PhoneAccount} cannot also be a connection manager.
327      */
328     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
329     @ApiTest(apis = {"android.telecom.TelecomManager#registerPhoneAccount",
330             "android.telecom.PhoneAccount"})
testRegisterConnectionManagerSelfManagedConnectionService()331     public void testRegisterConnectionManagerSelfManagedConnectionService() {
332         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
333             return;
334         }
335 
336         // Attempt to register both a call provider and self-managed account.
337         PhoneAccount toRegister = TestUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_1.toBuilder()
338                 .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED |
339                         PhoneAccount.CAPABILITY_CONNECTION_MANAGER)
340                 .build();
341 
342         registerAndExpectFailure(toRegister);
343     }
344 
345     /**
346      * Attempts to register a {@link android.telecom.PhoneAccount}, expecting a security exception
347      * which indicates that invalid capabilities were specified.
348      *
349      * @param toRegister The PhoneAccount to register.
350      */
registerAndExpectFailure(PhoneAccount toRegister)351     private void registerAndExpectFailure(PhoneAccount toRegister) {
352         try {
353             mTelecomManager.registerPhoneAccount(toRegister);
354         } catch (SecurityException se) {
355             assertEquals("Self-managed ConnectionServices cannot also be call capable, " +
356                     "connection managers, or SIM accounts.", se.getMessage());
357             return;
358         }
359         fail("Expected SecurityException");
360     }
361 
362     /**
363      * Tests ability to add a new self-managed incoming connection.
364      */
365     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
366     @ApiTest(apis = {"android.telecom.TelecomManager#addNewIncomingCall"})
testAddSelfManagedIncomingConnection()367     public void testAddSelfManagedIncomingConnection() throws Exception {
368         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
369             return;
370         }
371 
372         addAndVerifyIncomingCall(TestUtils.TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_1);
373         addAndVerifyIncomingCall(TestUtils.TEST_SELF_MANAGED_HANDLE_2, TEST_ADDRESS_3);
374         addAndVerifyIncomingCall(TestUtils.TEST_SELF_MANAGED_HANDLE_3, TEST_ADDRESS_4);
375     }
376 
addAndVerifyIncomingCall(PhoneAccountHandle handle, Uri address)377     private void addAndVerifyIncomingCall(PhoneAccountHandle handle, Uri address)
378             throws Exception {
379         TestUtils.addIncomingCall(getInstrumentation(), mTelecomManager, handle, address);
380 
381         // Ensure Telecom bound to the self managed CS
382         if (!CtsSelfManagedConnectionService.waitForBinding()) {
383             fail("Could not bind to Self-Managed ConnectionService");
384         }
385 
386         SelfManagedConnection connection = TestUtils.waitForAndGetConnection(address);
387 
388         // Expect callback indicating that UI should be shown.
389         connection.getOnShowIncomingUiInvokeCounter().waitForCount(1);
390         setActiveAndVerify(connection);
391 
392         // Ensure that the connection defaulted to voip audio mode.
393         assertTrue(connection.getAudioModeIsVoip());
394         // Ensure AudioManager has correct voip mode.
395         AudioManager audioManager = mContext.getSystemService(AudioManager.class);
396         assertAudioMode(audioManager, MODE_IN_COMMUNICATION);
397 
398         // Expect there to be no managed calls at the moment.
399         assertFalse(mTelecomManager.isInManagedCall());
400         assertTrue(mTelecomManager.isInCall());
401 
402         setDisconnectedAndVerify(connection);
403 
404         if (isLoggedCall(handle)) {
405             verifyCallLogging(address, CallLog.Calls.INCOMING_TYPE, handle);
406         }
407     }
408 
409     /**
410      * Tests ensures that Telecom disallow to place outgoing self-managed call when the ongoing
411      * managed call can not be held.
412      */
413     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
414     @ApiTest(apis = {"android.telecom.TelecomManager#placeCall"})
testDisallowOutgoingCallWhileOngoingManagedCallCanNotBeHeld()415     public void testDisallowOutgoingCallWhileOngoingManagedCallCanNotBeHeld() throws Exception {
416         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
417             return;
418         }
419 
420         // GIVEN an ongoing managed call that can not be held
421         addAndVerifyNewIncomingCall(createTestNumber(), null);
422         Connection connection = verifyConnectionForIncomingCall();
423         int capabilities = connection.getConnectionCapabilities();
424         capabilities &= ~Connection.CAPABILITY_HOLD;
425         connection.setConnectionCapabilities(capabilities);
426 
427         // answer the incoming call
428         MockInCallService inCallService = mInCallCallbacks.getService();
429         Call call = inCallService.getLastCall();
430         call.answer(VideoProfile.STATE_AUDIO_ONLY);
431         assertConnectionState(connection, Connection.STATE_ACTIVE);
432 
433         // WHEN place a self-managed outgoing call
434         TestUtils.placeOutgoingCall(getInstrumentation(), mTelecomManager,
435                 TestUtils.TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_1);
436 
437         // THEN the new outgoing call is failed.
438         CtsSelfManagedConnectionService.waitForBinding();
439         assertTrue(CtsSelfManagedConnectionService.getConnectionService().waitForUpdate(
440                 CtsSelfManagedConnectionService.CREATE_OUTGOING_CONNECTION_FAILED_LOCK));
441 
442         assertIsOutgoingCallPermitted(false, TestUtils.TEST_SELF_MANAGED_HANDLE_1);
443     }
444 
445     /**
446      * Tests ensures that Telecom update outgoing self-managed call state disconnected when
447      * remote side call is rejected.
448      */
449     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
450     @ApiTest(apis = {"android.telecom.TelecomManager#placeCall"})
testOutgoingCallRejectedByRemoteParty()451     public void testOutgoingCallRejectedByRemoteParty() throws Exception {
452         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
453             return;
454         }
455 
456         TestUtils.placeOutgoingCall(getInstrumentation(), mTelecomManager,
457                 TestUtils.TEST_SELF_MANAGED_HANDLE_2, TEST_ADDRESS_2);
458 
459         // Ensure Telecom bound to the self managed CS
460         if (!CtsSelfManagedConnectionService.waitForBinding()) {
461             fail("Could not bind to Self-Managed ConnectionService");
462         }
463 
464         SelfManagedConnection connection = TestUtils.waitForAndGetConnection(TEST_ADDRESS_2);
465         assertNotNull("Self-Managed Connection should NOT be null.", connection);
466         assertTrue("Self-Managed Connection should be outgoing.", !connection.isIncomingCall());
467 
468         // The self-managed ConnectionService must NOT have been prompted to show its incoming call
469         // UI for an outgoing call.
470         assertEquals(connection.getOnShowIncomingUiInvokeCounter().getInvokeCount(), 0);
471 
472         // Expect that the new outgoing call broadcast did not fire for the self-managed calls.
473         assertFalse(NewOutgoingCallBroadcastReceiver.isNewOutgoingCallBroadcastReceived());
474 
475         assertConnectionState(connection, Connection.STATE_INITIALIZING);
476         assertCallState(mInCallCallbacks.getService().getLastCall(), Call.STATE_DIALING);
477 
478         connection.setDialing();
479         assertConnectionState(connection, Connection.STATE_DIALING);
480 
481         connection.setDisconnected(new DisconnectCause(DisconnectCause.REMOTE));
482 
483         assertConnectionState(connection, Connection.STATE_DISCONNECTED);
484         assertCallState(mInCallCallbacks.getService().getLastCall(), Call.STATE_DISCONNECTED);
485 
486         setDisconnectedAndVerify(connection);
487     }
488 
489     /**
490      * Tests ensures that Telecom update self-managed call mute state when user sets mute option.
491      */
492     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
493     @ApiTest(apis = {"android.telecom.Connection#onMuteStateChanged"})
testSelfManagedCallMuteAndUnmute()494     public void testSelfManagedCallMuteAndUnmute() throws Exception {
495         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
496             return;
497         }
498 
499         SelfManagedConnection connection = null;
500 
501         try {
502             connection = placeSelfManagedCallAndGetConnection(TestUtils.TEST_SELF_MANAGED_HANDLE_2,
503                     TEST_ADDRESS_2);
504 
505             final MockInCallService inCallService = getInCallService();
506             final Call call = inCallService.getLastCall();
507 
508             assertMuteState(connection, false);
509 
510             // Explicitly call super implementation to enable detection of CTS coverage
511             ((InCallService) inCallService).setMuted(true);
512 
513             assertMuteState(connection, true);
514             assertMuteState(inCallService, true);
515 
516             inCallService.setMuted(false);
517             assertMuteState(connection, false);
518             assertMuteState(inCallService, false);
519         } finally {
520             if (connection != null) {
521                 // disconnect call
522                 connection.disconnectAndDestroy();
523                 // verify the call was disconnected
524                 assertIsInCall(false);
525                 assertIsInManagedCall(false);
526             }
527         }
528     }
529 
530     /**
531      * Tests ensures that Telecom update outgoing self-managed video call video state to false when
532      * remote side call is picked only for audio.
533      */
534     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
535     @ApiTest(apis = {"android.telecom.Connection#onAnswer"})
testVideoCallStateDowngradeToAudio()536     public void testVideoCallStateDowngradeToAudio() throws Exception {
537         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
538             return;
539         }
540 
541         TestUtils.placeOutgoingCall(getInstrumentation(), mTelecomManager,
542                 TestUtils.TEST_SELF_MANAGED_HANDLE_2, TEST_ADDRESS_2,
543                 VideoProfile.STATE_BIDIRECTIONAL);
544 
545         // Ensure Telecom bound to the self managed CS
546         if (!CtsSelfManagedConnectionService.waitForBinding()) {
547             fail("Could not bind to Self-Managed ConnectionService");
548         }
549 
550         SelfManagedConnection connection = TestUtils.waitForAndGetConnection(TEST_ADDRESS_2);
551         assertNotNull("Self-Managed Connection should NOT be null.", connection);
552         assertTrue("Self-Managed Connection should be outgoing.", !connection.isIncomingCall());
553 
554         final MockInCallService inCallService = mInCallCallbacks.getService();
555         final Call call = inCallService.getLastCall();
556 
557         connection.setDialing();
558         assertCallState(call, Call.STATE_DIALING);
559 
560         assertVideoState(call, VideoProfile.STATE_BIDIRECTIONAL);
561 
562         connection.setVideoState(VideoProfile.STATE_AUDIO_ONLY);
563 
564         assertEquals(VideoProfile.STATE_AUDIO_ONLY, connection.getVideoState());
565 
566         connection.setActive();
567         assertCallState(call, Call.STATE_ACTIVE);
568 
569         assertVideoState(call, VideoProfile.STATE_AUDIO_ONLY);
570         setDisconnectedAndVerify(connection);
571     }
572 
573     /**
574      * Tests ability to add a new self-managed outgoing connection.
575      * <p>
576      * A self-managed {@link ConnectionService} shall be able to place an outgoing call to tel or
577      * sip {@link Uri}s without being interrupted by system UX or other Telephony-related logic.
578      */
579     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
580     @ApiTest(apis = {"android.telecom.TelecomManager#placeCall"})
testAddSelfManagedOutgoingConnection()581     public void testAddSelfManagedOutgoingConnection() throws Exception {
582         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
583             return;
584         }
585         assertIsOutgoingCallPermitted(true, TestUtils.TEST_SELF_MANAGED_HANDLE_1);
586         placeAndVerifyOutgoingCall(TestUtils.TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_1);
587 
588         assertIsOutgoingCallPermitted(true, TestUtils.TEST_SELF_MANAGED_HANDLE_2);
589         placeAndVerifyOutgoingCall(TestUtils.TEST_SELF_MANAGED_HANDLE_2, TEST_ADDRESS_3);
590 
591         assertIsOutgoingCallPermitted(true, TestUtils.TEST_SELF_MANAGED_HANDLE_3);
592         placeAndVerifyOutgoingCall(TestUtils.TEST_SELF_MANAGED_HANDLE_3, TEST_ADDRESS_4);
593     }
594 
595     /**
596      * Ensure that a self-managed call which does not declare
597      * {@link PhoneAccount#EXTRA_LOG_SELF_MANAGED_CALLS} will NOT be logged in the call log.
598      * We do this as a separate case because we don't want on the logging latch used in the other
599      * tests if we don't expect a call to be logged (it would make the CTS mighty slow).
600      * @throws Exception
601      */
602     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
603     @ApiTest(apis = {"android.telecom.PhoneAccount#EXTRA_LOG_SELF_MANAGED_CALLS"})
testSelfManagedCallNotLogged()604     public void testSelfManagedCallNotLogged() throws Exception {
605         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
606             return;
607         }
608 
609         // First, complete the call which should not be logged.
610         Uri unloggedAddress = getTestNumber();
611         placeAndVerifyOutgoingCall(TestUtils.TEST_SELF_MANAGED_HANDLE_1, unloggedAddress);
612 
613         // Next, place a call which we DO expect to be logged.
614         Uri loggedAddress = getTestNumber();
615         placeAndVerifyOutgoingCall(TestUtils.TEST_SELF_MANAGED_HANDLE_2, loggedAddress);
616 
617         // The verification code for un-logged numbers doesn't actually wait on the call log latch
618         // since it would cause the tests to all run slow.  However, since we just logged two calls
619         // and the second one would have triggered the call log latch, we can assume that the last
620         // two entries in the call log should:
621         // 1. NOT contain the un-logged call.
622         // 2. CONTAIN the logged call.
623 
624         // Lets get the last two entries in the log in descending order by ID.  This means that the
625         // logged call will be first.
626         Cursor callsCursor = mContext.getContentResolver().query(CallLog.Calls.CONTENT_URI, null,
627                 null, null, CallLog.Calls._ID + " DESC limit 2;");
628         int numberIndex = callsCursor.getColumnIndex(CallLog.Calls.NUMBER);
629 
630         // Check that we see the expected log call.
631         if (callsCursor.moveToNext()) {
632             String number = callsCursor.getString(numberIndex);
633             assertEquals(loggedAddress.getSchemeSpecificPart(), number);
634         } else {
635             fail("Expected a logged call.");
636         }
637 
638         // Now check to ensure the call we DID NOT want to have logged is indeed not logged.
639         if (callsCursor.moveToNext()) {
640             // Something else was logged; make sure we did not log the call where the PhoneAccount
641             // does not indicate calls should be logged.
642             String number = callsCursor.getString(numberIndex);
643             assertNotEquals(unloggedAddress.getSchemeSpecificPart(), number);
644         } else {
645             // This is great; there was nothing else in the call log!
646         }
647 
648     }
649 
placeAndVerifyOutgoingCall(PhoneAccountHandle handle, Uri address)650     private void placeAndVerifyOutgoingCall(PhoneAccountHandle handle, Uri address) throws Exception {
651 
652         TestUtils.placeOutgoingCall(getInstrumentation(), mTelecomManager, handle, address);
653 
654         // Ensure Telecom bound to the self managed CS
655         if (!CtsSelfManagedConnectionService.waitForBinding()) {
656             fail("Could not bind to Self-Managed ConnectionService");
657         }
658 
659         SelfManagedConnection connection = TestUtils.waitForAndGetConnection(address);
660         assertNotNull("Self-Managed Connection should NOT be null.", connection);
661         assertTrue("Self-Managed Connection should be outgoing.", !connection.isIncomingCall());
662 
663         // The self-managed ConnectionService must NOT have been prompted to show its incoming call
664         // UI for an outgoing call.
665         assertEquals(connection.getOnShowIncomingUiInvokeCounter().getInvokeCount(), 0);
666 
667         setActiveAndVerify(connection);
668 
669         // Ensure that the connection defaulted to voip audio mode.
670         assertTrue(connection.getAudioModeIsVoip());
671         // Ensure AudioManager has correct voip mode.
672         AudioManager audioManager = mContext.getSystemService(AudioManager.class);
673         assertAudioMode(audioManager, MODE_IN_COMMUNICATION);
674 
675         // Expect there to be no managed calls at the moment.
676         assertFalse(mTelecomManager.isInManagedCall());
677         // But there should be a call (including self-managed).
678         assertTrue(mTelecomManager.isInCall());
679 
680         // Expect that the new outgoing call broadcast did not fire for the self-managed calls.
681         assertFalse(NewOutgoingCallBroadcastReceiver.isNewOutgoingCallBroadcastReceived());
682 
683         setDisconnectedAndVerify(connection);
684 
685         if (isLoggedCall(handle)) {
686             verifyCallLogging(address, CallLog.Calls.OUTGOING_TYPE, handle);
687         }
688     }
689 
690     /**
691      * Test the scenario where OEM tries to toggle {@link android.telecom.Connection
692      * #setAudioModeIsVoip(boolean)} to false. Telecom should restrict this action as it can cause
693      * unwanted behavior such as audio issues.
694      *
695      * @throws Exception ;should not hit exception.
696      */
697     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
698     @ApiTest(apis = {"android.telecom.Connection#setAudioModeIsVoip"})
testAudioModeRemainsVoip()699     public void testAudioModeRemainsVoip() throws Exception {
700         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
701             return;
702         }
703 
704         SelfManagedConnection connection = null;
705 
706         try {
707             connection = placeSelfManagedCallAndGetConnection(TEST_SELF_MANAGED_HANDLE_1,
708                     TEST_ADDRESS_1);
709 
710             // verify audio mode is voip
711             assertTrue(connection.getAudioModeIsVoip());
712 
713             // send request to change audioModeIsVoip to FALSE
714             connection.setAudioModeIsVoip(false);
715 
716             // verify audio mode is STILL voip (expected)
717             assertTrue(connection.getAudioModeIsVoip());
718         } finally {
719             if (connection != null) {
720                 // disconnect call
721                 connection.disconnectAndDestroy();
722                 // verify the call was disconnected
723                 assertIsInCall(false);
724                 assertIsInManagedCall(false);
725             }
726         }
727     }
728 
729     /**
730      * Test the scenario where a user starts a self-managed call and while that call is active,
731      * starts a sim based call.  This test verifies the audio mode is correct at every point.
732      *
733      * @throws Exception ;should not hit exception.
734      */
735     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
736     @ApiTest(apis = {"android.telecom.Connection#setAudioModeIsVoip"})
testSelfManagedAndSimBasedCallSwapping()737     public void testSelfManagedAndSimBasedCallSwapping() throws Exception {
738         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
739             return;
740         }
741         TestServiceConnection selfManagedConnection = null;
742 
743         Bundle extras = new Bundle();
744         extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
745                 TestUtils.TEST_SIM_PHONE_ACCOUNT.getAccountHandle());
746 
747         try {
748             registerSimAccountIfNeeded();
749             // 1. start a self-managed call & ensure ACTIVE & MODE_IN_COMMUNICATION
750             selfManagedConnection = bindExternalSelfManagedServiceAndRegister(
751                     TestUtils.TEST_SELF_MANAGED_CS_1_PHONE_ACCOUNT_1);
752             placeSelfManagedCallOnTestApp(selfManagedConnection.getInterface(),
753                     TestUtils.TEST_SELF_MANAGED_CS_1_HANDLE_1, TEST_ADDRESS_1);
754             mInCallCallbacks.resetLock();
755 
756             // 2. start an incoming SIM based call
757             placeAndVerifyCall(extras);
758             Connection simBasedConnection = verifyConnectionForOutgoingCall();
759 
760             // 3. assert incoming call is active
761             Call outgoingCall = getInCallService().getLastCall();
762             simBasedConnection.setActive();
763             assertCallState(outgoingCall, Call.STATE_ACTIVE);
764 
765             // 4. assert audio mode id MODE_IN_CALL
766             AudioManager audioManager = mContext.getSystemService(AudioManager.class);
767             assertAudioMode(audioManager, MODE_IN_CALL);
768 
769             // 5. end incoming SIM based call
770             simBasedConnection.setDisconnected(new DisconnectCause(DisconnectCause.LOCAL));
771             simBasedConnection.destroy();
772 
773             // 6. assert the incoming call is disconnected
774             assertCallState(getInCallService().getLastCall(), Call.STATE_DISCONNECTED);
775 
776             // 7. un-hold and assert self-managed call becomes active
777             setRemoteConnectionActiveAndVerify(selfManagedConnection);
778 
779             // 10. assert audio mode is MODE_IN_COMMUNICATION
780             assertAudioMode(audioManager, MODE_IN_COMMUNICATION);
781 
782         } finally {
783             unregisterSimPhoneAccount();
784             if (selfManagedConnection != null) {
785                 tearDownControl(selfManagedConnection);
786             }
787         }
788     }
789 
790     /**
791      * Test the scenario where a user starts a self-managed call and while that call is active,
792      * starts a sim based call. This tests simulates that the self-managed Connection does
793      * not respond to a hold request, which MUST trigger the self-managed Connection to disconnect.
794      */
795     @ApiTest(apis = {"android.telecom.Connection#onHold"})
testSelfManagedAndSimBasedCallHoldFailure()796     public void testSelfManagedAndSimBasedCallHoldFailure() throws Exception {
797         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)
798                 || !Flags.transactionalCsVerifier()) {
799             return;
800         }
801         SelfManagedConnection connection = null;
802         Connection simBasedConnection = null;
803 
804         Bundle extras = new Bundle();
805         extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
806                 TestUtils.TEST_SIM_PHONE_ACCOUNT.getAccountHandle());
807 
808         try {
809             registerSimAccountIfNeeded();
810             connection = placeSelfManagedCallAndGetConnection(TestUtils.TEST_SELF_MANAGED_HANDLE_2,
811                     TEST_ADDRESS_2);
812             Call selfManagedCall = getInCallService().getLastCall();
813             assertNotNull("SM call expected", selfManagedCall);
814             mInCallCallbacks.resetLock();
815 
816             // start an incoming SIM based call
817             addAndVerifyNewIncomingCall(createTestNumber(), null);
818             simBasedConnection = verifyConnectionForIncomingCall();
819 
820             // Answer SIM call and do not respond to hold request with SM call
821             connection.setSuppressHoldResponse(true);
822             Call incomingCall = getInCallService().getLastCall();
823             assertNotEquals("Incoming Managed Call not found", incomingCall,
824                     selfManagedCall);
825             assertNotNull("Incoming Managed call expected", incomingCall);
826             incomingCall.answer(VideoProfile.STATE_AUDIO_ONLY);
827 
828             // SM call will be disconnected due to no response to hold and SIM call will move to
829             // active
830             assertCallState(selfManagedCall, Call.STATE_DISCONNECTED);
831             assertCallState(incomingCall, Call.STATE_ACTIVE);
832 
833             // end incoming SIM based call
834             simBasedConnection.setDisconnected(new DisconnectCause(DisconnectCause.LOCAL));
835             simBasedConnection.destroy();
836             //assert the incoming call is disconnected
837             assertCallState(incomingCall, Call.STATE_DISCONNECTED);
838             assertIsInCall(false);
839 
840         } finally {
841             unregisterSimPhoneAccount();
842             if (connection != null && connection.getState() != Connection.STATE_DISCONNECTED) {
843                 connection.disconnectAndDestroy();
844             }
845             if (simBasedConnection != null && simBasedConnection.getState()
846                     != Connection.STATE_DISCONNECTED) {
847                 simBasedConnection.onDisconnect();
848             }
849             assertIsInCall(false);
850         }
851     }
852 
853     /**
854      * verify TelecomManager#acceptRingingCall does not change the state of a self-managed call from
855      * ringing to active. In short, TelecomManager#acceptRingingCall should not change the state
856      * of any self-manged connection.
857      *
858      * @throws Exception; should not throw exception
859      */
860     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
861     @ApiTest(apis = {"android.telecom.TelecomManager#acceptRingingCall"})
testAcceptRingingCallOnSingleSelfManagedCall()862     public void testAcceptRingingCallOnSingleSelfManagedCall() throws Exception {
863         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
864             return;
865         }
866 
867         SelfManagedConnection selfManagedConnection = null;
868 
869         try {
870             // verify handle can receive incoming self-manged call on the handle
871             assertIsIncomingCallPermitted(true, TestUtils.TEST_SELF_MANAGED_HANDLE_2);
872 
873             // start new incoming self-managed call
874             TestUtils.addIncomingCall(getInstrumentation(), mTelecomManager,
875                     TestUtils.TEST_SELF_MANAGED_HANDLE_2, TEST_ADDRESS_2);
876             selfManagedConnection = TestUtils.waitForAndGetConnection(TEST_ADDRESS_2);
877 
878             // verify the incoming self-managed call is ringing
879             TestUtils.waitOnAllHandlers(getInstrumentation());
880             assertEquals(Call.STATE_RINGING, selfManagedConnection.getState());
881 
882             // try to accept it but the expectation is Telecom will not answer the ringing call
883             mTelecomManager.acceptRingingCall();
884 
885             // assert there was no change in the ongoing call
886             TestUtils.waitOnAllHandlers(getInstrumentation());
887             assertEquals(Call.STATE_RINGING, selfManagedConnection.getState());
888         } finally {
889             if (selfManagedConnection != null) {
890                 selfManagedConnection.disconnectAndDestroy();
891             }
892         }
893     }
894 
895 
896     /**
897      * verify TelecomManager#acceptRingingCall does not change the state of an active self-managed
898      * call (by holding it) in favor of a new ringing self-managed call that comes in.  In short,
899      * TelecomManager#acceptRingingCall should not change the state of any self-manged connection.
900      *
901      * @throws Exception; should not throw exception
902      */
903     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
904     @ApiTest(apis = {"android.telecom.TelecomManager#acceptRingingCall"})
testAcceptRingingCallOnMultipleSelfManagedCalls()905     public void testAcceptRingingCallOnMultipleSelfManagedCalls() throws Exception {
906         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
907             return;
908         }
909 
910         SelfManagedConnection outgoing_SM_connection = null;
911         SelfManagedConnection incoming_SM_connection = null;
912 
913         try {
914             // verify both handles can place calls
915             assertIsOutgoingCallPermitted(true, TestUtils.TEST_SELF_MANAGED_HANDLE_1);
916             assertIsIncomingCallPermitted(true, TestUtils.TEST_SELF_MANAGED_HANDLE_2);
917 
918             // create an outgoing self-managed call
919             outgoing_SM_connection = placeSelfManagedCallAndGetConnection(
920                     TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_1);
921             assertEquals(outgoing_SM_connection.getState(), Call.STATE_ACTIVE);
922 
923             // start new incoming call
924             TestUtils.addIncomingCall(getInstrumentation(), mTelecomManager,
925                     TestUtils.TEST_SELF_MANAGED_HANDLE_2, TEST_ADDRESS_2);
926             incoming_SM_connection = TestUtils.waitForAndGetConnection(TEST_ADDRESS_2);
927 
928             // verify the incoming self-managed call is ringing
929             TestUtils.waitOnAllHandlers(getInstrumentation());
930             assertEquals(Call.STATE_RINGING, incoming_SM_connection.getState());
931 
932             // try to accept it but the expectation is Telecom will not answer the ringing call
933             mTelecomManager.acceptRingingCall();
934 
935             // assert there was no change in the 2 ongoing calls
936             TestUtils.waitOnAllHandlers(getInstrumentation());
937             assertEquals(Call.STATE_RINGING, incoming_SM_connection.getState());
938             assertEquals(Call.STATE_ACTIVE, outgoing_SM_connection.getState());
939         } finally {
940             if (outgoing_SM_connection != null) {
941                 outgoing_SM_connection.disconnectAndDestroy();
942             }
943             if (incoming_SM_connection != null) {
944                 incoming_SM_connection.disconnectAndDestroy();
945             }
946         }
947     }
948 
949     /**
950      * Verify TelecomManager#endCall cannot end an active self-managed call.
951      *
952      * @throws Exception; should not throw exception
953      */
954     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
955     @ApiTest(apis = {"android.telecom.TelecomManager#endCall"})
testEndCallOnSelfManagedCallOnActiveCall()956     public void testEndCallOnSelfManagedCallOnActiveCall() throws Exception {
957         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
958             return;
959         }
960 
961         SelfManagedConnection selfManagedConnection = null;
962 
963         try {
964             // start a self-managed call
965             assertIsOutgoingCallPermitted(true, TestUtils.TEST_SELF_MANAGED_HANDLE_1);
966             selfManagedConnection =
967                     placeSelfManagedCallAndGetConnection(TEST_SELF_MANAGED_HANDLE_1,
968                             TEST_ADDRESS_1);
969 
970             // set the self-managed call active and verify
971             setActiveAndVerify(selfManagedConnection);
972 
973             // try to end it but the expectation is Telecom cannot end the self-managed call
974             assertFalse(mTelecomManager.endCall());
975             TestUtils.waitOnAllHandlers(getInstrumentation());
976             assertEquals(Call.STATE_ACTIVE, selfManagedConnection.getState());
977 
978         } finally {
979             if (selfManagedConnection != null) {
980                 // disconnect call
981                 selfManagedConnection.disconnectAndDestroy();
982             }
983         }
984     }
985 
986     /**
987      * Verify TelecomManager#endCall cannot end a ringing self-managed call.
988      *
989      * @throws Exception; should not throw exception
990      */
991     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
992     @ApiTest(apis = {"android.telecom.TelecomManager#endCall"})
testEndCallOnSelfManagedCallOnRingingCall()993     public void testEndCallOnSelfManagedCallOnRingingCall() throws Exception {
994         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
995             return;
996         }
997 
998         SelfManagedConnection selfManagedConnection = null;
999 
1000         try {
1001             // start a self-managed call
1002             assertIsIncomingCallPermitted(true, TestUtils.TEST_SELF_MANAGED_HANDLE_1);
1003             TestUtils.addIncomingCall(getInstrumentation(), mTelecomManager,
1004                     TestUtils.TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_1);
1005             selfManagedConnection = TestUtils.waitForAndGetConnection(TEST_ADDRESS_1);
1006 
1007             // verify the self-managed call is ringing
1008             TestUtils.waitOnAllHandlers(getInstrumentation());
1009             assertEquals(selfManagedConnection.getState(), Call.STATE_RINGING);
1010 
1011             // try to end it but the expectation is Telecom cannot end the self-managed call
1012             assertFalse(mTelecomManager.endCall());
1013 
1014             // verify the self-managed call is still ringing
1015             TestUtils.waitOnAllHandlers(getInstrumentation());
1016             assertEquals(Call.STATE_RINGING, selfManagedConnection.getState());
1017 
1018         } finally {
1019             if (selfManagedConnection != null) {
1020                 // disconnect call
1021                 selfManagedConnection.disconnectAndDestroy();
1022             }
1023         }
1024     }
1025 
1026     /**
1027      * Tests ability to change the audio route via the
1028      * {@link android.telecom.Connection#setAudioRoute(int)} API.
1029      */
1030     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
1031     @ApiTest(apis = {"android.telecom.Connection#setAudioRoute"})
testAudioRoute()1032     public void testAudioRoute() throws Exception {
1033         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
1034             return;
1035         }
1036         TestUtils.placeOutgoingCall(getInstrumentation(), mTelecomManager,
1037                 TestUtils.TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_1);
1038         SelfManagedConnection connection = TestUtils.waitForAndGetConnection(TEST_ADDRESS_1);
1039         setActiveAndVerify(connection);
1040 
1041         TestUtils.InvokeCounter counter = connection.getCallAudioStateChangedInvokeCounter();
1042         counter.waitForCount(WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
1043         CallAudioState callAudioState = (CallAudioState) counter.getArgs(0)[0];
1044         int availableRoutes = callAudioState.getSupportedRouteMask();
1045 
1046         // Both the speaker and either wired or earpiece are required to test changing the audio
1047         // route. Skip this test if either of these routes is unavailable.
1048         if ((availableRoutes & CallAudioState.ROUTE_SPEAKER) == 0
1049                 || (availableRoutes & CallAudioState.ROUTE_WIRED_OR_EARPIECE) == 0) {
1050             return;
1051         }
1052 
1053         // Determine what the second route after SPEAKER should be, depending on what's supported.
1054         int secondRoute = (availableRoutes & CallAudioState.ROUTE_EARPIECE) == 0
1055                 ? CallAudioState.ROUTE_WIRED_HEADSET
1056                 : CallAudioState.ROUTE_EARPIECE;
1057 
1058         counter.clearArgs();
1059         connection.setAudioRoute(CallAudioState.ROUTE_SPEAKER);
1060         counter.waitForPredicate(new Predicate<CallAudioState>() {
1061                 @Override
1062                 public boolean test(CallAudioState cas) {
1063                     return cas.getRoute() == CallAudioState.ROUTE_SPEAKER;
1064                 }
1065             }, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
1066 
1067         counter.clearArgs();
1068         connection.setAudioRoute(secondRoute);
1069         counter.waitForPredicate(new Predicate<CallAudioState>() {
1070             @Override
1071             public boolean test(CallAudioState cas) {
1072                 return cas.getRoute() == secondRoute;
1073             }
1074         }, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
1075         if (TestUtils.HAS_BLUETOOTH) {
1076             // Call requestBluetoothAudio on a device. This will be a noop since no devices are
1077             // connected.
1078             connection.requestBluetoothAudio(TestUtils.BLUETOOTH_DEVICE1);
1079         }
1080         setDisconnectedAndVerify(connection);
1081     }
1082     /**
1083      * Tests that Telecom will allow the incoming call while the number of self-managed call is not
1084      * exceed the limit.
1085      * @throws Exception
1086      */
1087     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
1088     @ApiTest(apis = {"android.telecom.Connection#addNewIncomingCall"})
testIncomingWhileOngoingWithinLimit()1089     public void testIncomingWhileOngoingWithinLimit() throws Exception {
1090         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
1091             return;
1092         }
1093 
1094         // Create an ongoing call in the first self-managed PhoneAccount.
1095         TestUtils.placeOutgoingCall(getInstrumentation(), mTelecomManager,
1096                 TestUtils.TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_1);
1097         SelfManagedConnection connection = TestUtils.waitForAndGetConnection(TEST_ADDRESS_1);
1098         setActiveAndVerify(connection);
1099 
1100         assertIsIncomingCallPermitted(true, TestUtils.TEST_SELF_MANAGED_HANDLE_2);
1101         // Attempt to create a new incoming call for the other PhoneAccount; it should succeed.
1102         TestUtils.addIncomingCall(getInstrumentation(), mTelecomManager,
1103                 TestUtils.TEST_SELF_MANAGED_HANDLE_2, TEST_ADDRESS_2);
1104         SelfManagedConnection connection2 = TestUtils.waitForAndGetConnection(TEST_ADDRESS_2);
1105 
1106         connection2.disconnectAndDestroy();
1107         setDisconnectedAndVerify(connection);
1108     }
1109 
1110     /**
1111      * Tests the self-managed ConnectionService has gained the focus when it become active.
1112      */
1113     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
1114     @ApiTest(apis = {"android.telecom.ConnectionService#onConnectionServiceFocusLost",
1115             "android.telecom.ConnectionService#onConnectionServiceFocusGained"})
testSelfManagedConnectionServiceGainedFocus()1116     public void testSelfManagedConnectionServiceGainedFocus() throws Exception {
1117         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
1118             return;
1119         }
1120 
1121         assertIsIncomingCallPermitted(true, TestUtils.TEST_SELF_MANAGED_HANDLE_1);
1122         // Attempt to create a new Incoming self-managed call
1123         TestUtils.addIncomingCall(getInstrumentation(), mTelecomManager,
1124                 TestUtils.TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_1);
1125         SelfManagedConnection connection = TestUtils.waitForAndGetConnection(TEST_ADDRESS_1);
1126 
1127         setActiveAndVerify(connection);
1128 
1129         // The ConnectionService has gained the focus
1130         assertTrue(CtsSelfManagedConnectionService.getConnectionService().waitForUpdate(
1131                 CtsSelfManagedConnectionService.FOCUS_GAINED_LOCK));
1132 
1133         setDisconnectedAndVerify(connection);
1134     }
1135 
1136     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
1137     @ApiTest(apis = {"android.telecom.ConnectionService#onConnectionServiceFocusLost",
1138             "android.telecom.ConnectionService#onConnectionServiceFocusGained"})
testSelfManagedConnectionServiceLostFocus()1139     public void testSelfManagedConnectionServiceLostFocus() throws Exception {
1140         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
1141             return;
1142         }
1143 
1144         // GIVEN an ongoing self-managed call
1145         TestUtils.addIncomingCall(getInstrumentation(), mTelecomManager,
1146                 TestUtils.TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_1);
1147         SelfManagedConnection connection = TestUtils.waitForAndGetConnection(TEST_ADDRESS_1);
1148         setActiveAndVerify(connection);
1149         assertTrue(CtsSelfManagedConnectionService.getConnectionService().waitForUpdate(
1150                 CtsSelfManagedConnectionService.FOCUS_GAINED_LOCK));
1151 
1152         // WHEN place a managed call
1153         mInCallCallbacks.resetLock();
1154         placeAndVerifyCall();
1155         verifyConnectionForOutgoingCall().setActive();
1156         assertTrue(connectionService.waitForEvent(
1157                 MockConnectionService.EVENT_CONNECTION_SERVICE_FOCUS_GAINED));
1158 
1159         // THEN the self-managed ConnectionService lost the focus
1160 
1161         connection.disconnectAndDestroy();
1162         assertTrue(CtsSelfManagedConnectionService.getConnectionService().waitForUpdate(
1163                 CtsSelfManagedConnectionService.FOCUS_LOST_LOCK));
1164     }
1165 
1166     /**
1167      * Tests that Telecom will disallow the incoming call while the ringing call is existed.
1168      */
1169     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
1170     @ApiTest(apis = {"android.telecom.TelecomManager#addNewIncomingCall"})
testRingCallLimitForOnePhoneAccount()1171     public void testRingCallLimitForOnePhoneAccount() {
1172         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
1173             return;
1174         }
1175 
1176         // GIVEN a self-managed call which state is ringing
1177         TestUtils.addIncomingCall(getInstrumentation(), mTelecomManager,
1178                 TestUtils.TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_1);
1179 
1180         assertIsIncomingCallPermitted(false, TestUtils.TEST_SELF_MANAGED_HANDLE_1);
1181         // WHEN create a new incoming call for the the same PhoneAccount
1182         TestUtils.addIncomingCall(getInstrumentation(), mTelecomManager,
1183                 TestUtils.TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_1);
1184 
1185         // THEN the new incoming call is denied
1186         assertTrue(CtsSelfManagedConnectionService.getConnectionService().waitForUpdate(
1187                 CtsSelfManagedConnectionService.CREATE_INCOMING_CONNECTION_FAILED_LOCK));
1188     }
1189 
1190     /**
1191      * Tests that Telecom enforces a maximum number of calls for a self-managed ConnectionService.
1192      *
1193      * @throws Exception
1194      */
1195     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
1196     @ApiTest(apis = {"android.telecom.TelecomManager#placeCall"})
testCallLimit()1197     public void testCallLimit() throws Exception {
1198         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
1199             return;
1200         }
1201 
1202         List<SelfManagedConnection> connections = new ArrayList<>();
1203         // Create 10 calls; they should succeed.
1204         for (int ix = 0; ix < 10; ix++) {
1205             Uri address = Uri.fromParts("sip", "test" + ix + "@test.com", null);
1206             // Create an ongoing call in the first self-managed PhoneAccount.
1207             assertIsOutgoingCallPermitted(true, TestUtils.TEST_SELF_MANAGED_HANDLE_1);
1208             TestUtils.placeOutgoingCall(getInstrumentation(), mTelecomManager,
1209                     TestUtils.TEST_SELF_MANAGED_HANDLE_1, address);
1210             SelfManagedConnection connection = TestUtils.waitForAndGetConnection(address);
1211             setActiveAndVerify(connection);
1212             connections.add(connection);
1213         }
1214 
1215         // Try adding an 11th.  It should fail to be created.
1216         assertIsIncomingCallPermitted(false, TestUtils.TEST_SELF_MANAGED_HANDLE_1);
1217         TestUtils.addIncomingCall(getInstrumentation(), mTelecomManager,
1218                 TestUtils.TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_2);
1219         assertTrue("Expected onCreateIncomingConnectionFailed callback",
1220                 CtsSelfManagedConnectionService.getConnectionService().waitForUpdate(
1221                         CtsSelfManagedConnectionService.CREATE_INCOMING_CONNECTION_FAILED_LOCK));
1222 
1223         connections.forEach((selfManagedConnection) ->
1224                 selfManagedConnection.disconnectAndDestroy());
1225 
1226         waitOnAllHandlers(getInstrumentation());
1227     }
1228 
1229     /**
1230      * Start a self-managed call and then dial an emergency call and make sure the self-managed
1231      * call is successfully disconnected.
1232      */
1233     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
1234     @ApiTest(apis = {"android.telecom.TelecomManager#placeCall"})
testDisconnectSelfManagedCallForEmergency()1235     public void testDisconnectSelfManagedCallForEmergency() throws Exception {
1236         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
1237             return;
1238         }
1239         setupForEmergencyCalling(TEST_EMERGENCY_NUMBER);
1240 
1241         Uri address = getTestNumber();
1242         TestUtils.placeOutgoingCall(getInstrumentation(), mTelecomManager,
1243                 TEST_SELF_MANAGED_HANDLE_1, address);
1244         // Ensure Telecom bound to the self managed CS
1245         if (!CtsSelfManagedConnectionService.waitForBinding()) {
1246             fail("Could not bind to Self-Managed ConnectionService");
1247         }
1248         SelfManagedConnection connection = TestUtils.waitForAndGetConnection(address);
1249         assertNotNull("Self-Managed Connection should NOT be null.", connection);
1250         assertTrue("Self-Managed Connection should be outgoing.", !connection.isIncomingCall());
1251         // The self-managed ConnectionService must NOT have been prompted to show its incoming call
1252         // UI for an outgoing call.
1253         assertEquals(connection.getOnShowIncomingUiInvokeCounter().getInvokeCount(), 0);
1254         setActiveAndVerify(connection);
1255 
1256         mInCallCallbacks.resetLock();
1257         placeAndVerifyEmergencyCall(true /*supportsHold*/);
1258         Call eCall = getInCallService().getLastCall();
1259 
1260         assertIsInCall(true);
1261         assertIsInManagedCall(true);
1262         try {
1263             TestUtils.waitOnAllHandlers(getInstrumentation());
1264         } catch (Exception e) {
1265             fail("Failed to wait on handlers " + e);
1266         }
1267         assertCallState(eCall, Call.STATE_DIALING);
1268         // The self-managed Connection should be disconnected!
1269         assertConnectionState(connection, Connection.STATE_DISCONNECTED);
1270     }
1271 
1272     /**
1273      * Start a managed emergency call and then ensure that a subsequent self-managed call fails to
1274      * be created.
1275      */
1276     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
testEmergencyCallOngoingNewOutgoingCall()1277     public void testEmergencyCallOngoingNewOutgoingCall() throws Exception {
1278         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
1279             return;
1280         }
1281 
1282         setupForEmergencyCalling(TEST_EMERGENCY_NUMBER);
1283         placeAndVerifyEmergencyCall(true /*supportsHold*/);
1284         assertIsInCall(true);
1285         assertIsInManagedCall(true);
1286         try {
1287             TestUtils.waitOnAllHandlers(getInstrumentation());
1288         } catch (Exception e) {
1289             fail("Failed to wait on handlers " + e);
1290         }
1291 
1292         // Try adding a self managed outgoing call.  It should fail to be created.
1293         TestUtils.placeOutgoingCall(getInstrumentation(), mTelecomManager,
1294                 TestUtils.TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_1);
1295         assertTrue("Expected onCreateOutgoingConnectionFailed callback",
1296                 CtsSelfManagedConnectionService.getConnectionService().waitForUpdate(
1297                         CtsSelfManagedConnectionService.CREATE_OUTGOING_CONNECTION_FAILED_LOCK));
1298     }
1299 
1300     /**
1301      * Start a managed emergency call and then ensure that a subsequent self-managed call fails to
1302      * be created.
1303      */
1304     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
testEmergencyCallOngoingIncomingCall()1305     public void testEmergencyCallOngoingIncomingCall() throws Exception {
1306         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
1307             return;
1308         }
1309 
1310         setupForEmergencyCalling(TEST_EMERGENCY_NUMBER);
1311         placeAndVerifyEmergencyCall(true /*supportsHold*/);
1312         assertIsInCall(true);
1313         assertIsInManagedCall(true);
1314         try {
1315             TestUtils.waitOnAllHandlers(getInstrumentation());
1316         } catch (Exception e) {
1317             fail("Failed to wait on handlers " + e);
1318         }
1319 
1320         // Try adding a self managed incoming call.  It should fail to be created.
1321         TestUtils.addIncomingCall(getInstrumentation(), mTelecomManager,
1322                 TestUtils.TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_1);
1323         assertTrue("Expected onCreateIncomingConnectionFailed callback",
1324                 CtsSelfManagedConnectionService.getConnectionService().waitForUpdate(
1325                         CtsSelfManagedConnectionService.CREATE_INCOMING_CONNECTION_FAILED_LOCK));
1326     }
1327 
1328     /**
1329      * Place a new outgoing call using a self-managed PhoneAccount that is not registered to
1330      * Telecom. Even if the app has CALL_PHONE/MANAGE_OWN_CALLS, the call will be sent as if there
1331      * was no PhoneAccount specified, since only the owner of a self-managed ConnectionService can
1332      * initiate a call to that Service.
1333      */
1334     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
1335     @ApiTest(apis = {"android.telecom.TelecomManager#placeCall"})
testPlaceCallToNonRegisteredSelfManagedConnectionService()1336     public void testPlaceCallToNonRegisteredSelfManagedConnectionService() throws Exception {
1337         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
1338             return;
1339         }
1340 
1341         // Place a new outgoing call request for a self-managed ConnectionService that is not
1342         // registered.
1343         TestUtils.placeOutgoingCall(getInstrumentation(), mTelecomManager,
1344                 TestUtils.TEST_SELF_MANAGED_CS_1_HANDLE_1, TEST_ADDRESS_2);
1345         // verify the default CTS ConnectionService received an incoming connection request because
1346         // we have CALL_PHONE permission.
1347         verifyConnectionForOutgoingCall();
1348     }
1349 
1350     /**
1351      * Place a new outgoing call request to a registered self-managed ConnectionService that
1352      * is owned by a different application.
1353      * Even if the app has CALL_PHONE/MANAGE_OWN_CALLS, the call will be sent as if there
1354      * was no PhoneAccount specified.
1355      */
1356     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
1357     @ApiTest(apis = {"android.telecom.TelecomManager#placeCall"})
testPlaceCallToRegisteredSelfManagedConnectionService()1358     public void testPlaceCallToRegisteredSelfManagedConnectionService() throws Exception {
1359         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
1360             return;
1361         }
1362         TestServiceConnection conn = null;
1363         try {
1364             conn = bindExternalSelfManagedServiceAndRegister(
1365                     TestUtils.TEST_SELF_MANAGED_CS_1_PHONE_ACCOUNT_1);
1366 
1367             // Try to place a call from this CTS app to the self-managed CS. We should not see any
1368             // call to the self-managed CS. Instead, it will go over the default CTS ConnectionService
1369             // because we have CALL_PHONE permission.
1370             TestUtils.placeOutgoingCall(getInstrumentation(), mTelecomManager,
1371                     TestUtils.TEST_SELF_MANAGED_CS_1_HANDLE_1, TEST_ADDRESS_2);
1372             // verify the CTS default ConnectionService received an incoming connection request.
1373             verifyConnectionForOutgoingCall();
1374         } finally {
1375             if (conn != null) tearDownControl(conn);
1376         }
1377     }
1378 
1379     /**
1380      * Try to start a self-managed call on a ConnectionService that does not have the CALL_PHONE
1381      * permission, only MANAGE_OWN_CALLS. If this happens, the call should fail with a
1382      * SecurityException.
1383      */
1384     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
1385     @ApiTest(apis = {"android.telecom.TelecomManager#placeCall"})
testPlaceIncorrectSelfManagedCallFromRemote()1386     public void testPlaceIncorrectSelfManagedCallFromRemote() throws Exception {
1387         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
1388             return;
1389         }
1390         TestServiceConnection conn = null;
1391         try {
1392             conn = bindExternalSelfManagedServiceAndRegister(
1393                     TestUtils.TEST_SELF_MANAGED_CS_1_PHONE_ACCOUNT_1);
1394 
1395             // Try to start a self-managed call using this Self-Managed ConnectionService's
1396             // PhoneAccount from the remote, which should fail with a SecurityException because the
1397             // remote does not have the CALL_PHONE permission.
1398             try {
1399                 boolean result = conn.getInterface().placeOutgoingCall(
1400                         TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_2.toString());
1401                 fail("A ConnectionService must not be able to place a self-managed call that "
1402                         + "belongs to another ConnectionService. A SecurityException was expected, "
1403                         + "result: " + result);
1404             } catch (SecurityException e) {
1405                 //expected
1406             }
1407         } finally {
1408             if (conn != null) tearDownControl(conn);
1409         }
1410     }
1411 
1412     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
testCallSwapBetweenTwoSelfManagedConnectionServices()1413     public void testCallSwapBetweenTwoSelfManagedConnectionServices() throws Exception {
1414         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
1415             return;
1416         }
1417 
1418         TestServiceConnection conn = bindExternalSelfManagedServiceAndRegister(
1419                 TestUtils.TEST_SELF_MANAGED_CS_1_PHONE_ACCOUNT_1);
1420 
1421         //Place self-managed CS first call from test app
1422         placeSelfManagedCallOnTestApp(conn.getInterface(),
1423                 TestUtils.TEST_SELF_MANAGED_CS_1_HANDLE_1, TEST_ADDRESS_1);
1424 
1425         //Get test app call from inCallService
1426         final MockInCallService inCallService = mInCallCallbacks.getService();
1427         final Call call1 = inCallService.getLastCall();
1428 
1429         // Ensure that the connection defaulted to voip audio mode.
1430         assertTrue(conn.getInterface().getAudioModeIsVoip());
1431         // Ensure AudioManager has correct voip mode.
1432         AudioManager audioManager = mContext.getSystemService(AudioManager.class);
1433         assertAudioMode(audioManager, MODE_IN_COMMUNICATION);
1434 
1435         //Place self-managed CS second call
1436         SelfManagedConnection connection =
1437                 placeSelfManagedCallAndGetConnection(TestUtils.TEST_SELF_MANAGED_HANDLE_4,
1438                     TEST_ADDRESS_2);
1439 
1440         final Call call2 = inCallService.getLastCall();
1441 
1442         //first call on hold after second call is active
1443         assertCallState(call1, Call.STATE_HOLDING);
1444         assertEquals(conn.getInterface().getConnectionState(), Connection.STATE_HOLDING);
1445         assertCallState(call2, Call.STATE_ACTIVE);
1446         assertConnectionState(connection, Connection.STATE_ACTIVE);
1447 
1448         // Ensure that the connection defaulted to voip audio mode.
1449         assertTrue(connection.getAudioModeIsVoip());
1450         assertTrue(conn.getInterface().getAudioModeIsVoip());
1451         // Ensure AudioManager has correct voip mode.
1452         assertAudioMode(audioManager, MODE_IN_COMMUNICATION);
1453 
1454         //unhold the first call should keep the second call on hold
1455         call1.unhold();
1456         assertTrue(conn.getInterface().waitOnUnHold());
1457         assertTrue(connection.waitOnHold());
1458         assertCallState(call2, Call.STATE_HOLDING);
1459         assertConnectionState(connection, Connection.STATE_HOLDING);
1460         assertCallState(call1, Call.STATE_ACTIVE);
1461         assertEquals(conn.getInterface().getConnectionState(), Connection.STATE_ACTIVE);
1462 
1463         // Ensure that the connection defaulted to voip audio mode.
1464         assertTrue(connection.getAudioModeIsVoip());
1465         assertTrue(conn.getInterface().getAudioModeIsVoip());
1466         // Ensure AudioManager has correct voip mode.
1467         assertAudioMode(audioManager, MODE_IN_COMMUNICATION);
1468 
1469         //unhold the first call should keep the second call on hold
1470         call2.unhold();
1471         assertTrue(conn.getInterface().waitOnHold());
1472         assertTrue(connection.waitOnUnHold());
1473         assertCallState(call1, Call.STATE_HOLDING);
1474         assertEquals(conn.getInterface().getConnectionState(), Connection.STATE_HOLDING);
1475         assertCallState(call2, Call.STATE_ACTIVE);
1476         assertConnectionState(connection, Connection.STATE_ACTIVE);
1477 
1478         // Ensure that the connection defaulted to voip audio mode.
1479         assertTrue(connection.getAudioModeIsVoip());
1480         assertTrue(conn.getInterface().getAudioModeIsVoip());
1481         // Ensure AudioManager has correct voip mode.
1482         assertAudioMode(audioManager, MODE_IN_COMMUNICATION);
1483 
1484         // disconnect active 2nd call
1485         connection.disconnectAndDestroy();
1486 
1487         assertIsInCall(true);
1488         assertIsInManagedCall(false);
1489 
1490         //first call should be on hold
1491         assertCallState(call1, Call.STATE_HOLDING);
1492         assertEquals(conn.getInterface().getConnectionState(), Connection.STATE_HOLDING);
1493 
1494         // Ensure that the connection defaulted to voip audio mode.
1495         assertTrue(conn.getInterface().getAudioModeIsVoip());
1496         // Ensure AudioManager has correct voip mode.
1497         assertAudioMode(audioManager, MODE_IN_COMMUNICATION);
1498 
1499         //unhold first call
1500         call1.unhold();
1501         assertCallState(call1, Call.STATE_ACTIVE);
1502         assertEquals(conn.getInterface().getConnectionState(), Connection.STATE_ACTIVE);
1503 
1504         // Ensure that the connection defaulted to voip audio mode.
1505         assertTrue(conn.getInterface().getAudioModeIsVoip());
1506         // Ensure AudioManager has correct voip mode.
1507         assertAudioMode(audioManager, MODE_IN_COMMUNICATION);
1508 
1509         conn.getInterface().disconnectConnection();
1510 
1511         assertCallState(call1, Call.STATE_DISCONNECTED);
1512 
1513         tearDownControl(conn);
1514 
1515         assertIsInCall(false);
1516         assertIsInManagedCall(false);
1517     }
1518 
1519     /**
1520      * Start a self-managed no hold capable call on different app and accept incoming managed call
1521      * should disconnect self-managed call
1522      */
1523     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
testManagedCallWhileNoHoldCapabilitySelfMaganedCallActive()1524     public void testManagedCallWhileNoHoldCapabilitySelfMaganedCallActive() throws Exception {
1525         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
1526             return;
1527         }
1528 
1529         // register a self-managed phone account from self-managed CS test app
1530         TestServiceConnection conn = bindExternalSelfManagedServiceAndRegister(
1531                 TestUtils.TEST_SELF_MANAGED_CS_1_PHONE_ACCOUNT_3);
1532 
1533         // place a self-managed call
1534         conn.getInterface().initiateIncomingCall(
1535                 TestUtils.TEST_SELF_MANAGED_CS_1_HANDLE_3, TEST_ADDRESS_2.toString());
1536 
1537         // Wait for Telecom to finish creating the new connection.
1538         try {
1539             TestUtils.waitOnAllHandlers(getInstrumentation());
1540         } catch (Exception e) {
1541             fail("Failed to wait on handlers");
1542         }
1543 
1544         assertTrue(conn.getInterface().waitForBinding());
1545 
1546         conn.getInterface().setConnectionCapabilityNoHold();
1547 
1548         conn.getInterface().setConnectionActive();
1549 
1550         assertEquals(Connection.STATE_ACTIVE, conn.getInterface().getConnectionState());
1551 
1552         // add new managed call
1553         addAndVerifyNewIncomingCall(createTestNumber(), null);
1554         Connection connection = verifyConnectionForIncomingCall();
1555 
1556         assertConnectionState(connection, Connection.STATE_RINGING);
1557         assertEquals(Connection.STATE_ACTIVE, conn.getInterface().getConnectionState());
1558 
1559         // answer the incoming call
1560         MockInCallService inCallService = mInCallCallbacks.getService();
1561         Call call = inCallService.getLastCall();
1562 
1563         call.answer(VideoProfile.STATE_AUDIO_ONLY);
1564 
1565         assertConnectionState(connection, Connection.STATE_ACTIVE);
1566 
1567         assertTrue(conn.getInterface().waitOnDisconnect());
1568         assertEquals(Connection.STATE_DISCONNECTED, conn.getInterface().getConnectionState());
1569 
1570         tearDownControl(conn);
1571 
1572         call.disconnect();
1573     }
1574 
1575     /**
1576      * Tests ability to change the call endpoint via the
1577      * {@link android.telecom.Connection#requestCallEndpointChange} API.
1578      */
1579     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
1580     @ApiTest(apis = {"android.telecom.Connection#requestCallEndpointChange"})
testCallEndpoint()1581     public void testCallEndpoint() throws Exception {
1582         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
1583             return;
1584         }
1585         TestUtils.placeOutgoingCall(getInstrumentation(), mTelecomManager,
1586                 TestUtils.TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_1);
1587         SelfManagedConnection connection = TestUtils.waitForAndGetConnection(TEST_ADDRESS_1);
1588         setActiveAndVerify(connection);
1589 
1590         TestUtils.InvokeCounter currentEndpointCounter =
1591                 connection.getCallEndpointChangedInvokeCounter();
1592         currentEndpointCounter.waitForCount(WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
1593         CallEndpoint currentEndpoint = (CallEndpoint) currentEndpointCounter.getArgs(0)[0];
1594         int currentEndpointType = currentEndpoint.getEndpointType();
1595 
1596         TestUtils.InvokeCounter availableEndpointsCounter =
1597                 connection.getAvailableEndpointsChangedInvokeCounter();
1598         availableEndpointsCounter.waitForCount(WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
1599         List<CallEndpoint> availableEndpoints =
1600                 (List<CallEndpoint>) availableEndpointsCounter.getArgs(0)[0];
1601 
1602         CallEndpoint anotherEndpoint = null;
1603         for (CallEndpoint endpoint : availableEndpoints) {
1604             if (endpoint.getEndpointType() != currentEndpointType) {
1605                 anotherEndpoint = endpoint;
1606                 break;
1607             }
1608         }
1609         if (anotherEndpoint != null) {
1610             Executor executor = mContext.getMainExecutor();
1611             final int anotherEndpointType = anotherEndpoint.getEndpointType();
1612             currentEndpointCounter.clearArgs();
1613             connection.requestCallEndpointChange(anotherEndpoint, executor,
1614                     new OutcomeReceiver<>() {
1615                         @Override
1616                         public void onResult(Void result) {}
1617                         @Override
1618                         public void onError(CallEndpointException exception) {}
1619                     });
1620             currentEndpointCounter.waitForPredicate(new Predicate<CallEndpoint>() {
1621                 @Override
1622                 public boolean test(CallEndpoint cep) {
1623                     return cep.getEndpointType() == anotherEndpointType;
1624                 }
1625             }, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
1626 
1627             // wait for the CallAudioManager to process the CallAudioRoute update
1628             waitOnAllHandlers(getInstrumentation());
1629 
1630             currentEndpointCounter.clearArgs();
1631             connection.requestCallEndpointChange(currentEndpoint, executor,
1632                     new OutcomeReceiver<>() {
1633                         @Override
1634                         public void onResult(Void result) {}
1635                         @Override
1636                         public void onError(CallEndpointException exception) {}
1637                     });
1638             currentEndpointCounter.waitForPredicate(new Predicate<CallEndpoint>() {
1639                 @Override
1640                 public boolean test(CallEndpoint cep) {
1641                     return cep.getEndpointType() == currentEndpointType;
1642                 }
1643             }, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
1644 
1645         }
1646         setDisconnectedAndVerify(connection);
1647     }
1648 
1649     /**
1650      * Verifies that {@link TelecomManager#isInSelfManagedCall} properly reports if a call is
1651      * self-managed.
1652      */
1653     @CddTest(requirements = "7.4.1.2/C-12-1,C-12-2")
1654     @ApiTest(apis = {"android.telecom.TelecomManager#isInSelfManagedCall"})
testIsInSelfManagedCall()1655     public void testIsInSelfManagedCall() throws Exception {
1656         if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)
1657                 || !Flags.telecomResolveHiddenDependencies()) {
1658             return;
1659         }
1660         InstrumentationRegistry.getInstrumentation().getUiAutomation()
1661                 .adoptShellPermissionIdentity();
1662 
1663         // Specific user defined scenarios:
1664         // Verify TelecomManager#isInSelfManagedCall for specified user -> true.
1665         verifyIsInSelfManagedCallCrossUsers(TEST_SELF_MANAGED_HANDLE_1,
1666                 TEST_SELF_MANAGED_HANDLE_1.getUserHandle());
1667         // Deliberately pass in different UserHandle different from the phone account handle user to
1668         // ensure that the API indicates that there aren't any ongoing calls -> false.
1669         verifyIsInSelfManagedCallCrossUsers(TEST_SELF_MANAGED_HANDLE_1,
1670                 UserHandle.of(UserHandle.MIN_SECONDARY_USER_ID));
1671 
1672         // Cross-user scenario: ensure that passing UserHandle.ALL correctly identifies calls for
1673         // any user with self-managed calls.
1674         verifyIsInSelfManagedCallCrossUsers(TEST_SELF_MANAGED_HANDLE_1, UserHandle.ALL);
1675 
1676         InstrumentationRegistry.getInstrumentation().getUiAutomation()
1677                 .dropShellPermissionIdentity();
1678     }
1679 
verifyIsInSelfManagedCallCrossUsers(PhoneAccountHandle handle, UserHandle userHandle)1680     private void verifyIsInSelfManagedCallCrossUsers(PhoneAccountHandle handle,
1681             UserHandle userHandle) throws Exception {
1682         SelfManagedConnection connection = null;
1683 
1684         boolean assertIsInSelfManagedCall = true;
1685         if (!userHandle.equals(UserHandle.ALL) && !handle.getUserHandle().equals(userHandle)) {
1686             assertIsInSelfManagedCall = false;
1687         }
1688 
1689         try {
1690             connection = placeSelfManagedCallAndGetConnection(handle, TEST_ADDRESS_1);
1691             boolean isInSelfManagedCall;
1692             isInSelfManagedCall = mTelecomManager.isInSelfManagedCall(
1693                     handle.getComponentName().getPackageName(), userHandle);
1694             assertEquals(assertIsInSelfManagedCall, isInSelfManagedCall);
1695         } finally {
1696             if (connection != null) {
1697                 // Disconnect the call
1698                 connection.disconnectAndDestroy();
1699                 TestUtils.waitOnAllHandlers(getInstrumentation());
1700                 assertIsInCall(false);
1701             }
1702         }
1703     }
1704 
registerSimAccountIfNeeded()1705     private void registerSimAccountIfNeeded() {
1706         if (mTelecomManager.getPhoneAccount(TestUtils.TEST_SIM_PHONE_ACCOUNT.getAccountHandle())
1707                 == null) {
1708             runWithShellPermissionIdentity(() -> {
1709                 mTelecomManager.registerPhoneAccount(TestUtils.TEST_SIM_PHONE_ACCOUNT);
1710             });
1711         }
1712     }
1713 
unregisterSimPhoneAccount()1714     private void unregisterSimPhoneAccount() {
1715         runWithShellPermissionIdentity(() -> {
1716             mTelecomManager.unregisterPhoneAccount(
1717                     TestUtils.TEST_SIM_PHONE_ACCOUNT.getAccountHandle());
1718         });
1719     }
1720 
setRemoteConnectionActiveAndVerify(TestServiceConnection conn)1721     private void setRemoteConnectionActiveAndVerify(TestServiceConnection conn) throws Exception {
1722         // Set the connection active.
1723         conn.getInterface().setConnectionActive();
1724 
1725         // Check with Telecom if we're in a call.
1726         assertIsInCall(true);
1727         assertIsInManagedCall(false);
1728     }
1729 
1730     /**
1731      * Sets a connection active, and verifies TelecomManager thinks we're in call but not in a
1732      * managed call.
1733      * @param connection The connection.
1734      */
setActiveAndVerify(SelfManagedConnection connection)1735     private void setActiveAndVerify(SelfManagedConnection connection) throws Exception {
1736         // Set the connection active.
1737         connection.setActive();
1738 
1739         // Check with Telecom if we're in a call.
1740         assertIsInCall(true);
1741         assertIsInManagedCall(false);
1742     }
1743 
1744     /**
1745      * Sets a connection to be disconnected, and then waits until the TelecomManager reports it is
1746      * no longer in a call.
1747      * @param connection The connection to disconnect/destroy.
1748      */
setDisconnectedAndVerify(SelfManagedConnection connection)1749     private void setDisconnectedAndVerify(SelfManagedConnection connection) {
1750         // Now, disconnect call and clean it up.
1751         connection.disconnectAndDestroy();
1752 
1753         assertIsInCall(false);
1754         assertIsInManagedCall(false);
1755     }
1756 
1757     /**
1758      * helper method that creates and returns a self-managed connection with a given handle
1759      * and address.  Additionally, some checks are made to ensure the self-managed connection was
1760      * successful.
1761      */
placeSelfManagedCallAndGetConnection(PhoneAccountHandle handle, Uri address)1762     private SelfManagedConnection placeSelfManagedCallAndGetConnection(PhoneAccountHandle handle,
1763             Uri address) throws Exception {
1764         // place a self-managed call
1765         assertIsOutgoingCallPermitted(true, TestUtils.TEST_SELF_MANAGED_HANDLE_1);
1766 
1767         TestUtils.placeOutgoingCall(getInstrumentation(), mTelecomManager, handle, address);
1768 
1769         // Ensure Telecom bound to the self managed CS
1770         if (!CtsSelfManagedConnectionService.waitForBinding()) {
1771             fail("Could not bind to Self-Managed ConnectionService");
1772         }
1773 
1774         SelfManagedConnection connection = TestUtils.waitForAndGetConnection(address);
1775 
1776         assertNotNull("Self-Managed Connection should NOT be null.", connection);
1777         assertTrue("Self-Managed Connection should be outgoing.", !connection.isIncomingCall());
1778 
1779         // The self-managed ConnectionService must NOT have been prompted to show its incoming call
1780         // UI for an outgoing call.
1781         assertEquals(connection.getOnShowIncomingUiInvokeCounter().getInvokeCount(), 0);
1782 
1783         setActiveAndVerify(connection);
1784 
1785         // Ensure that the connection defaulted to voip audio mode.
1786         assertTrue(connection.getAudioModeIsVoip());
1787         // Ensure AudioManager has correct voip mode.
1788         AudioManager audioManager = mContext.getSystemService(AudioManager.class);
1789         assertAudioMode(audioManager, MODE_IN_COMMUNICATION);
1790 
1791         // Expect there to be no managed calls at the moment.
1792         assertFalse(mTelecomManager.isInManagedCall());
1793         // But there should be a call (including self-managed).
1794         assertTrue(mTelecomManager.isInCall());
1795 
1796         // Expect that the new outgoing call broadcast did not fire for the self-managed calls.
1797         assertFalse(NewOutgoingCallBroadcastReceiver.isNewOutgoingCallBroadcastReceived());
1798 
1799         return connection;
1800     }
1801 
1802     /**
1803      * helper method that creates and returns a self-managed connection with a given handle
1804      * and address.  Additionally, some checks are made to ensure the self-managed connection was
1805      * successful.
1806      */
placeSelfManagedCallOnTestApp( ICtsSelfManagedConnectionServiceControl serviceControl, PhoneAccountHandle handle, Uri address)1807     private void placeSelfManagedCallOnTestApp(
1808             ICtsSelfManagedConnectionServiceControl serviceControl,
1809             PhoneAccountHandle handle, Uri address) throws Exception {
1810         // place a self-managed call
1811         assertTrue(serviceControl.placeOutgoingCall(handle, address.toString()));
1812 
1813         // Wait for Telecom to finish creating the new connection.
1814         try {
1815             TestUtils.waitOnAllHandlers(getInstrumentation());
1816         } catch (Exception e) {
1817             fail("Failed to wait on handlers");
1818         }
1819 
1820         // Ensure Telecom bound to the self managed CS
1821         if (!serviceControl.waitForBinding()) {
1822             fail("Could not bind to Self-Managed ConnectionService");
1823         }
1824 
1825         if (!serviceControl.isConnectionAvailable()) {
1826             fail("Connection not available for Self-Managed ConnectionService");
1827         }
1828 
1829         serviceControl.setConnectionActive();
1830 
1831         assertTrue("Self-Managed Connection should be outgoing.", !serviceControl.isIncomingCall());
1832 
1833         // The self-managed ConnectionService must NOT have been prompted to show its incoming call
1834         // UI for an outgoing call.
1835         assertEquals(serviceControl.getOnShowIncomingUiInvokeCounter(), 0);
1836 
1837         // Ensure that the connection defaulted to voip audio mode.
1838         assertTrue(serviceControl.getAudioModeIsVoip());
1839         // Ensure AudioManager has correct voip mode.
1840         AudioManager audioManager = mContext.getSystemService(AudioManager.class);
1841         assertAudioMode(audioManager, MODE_IN_COMMUNICATION);
1842 
1843         // Expect there to be no managed calls at the moment.
1844         assertFalse(mTelecomManager.isInManagedCall());
1845         // But there should be a call (including self-managed).
1846         assertTrue(mTelecomManager.isInCall());
1847 
1848         // Expect that the new outgoing call broadcast did not fire for the self-managed calls.
1849         assertFalse(NewOutgoingCallBroadcastReceiver.isNewOutgoingCallBroadcastReceived());
1850     }
1851 }
1852