| /* |
| * Copyright (C) 2015 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License |
| */ |
| |
| package android.telecom.cts; |
| |
| import static android.telecom.Connection.PROPERTY_HIGH_DEF_AUDIO; |
| import static android.telecom.Connection.PROPERTY_WIFI; |
| import static android.telecom.cts.TestUtils.*; |
| |
| import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity; |
| |
| import static org.hamcrest.CoreMatchers.instanceOf; |
| import static org.junit.Assert.assertNotEquals; |
| import static org.junit.Assert.assertThat; |
| |
| import android.content.Context; |
| import android.database.Cursor; |
| import android.graphics.drawable.Icon; |
| import android.location.Location; |
| import android.media.AudioManager; |
| import android.net.Uri; |
| import android.os.Bundle; |
| import android.os.ParcelUuid; |
| import android.provider.CallLog; |
| import android.telecom.Call; |
| import android.telecom.Connection; |
| import android.telecom.ConnectionRequest; |
| import android.telecom.DisconnectCause; |
| import android.telecom.GatewayInfo; |
| import android.telecom.PhoneAccount; |
| import android.telecom.PhoneAccountHandle; |
| import android.telecom.StatusHints; |
| import android.telecom.TelecomManager; |
| import android.telephony.TelephonyManager; |
| import android.text.TextUtils; |
| |
| import java.util.Arrays; |
| import java.util.List; |
| import java.util.concurrent.CountDownLatch; |
| import java.util.concurrent.TimeUnit; |
| |
| /** |
| * Suites of tests that verifies the various Call details. |
| */ |
| public class CallDetailsTest extends BaseTelecomTestWithMockServices { |
| |
| public static final int CONNECTION_PROPERTIES = PROPERTY_HIGH_DEF_AUDIO | PROPERTY_WIFI; |
| public static final int CONNECTION_CAPABILITIES = |
| Connection.CAPABILITY_HOLD | Connection.CAPABILITY_MUTE; |
| public static final int CALL_CAPABILITIES = |
| Call.Details.CAPABILITY_HOLD | Call.Details.CAPABILITY_MUTE; |
| public static final int CALL_PROPERTIES = |
| Call.Details.PROPERTY_HIGH_DEF_AUDIO | Call.Details.PROPERTY_WIFI; |
| public static final String CALLER_DISPLAY_NAME = "CTS test"; |
| public static final int CALLER_DISPLAY_NAME_PRESENTATION = TelecomManager.PRESENTATION_ALLOWED; |
| public static final String TEST_SUBJECT = "test"; |
| public static final String TEST_CHILD_NUMBER = "650-555-1212"; |
| public static final String TEST_FORWARDED_NUMBER = "650-555-1212"; |
| public static final String TEST_EXTRA_KEY = "android.test.extra.TEST"; |
| public static final String TEST_EXTRA_KEY2 = "android.test.extra.TEST2"; |
| public static final String TEST_EXTRA_KEY3 = "android.test.extra.TEST3"; |
| public static final float TEST_EXTRA_BITRATE = 23.85f ; |
| public static final float TEST_EXTRA_BANDWIDTH = 7.0f ; |
| public static final String TEST_INVALID_EXTRA_KEY = "blah"; |
| public static final int TEST_EXTRA_VALUE = 10; |
| public static final String TEST_EVENT = "com.test.event.TEST"; |
| public static final Uri TEST_DEFLECT_URI = Uri.fromParts("tel", "+16505551212", null); |
| private static final int ASYNC_TIMEOUT = 10000; |
| private StatusHints mStatusHints; |
| private Bundle mExtras = new Bundle(); |
| |
| private MockInCallService mInCallService; |
| private Call mCall; |
| private MockConnection mConnection; |
| |
| @Override |
| protected void setUp() throws Exception { |
| super.setUp(); |
| if (mShouldTestTelecom) { |
| PhoneAccount account = setupConnectionService( |
| new MockConnectionService() { |
| @Override |
| public Connection onCreateOutgoingConnection( |
| PhoneAccountHandle connectionManagerPhoneAccount, |
| ConnectionRequest request) { |
| Connection connection = super.onCreateOutgoingConnection( |
| connectionManagerPhoneAccount, |
| request); |
| mConnection = (MockConnection) connection; |
| // Modify the connection object created with local values. |
| connection.setConnectionCapabilities(CONNECTION_CAPABILITIES); |
| connection.setConnectionProperties(CONNECTION_PROPERTIES); |
| connection.setCallerDisplayName( |
| CALLER_DISPLAY_NAME, |
| CALLER_DISPLAY_NAME_PRESENTATION); |
| connection.setExtras(mExtras); |
| mStatusHints = new StatusHints( |
| "CTS test", |
| Icon.createWithResource( |
| getInstrumentation().getContext(), |
| R.drawable.ic_phone_24dp), |
| null); |
| connection.setStatusHints(mStatusHints); |
| lock.release(); |
| return connection; |
| } |
| }, FLAG_REGISTER | FLAG_ENABLE); |
| |
| // Make sure there is another phone account. |
| mTelecomManager.registerPhoneAccount(TestUtils.TEST_PHONE_ACCOUNT_2); |
| TestUtils.enablePhoneAccount( |
| getInstrumentation(), TestUtils.TEST_PHONE_ACCOUNT_HANDLE_2); |
| |
| /** Place a call as a part of the setup before we test the various |
| * Call details. |
| */ |
| placeAndVerifyCall(); |
| verifyConnectionForOutgoingCall(); |
| |
| mInCallService = mInCallCallbacks.getService(); |
| mCall = mInCallService.getLastCall(); |
| |
| assertCallState(mCall, Call.STATE_DIALING); |
| } |
| } |
| |
| /** |
| * Tests whether the getAccountHandle() getter returns the correct object. |
| */ |
| public void testAccountHandle() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| assertThat(mCall.getDetails().getAccountHandle(), instanceOf(PhoneAccountHandle.class)); |
| assertEquals(TEST_PHONE_ACCOUNT_HANDLE, mCall.getDetails().getAccountHandle()); |
| } |
| |
| /** |
| * Tests whether the getCallCapabilities() getter returns the correct object. |
| */ |
| public void testCallCapabilities() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| assertThat(mCall.getDetails().getCallCapabilities(), instanceOf(Integer.class)); |
| assertEquals(CALL_CAPABILITIES, mCall.getDetails().getCallCapabilities()); |
| assertTrue(mCall.getDetails().can(Call.Details.CAPABILITY_HOLD)); |
| assertTrue(mCall.getDetails().can(Call.Details.CAPABILITY_MUTE)); |
| assertFalse(mCall.getDetails().can(Call.Details.CAPABILITY_MANAGE_CONFERENCE)); |
| assertFalse(mCall.getDetails().can(Call.Details.CAPABILITY_RESPOND_VIA_TEXT)); |
| } |
| |
| /** |
| * Tests propagation of the local video capabilities from telephony through to in-call. |
| */ |
| public void testCallLocalVideoCapability() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| // Note: Local support for video is disabled when a call is in dialing state. |
| mConnection.setConnectionCapabilities( |
| Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL); |
| assertCallCapabilities(mCall, 0); |
| |
| mConnection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORTS_VT_LOCAL_RX); |
| assertCallCapabilities(mCall, 0); |
| |
| mConnection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORTS_VT_LOCAL_TX); |
| assertCallCapabilities(mCall, 0); |
| |
| mConnection.setConnectionCapabilities( |
| Connection.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL); |
| assertCallCapabilities(mCall, 0); |
| |
| mConnection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORTS_VT_REMOTE_RX); |
| assertCallCapabilities(mCall, 0); |
| |
| mConnection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORTS_VT_REMOTE_TX); |
| assertCallCapabilities(mCall, 0); |
| |
| // Set call active; we expect the capabilities to make it through now. |
| mConnection.setActive(); |
| |
| mConnection.setConnectionCapabilities( |
| Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL); |
| assertCallCapabilities(mCall, Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL); |
| |
| mConnection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORTS_VT_LOCAL_RX); |
| assertCallCapabilities(mCall, Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_RX); |
| |
| mConnection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORTS_VT_LOCAL_TX); |
| assertCallCapabilities(mCall, Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_TX); |
| |
| mConnection.setConnectionCapabilities( |
| Connection.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL); |
| assertCallCapabilities(mCall, Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL); |
| |
| mConnection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORTS_VT_REMOTE_RX); |
| assertCallCapabilities(mCall, Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_RX); |
| |
| mConnection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORTS_VT_REMOTE_TX); |
| assertCallCapabilities(mCall, Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_TX); |
| } |
| |
| /** |
| * Tests passing call capabilities from Connections to Calls. |
| */ |
| public void testCallCapabilityPropagation() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| mConnection.setConnectionCapabilities(Connection.CAPABILITY_CAN_PAUSE_VIDEO); |
| assertCallCapabilities(mCall, Call.Details.CAPABILITY_CAN_PAUSE_VIDEO); |
| |
| mConnection.setConnectionCapabilities(Connection.CAPABILITY_HOLD); |
| assertCallCapabilities(mCall, Call.Details.CAPABILITY_HOLD); |
| |
| mConnection.setConnectionCapabilities(Connection.CAPABILITY_MANAGE_CONFERENCE); |
| assertCallCapabilities(mCall, Call.Details.CAPABILITY_MANAGE_CONFERENCE); |
| |
| mConnection.setConnectionCapabilities(Connection.CAPABILITY_MERGE_CONFERENCE); |
| assertCallCapabilities(mCall, Call.Details.CAPABILITY_MERGE_CONFERENCE); |
| |
| mConnection.setConnectionCapabilities(Connection.CAPABILITY_MUTE); |
| assertCallCapabilities(mCall, Call.Details.CAPABILITY_MUTE); |
| |
| mConnection.setConnectionCapabilities(Connection.CAPABILITY_RESPOND_VIA_TEXT); |
| assertCallCapabilities(mCall, Call.Details.CAPABILITY_RESPOND_VIA_TEXT); |
| |
| mConnection.setConnectionCapabilities(Connection.CAPABILITY_SEPARATE_FROM_CONFERENCE); |
| assertCallCapabilities(mCall, Call.Details.CAPABILITY_SEPARATE_FROM_CONFERENCE); |
| |
| mConnection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORT_HOLD); |
| assertCallCapabilities(mCall, Call.Details.CAPABILITY_SUPPORT_HOLD); |
| |
| mConnection.setConnectionCapabilities(Connection.CAPABILITY_SWAP_CONFERENCE); |
| assertCallCapabilities(mCall, Call.Details.CAPABILITY_SWAP_CONFERENCE); |
| } |
| |
| /** |
| * Tests passing call properties from Connections to Calls. |
| */ |
| public void testCallPropertyPropagation() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| mConnection.setConnectionProperties(Connection.PROPERTY_EMERGENCY_CALLBACK_MODE); |
| assertCallProperties(mCall, Call.Details.PROPERTY_EMERGENCY_CALLBACK_MODE); |
| |
| mConnection.setConnectionProperties(Connection.PROPERTY_GENERIC_CONFERENCE); |
| assertCallProperties(mCall, Call.Details.PROPERTY_GENERIC_CONFERENCE); |
| |
| mConnection.setConnectionProperties(Connection.PROPERTY_HIGH_DEF_AUDIO); |
| assertCallProperties(mCall, Call.Details.PROPERTY_HIGH_DEF_AUDIO); |
| |
| mConnection.setConnectionProperties(Connection.PROPERTY_WIFI); |
| assertCallProperties(mCall, Call.Details.PROPERTY_WIFI); |
| |
| mConnection.setConnectionProperties(Connection.PROPERTY_IS_EXTERNAL_CALL); |
| assertCallProperties(mCall, Call.Details.PROPERTY_IS_EXTERNAL_CALL); |
| |
| mConnection.setConnectionProperties(Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY); |
| assertCallProperties(mCall, Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY); |
| |
| mConnection.setConnectionProperties(Connection.PROPERTY_IS_DOWNGRADED_CONFERENCE); |
| // Not propagated |
| assertCallProperties(mCall, 0); |
| |
| mConnection.setConnectionProperties(Connection.PROPERTY_IS_RTT); |
| assertCallProperties(mCall, Call.Details.PROPERTY_RTT); |
| |
| mConnection.setConnectionProperties(Connection.PROPERTY_ASSISTED_DIALING); |
| assertCallProperties(mCall, Call.Details.PROPERTY_ASSISTED_DIALING); |
| |
| mConnection.setConnectionProperties(Connection.PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL); |
| assertCallProperties(mCall, Call.Details.PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL); |
| |
| mConnection.setConnectionProperties(Connection.PROPERTY_REMOTELY_HOSTED); |
| // Not propagated |
| assertCallProperties(mCall, 0); |
| |
| mConnection.setConnectionProperties(Connection.PROPERTY_CROSS_SIM); |
| assertCallProperties(mCall, Call.Details.PROPERTY_CROSS_SIM); |
| } |
| |
| /** |
| * Tests whether the getCallerDisplayName() getter returns the correct object. |
| */ |
| public void testCallerDisplayName() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| assertThat(mCall.getDetails().getCallerDisplayName(), instanceOf(String.class)); |
| assertEquals(CALLER_DISPLAY_NAME, mCall.getDetails().getCallerDisplayName()); |
| } |
| |
| /** |
| * Tests whether the getCallerDisplayNamePresentation() getter returns the correct object. |
| */ |
| public void testCallerDisplayNamePresentation() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| assertThat(mCall.getDetails().getCallerDisplayNamePresentation(), instanceOf(Integer.class)); |
| assertEquals(CALLER_DISPLAY_NAME_PRESENTATION, mCall.getDetails().getCallerDisplayNamePresentation()); |
| } |
| |
| /** |
| * Test the contacts display name. We don't have anything set up in contacts, so expect it to |
| * be null |
| */ |
| public void testContactDisplayName() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| assertTrue(TextUtils.isEmpty(mCall.getDetails().getContactDisplayName())); |
| } |
| |
| /** |
| * Tests whether the getCallProperties() getter returns the correct object. |
| */ |
| public void testCallProperties() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| assertThat(mCall.getDetails().getCallProperties(), instanceOf(Integer.class)); |
| |
| assertEquals(CALL_PROPERTIES, mCall.getDetails().getCallProperties()); |
| } |
| |
| /** |
| * Tests whether the getConnectTimeMillis() getter returns the correct object. |
| */ |
| public void testConnectTimeMillis() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| assertThat(mCall.getDetails().getConnectTimeMillis(), instanceOf(Long.class)); |
| } |
| |
| /** |
| * Tests whether the getCreationTimeMillis() getter returns the correct object. |
| */ |
| public void testCreationTimeMillis() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| assertThat(mCall.getDetails().getCreationTimeMillis(), instanceOf(Long.class)); |
| } |
| |
| /** |
| * Tests whether the getDisconnectCause() getter returns the correct object. |
| */ |
| public void testDisconnectCause() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| assertThat(mCall.getDetails().getDisconnectCause(), instanceOf(DisconnectCause.class)); |
| } |
| |
| /** |
| * Tests whether the getExtras() getter returns the correct object. |
| */ |
| public void testExtras() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| if (mCall.getDetails().getExtras() != null) { |
| assertThat(mCall.getDetails().getExtras(), instanceOf(Bundle.class)); |
| } |
| } |
| |
| /** |
| * Tests whether the getIntentExtras() getter returns the correct object. |
| */ |
| public void testIntentExtras() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| assertThat(mCall.getDetails().getIntentExtras(), instanceOf(Bundle.class)); |
| } |
| |
| /** |
| * Tests whether the getGatewayInfo() getter returns the correct object. |
| */ |
| public void testGatewayInfo() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| if (mCall.getDetails().getGatewayInfo() != null) { |
| assertThat(mCall.getDetails().getGatewayInfo(), instanceOf(GatewayInfo.class)); |
| } |
| } |
| |
| /** |
| * Tests whether the getHandle() getter returns the correct object. |
| */ |
| public void testHandle() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| assertThat(mCall.getDetails().getHandle(), instanceOf(Uri.class)); |
| assertEquals(getTestNumber(), mCall.getDetails().getHandle()); |
| } |
| |
| /** |
| * Tests whether the getHandlePresentation() getter returns the correct object. |
| */ |
| public void testHandlePresentation() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| assertThat(mCall.getDetails().getHandlePresentation(), instanceOf(Integer.class)); |
| assertEquals(MockConnectionService.CONNECTION_PRESENTATION, mCall.getDetails().getHandlePresentation()); |
| } |
| |
| /** |
| * Tests whether the getStatusHints() getter returns the correct object. |
| */ |
| public void testStatusHints() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| assertThat(mCall.getDetails().getStatusHints(), instanceOf(StatusHints.class)); |
| assertEquals(mStatusHints.getLabel(), mCall.getDetails().getStatusHints().getLabel()); |
| assertEquals( |
| mStatusHints.getIcon().toString(), |
| mCall.getDetails().getStatusHints().getIcon().toString()); |
| assertEquals(mStatusHints.getExtras(), mCall.getDetails().getStatusHints().getExtras()); |
| } |
| |
| /** |
| * Tests whether the getVideoState() getter returns the correct object. |
| */ |
| public void testVideoState() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| assertThat(mCall.getDetails().getVideoState(), instanceOf(Integer.class)); |
| } |
| |
| /** |
| * Tests communication of {@link Connection#setExtras(Bundle)} through to |
| * {@link Call.Details#getExtras()}. |
| */ |
| public void testExtrasPropagation() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| Bundle exampleExtras = new Bundle(); |
| exampleExtras.putString(Connection.EXTRA_CALL_SUBJECT, TEST_SUBJECT); |
| |
| // EXTRA_PRIORITY |
| exampleExtras.putInt(TelecomManager.EXTRA_PRIORITY, TelecomManager.PRIORITY_URGENT); |
| |
| // EXTRA_CALL_LOCATION |
| Location testLocation = new Location("CallDetailsTest"); |
| double latitude = 123; |
| double longitude = 456; |
| testLocation.setLatitude(latitude); |
| testLocation.setLongitude(longitude); |
| exampleExtras.putParcelable(TelecomManager.EXTRA_LOCATION, testLocation); |
| |
| // EXTRA_HAS_PICTURE |
| exampleExtras.putBoolean(TelecomManager.EXTRA_HAS_PICTURE, true); |
| |
| // EXTRA_INCOMING_PICTURE |
| Uri testIncomingPictureUrl = Uri.parse("content://carrier.xyz/picture1"); |
| exampleExtras.putParcelable(TelecomManager.EXTRA_PICTURE_URI, testIncomingPictureUrl); |
| |
| // EXTRA_OUTGOING_PICTURE |
| ParcelUuid testOutgoingPicture = ParcelUuid.fromString("11111111-2222-3333-4444-55555555"); |
| exampleExtras.putParcelable(TelecomManager.EXTRA_OUTGOING_PICTURE, testOutgoingPicture); |
| |
| exampleExtras.putString(Connection.EXTRA_CHILD_ADDRESS, TEST_CHILD_NUMBER); |
| exampleExtras.putString(Connection.EXTRA_LAST_FORWARDED_NUMBER, TEST_FORWARDED_NUMBER); |
| exampleExtras.putInt(TEST_EXTRA_KEY, TEST_EXTRA_VALUE); |
| exampleExtras.putInt(Connection.EXTRA_AUDIO_CODEC, Connection.AUDIO_CODEC_AMR); |
| exampleExtras.putFloat(Connection.EXTRA_AUDIO_CODEC_BITRATE_KBPS, TEST_EXTRA_BITRATE); |
| exampleExtras.putFloat(Connection.EXTRA_AUDIO_CODEC_BANDWIDTH_KHZ, TEST_EXTRA_BANDWIDTH); |
| mConnection.setExtras(exampleExtras); |
| |
| // Make sure we got back a bundle with the call subject key set. |
| assertCallExtras(mCall, Connection.EXTRA_CALL_SUBJECT); |
| |
| Bundle callExtras = mCall.getDetails().getExtras(); |
| assertEquals(TEST_SUBJECT, callExtras.getString(Connection.EXTRA_CALL_SUBJECT)); |
| assertEquals(TEST_CHILD_NUMBER, callExtras.getString(Connection.EXTRA_CHILD_ADDRESS)); |
| assertEquals(TEST_FORWARDED_NUMBER, |
| callExtras.getString(Connection.EXTRA_LAST_FORWARDED_NUMBER)); |
| assertEquals(TEST_EXTRA_VALUE, callExtras.getInt(TEST_EXTRA_KEY)); |
| assertEquals(Connection.AUDIO_CODEC_AMR, |
| callExtras.getInt(Connection.EXTRA_AUDIO_CODEC)); |
| assertEquals(TEST_EXTRA_BITRATE, |
| callExtras.getFloat(Connection.EXTRA_AUDIO_CODEC_BITRATE_KBPS), 0.01); |
| assertEquals(TEST_EXTRA_BANDWIDTH, |
| callExtras.getFloat(Connection.EXTRA_AUDIO_CODEC_BANDWIDTH_KHZ), 0.01); |
| |
| assertEquals(TelecomManager.PRIORITY_URGENT, exampleExtras.getInt( |
| TelecomManager.EXTRA_PRIORITY)); |
| Location testGetLocation = exampleExtras.getParcelable(TelecomManager.EXTRA_LOCATION); |
| assertEquals(latitude, testGetLocation.getLatitude(), 0); |
| assertEquals(longitude, testGetLocation.getLongitude(), 0); |
| assertEquals(true, exampleExtras.getBoolean(TelecomManager.EXTRA_HAS_PICTURE)); |
| assertEquals(testIncomingPictureUrl, |
| exampleExtras.getParcelable(TelecomManager.EXTRA_PICTURE_URI)); |
| assertEquals(testOutgoingPicture, |
| exampleExtras.getParcelable(TelecomManager.EXTRA_OUTGOING_PICTURE)); |
| } |
| |
| /** |
| * Tests that extra keys outside of the standard android.* namespace are not sent to a third |
| * party InCallService (the CTS test InCallService is technically not the OEM stock dialer). |
| */ |
| public void testExtrasBlocking() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| Bundle exampleExtras = new Bundle(); |
| exampleExtras.putString(Connection.EXTRA_CALL_SUBJECT, TEST_SUBJECT); |
| exampleExtras.putString(TEST_INVALID_EXTRA_KEY, "Secrets!"); |
| exampleExtras.putString(Connection.EXTRA_SIP_INVITE, "Sip headers!!"); |
| // Some ImsCallProfile system API extra keys we don't want to exposure to non-system |
| // dialer apps; its a bit of an implementation detail but good to verify that these are |
| // never exposed unintentionally. |
| exampleExtras.putString("oi", "5551212"); |
| exampleExtras.putString("cna", "Joe"); |
| exampleExtras.putInt("oir", TelecomManager.PRESENTATION_ALLOWED); |
| exampleExtras.putInt("cnap", TelecomManager.PRESENTATION_ALLOWED); |
| |
| mConnection.setExtras(exampleExtras); |
| |
| // Make sure we got back a bundle with the call subject key set. |
| assertCallExtras(mCall, Connection.EXTRA_CALL_SUBJECT); |
| |
| Bundle callExtras = mCall.getDetails().getExtras(); |
| assertEquals(TEST_SUBJECT, callExtras.getString(Connection.EXTRA_CALL_SUBJECT)); |
| assertFalse(callExtras.containsKey(TEST_INVALID_EXTRA_KEY)); |
| assertFalse(callExtras.containsKey(Connection.EXTRA_SIP_INVITE)); |
| // Some ImsCallProfile extra keys that should not be exposed to non-system dialers. |
| assertFalse(callExtras.containsKey("oi")); |
| assertFalse(callExtras.containsKey("cna")); |
| assertFalse(callExtras.containsKey("oir")); |
| assertFalse(callExtras.containsKey("cnap")); |
| } |
| |
| /** |
| * Tests that {@link Connection} extras changes made via {@link Connection#putExtras(Bundle)} |
| * are propagated to the {@link Call} via |
| * {@link android.telecom.Call.Callback#onDetailsChanged(Call, Call.Details)}. |
| */ |
| public void testConnectionPutExtras() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| Bundle testBundle = new Bundle(); |
| testBundle.putString(TEST_EXTRA_KEY, TEST_SUBJECT); |
| testBundle.putInt(TEST_EXTRA_KEY2, TEST_EXTRA_VALUE); |
| testBundle.putBoolean(Connection.EXTRA_DISABLE_ADD_CALL, true); |
| mConnection.putExtras(testBundle); |
| // Wait for the 3rd invocation; setExtras is called in the setup method. |
| mOnExtrasChangedCounter.waitForCount(3, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS); |
| |
| Bundle extras = mCall.getDetails().getExtras(); |
| assertTrue(extras.containsKey(TEST_EXTRA_KEY)); |
| assertEquals(TEST_SUBJECT, extras.getString(TEST_EXTRA_KEY)); |
| assertTrue(extras.containsKey(TEST_EXTRA_KEY2)); |
| assertEquals(TEST_EXTRA_VALUE, extras.getInt(TEST_EXTRA_KEY2)); |
| assertTrue(extras.getBoolean(Connection.EXTRA_DISABLE_ADD_CALL)); |
| } |
| |
| public void testConnectionHoldTone() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| // These tests are admittedly lame; the events are absorbed in telecom and start a tone and |
| // stop it. There is no other signal that the tone is starting/stopping otherwise. |
| mConnection.sendConnectionEvent(Connection.EVENT_ON_HOLD_TONE_START, null); |
| mConnection.sendConnectionEvent(Connection.EVENT_ON_HOLD_TONE_END, null); |
| } |
| |
| /** |
| * Tests that {@link Connection} extras changes made via {@link Connection#removeExtras(List)} |
| * are propagated to the {@link Call} via |
| * {@link android.telecom.Call.Callback#onDetailsChanged(Call, Call.Details)}. |
| */ |
| public void testConnectionRemoveExtras() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| testConnectionPutExtras(); |
| |
| mConnection.removeExtras(Arrays.asList(TEST_EXTRA_KEY)); |
| verifyRemoveConnectionExtras(); |
| } |
| |
| /** |
| * Tests that {@link Connection} extras changes made via {@link Connection#removeExtras(List)} |
| * are propagated to the {@link Call} via |
| * {@link android.telecom.Call.Callback#onDetailsChanged(Call, Call.Details)}. |
| */ |
| public void testConnectionRemoveExtras2() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| testConnectionPutExtras(); |
| |
| mConnection.removeExtras(TEST_EXTRA_KEY); |
| // testConnectionPutExtra will have waited for the 3rd invocation, so wait for the 4th here. |
| verifyRemoveConnectionExtras(); |
| } |
| |
| private void verifyRemoveConnectionExtras() { |
| // testConnectionPutExtra will have waited for the 3rd invocation, so wait for the 4th here. |
| mOnExtrasChangedCounter.waitForCount(4, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS); |
| |
| Bundle extras = mCall.getDetails().getExtras(); |
| assertFalse(extras.containsKey(TEST_EXTRA_KEY)); |
| assertTrue(extras.containsKey(TEST_EXTRA_KEY2)); |
| assertEquals(TEST_EXTRA_VALUE, extras.getInt(TEST_EXTRA_KEY2)); |
| } |
| |
| /** |
| * Tests that {@link Call} extras changes made via {@link Call#putExtras(Bundle)} are propagated |
| * to {@link Connection#onExtrasChanged(Bundle)}. |
| */ |
| public void testCallPutExtras() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| Bundle testBundle = new Bundle(); |
| testBundle.putString(TEST_EXTRA_KEY, TEST_SUBJECT); |
| final InvokeCounter counter = mConnection.getInvokeCounter( |
| MockConnection.ON_EXTRAS_CHANGED); |
| mCall.putExtras(testBundle); |
| counter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS); |
| Bundle extras = mConnection.getExtras(); |
| |
| assertNotNull(extras); |
| assertTrue(extras.containsKey(TEST_EXTRA_KEY)); |
| assertEquals(TEST_SUBJECT, extras.getString(TEST_EXTRA_KEY)); |
| } |
| |
| /** |
| * Tests that {@link Call} extra operations using {@link Call#removeExtras(List)} are propagated |
| * to the {@link Connection} via {@link Connection#onExtrasChanged(Bundle)}. |
| * |
| * This test specifically tests addition and removal of extras values. |
| */ |
| public void testCallRemoveExtras() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| final InvokeCounter counter = setupCallExtras(); |
| Bundle extras; |
| |
| mCall.removeExtras(Arrays.asList(TEST_EXTRA_KEY)); |
| counter.waitForCount(2, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS); |
| extras = mConnection.getExtras(); |
| assertNotNull(extras); |
| assertFalse(extras.containsKey(TEST_EXTRA_KEY)); |
| assertTrue(extras.containsKey(TEST_EXTRA_KEY2)); |
| assertEquals(TEST_EXTRA_VALUE, extras.getInt(TEST_EXTRA_KEY2)); |
| assertTrue(extras.containsKey(TEST_EXTRA_KEY3)); |
| assertEquals(TEST_SUBJECT, extras.getString(TEST_EXTRA_KEY3)); |
| |
| mCall.removeExtras(Arrays.asList(TEST_EXTRA_KEY2, TEST_EXTRA_KEY3)); |
| counter.waitForCount(3, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS); |
| extras = mConnection.getExtras(); |
| assertFalse(extras.containsKey(TEST_EXTRA_KEY2)); |
| assertFalse(extras.containsKey(TEST_EXTRA_KEY3)); |
| } |
| |
| /** |
| * Tests that {@link Call} extra operations using {@link Call#removeExtras(String[])} are |
| * propagated to the {@link Connection} via {@link Connection#onExtrasChanged(Bundle)}. |
| * |
| * This test specifically tests addition and removal of extras values. |
| */ |
| public void testCallRemoveExtras2() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| final InvokeCounter counter = setupCallExtras(); |
| Bundle extras; |
| |
| mCall.removeExtras(TEST_EXTRA_KEY); |
| counter.waitForCount(2, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS); |
| extras = mConnection.getExtras(); |
| assertNotNull(extras); |
| assertFalse(extras.containsKey(TEST_EXTRA_KEY)); |
| assertTrue(extras.containsKey(TEST_EXTRA_KEY2)); |
| assertEquals(TEST_EXTRA_VALUE, extras.getInt(TEST_EXTRA_KEY2)); |
| assertTrue(extras.containsKey(TEST_EXTRA_KEY3)); |
| assertEquals(TEST_SUBJECT, extras.getString(TEST_EXTRA_KEY3)); |
| } |
| |
| private InvokeCounter setupCallExtras() { |
| Bundle testBundle = new Bundle(); |
| testBundle.putString(TEST_EXTRA_KEY, TEST_SUBJECT); |
| testBundle.putInt(TEST_EXTRA_KEY2, TEST_EXTRA_VALUE); |
| testBundle.putString(TEST_EXTRA_KEY3, TEST_SUBJECT); |
| final InvokeCounter counter = mConnection.getInvokeCounter( |
| MockConnection.ON_EXTRAS_CHANGED); |
| mCall.putExtras(testBundle); |
| counter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS); |
| Bundle extras = mConnection.getExtras(); |
| |
| assertNotNull(extras); |
| assertTrue(extras.containsKey(TEST_EXTRA_KEY)); |
| assertEquals(TEST_SUBJECT, extras.getString(TEST_EXTRA_KEY)); |
| assertTrue(extras.containsKey(TEST_EXTRA_KEY2)); |
| assertEquals(TEST_EXTRA_VALUE, extras.getInt(TEST_EXTRA_KEY2)); |
| assertTrue(extras.containsKey(TEST_EXTRA_KEY3)); |
| assertEquals(TEST_SUBJECT, extras.getString(TEST_EXTRA_KEY3)); |
| return counter; |
| } |
| |
| /** |
| * Tests that {@link Connection} events are propagated from |
| * {@link Connection#sendConnectionEvent(String, Bundle)} to |
| * {@link android.telecom.Call.Callback#onConnectionEvent(Call, String, Bundle)}. |
| */ |
| public void testConnectionEvent() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| Bundle testBundle = new Bundle(); |
| testBundle.putString(TEST_EXTRA_KEY, TEST_SUBJECT); |
| |
| mConnection.sendConnectionEvent(Connection.EVENT_CALL_PULL_FAILED, testBundle); |
| mOnConnectionEventCounter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS); |
| String event = (String) (mOnConnectionEventCounter.getArgs(0)[1]); |
| Bundle extras = (Bundle) (mOnConnectionEventCounter.getArgs(0)[2]); |
| |
| assertEquals(Connection.EVENT_CALL_PULL_FAILED, event); |
| assertNotNull(extras); |
| assertTrue(extras.containsKey(TEST_EXTRA_KEY)); |
| assertEquals(TEST_SUBJECT, extras.getString(TEST_EXTRA_KEY)); |
| mOnConnectionEventCounter.reset(); |
| |
| mConnection.sendConnectionEvent(Connection.EVENT_CALL_HOLD_FAILED, null); |
| // Don't expect this to make it through; used internally in Telecom. |
| |
| mConnection.sendConnectionEvent(Connection.EVENT_MERGE_START, null); |
| mOnConnectionEventCounter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS); |
| event = (String) (mOnConnectionEventCounter.getArgs(0)[1]); |
| extras = (Bundle) (mOnConnectionEventCounter.getArgs(0)[2]); |
| assertEquals(Connection.EVENT_MERGE_START, event); |
| assertNull(extras); |
| mOnConnectionEventCounter.reset(); |
| |
| mConnection.sendConnectionEvent(Connection.EVENT_MERGE_COMPLETE, null); |
| mOnConnectionEventCounter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS); |
| event = (String) (mOnConnectionEventCounter.getArgs(0)[1]); |
| extras = (Bundle) (mOnConnectionEventCounter.getArgs(0)[2]); |
| assertEquals(Connection.EVENT_MERGE_COMPLETE, event); |
| assertNull(extras); |
| mOnConnectionEventCounter.reset(); |
| |
| mConnection.sendConnectionEvent(Connection.EVENT_CALL_REMOTELY_HELD, null); |
| mOnConnectionEventCounter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS); |
| event = (String) (mOnConnectionEventCounter.getArgs(0)[1]); |
| extras = (Bundle) (mOnConnectionEventCounter.getArgs(0)[2]); |
| assertEquals(Connection.EVENT_CALL_REMOTELY_HELD, event); |
| assertNull(extras); |
| mOnConnectionEventCounter.reset(); |
| |
| mConnection.sendConnectionEvent(Connection.EVENT_CALL_REMOTELY_UNHELD, null); |
| mOnConnectionEventCounter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS); |
| event = (String) (mOnConnectionEventCounter.getArgs(0)[1]); |
| extras = (Bundle) (mOnConnectionEventCounter.getArgs(0)[2]); |
| assertEquals(Connection.EVENT_CALL_REMOTELY_UNHELD, event); |
| assertNull(extras); |
| mOnConnectionEventCounter.reset(); |
| } |
| |
| /** |
| * Verifies that a request to deflect a ringing {@link Call} is relayed to a {@link Connection}. |
| */ |
| public void testDeflect() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| // Only ringing calls support deflection |
| mConnection.setRinging(); |
| assertCallState(mCall, Call.STATE_RINGING); |
| |
| final InvokeCounter counter = mConnection.getInvokeCounter(MockConnection.ON_DEFLECT); |
| mCall.deflect(TEST_DEFLECT_URI); |
| counter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS); |
| Uri address = (Uri) (counter.getArgs(0)[0]); |
| |
| assertEquals(TEST_DEFLECT_URI, address); |
| } |
| |
| /** |
| * Tests that {@link Call} events are propagated from {@link Call#sendCallEvent(String, Bundle)} |
| * to {@link Connection#onCallEvent(String, Bundle)}. |
| */ |
| public void testCallEvent() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| Bundle testBundle = new Bundle(); |
| testBundle.putString(TEST_EXTRA_KEY, TEST_SUBJECT); |
| final InvokeCounter counter = mConnection.getInvokeCounter(MockConnection.ON_CALL_EVENT); |
| mCall.sendCallEvent(TEST_EVENT, testBundle); |
| counter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS); |
| |
| String event = (String) (counter.getArgs(0)[0]); |
| Bundle extras = (Bundle) (counter.getArgs(0)[1]); |
| |
| assertEquals(TEST_EVENT, event); |
| assertNotNull(extras); |
| assertTrue(extras.containsKey(TEST_EXTRA_KEY)); |
| assertEquals(TEST_SUBJECT, extras.getString(TEST_EXTRA_KEY)); |
| } |
| |
| /** |
| * Verifies that the AudioManager audio mode changes as expected based on whether a connection |
| * is using voip audio mode or not. |
| */ |
| public void testSetVoipAudioMode() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| mConnection.setAudioModeIsVoip(true); |
| assertCallProperties(mCall, Call.Details.PROPERTY_VOIP_AUDIO_MODE); |
| AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); |
| assertAudioMode(audioManager, AudioManager.MODE_IN_COMMUNICATION); |
| |
| mConnection.setAudioModeIsVoip(false); |
| assertDoesNotHaveCallProperties(mCall, Call.Details.PROPERTY_VOIP_AUDIO_MODE); |
| assertAudioMode(audioManager, AudioManager.MODE_IN_CALL); |
| } |
| |
| /** |
| * Tests whether the getCallDirection() getter returns correct call direction. |
| */ |
| public void testGetCallDirection() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| assertEquals(Call.Details.DIRECTION_OUTGOING, mCall.getDetails().getCallDirection()); |
| assertFalse(Call.Details.DIRECTION_INCOMING == mCall.getDetails().getCallDirection()); |
| assertFalse(Call.Details.DIRECTION_UNKNOWN == mCall.getDetails().getCallDirection()); |
| } |
| |
| /** |
| * Asserts that a call's extras contain a specified key. |
| * |
| * @param call The call. |
| * @param expectedKey The expected extras key. |
| */ |
| private void assertCallExtras(final Call call, final String expectedKey) { |
| waitUntilConditionIsTrueOrTimeout( |
| new Condition() { |
| @Override |
| public Object expected() { |
| return expectedKey; |
| } |
| |
| @Override |
| public Object actual() { |
| return call.getDetails().getExtras().containsKey(expectedKey) ? expectedKey |
| : ""; |
| } |
| }, |
| TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS, |
| "Call should have extras key " + expectedKey |
| ); |
| } |
| |
| /** |
| * Tests whether the CallLogManager logs the features of a call(HD call, Wifi call, VoLTE) |
| * correctly. |
| */ |
| public void testLogFeatures() throws Exception { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| // Register content observer on call log and get latch |
| CountDownLatch callLogEntryLatch = getCallLogEntryLatch(); |
| |
| Bundle testBundle = new Bundle(); |
| testBundle.putInt(TelecomManager.EXTRA_CALL_NETWORK_TYPE, |
| TelephonyManager.NETWORK_TYPE_LTE); |
| mConnection.putExtras(testBundle); |
| // Wait for the 2nd invocation; setExtras is called in the setup method. |
| mOnExtrasChangedCounter.waitForCount(2, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS); |
| |
| Bundle extra = mCall.getDetails().getExtras(); |
| |
| mCall.disconnect(); |
| |
| // Wait on the call log latch. |
| callLogEntryLatch.await(ASYNC_TIMEOUT, TimeUnit.MILLISECONDS); |
| |
| // Verify the contents of the call log |
| Cursor callsCursor = mContext.getContentResolver().query(CallLog.Calls.CONTENT_URI, null, |
| null, null, "_id DESC"); |
| callsCursor.moveToFirst(); |
| int features = callsCursor.getInt(callsCursor.getColumnIndex("features")); |
| assertEquals(CallLog.Calls.FEATURES_HD_CALL, |
| features & CallLog.Calls.FEATURES_HD_CALL); |
| assertEquals(CallLog.Calls.FEATURES_WIFI, features & CallLog.Calls.FEATURES_WIFI); |
| assertEquals(CallLog.Calls.FEATURES_VOLTE, features & CallLog.Calls.FEATURES_VOLTE); |
| } |
| |
| /** |
| * Verifies operation of the test telecom call ID system APIs. |
| */ |
| public void testTelecomCallId() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| mConnection.setTelecomCallId("Hello"); |
| assertEquals("Hello", mConnection.getTelecomCallId()); |
| } |
| |
| /** |
| * Verifies propagation of radio tech extra. |
| */ |
| public void testSetCallRadioTech() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| Bundle radioTechExtras = new Bundle(); |
| radioTechExtras.putInt(TelecomManager.EXTRA_CALL_NETWORK_TYPE, |
| TelephonyManager.NETWORK_TYPE_LTE); |
| mConnection.putExtras(radioTechExtras); |
| |
| assertCallExtras(mCall, TelecomManager.EXTRA_CALL_NETWORK_TYPE); |
| assertEquals(TelephonyManager.NETWORK_TYPE_LTE, |
| mCall.getDetails().getExtras().getInt(TelecomManager.EXTRA_CALL_NETWORK_TYPE)); |
| } |
| |
| /** |
| * Verifies resetting the connection time. |
| */ |
| public void testResetConnectionTime() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| long currentTime = mConnection.getConnectTimeMillis(); |
| mConnection.resetConnectionTime(); |
| |
| // Make sure the connect time isn't the original value. |
| assertCallConnectTimeChanged(mCall, currentTime); |
| } |
| |
| /** |
| * Verifies {@link Connection#notifyConferenceMergeFailed()} results in the |
| * {@link Connection#EVENT_CALL_MERGE_FAILED} connection event being received by the telecom |
| * call. |
| */ |
| public void testMergeFail() { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| |
| mConnection.notifyConferenceMergeFailed(); |
| |
| mOnConnectionEventCounter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS); |
| String event = (String) (mOnConnectionEventCounter.getArgs(0)[1]); |
| Bundle extras = (Bundle) (mOnConnectionEventCounter.getArgs(0)[2]); |
| |
| assertEquals(Connection.EVENT_CALL_MERGE_FAILED, event); |
| assertNull(extras); |
| } |
| |
| /** |
| * Verifies {@link Connection#setPhoneAccountHandle(PhoneAccountHandle)} propagates to the |
| * dialer app. |
| */ |
| public void testChangePhoneAccount() throws Exception { |
| if (!mShouldTestTelecom) { |
| return; |
| } |
| mConnection.setActive(); |
| assertCallState(mCall, Call.STATE_ACTIVE); |
| |
| mConnection.setPhoneAccountHandle(TEST_PHONE_ACCOUNT_HANDLE_2); |
| assertEquals(TEST_PHONE_ACCOUNT_HANDLE_2, mConnection.getPhoneAccountHandle()); |
| mOnPhoneAccountChangedCounter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS); |
| assertEquals(TEST_PHONE_ACCOUNT_HANDLE_2, mOnPhoneAccountChangedCounter.getArgs(0)[1]); |
| } |
| } |