xref: /aosp_15_r20/cts/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java (revision b7c941bb3fa97aba169d73cee0bed2de8ac964bf)
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package android.telecom.cts;
18 
19 import static android.telecom.Connection.PROPERTY_HIGH_DEF_AUDIO;
20 import static android.telecom.Connection.PROPERTY_WIFI;
21 import static android.telecom.cts.TestUtils.InvokeCounter;
22 import static android.telecom.cts.TestUtils.TEST_PHONE_ACCOUNT_HANDLE;
23 import static android.telecom.cts.TestUtils.TEST_PHONE_ACCOUNT_HANDLE_2;
24 import static android.telecom.cts.TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS;
25 
26 import static org.hamcrest.CoreMatchers.instanceOf;
27 import static org.junit.Assert.assertThat;
28 
29 import android.content.ContentProviderOperation;
30 import android.content.ContentResolver;
31 import android.content.Context;
32 import android.database.Cursor;
33 import android.graphics.drawable.Icon;
34 import android.location.Location;
35 import android.media.AudioManager;
36 import android.net.Uri;
37 import android.os.Bundle;
38 import android.os.ParcelUuid;
39 import android.provider.CallLog;
40 import android.provider.ContactsContract;
41 import android.provider.ContactsContract.PhoneLookup;
42 import android.telecom.Call;
43 import android.telecom.Connection;
44 import android.telecom.ConnectionRequest;
45 import android.telecom.DisconnectCause;
46 import android.telecom.GatewayInfo;
47 import android.telecom.PhoneAccount;
48 import android.telecom.PhoneAccountHandle;
49 import android.telecom.StatusHints;
50 import android.telecom.TelecomManager;
51 import android.telephony.TelephonyManager;
52 
53 import com.android.compatibility.common.util.ApiTest;
54 import com.android.compatibility.common.util.FileUtils;
55 import com.android.server.telecom.flags.Flags;
56 
57 import java.io.InputStream;
58 import java.util.ArrayList;
59 import java.util.Arrays;
60 import java.util.List;
61 import java.util.concurrent.CountDownLatch;
62 import java.util.concurrent.TimeUnit;
63 
64 /**
65  * Suites of tests that verifies the various Call details.
66  */
67 public class CallDetailsTest extends BaseTelecomTestWithMockServices {
68     public static final int WAIT_FOR_PHOTO_URI_TIMEOUT = 10000;
69     public static final int CONNECTION_PROPERTIES =  PROPERTY_HIGH_DEF_AUDIO | PROPERTY_WIFI;
70     public static final int CONNECTION_CAPABILITIES =
71             Connection.CAPABILITY_HOLD | Connection.CAPABILITY_MUTE;
72     public static final int CALL_CAPABILITIES =
73             Call.Details.CAPABILITY_HOLD | Call.Details.CAPABILITY_MUTE;
74     public static final int CALL_PROPERTIES =
75             Call.Details.PROPERTY_HIGH_DEF_AUDIO | Call.Details.PROPERTY_WIFI;
76     public static final String CALLER_DISPLAY_NAME = "CTS test";
77     public static final int CALLER_DISPLAY_NAME_PRESENTATION = TelecomManager.PRESENTATION_ALLOWED;
78     public static final String TEST_SUBJECT = "test";
79     public static final String TEST_CHILD_NUMBER = "650-555-1212";
80     public static final String TEST_FORWARDED_NUMBER = "650-555-1212";
81     public static final String TEST_EXTRA_KEY = "android.test.extra.TEST";
82     public static final String TEST_EXTRA_KEY2 = "android.test.extra.TEST2";
83     public static final String TEST_EXTRA_KEY3 = "android.test.extra.TEST3";
84     public static final float TEST_EXTRA_BITRATE = 23.85f ;
85     public static final float TEST_EXTRA_BANDWIDTH = 7.0f ;
86     public static final String TEST_INVALID_EXTRA_KEY = "blah";
87     public static final int TEST_EXTRA_VALUE = 10;
88     public static final String TEST_EVENT = "com.test.event.TEST";
89     public static final Uri TEST_DEFLECT_URI = Uri.fromParts("tel", "+16505551212", null);
90     private static final int ASYNC_TIMEOUT = 10000;
91     private StatusHints mStatusHints;
92     private Bundle mExtras = new Bundle();
93     private Uri mContactUri;
94 
95     private MockInCallService mInCallService;
96     private Call mCall;
97     private MockConnection mConnection;
98 
99     @Override
setUp()100     protected void setUp() throws Exception {
101         boolean isSetUpComplete = false;
102         super.setUp();
103         if (mShouldTestTelecom) {
104             try {
105                 PhoneAccount account = setupConnectionService(
106                         new MockConnectionService() {
107                             @Override
108                             public Connection onCreateOutgoingConnection(
109                                     PhoneAccountHandle connectionManagerPhoneAccount,
110                                     ConnectionRequest request) {
111                                 Connection connection = super.onCreateOutgoingConnection(
112                                         connectionManagerPhoneAccount,
113                                         request);
114                                 mConnection = (MockConnection) connection;
115                                 // Modify the connection object created with local values.
116                                 connection.setConnectionCapabilities(CONNECTION_CAPABILITIES);
117                                 connection.setConnectionProperties(CONNECTION_PROPERTIES);
118                                 connection.setCallerDisplayName(
119                                         CALLER_DISPLAY_NAME,
120                                         CALLER_DISPLAY_NAME_PRESENTATION);
121                                 connection.setExtras(mExtras);
122                                 mStatusHints = new StatusHints(
123                                         "CTS test",
124                                         Icon.createWithResource(
125                                                 getInstrumentation().getContext(),
126                                                 R.drawable.ic_phone_24dp),
127                                         null);
128                                 connection.setStatusHints(mStatusHints);
129                                 lock.release();
130                                 return connection;
131                             }
132                         }, FLAG_REGISTER | FLAG_ENABLE);
133 
134                 // Make sure there is another phone account.
135                 mTelecomManager.registerPhoneAccount(TestUtils.TEST_PHONE_ACCOUNT_2);
136                 TestUtils.enablePhoneAccount(
137                         getInstrumentation(), TestUtils.TEST_PHONE_ACCOUNT_HANDLE_2);
138 
139                 // Add photo URI to calling number
140                 ContentResolver resolver =
141                         getInstrumentation().getTargetContext().getContentResolver();
142                 try {
143                     mContactUri = insertContactWithPhoto(
144                             resolver, getTestNumber().getSchemeSpecificPart());
145                 } catch (Exception e) {
146                     assertTrue("Failed to insert test contact into ContactsProvider", false);
147                 }
148 
149                 /** Place a call as a part of the setup before we test the various
150                  *  Call details.
151                  */
152                 Bundle bundle = new Bundle();
153                 bundle.putParcelable(TestUtils.EXTRA_PHONE_NUMBER, getTestNumber());
154                 placeAndVerifyCall(bundle);
155                 verifyConnectionForOutgoingCall();
156 
157                 mInCallService = mInCallCallbacks.getService();
158                 mCall = mInCallService.getLastCall();
159 
160                 assertCallState(mCall, Call.STATE_DIALING);
161                 isSetUpComplete = true;
162             } finally {
163                 // Force tearDown if setUp errors out to ensure unused listeners are cleaned up.
164                 if (!isSetUpComplete) {
165                     tearDown();
166                 }
167             }
168         }
169     }
170 
171     @Override
tearDown()172     protected void tearDown() throws Exception {
173         try {
174             if (mShouldTestTelecom) {
175                 mTelecomManager.unregisterPhoneAccount(
176                         TestUtils.TEST_PHONE_ACCOUNT_2.getAccountHandle());
177                 if (mContactUri != null) {
178                     ContentResolver resolver =
179                             getInstrumentation().getTargetContext().getContentResolver();
180                     TestUtils.deleteContact(resolver, mContactUri);
181                 }
182             }
183         } finally {
184             super.tearDown();
185         }
186     }
187 
188     /**
189      * Tests whether the getAccountHandle() getter returns the correct object.
190      */
testAccountHandle()191     public void testAccountHandle() {
192         if (!mShouldTestTelecom) {
193             return;
194         }
195 
196         assertThat(mCall.getDetails().getAccountHandle(), instanceOf(PhoneAccountHandle.class));
197         assertEquals(TEST_PHONE_ACCOUNT_HANDLE, mCall.getDetails().getAccountHandle());
198     }
199 
200     /**
201      * Tests whether the getCallCapabilities() getter returns the correct object.
202      */
testCallCapabilities()203     public void testCallCapabilities() {
204         if (!mShouldTestTelecom) {
205             return;
206         }
207 
208         assertThat(mCall.getDetails().getCallCapabilities(), instanceOf(Integer.class));
209         assertEquals(CALL_CAPABILITIES, mCall.getDetails().getCallCapabilities());
210         assertTrue(mCall.getDetails().can(Call.Details.CAPABILITY_HOLD));
211         assertTrue(mCall.getDetails().can(Call.Details.CAPABILITY_MUTE));
212         assertFalse(mCall.getDetails().can(Call.Details.CAPABILITY_MANAGE_CONFERENCE));
213         assertFalse(mCall.getDetails().can(Call.Details.CAPABILITY_RESPOND_VIA_TEXT));
214     }
215 
216     /**
217      * Tests propagation of the local video capabilities from telephony through to in-call.
218      */
testCallLocalVideoCapability()219     public void testCallLocalVideoCapability() {
220         if (!mShouldTestTelecom) {
221             return;
222         }
223 
224         // Note: Local support for video is disabled when a call is in dialing state.
225         mConnection.setConnectionCapabilities(
226                 Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL);
227         assertCallCapabilities(mCall, 0);
228 
229         mConnection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORTS_VT_LOCAL_RX);
230         assertCallCapabilities(mCall, 0);
231 
232         mConnection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORTS_VT_LOCAL_TX);
233         assertCallCapabilities(mCall, 0);
234 
235         mConnection.setConnectionCapabilities(
236                 Connection.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL);
237         assertCallCapabilities(mCall, 0);
238 
239         mConnection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORTS_VT_REMOTE_RX);
240         assertCallCapabilities(mCall, 0);
241 
242         mConnection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORTS_VT_REMOTE_TX);
243         assertCallCapabilities(mCall, 0);
244 
245         // Set call active; we expect the capabilities to make it through now.
246         mConnection.setActive();
247 
248         mConnection.setConnectionCapabilities(
249                 Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL);
250         assertCallCapabilities(mCall, Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL);
251 
252         mConnection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORTS_VT_LOCAL_RX);
253         assertCallCapabilities(mCall, Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_RX);
254 
255         mConnection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORTS_VT_LOCAL_TX);
256         assertCallCapabilities(mCall, Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_TX);
257 
258         mConnection.setConnectionCapabilities(
259                 Connection.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL);
260         assertCallCapabilities(mCall, Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL);
261 
262         mConnection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORTS_VT_REMOTE_RX);
263         assertCallCapabilities(mCall, Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_RX);
264 
265         mConnection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORTS_VT_REMOTE_TX);
266         assertCallCapabilities(mCall, Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_TX);
267     }
268 
269     /**
270      * Tests passing call capabilities from Connections to Calls.
271      */
testCallCapabilityPropagation()272     public void testCallCapabilityPropagation() {
273         if (!mShouldTestTelecom) {
274             return;
275         }
276 
277         mConnection.setConnectionCapabilities(Connection.CAPABILITY_CAN_PAUSE_VIDEO);
278         assertCallCapabilities(mCall, Call.Details.CAPABILITY_CAN_PAUSE_VIDEO);
279 
280         mConnection.setConnectionCapabilities(Connection.CAPABILITY_HOLD);
281         assertCallCapabilities(mCall, Call.Details.CAPABILITY_HOLD);
282 
283         mConnection.setConnectionCapabilities(Connection.CAPABILITY_MANAGE_CONFERENCE);
284         assertCallCapabilities(mCall, Call.Details.CAPABILITY_MANAGE_CONFERENCE);
285 
286         mConnection.setConnectionCapabilities(Connection.CAPABILITY_MERGE_CONFERENCE);
287         assertCallCapabilities(mCall, Call.Details.CAPABILITY_MERGE_CONFERENCE);
288 
289         mConnection.setConnectionCapabilities(Connection.CAPABILITY_MUTE);
290         assertCallCapabilities(mCall, Call.Details.CAPABILITY_MUTE);
291 
292         mConnection.setConnectionCapabilities(Connection.CAPABILITY_RESPOND_VIA_TEXT);
293         assertCallCapabilities(mCall, Call.Details.CAPABILITY_RESPOND_VIA_TEXT);
294 
295         mConnection.setConnectionCapabilities(Connection.CAPABILITY_SEPARATE_FROM_CONFERENCE);
296         assertCallCapabilities(mCall, Call.Details.CAPABILITY_SEPARATE_FROM_CONFERENCE);
297 
298         mConnection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORT_HOLD);
299         assertCallCapabilities(mCall, Call.Details.CAPABILITY_SUPPORT_HOLD);
300 
301         mConnection.setConnectionCapabilities(Connection.CAPABILITY_SWAP_CONFERENCE);
302         assertCallCapabilities(mCall, Call.Details.CAPABILITY_SWAP_CONFERENCE);
303     }
304 
305     /**
306      * Tests passing call properties from Connections to Calls.
307      */
testCallPropertyPropagation()308     public void testCallPropertyPropagation() {
309         if (!mShouldTestTelecom) {
310             return;
311         }
312 
313         mConnection.setConnectionProperties(Connection.PROPERTY_EMERGENCY_CALLBACK_MODE);
314         assertCallProperties(mCall, Call.Details.PROPERTY_EMERGENCY_CALLBACK_MODE);
315 
316         mConnection.setConnectionProperties(Connection.PROPERTY_GENERIC_CONFERENCE);
317         assertCallProperties(mCall, Call.Details.PROPERTY_GENERIC_CONFERENCE);
318 
319         mConnection.setConnectionProperties(Connection.PROPERTY_HIGH_DEF_AUDIO);
320         assertCallProperties(mCall, Call.Details.PROPERTY_HIGH_DEF_AUDIO);
321 
322         mConnection.setConnectionProperties(Connection.PROPERTY_WIFI);
323         assertCallProperties(mCall, Call.Details.PROPERTY_WIFI);
324 
325         mConnection.setConnectionProperties(Connection.PROPERTY_IS_EXTERNAL_CALL);
326         assertCallProperties(mCall, Call.Details.PROPERTY_IS_EXTERNAL_CALL);
327 
328         mConnection.setConnectionProperties(Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY);
329         assertCallProperties(mCall, Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY);
330 
331         mConnection.setConnectionProperties(Connection.PROPERTY_IS_DOWNGRADED_CONFERENCE);
332         // Not propagated
333         assertCallProperties(mCall, 0);
334 
335         mConnection.setConnectionProperties(Connection.PROPERTY_IS_RTT);
336         assertCallProperties(mCall, Call.Details.PROPERTY_RTT);
337 
338         mConnection.setConnectionProperties(Connection.PROPERTY_ASSISTED_DIALING);
339         assertCallProperties(mCall, Call.Details.PROPERTY_ASSISTED_DIALING);
340 
341         mConnection.setConnectionProperties(Connection.PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL);
342         assertCallProperties(mCall, Call.Details.PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL);
343 
344         mConnection.setConnectionProperties(Connection.PROPERTY_REMOTELY_HOSTED);
345         // Not propagated
346         assertCallProperties(mCall, 0);
347 
348         mConnection.setConnectionProperties(Connection.PROPERTY_CROSS_SIM);
349         assertCallProperties(mCall, Call.Details.PROPERTY_CROSS_SIM);
350     }
351 
352     /**
353      * Tests whether the getCallerDisplayName() getter returns the correct object.
354      */
testCallerDisplayName()355     public void testCallerDisplayName() {
356         // Wearable device can skip contact lookup
357         if (!mShouldTestTelecom || mWatchDevice) {
358             return;
359         }
360 
361 
362         assertThat(mCall.getDetails().getCallerDisplayName(), instanceOf(String.class));
363         assertEquals(CALLER_DISPLAY_NAME, mCall.getDetails().getCallerDisplayName());
364     }
365 
366     /**
367      * We need to use actual photo data as any non photo information used would fails to be inserted
368      * into the contacts provider database per validity checks performed prior to inserting.
369      */
getTestPhotoData(Context context)370     public static byte[] getTestPhotoData(Context context) {
371         InputStream input = context.getResources().openRawResource(R.drawable.ic_phone_24dp);
372         return FileUtils.readInputStreamFully(input);
373     }
374 
375     /**
376      * This function is similar to {@link TestUtils#insertContact with the exception that it
377      * inserts a photo with the contact.
378      */
insertContactWithPhoto(ContentResolver contentResolver, String phoneNumber)379     public Uri insertContactWithPhoto(ContentResolver contentResolver, String phoneNumber)
380             throws Exception {
381         ArrayList<ContentProviderOperation> ops = new ArrayList<>();
382         ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
383                         .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, "test_type")
384                         .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, "test_name")
385                         .build());
386         ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
387                         .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
388                         .withValue(ContactsContract.Data.MIMETYPE,
389                                 ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
390                         .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,
391                                 CALLER_DISPLAY_NAME)
392                         .build());
393         // Create another row for the Photo URI content as it uses a different MIME type, reference
394         // same raw contact id
395         ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
396                         .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
397                         .withValue(ContactsContract.Data.MIMETYPE,
398                                 ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
399                         .withValue(
400                                 ContactsContract.Contacts.Photo.PHOTO, getTestPhotoData(mContext))
401                         .withYieldAllowed(true)
402                         .build());
403         // Create another row for the Phone number as it uses a different MIME type, reference same
404         // raw contact id
405         ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
406                         .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
407                         .withValue(ContactsContract.Data.MIMETYPE,
408                                 ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
409                         .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phoneNumber)
410                         .withValue(ContactsContract.CommonDataKinds.Phone.TYPE,
411                                 ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE)
412                         .withYieldAllowed(true)
413                         .build());
414         return contentResolver.applyBatch(ContactsContract.AUTHORITY, ops)[0].uri;
415     }
416 
417     /**
418      * Tests whether the getCallerPhotoUri() getter returns the correct object.
419      */
testContactPhotoUri()420     public void testContactPhotoUri() {
421         // Wearable device can skip contact lookup
422         if (!mShouldTestTelecom || mWatchDevice) {
423             return;
424         }
425 
426         String phoneNumber = getTestNumber().getSchemeSpecificPart();
427 
428         Uri contactRef = PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
429                                  .appendPath(phoneNumber)
430                                  .build();
431 
432         Cursor cursor = getInstrumentation().getContext().getContentResolver().query(
433                 contactRef, null, null, null, null, null);
434 
435         cursor.moveToFirst();
436         int columnIndex = cursor.getColumnIndex(PhoneLookup.PHOTO_URI);
437         assertTrue("photoURI should exist",
438                 (columnIndex != -1) && (cursor.getString(columnIndex) != null));
439         Uri photoUri = Uri.parse(cursor.getString(columnIndex));
440 
441         // The photo URI is set until the CallerInfo query is done, at that time the photo URI
442         // should exist, so wait until the value before testing that the value matches the
443         // photo URI from contacts provider.
444         waitUntilConditionIsTrueOrTimeout(
445                 new Condition() {
446                     @Override
447                     public Object expected() {
448                         return true;
449                     }
450 
451                     @Override
452                     public Object actual() {
453                         return mCall.getDetails() != null
454                                 && mCall.getDetails().getContactPhotoUri() != null
455                                 && mCall.getDetails().getContactPhotoUri().toString().equals(
456                                         photoUri.toString());
457                     }
458                 },
459                 WAIT_FOR_PHOTO_URI_TIMEOUT,
460                 // If test flakes on this line, consider increasing the timeout as it may
461                 // not have had enough time to perform the query for the photo uri.
462                 "Photo URI should match between Contacts Provider and call details");
463     }
464 
465     /**
466      * Tests whether the getCallerDisplayNamePresentation() getter returns the correct object.
467      */
testCallerDisplayNamePresentation()468     public void testCallerDisplayNamePresentation() {
469         // Wearable device can skip contact lookup
470         if (!mShouldTestTelecom || mWatchDevice) {
471             return;
472         }
473 
474 
475         assertThat(mCall.getDetails().getCallerDisplayNamePresentation(), instanceOf(Integer.class));
476         assertEquals(CALLER_DISPLAY_NAME_PRESENTATION, mCall.getDetails().getCallerDisplayNamePresentation());
477     }
478 
479     /**
480      * Test the contacts display name.
481      */
testContactDisplayName()482     public void testContactDisplayName() {
483         // Wearable device can skip contact lookup
484         if (!mShouldTestTelecom || mWatchDevice) {
485             return;
486         }
487 
488         assertEquals(CALLER_DISPLAY_NAME, mCall.getDetails().getContactDisplayName());
489     }
490 
491     /**
492      * Tests whether the getCallProperties() getter returns the correct object.
493      */
testCallProperties()494     public void testCallProperties() {
495         if (!mShouldTestTelecom) {
496             return;
497         }
498 
499         assertThat(mCall.getDetails().getCallProperties(), instanceOf(Integer.class));
500 
501         assertEquals(CALL_PROPERTIES, mCall.getDetails().getCallProperties());
502     }
503 
504     /**
505      * Tests whether the getId() getter returns the correct object.
506      */
testCallId()507     public void testCallId() {
508         if (!mShouldTestTelecom || !Flags.callDetailsIdChanges()) {
509             return;
510         }
511 
512         assertThat(mCall.getDetails().getId(), instanceOf(String.class));
513     }
514 
515     /**
516      * Tests whether the getConnectTimeMillis() getter returns the correct object.
517      */
testConnectTimeMillis()518     public void testConnectTimeMillis() {
519         if (!mShouldTestTelecom) {
520             return;
521         }
522 
523         assertThat(mCall.getDetails().getConnectTimeMillis(), instanceOf(Long.class));
524     }
525 
526     /**
527      * Tests whether the getCreationTimeMillis() getter returns the correct object.
528      */
testCreationTimeMillis()529     public void testCreationTimeMillis() {
530         if (!mShouldTestTelecom) {
531             return;
532         }
533 
534         assertThat(mCall.getDetails().getCreationTimeMillis(), instanceOf(Long.class));
535     }
536 
537     /**
538      * Tests whether the getDisconnectCause() getter returns the correct object.
539      */
testDisconnectCause()540     public void testDisconnectCause() {
541         if (!mShouldTestTelecom) {
542             return;
543         }
544 
545         assertThat(mCall.getDetails().getDisconnectCause(), instanceOf(DisconnectCause.class));
546     }
547 
548     /**
549      * Tests whether the getExtras() getter returns the correct object.
550      */
testExtras()551     public void testExtras() {
552         if (!mShouldTestTelecom) {
553             return;
554         }
555 
556         if (mCall.getDetails().getExtras() != null) {
557             assertThat(mCall.getDetails().getExtras(), instanceOf(Bundle.class));
558         }
559     }
560 
561     /**
562      * Tests whether the getIntentExtras() getter returns the correct object.
563      */
testIntentExtras()564     public void testIntentExtras() {
565         if (!mShouldTestTelecom) {
566             return;
567         }
568 
569         assertThat(mCall.getDetails().getIntentExtras(), instanceOf(Bundle.class));
570     }
571 
572     /**
573      * Tests whether the getGatewayInfo() getter returns the correct object.
574      */
testGatewayInfo()575     public void testGatewayInfo() {
576         if (!mShouldTestTelecom) {
577             return;
578         }
579 
580         if (mCall.getDetails().getGatewayInfo() != null) {
581             assertThat(mCall.getDetails().getGatewayInfo(), instanceOf(GatewayInfo.class));
582         }
583     }
584 
585     /**
586      * Tests whether the getHandle() getter returns the correct object.
587      */
testHandle()588     public void testHandle() {
589         if (!mShouldTestTelecom) {
590             return;
591         }
592 
593         assertThat(mCall.getDetails().getHandle(), instanceOf(Uri.class));
594         assertEquals(getTestNumber(), mCall.getDetails().getHandle());
595     }
596 
597     /**
598      * Tests whether the getHandlePresentation() getter returns the correct object.
599      */
testHandlePresentation()600     public void testHandlePresentation() {
601         if (!mShouldTestTelecom) {
602             return;
603         }
604 
605         assertThat(mCall.getDetails().getHandlePresentation(), instanceOf(Integer.class));
606         assertEquals(MockConnectionService.CONNECTION_PRESENTATION, mCall.getDetails().getHandlePresentation());
607     }
608 
609     /**
610      * Tests whether the getStatusHints() getter returns the correct object.
611      */
testStatusHints()612     public void testStatusHints() {
613         if (!mShouldTestTelecom) {
614             return;
615         }
616 
617         assertThat(mCall.getDetails().getStatusHints(), instanceOf(StatusHints.class));
618         assertEquals(mStatusHints.getLabel(), mCall.getDetails().getStatusHints().getLabel());
619         assertEquals(
620                 mStatusHints.getIcon().toString(),
621                 mCall.getDetails().getStatusHints().getIcon().toString());
622         assertEquals(mStatusHints.getExtras(), mCall.getDetails().getStatusHints().getExtras());
623     }
624 
625     /**
626      * Tests whether the getVideoState() getter returns the correct object.
627      */
testVideoState()628     public void testVideoState() {
629         if (!mShouldTestTelecom) {
630             return;
631         }
632 
633         assertThat(mCall.getDetails().getVideoState(), instanceOf(Integer.class));
634     }
635 
636     /**
637      * Tests communication of {@link Connection#setExtras(Bundle)} through to
638      * {@link Call.Details#getExtras()}.
639      */
testExtrasPropagation()640     public void testExtrasPropagation() {
641         if (!mShouldTestTelecom) {
642             return;
643         }
644 
645         Bundle exampleExtras = new Bundle();
646         exampleExtras.putString(Connection.EXTRA_CALL_SUBJECT, TEST_SUBJECT);
647 
648         // EXTRA_PRIORITY
649         exampleExtras.putInt(TelecomManager.EXTRA_PRIORITY, TelecomManager.PRIORITY_URGENT);
650 
651         // EXTRA_CALL_LOCATION
652         Location testLocation = new Location("CallDetailsTest");
653         double latitude = 123;
654         double longitude = 456;
655         testLocation.setLatitude(latitude);
656         testLocation.setLongitude(longitude);
657         exampleExtras.putParcelable(TelecomManager.EXTRA_LOCATION, testLocation);
658 
659         // EXTRA_HAS_PICTURE
660         exampleExtras.putBoolean(TelecomManager.EXTRA_HAS_PICTURE, true);
661 
662         // EXTRA_INCOMING_PICTURE
663         Uri testIncomingPictureUrl = Uri.parse("content://carrier.xyz/picture1");
664         exampleExtras.putParcelable(TelecomManager.EXTRA_PICTURE_URI, testIncomingPictureUrl);
665 
666         // EXTRA_OUTGOING_PICTURE
667         ParcelUuid testOutgoingPicture = ParcelUuid.fromString("11111111-2222-3333-4444-55555555");
668         exampleExtras.putParcelable(TelecomManager.EXTRA_OUTGOING_PICTURE, testOutgoingPicture);
669 
670         exampleExtras.putString(Connection.EXTRA_CHILD_ADDRESS, TEST_CHILD_NUMBER);
671         exampleExtras.putString(Connection.EXTRA_LAST_FORWARDED_NUMBER, TEST_FORWARDED_NUMBER);
672         exampleExtras.putInt(TEST_EXTRA_KEY, TEST_EXTRA_VALUE);
673         exampleExtras.putInt(Connection.EXTRA_AUDIO_CODEC, Connection.AUDIO_CODEC_AMR);
674         exampleExtras.putFloat(Connection.EXTRA_AUDIO_CODEC_BITRATE_KBPS, TEST_EXTRA_BITRATE);
675         exampleExtras.putFloat(Connection.EXTRA_AUDIO_CODEC_BANDWIDTH_KHZ, TEST_EXTRA_BANDWIDTH);
676         mConnection.setExtras(exampleExtras);
677 
678         // Make sure we got back a bundle with the call subject key set.
679         assertCallExtras(mCall, Connection.EXTRA_CALL_SUBJECT);
680 
681         Bundle callExtras = mCall.getDetails().getExtras();
682         assertEquals(TEST_SUBJECT, callExtras.getString(Connection.EXTRA_CALL_SUBJECT));
683         assertEquals(TEST_CHILD_NUMBER, callExtras.getString(Connection.EXTRA_CHILD_ADDRESS));
684         assertEquals(TEST_FORWARDED_NUMBER,
685                 callExtras.getString(Connection.EXTRA_LAST_FORWARDED_NUMBER));
686         assertEquals(TEST_EXTRA_VALUE, callExtras.getInt(TEST_EXTRA_KEY));
687         assertEquals(Connection.AUDIO_CODEC_AMR,
688                 callExtras.getInt(Connection.EXTRA_AUDIO_CODEC));
689         assertEquals(TEST_EXTRA_BITRATE,
690                 callExtras.getFloat(Connection.EXTRA_AUDIO_CODEC_BITRATE_KBPS), 0.01);
691         assertEquals(TEST_EXTRA_BANDWIDTH,
692                 callExtras.getFloat(Connection.EXTRA_AUDIO_CODEC_BANDWIDTH_KHZ), 0.01);
693 
694         assertEquals(TelecomManager.PRIORITY_URGENT, exampleExtras.getInt(
695                 TelecomManager.EXTRA_PRIORITY));
696         Location testGetLocation = exampleExtras.getParcelable(TelecomManager.EXTRA_LOCATION);
697         assertEquals(latitude, testGetLocation.getLatitude(), 0);
698         assertEquals(longitude, testGetLocation.getLongitude(), 0);
699         assertEquals(true, exampleExtras.getBoolean(TelecomManager.EXTRA_HAS_PICTURE));
700         assertEquals(testIncomingPictureUrl,
701                 exampleExtras.getParcelable(TelecomManager.EXTRA_PICTURE_URI));
702         assertEquals(testOutgoingPicture,
703                 exampleExtras.getParcelable(TelecomManager.EXTRA_OUTGOING_PICTURE));
704     }
705 
706     /**
707      * Tests that extra keys outside of the standard android.* namespace are not sent to a third
708      * party InCallService (the CTS test InCallService is technically not the OEM stock dialer).
709      */
testExtrasBlocking()710     public void testExtrasBlocking() {
711         if (!mShouldTestTelecom) {
712             return;
713         }
714 
715         Bundle exampleExtras = new Bundle();
716         exampleExtras.putString(Connection.EXTRA_CALL_SUBJECT, TEST_SUBJECT);
717         exampleExtras.putString(TEST_INVALID_EXTRA_KEY, "Secrets!");
718         exampleExtras.putString(Connection.EXTRA_SIP_INVITE, "Sip headers!!");
719         // Some ImsCallProfile system API extra keys we don't want to exposure to non-system
720         // dialer apps; its a bit of an implementation detail but good to verify that these are
721         // never exposed unintentionally.
722         exampleExtras.putString("oi", "5551212");
723         exampleExtras.putString("cna", "Joe");
724         exampleExtras.putInt("oir", TelecomManager.PRESENTATION_ALLOWED);
725         exampleExtras.putInt("cnap", TelecomManager.PRESENTATION_ALLOWED);
726 
727         mConnection.setExtras(exampleExtras);
728 
729         // Make sure we got back a bundle with the call subject key set.
730         assertCallExtras(mCall, Connection.EXTRA_CALL_SUBJECT);
731 
732         Bundle callExtras = mCall.getDetails().getExtras();
733         assertEquals(TEST_SUBJECT, callExtras.getString(Connection.EXTRA_CALL_SUBJECT));
734         assertFalse(callExtras.containsKey(TEST_INVALID_EXTRA_KEY));
735         assertFalse(callExtras.containsKey(Connection.EXTRA_SIP_INVITE));
736         // Some ImsCallProfile extra keys that should not be exposed to non-system dialers.
737         assertFalse(callExtras.containsKey("oi"));
738         assertFalse(callExtras.containsKey("cna"));
739         assertFalse(callExtras.containsKey("oir"));
740         assertFalse(callExtras.containsKey("cnap"));
741     }
742 
743     /**
744      * Verify the {@link  android.telecom.Call#EXTRA_IS_BUSINESS_CALL} and the
745      * {@link android.telecom.Call#EXTRA_ASSERTED_DISPLAY_NAME} can be set and fetched
746      * via the {@link android.telecom.Connection#setExtras(Bundle)} method.
747      */
testBusinessComposerExtras()748     public void testBusinessComposerExtras() {
749         if (!mShouldTestTelecom || !Flags.businessCallComposer()) {
750             return;
751         }
752         Bundle exampleExtras = new Bundle();
753         exampleExtras.putBoolean(Call.EXTRA_IS_BUSINESS_CALL, true);
754         exampleExtras.putString(Call.EXTRA_ASSERTED_DISPLAY_NAME, "Google");
755         mConnection.setExtras(exampleExtras);
756         assertCallExtras(mCall, Call.EXTRA_IS_BUSINESS_CALL);
757         assertCallExtras(mCall, Call.EXTRA_ASSERTED_DISPLAY_NAME);
758     }
759 
760     /**
761      * Tests that {@link Connection} extras changes made via {@link Connection#putExtras(Bundle)}
762      * are propagated to the {@link Call} via
763      * {@link android.telecom.Call.Callback#onDetailsChanged(Call, Call.Details)}.
764      */
testConnectionPutExtras()765     public void testConnectionPutExtras() {
766         if (!mShouldTestTelecom) {
767             return;
768         }
769 
770         Bundle testBundle = new Bundle();
771         testBundle.putString(TEST_EXTRA_KEY, TEST_SUBJECT);
772         testBundle.putInt(TEST_EXTRA_KEY2, TEST_EXTRA_VALUE);
773         testBundle.putBoolean(Connection.EXTRA_DISABLE_ADD_CALL, true);
774         mConnection.putExtras(testBundle);
775         // Wait for the 3rd invocation; setExtras is called in the setup method.
776         mOnExtrasChangedCounter.waitForCount(3, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
777 
778         Bundle extras = mCall.getDetails().getExtras();
779         assertTrue(extras.containsKey(TEST_EXTRA_KEY));
780         assertEquals(TEST_SUBJECT, extras.getString(TEST_EXTRA_KEY));
781         assertTrue(extras.containsKey(TEST_EXTRA_KEY2));
782         assertEquals(TEST_EXTRA_VALUE, extras.getInt(TEST_EXTRA_KEY2));
783         assertTrue(extras.getBoolean(Connection.EXTRA_DISABLE_ADD_CALL));
784     }
785 
testConnectionHoldTone()786     public void testConnectionHoldTone() {
787         if (!mShouldTestTelecom) {
788             return;
789         }
790 
791         // These tests are admittedly lame; the events are absorbed in telecom and start a tone and
792         // stop it.  There is no other signal that the tone is starting/stopping otherwise.
793         mConnection.sendConnectionEvent(Connection.EVENT_ON_HOLD_TONE_START, null);
794         mConnection.sendConnectionEvent(Connection.EVENT_ON_HOLD_TONE_END, null);
795     }
796 
797     /**
798      * Tests that {@link Connection} extras changes made via {@link Connection#removeExtras(List)}
799      * are propagated to the {@link Call} via
800      * {@link android.telecom.Call.Callback#onDetailsChanged(Call, Call.Details)}.
801      */
testConnectionRemoveExtras()802     public void testConnectionRemoveExtras() {
803         if (!mShouldTestTelecom) {
804             return;
805         }
806 
807         testConnectionPutExtras();
808 
809         mConnection.removeExtras(Arrays.asList(TEST_EXTRA_KEY));
810         verifyRemoveConnectionExtras();
811     }
812 
813     /**
814      * Tests that {@link Connection} extras changes made via {@link Connection#removeExtras(List)}
815      * are propagated to the {@link Call} via
816      * {@link android.telecom.Call.Callback#onDetailsChanged(Call, Call.Details)}.
817      */
testConnectionRemoveExtras2()818     public void testConnectionRemoveExtras2() {
819         if (!mShouldTestTelecom) {
820             return;
821         }
822 
823         testConnectionPutExtras();
824 
825         mConnection.removeExtras(TEST_EXTRA_KEY);
826         // testConnectionPutExtra will have waited for the 3rd invocation, so wait for the 4th here.
827         verifyRemoveConnectionExtras();
828     }
829 
verifyRemoveConnectionExtras()830     private void verifyRemoveConnectionExtras() {
831         // testConnectionPutExtra will have waited for the 3rd invocation, so wait for the 4th here.
832         mOnExtrasChangedCounter.waitForCount(4, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
833 
834         Bundle extras = mCall.getDetails().getExtras();
835         assertFalse(extras.containsKey(TEST_EXTRA_KEY));
836         assertTrue(extras.containsKey(TEST_EXTRA_KEY2));
837         assertEquals(TEST_EXTRA_VALUE, extras.getInt(TEST_EXTRA_KEY2));
838     }
839 
840     /**
841      * Tests that {@link Call} extras changes made via {@link Call#putExtras(Bundle)} are propagated
842      * to {@link Connection#onExtrasChanged(Bundle)}.
843      */
844     @ApiTest(apis = {"android.telecom.Call#putExtras", "android.telecom.Connection#getExtras",
845             "android.telecom.Connection#onExtrasChanged"})
testCallPutExtras()846     public void testCallPutExtras() {
847         if (!mShouldTestTelecom) {
848             return;
849         }
850 
851         Bundle testBundle = new Bundle();
852         testBundle.putString(TEST_EXTRA_KEY, TEST_SUBJECT);
853         final InvokeCounter counter = mConnection.getInvokeCounter(
854                 MockConnection.ON_EXTRAS_CHANGED);
855         mCall.putExtras(testBundle);
856         counter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
857         Bundle extras = mConnection.getExtras();
858 
859         assertNotNull(extras);
860         assertTrue(extras.containsKey(TEST_EXTRA_KEY));
861         assertEquals(TEST_SUBJECT, extras.getString(TEST_EXTRA_KEY));
862     }
863 
864     /**
865      * Tests that {@link Call} extra operations using {@link Call#removeExtras(List)} are propagated
866      * to the {@link Connection} via {@link Connection#onExtrasChanged(Bundle)}.
867      *
868      * This test specifically tests addition and removal of extras values.
869      */
testCallRemoveExtras()870     public void testCallRemoveExtras() {
871         if (!mShouldTestTelecom) {
872             return;
873         }
874 
875         final InvokeCounter counter = setupCallExtras();
876         Bundle extras;
877 
878         mCall.removeExtras(Arrays.asList(TEST_EXTRA_KEY));
879         counter.waitForCount(2, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
880         extras = mConnection.getExtras();
881         assertNotNull(extras);
882         assertFalse(extras.containsKey(TEST_EXTRA_KEY));
883         assertTrue(extras.containsKey(TEST_EXTRA_KEY2));
884         assertEquals(TEST_EXTRA_VALUE, extras.getInt(TEST_EXTRA_KEY2));
885         assertTrue(extras.containsKey(TEST_EXTRA_KEY3));
886         assertEquals(TEST_SUBJECT, extras.getString(TEST_EXTRA_KEY3));
887 
888         mCall.removeExtras(Arrays.asList(TEST_EXTRA_KEY2, TEST_EXTRA_KEY3));
889         counter.waitForCount(3, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
890         extras = mConnection.getExtras();
891         assertFalse(extras.containsKey(TEST_EXTRA_KEY2));
892         assertFalse(extras.containsKey(TEST_EXTRA_KEY3));
893     }
894 
895     /**
896      * Tests that {@link Call} extra operations using {@link Call#removeExtras(String[])} are
897      * propagated to the {@link Connection} via {@link Connection#onExtrasChanged(Bundle)}.
898      *
899      * This test specifically tests addition and removal of extras values.
900      */
testCallRemoveExtras2()901     public void testCallRemoveExtras2() {
902         if (!mShouldTestTelecom) {
903             return;
904         }
905 
906         final InvokeCounter counter = setupCallExtras();
907         Bundle extras;
908 
909         mCall.removeExtras(TEST_EXTRA_KEY);
910         counter.waitForCount(2, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
911         extras = mConnection.getExtras();
912         assertNotNull(extras);
913         assertFalse(extras.containsKey(TEST_EXTRA_KEY));
914         assertTrue(extras.containsKey(TEST_EXTRA_KEY2));
915         assertEquals(TEST_EXTRA_VALUE, extras.getInt(TEST_EXTRA_KEY2));
916         assertTrue(extras.containsKey(TEST_EXTRA_KEY3));
917         assertEquals(TEST_SUBJECT, extras.getString(TEST_EXTRA_KEY3));
918     }
919 
setupCallExtras()920     private InvokeCounter setupCallExtras() {
921         Bundle testBundle = new Bundle();
922         testBundle.putString(TEST_EXTRA_KEY, TEST_SUBJECT);
923         testBundle.putInt(TEST_EXTRA_KEY2, TEST_EXTRA_VALUE);
924         testBundle.putString(TEST_EXTRA_KEY3, TEST_SUBJECT);
925         final InvokeCounter counter = mConnection.getInvokeCounter(
926                 MockConnection.ON_EXTRAS_CHANGED);
927         mCall.putExtras(testBundle);
928         counter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
929         Bundle extras = mConnection.getExtras();
930 
931         assertNotNull(extras);
932         assertTrue(extras.containsKey(TEST_EXTRA_KEY));
933         assertEquals(TEST_SUBJECT, extras.getString(TEST_EXTRA_KEY));
934         assertTrue(extras.containsKey(TEST_EXTRA_KEY2));
935         assertEquals(TEST_EXTRA_VALUE, extras.getInt(TEST_EXTRA_KEY2));
936         assertTrue(extras.containsKey(TEST_EXTRA_KEY3));
937         assertEquals(TEST_SUBJECT, extras.getString(TEST_EXTRA_KEY3));
938         return counter;
939     }
940 
941     /**
942      * Tests that {@link Connection} events are propagated from
943      * {@link Connection#sendConnectionEvent(String, Bundle)} to
944      * {@link android.telecom.Call.Callback#onConnectionEvent(Call, String, Bundle)}.
945      */
testConnectionEvent()946     public void testConnectionEvent() {
947         if (!mShouldTestTelecom) {
948             return;
949         }
950 
951         Bundle testBundle = new Bundle();
952         testBundle.putString(TEST_EXTRA_KEY, TEST_SUBJECT);
953 
954         mConnection.sendConnectionEvent(Connection.EVENT_CALL_PULL_FAILED, testBundle);
955         mOnConnectionEventCounter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
956         String event = (String) (mOnConnectionEventCounter.getArgs(0)[1]);
957         Bundle extras = (Bundle) (mOnConnectionEventCounter.getArgs(0)[2]);
958 
959         assertEquals(Connection.EVENT_CALL_PULL_FAILED, event);
960         assertNotNull(extras);
961         assertTrue(extras.containsKey(TEST_EXTRA_KEY));
962         assertEquals(TEST_SUBJECT, extras.getString(TEST_EXTRA_KEY));
963         mOnConnectionEventCounter.reset();
964 
965         mConnection.sendConnectionEvent(Connection.EVENT_CALL_HOLD_FAILED, null);
966         // Don't expect this to make it through; used internally in Telecom.
967 
968         mConnection.sendConnectionEvent(Connection.EVENT_MERGE_START, null);
969         mOnConnectionEventCounter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
970         event = (String) (mOnConnectionEventCounter.getArgs(0)[1]);
971         extras = (Bundle) (mOnConnectionEventCounter.getArgs(0)[2]);
972         assertEquals(Connection.EVENT_MERGE_START, event);
973         assertNull(extras);
974         mOnConnectionEventCounter.reset();
975 
976         mConnection.sendConnectionEvent(Connection.EVENT_MERGE_COMPLETE, null);
977         mOnConnectionEventCounter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
978         event = (String) (mOnConnectionEventCounter.getArgs(0)[1]);
979         extras = (Bundle) (mOnConnectionEventCounter.getArgs(0)[2]);
980         assertEquals(Connection.EVENT_MERGE_COMPLETE, event);
981         assertNull(extras);
982         mOnConnectionEventCounter.reset();
983 
984         mConnection.sendConnectionEvent(Connection.EVENT_CALL_REMOTELY_HELD, null);
985         mOnConnectionEventCounter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
986         event = (String) (mOnConnectionEventCounter.getArgs(0)[1]);
987         extras = (Bundle) (mOnConnectionEventCounter.getArgs(0)[2]);
988         assertEquals(Connection.EVENT_CALL_REMOTELY_HELD, event);
989         assertNull(extras);
990         mOnConnectionEventCounter.reset();
991 
992         mConnection.sendConnectionEvent(Connection.EVENT_CALL_REMOTELY_UNHELD, null);
993         mOnConnectionEventCounter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
994         event = (String) (mOnConnectionEventCounter.getArgs(0)[1]);
995         extras = (Bundle) (mOnConnectionEventCounter.getArgs(0)[2]);
996         assertEquals(Connection.EVENT_CALL_REMOTELY_UNHELD, event);
997         assertNull(extras);
998         mOnConnectionEventCounter.reset();
999 
1000         TestParcelable testParcelable = createTestParcelable();
1001         testBundle = createTestBundle(testParcelable);
1002         mConnection.sendConnectionEvent(OTT_TEST_EVENT_NAME, testBundle);
1003         mOnConnectionEventCounter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
1004         event = (String) (mOnConnectionEventCounter.getArgs(0)[1]);
1005         extras = (Bundle) (mOnConnectionEventCounter.getArgs(0)[2]);
1006         assertEquals(OTT_TEST_EVENT_NAME, event);
1007         verifyTestBundle(extras, testParcelable);
1008         mOnConnectionEventCounter.reset();
1009     }
1010 
1011     /**
1012      * Verifies that a request to deflect a ringing {@link Call} is relayed to a {@link Connection}.
1013      */
testDeflect()1014     public void testDeflect() {
1015         if (!mShouldTestTelecom) {
1016             return;
1017         }
1018         // Only ringing calls support deflection
1019         mConnection.setRinging();
1020         assertCallState(mCall, Call.STATE_RINGING);
1021 
1022         final InvokeCounter counter = mConnection.getInvokeCounter(MockConnection.ON_DEFLECT);
1023         mCall.deflect(TEST_DEFLECT_URI);
1024         counter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
1025         Uri address = (Uri) (counter.getArgs(0)[0]);
1026 
1027         assertEquals(TEST_DEFLECT_URI, address);
1028     }
1029 
1030     /**
1031      * Tests that {@link Call} events are propagated from {@link Call#sendCallEvent(String, Bundle)}
1032      * to {@link Connection#onCallEvent(String, Bundle)}.
1033      */
testCallEvent()1034     public void testCallEvent() {
1035         if (!mShouldTestTelecom) {
1036             return;
1037         }
1038 
1039         Bundle testBundle = new Bundle();
1040         testBundle.putString(TEST_EXTRA_KEY, TEST_SUBJECT);
1041         final InvokeCounter counter = mConnection.getInvokeCounter(MockConnection.ON_CALL_EVENT);
1042         mCall.sendCallEvent(TEST_EVENT, testBundle);
1043         counter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
1044 
1045         String event = (String) (counter.getArgs(0)[0]);
1046         Bundle extras = (Bundle) (counter.getArgs(0)[1]);
1047 
1048         assertEquals(TEST_EVENT, event);
1049         assertNotNull(extras);
1050         assertTrue(extras.containsKey(TEST_EXTRA_KEY));
1051         assertEquals(TEST_SUBJECT, extras.getString(TEST_EXTRA_KEY));
1052 
1053         // Also send a more complicated Bundle as a Call Event
1054         TestParcelable testParcelable = createTestParcelable();
1055         testBundle = createTestBundle(testParcelable);
1056         mCall.sendCallEvent(OTT_TEST_EVENT_NAME, testBundle);
1057         counter.waitForCount(2, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
1058         event = (String) (counter.getArgs(1)[0]);
1059         extras = (Bundle) (counter.getArgs(1)[1]);
1060         assertEquals(OTT_TEST_EVENT_NAME, event);
1061         verifyTestBundle(extras, testParcelable);
1062     }
1063 
1064     /**
1065      * Verifies that the AudioManager audio mode changes as expected based on whether a connection
1066      * is using voip audio mode or not.
1067      */
testSetVoipAudioMode()1068     public void testSetVoipAudioMode() {
1069         if (!mShouldTestTelecom) {
1070             return;
1071         }
1072         mConnection.setAudioModeIsVoip(true);
1073         assertCallProperties(mCall, Call.Details.PROPERTY_VOIP_AUDIO_MODE);
1074         AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
1075         assertAudioMode(audioManager, AudioManager.MODE_IN_COMMUNICATION);
1076 
1077         mConnection.setAudioModeIsVoip(false);
1078         assertDoesNotHaveCallProperties(mCall, Call.Details.PROPERTY_VOIP_AUDIO_MODE);
1079         assertAudioMode(audioManager, AudioManager.MODE_IN_CALL);
1080     }
1081 
1082     /**
1083      * Tests whether the getCallDirection() getter returns correct call direction.
1084      */
testGetCallDirection()1085     public void testGetCallDirection() {
1086         if (!mShouldTestTelecom) {
1087             return;
1088         }
1089 
1090         assertEquals(Call.Details.DIRECTION_OUTGOING, mCall.getDetails().getCallDirection());
1091         assertFalse(Call.Details.DIRECTION_INCOMING == mCall.getDetails().getCallDirection());
1092         assertFalse(Call.Details.DIRECTION_UNKNOWN == mCall.getDetails().getCallDirection());
1093     }
1094 
1095     /**
1096      * Asserts that a call's extras contain a specified key.
1097      *
1098      * @param call The call.
1099      * @param expectedKey The expected extras key.
1100      */
assertCallExtras(final Call call, final String expectedKey)1101     private void assertCallExtras(final Call call, final String expectedKey) {
1102         waitUntilConditionIsTrueOrTimeout(
1103                 new Condition() {
1104                     @Override
1105                     public Object expected() {
1106                         return expectedKey;
1107                     }
1108 
1109                     @Override
1110                     public Object actual() {
1111                         return call.getDetails().getExtras().containsKey(expectedKey) ? expectedKey
1112                                 : "";
1113                     }
1114                 },
1115                 TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
1116                 "Call should have extras key " + expectedKey
1117         );
1118     }
1119 
1120     /**
1121      * Tests whether the CallLogManager logs the features of a call(HD call, Wifi call, VoLTE)
1122      * correctly.
1123      */
testLogFeatures()1124     public void testLogFeatures() throws Exception {
1125         if (!mShouldTestTelecom) {
1126             return;
1127         }
1128 
1129         // Register content observer on call log and get latch
1130         CountDownLatch callLogEntryLatch = getCallLogEntryLatch();
1131 
1132         Bundle testBundle = new Bundle();
1133         testBundle.putInt(TelecomManager.EXTRA_CALL_NETWORK_TYPE,
1134                           TelephonyManager.NETWORK_TYPE_LTE);
1135         mConnection.putExtras(testBundle);
1136         // Wait for the 2nd invocation; setExtras is called in the setup method.
1137         mOnExtrasChangedCounter.waitForCount(2, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
1138 
1139         Bundle extra = mCall.getDetails().getExtras();
1140 
1141         mCall.disconnect();
1142 
1143         // Wait on the call log latch.
1144         callLogEntryLatch.await(ASYNC_TIMEOUT, TimeUnit.MILLISECONDS);
1145 
1146         // Verify the contents of the call log
1147         Cursor callsCursor = mContext.getContentResolver().query(CallLog.Calls.CONTENT_URI, null,
1148                 null, null, "_id DESC");
1149         callsCursor.moveToFirst();
1150         int features = callsCursor.getInt(callsCursor.getColumnIndex("features"));
1151         assertEquals(CallLog.Calls.FEATURES_HD_CALL,
1152                 features & CallLog.Calls.FEATURES_HD_CALL);
1153         assertEquals(CallLog.Calls.FEATURES_WIFI, features & CallLog.Calls.FEATURES_WIFI);
1154         assertEquals(CallLog.Calls.FEATURES_VOLTE, features & CallLog.Calls.FEATURES_VOLTE);
1155     }
1156 
1157     /**
1158      * Verifies operation of the test telecom call ID system APIs.
1159      */
testTelecomCallId()1160     public void testTelecomCallId() {
1161         if (!mShouldTestTelecom) {
1162             return;
1163         }
1164         mConnection.setTelecomCallId("Hello");
1165         assertEquals("Hello", mConnection.getTelecomCallId());
1166     }
1167 
1168     /**
1169      * Verifies propagation of radio tech extra.
1170      */
testSetCallRadioTech()1171     public void testSetCallRadioTech() {
1172         if (!mShouldTestTelecom) {
1173             return;
1174         }
1175         Bundle radioTechExtras = new Bundle();
1176         radioTechExtras.putInt(TelecomManager.EXTRA_CALL_NETWORK_TYPE,
1177                 TelephonyManager.NETWORK_TYPE_LTE);
1178         mConnection.putExtras(radioTechExtras);
1179 
1180         assertCallExtras(mCall, TelecomManager.EXTRA_CALL_NETWORK_TYPE);
1181         assertEquals(TelephonyManager.NETWORK_TYPE_LTE,
1182                 mCall.getDetails().getExtras().getInt(TelecomManager.EXTRA_CALL_NETWORK_TYPE));
1183     }
1184 
1185     /**
1186      * Verifies resetting the connection time.
1187      */
testResetConnectionTime()1188     public void testResetConnectionTime() {
1189         if (!mShouldTestTelecom) {
1190             return;
1191         }
1192 
1193         long currentTime = mConnection.getConnectTimeMillis();
1194         mConnection.resetConnectionTime();
1195 
1196         // Make sure the connect time isn't the original value.
1197         assertCallConnectTimeChanged(mCall, currentTime);
1198     }
1199 
1200     /**
1201      * Verifies {@link Connection#notifyConferenceMergeFailed()} results in the
1202      * {@link Connection#EVENT_CALL_MERGE_FAILED} connection event being received by the telecom
1203      * call.
1204      */
testMergeFail()1205     public void testMergeFail() {
1206         if (!mShouldTestTelecom) {
1207             return;
1208         }
1209 
1210         mConnection.notifyConferenceMergeFailed();
1211 
1212         mOnConnectionEventCounter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
1213         String event = (String) (mOnConnectionEventCounter.getArgs(0)[1]);
1214         Bundle extras = (Bundle) (mOnConnectionEventCounter.getArgs(0)[2]);
1215 
1216         assertEquals(Connection.EVENT_CALL_MERGE_FAILED, event);
1217         assertNull(extras);
1218     }
1219 
1220     /**
1221      * Verifies {@link Connection#setPhoneAccountHandle(PhoneAccountHandle)} propagates to the
1222      * dialer app.
1223      */
testChangePhoneAccount()1224     public void testChangePhoneAccount() throws Exception {
1225         if (!mShouldTestTelecom) {
1226             return;
1227         }
1228         mConnection.setActive();
1229         assertCallState(mCall, Call.STATE_ACTIVE);
1230 
1231         mConnection.setPhoneAccountHandle(TEST_PHONE_ACCOUNT_HANDLE_2);
1232         assertEquals(TEST_PHONE_ACCOUNT_HANDLE_2, mConnection.getPhoneAccountHandle());
1233         mOnPhoneAccountChangedCounter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
1234         assertEquals(TEST_PHONE_ACCOUNT_HANDLE_2, mOnPhoneAccountChangedCounter.getArgs(0)[1]);
1235     }
1236 }
1237