blob: 5a125ebdb6c7c4c59f1dd6b6946afc7ae6f9ee8d [file] [log] [blame]
/*
* Copyright (C) 2021 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.telephony.ims.cts;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import android.annotation.NonNull;
import android.app.UiAutomation;
import android.content.Context;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
import android.telecom.Call;
import android.telecom.PhoneAccount;
import android.telecom.TelecomManager;
import android.telephony.AccessNetworkConstants;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager;
import android.telephony.cts.InCallServiceStateValidator;
import android.telephony.ims.ImsCallSessionListener;
import android.telephony.ims.MediaQualityStatus;
import android.telephony.ims.feature.MmTelFeature;
import android.util.Log;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
/**
* CTS tests for ImsCall .
*/
@RunWith(AndroidJUnit4.class)
public class ImsCallingTest extends ImsCallingBase {
protected static final String LOG_TAG = "CtsImsCallingTest";
private Call mCall1 = null;
private Call mCall2 = null;
private Call mCall3 = null;
private Call mConferenceCall = null;
private TestImsCallSessionImpl mCallSession1 = null;
private TestImsCallSessionImpl mCallSession2 = null;
private TestImsCallSessionImpl mCallSession3 = null;
private TestImsCallSessionImpl mConfCallSession = null;
// the timeout to wait result in milliseconds
private static final int WAIT_UPDATE_TIMEOUT_MS = 2000;
static {
initializeLatches();
}
@BeforeClass
public static void beforeAllTests() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
}
TelephonyManager tm = (TelephonyManager) getContext()
.getSystemService(Context.TELEPHONY_SERVICE);
sTestSub = ImsUtils.getPreferredActiveSubId();
sTestSlot = SubscriptionManager.getSlotIndex(sTestSub);
if (tm.getSimState(sTestSlot) != TelephonyManager.SIM_STATE_READY) {
return;
}
beforeAllTestsBase();
}
@AfterClass
public static void afterAllTests() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
}
afterAllTestsBase();
}
@Before
public void beforeTest() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
}
TelephonyManager tm = (TelephonyManager) InstrumentationRegistry.getInstrumentation()
.getContext().getSystemService(Context.TELEPHONY_SERVICE);
if (tm.getSimState(sTestSlot) != TelephonyManager.SIM_STATE_READY) {
fail("This test requires that there is a SIM in the device!");
}
// Correctness check: ensure that the subscription hasn't changed between tests.
int subId = SubscriptionManager.getSubscriptionId(sTestSlot);
if (subId != sTestSub) {
fail("The found subId " + subId + " does not match the test sub id " + sTestSub);
}
}
@After
public void afterTest() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
}
resetCallSessionObjects();
if (!mCalls.isEmpty() && (mCurrentCallId != null)) {
Call call = mCalls.get(mCurrentCallId);
call.disconnect();
}
//Set the untracked CountDownLatches which are reseted in ServiceCallBack
for (int i = 0; i < LATCH_MAX; i++) {
sLatches[i] = new CountDownLatch(1);
}
if (sServiceConnector != null && sIsBound) {
TestImsService imsService = sServiceConnector.getCarrierService();
sServiceConnector.disconnectCarrierImsService();
sIsBound = false;
imsService.waitForExecutorFinish();
}
}
@Test
public void testOutGoingCall() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
}
bindImsService();
mServiceCallBack = new ServiceCallBack();
InCallServiceStateValidator.setCallbacks(mServiceCallBack);
TelecomManager telecomManager = (TelecomManager) InstrumentationRegistry
.getInstrumentation().getContext().getSystemService(Context.TELECOM_SERVICE);
final Uri imsUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, String.valueOf(++sCounter), null);
Bundle extras = new Bundle();
// Place outgoing call
telecomManager.placeCall(imsUri, extras);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_ADDED, WAIT_FOR_CALL_STATE));
Call call = getCall(mCurrentCallId);
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DIALING, WAIT_FOR_CALL_STATE));
TestImsCallSessionImpl callSession = sServiceConnector.getCarrierService().getMmTelFeature()
.getImsCallsession();
isCallActive(call, callSession);
call.disconnect();
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
isCallDisconnected(call, callSession);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
waitForUnboundService();
}
@Test
public void testOutGoingCallStartFailed() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
}
bindImsService();
mServiceCallBack = new ServiceCallBack();
InCallServiceStateValidator.setCallbacks(mServiceCallBack);
TelecomManager telecomManager = (TelecomManager) InstrumentationRegistry
.getInstrumentation().getContext().getSystemService(Context.TELECOM_SERVICE);
final Uri imsUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, String.valueOf(++sCounter), null);
Bundle extras = new Bundle();
// Place outgoing call
telecomManager.placeCall(imsUri, extras);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_ADDED, WAIT_FOR_CALL_STATE));
Call call = getCall(mCurrentCallId);
waitUntilConditionIsTrueOrTimeout(
new Condition() {
@Override
public Object expected() {
return true;
}
@Override
public Object actual() {
TestMmTelFeature mmtelfeatue = sServiceConnector.getCarrierService()
.getMmTelFeature();
return (mmtelfeatue.isCallSessionCreated()) ? true : false;
}
}, WAIT_FOR_CONDITION, "CallSession Created");
TestImsCallSessionImpl callSession = sServiceConnector.getCarrierService().getMmTelFeature()
.getImsCallsession();
assertNotNull("Unable to get callSession, its null", callSession);
callSession.addTestType(TestImsCallSessionImpl.TEST_TYPE_MO_FAILED);
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DIALING, WAIT_FOR_CALL_STATE));
isCallDisconnected(call, callSession);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
waitForUnboundService();
}
@Test
public void testIncomingCall() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
}
bindImsService();
mServiceCallBack = new ServiceCallBack();
InCallServiceStateValidator.setCallbacks(mServiceCallBack);
Bundle extras = new Bundle();
sServiceConnector.getCarrierService().getMmTelFeature().onIncomingCallReceived(extras);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_ADDED, WAIT_FOR_CALL_STATE));
Call call = getCall(mCurrentCallId);
if (call.getDetails().getState() == Call.STATE_RINGING) {
call.answer(0);
}
TestImsCallSessionImpl callSession = sServiceConnector.getCarrierService().getMmTelFeature()
.getImsCallsession();
isCallActive(call, callSession);
callSession.terminateIncomingCall();
isCallDisconnected(call, callSession);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
waitForUnboundService();
}
@Test
public void testIncomingCallReturnListener() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
}
bindImsService();
mServiceCallBack = new ServiceCallBack();
InCallServiceStateValidator.setCallbacks(mServiceCallBack);
Bundle extras = new Bundle();
ImsCallSessionListener isl = sServiceConnector.getCarrierService().getMmTelFeature()
.onIncomingCallReceivedReturnListener(extras);
assertTrue("failed to get ImsCallSessionListener..", Objects.nonNull(isl));
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_ADDED, WAIT_FOR_CALL_STATE));
Call call = getCall(mCurrentCallId);
if (call.getDetails().getState() == Call.STATE_RINGING) {
call.answer(0);
}
TestImsCallSessionImpl callSession = sServiceConnector.getCarrierService().getMmTelFeature()
.getImsCallsession();
isCallActive(call, callSession);
callSession.terminateIncomingCall();
isCallDisconnected(call, callSession);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
waitForUnboundService();
}
@Test
public void testIncomingCallReject() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
}
bindImsService();
mServiceCallBack = new ServiceCallBack();
InCallServiceStateValidator.setCallbacks(mServiceCallBack);
Bundle extras = new Bundle();
sServiceConnector.getCarrierService().getMmTelFeature().onIncomingCallReceived(extras);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_ADDED, WAIT_FOR_CALL_STATE));
Call call = getCall(mCurrentCallId);
if (call.getDetails().getState() == Call.STATE_RINGING) {
call.reject(504);
}
TestImsCallSessionImpl callSession = sServiceConnector.getCarrierService().getMmTelFeature()
.getImsCallsession();
isCallDisconnected(call, callSession);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
waitForUnboundService();
}
@Test
public void testOutGoingCallForExecutor() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
}
sServiceConnector.setExecutorTestType(true);
bindImsService();
mServiceCallBack = new ServiceCallBack();
InCallServiceStateValidator.setCallbacks(mServiceCallBack);
TelecomManager telecomManager = (TelecomManager) InstrumentationRegistry
.getInstrumentation().getContext().getSystemService(Context.TELECOM_SERVICE);
final Uri imsUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, String.valueOf(++sCounter), null);
Bundle extras = new Bundle();
// Place outgoing call
telecomManager.placeCall(imsUri, extras);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_ADDED, WAIT_FOR_CALL_STATE));
Call call = getCall(mCurrentCallId);
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DIALING, WAIT_FOR_CALL_STATE));
TestImsCallSessionImpl callSession = sServiceConnector.getCarrierService().getMmTelFeature()
.getImsCallsession();
isCallActive(call, callSession);
call.disconnect();
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
isCallDisconnected(call, callSession);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
waitForUnboundService();
}
@Test
public void testOutGoingCallHoldResume() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
}
bindImsService();
mServiceCallBack = new ServiceCallBack();
InCallServiceStateValidator.setCallbacks(mServiceCallBack);
TelecomManager telecomManager = (TelecomManager) InstrumentationRegistry
.getInstrumentation().getContext().getSystemService(Context.TELECOM_SERVICE);
final Uri imsUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, String.valueOf(++sCounter), null);
Bundle extras = new Bundle();
// Place outgoing call
telecomManager.placeCall(imsUri, extras);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_ADDED, WAIT_FOR_CALL_STATE));
Call call = getCall(mCurrentCallId);
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DIALING, WAIT_FOR_CALL_STATE));
TestImsCallSessionImpl callSession = sServiceConnector.getCarrierService().getMmTelFeature()
.getImsCallsession();
isCallActive(call, callSession);
// Put on hold
call.hold();
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_HOLDING, WAIT_FOR_CALL_STATE));
ImsUtils.waitInCurrentState(WAIT_IN_CURRENT_STATE);
// Put on resume
call.unhold();
isCallActive(call, callSession);
call.disconnect();
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
isCallDisconnected(call, callSession);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
waitForUnboundService();
}
@Test
public void testOutGoingCallHoldFailure() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
}
bindImsService();
mServiceCallBack = new ServiceCallBack();
InCallServiceStateValidator.setCallbacks(mServiceCallBack);
TelecomManager telecomManager = (TelecomManager) InstrumentationRegistry
.getInstrumentation().getContext().getSystemService(Context.TELECOM_SERVICE);
final Uri imsUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, String.valueOf(++sCounter), null);
Bundle extras = new Bundle();
// Place outgoing call
telecomManager.placeCall(imsUri, extras);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_ADDED, WAIT_FOR_CALL_STATE));
Call call = getCall(mCurrentCallId);
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DIALING, WAIT_FOR_CALL_STATE));
TestImsCallSessionImpl callSession = sServiceConnector.getCarrierService().getMmTelFeature()
.getImsCallsession();
isCallActive(call, callSession);
callSession.addTestType(TestImsCallSessionImpl.TEST_TYPE_HOLD_FAILED);
ImsUtils.waitInCurrentState(WAIT_IN_CURRENT_STATE);
call.hold();
assertTrue("call is not in Active State", (call.getDetails().getState()
== call.STATE_ACTIVE));
call.disconnect();
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
isCallDisconnected(call, callSession);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
waitForUnboundService();
}
@Test
public void testOutGoingCallResumeFailure() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
}
bindImsService();
mServiceCallBack = new ServiceCallBack();
InCallServiceStateValidator.setCallbacks(mServiceCallBack);
TelecomManager telecomManager = (TelecomManager) InstrumentationRegistry
.getInstrumentation().getContext().getSystemService(Context.TELECOM_SERVICE);
final Uri imsUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, String.valueOf(++sCounter), null);
Bundle extras = new Bundle();
// Place outgoing call
telecomManager.placeCall(imsUri, extras);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_ADDED, WAIT_FOR_CALL_STATE));
Call call = getCall(mCurrentCallId);
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DIALING, WAIT_FOR_CALL_STATE));
TestImsCallSessionImpl callSession = sServiceConnector.getCarrierService().getMmTelFeature()
.getImsCallsession();
isCallActive(call, callSession);
// Put on hold
call.hold();
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_HOLDING, WAIT_FOR_CALL_STATE));
callSession.addTestType(TestImsCallSessionImpl.TEST_TYPE_RESUME_FAILED);
ImsUtils.waitInCurrentState(WAIT_IN_CURRENT_STATE);
call.unhold();
assertTrue("Call is not in Hold State", (call.getDetails().getState()
== call.STATE_HOLDING));
call.disconnect();
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
isCallDisconnected(call, callSession);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
waitForUnboundService();
}
@Test
public void testOutGoingCallReceivedHoldResume() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
}
bindImsService();
mServiceCallBack = new ServiceCallBack();
InCallServiceStateValidator.setCallbacks(mServiceCallBack);
TelecomManager telecomManager = (TelecomManager) InstrumentationRegistry
.getInstrumentation().getContext().getSystemService(Context.TELECOM_SERVICE);
final Uri imsUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, String.valueOf(++sCounter), null);
Bundle extras = new Bundle();
telecomManager.placeCall(imsUri, extras);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_ADDED, WAIT_FOR_CALL_STATE));
Call call = getCall(mCurrentCallId);
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DIALING, WAIT_FOR_CALL_STATE));
TestImsCallSessionImpl callSession = sServiceConnector.getCarrierService().getMmTelFeature()
.getImsCallsession();
isCallActive(call, callSession);
// received hold and checking it is still active and received the connection event
// EVENT_CALL_REMOTELY_HELD
callSession.sendHoldReceived();
assertTrue("Call is not in Active State", (call.getDetails().getState()
== Call.STATE_ACTIVE));
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOTELY_HELD, WAIT_FOR_CALL_STATE));
// received resume and checking it is still active and received the connection event
// EVENT_CALL_REMOTELY_UNHELD
callSession.sendResumeReceived();
assertTrue("Call is not in Active State", (call.getDetails().getState()
== Call.STATE_ACTIVE));
assertTrue(
callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOTELY_UNHELD, WAIT_FOR_CALL_STATE));
call.disconnect();
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
isCallDisconnected(call, callSession);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
waitForUnboundService();
}
@Test
public void testOutGoingIncomingMultiCall() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
}
bindImsService();
mServiceCallBack = new ServiceCallBack();
InCallServiceStateValidator.setCallbacks(mServiceCallBack);
TelecomManager telecomManager = (TelecomManager) InstrumentationRegistry
.getInstrumentation().getContext().getSystemService(Context.TELECOM_SERVICE);
final Uri imsUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, String.valueOf(++sCounter), null);
Bundle extras = new Bundle();
// Place outgoing call
telecomManager.placeCall(imsUri, extras);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_ADDED, WAIT_FOR_CALL_STATE));
Call moCall = getCall(mCurrentCallId);
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DIALING, WAIT_FOR_CALL_STATE));
TestImsCallSessionImpl moCallSession = sServiceConnector.getCarrierService()
.getMmTelFeature().getImsCallsession();
isCallActive(moCall, moCallSession);
assertTrue("Call is not in Active State", (moCall.getDetails().getState()
== Call.STATE_ACTIVE));
extras.putBoolean("android.telephony.ims.feature.extra.IS_USSD", false);
extras.putBoolean("android.telephony.ims.feature.extra.IS_UNKNOWN_CALL", false);
extras.putString("android:imsCallID", String.valueOf(++sCounter));
extras.putLong("android:phone_id", 123456);
sServiceConnector.getCarrierService().getMmTelFeature().onIncomingCallReceived(extras);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_ADDED, WAIT_FOR_CALL_STATE));
Call mtCall = null;
if (mCurrentCallId != null) {
mtCall = getCall(mCurrentCallId);
if (mtCall.getDetails().getState() == Call.STATE_RINGING) {
mtCall.answer(0);
}
}
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_HOLDING, WAIT_FOR_CALL_STATE));
TestImsCallSessionImpl mtCallSession = sServiceConnector.getCarrierService()
.getMmTelFeature().getImsCallsession();
isCallActive(mtCall, mtCallSession);
assertTrue("Call is not in Active State", (mtCall.getDetails().getState()
== Call.STATE_ACTIVE));
mtCall.disconnect();
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
isCallDisconnected(mtCall, mtCallSession);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
isCallActive(moCall, moCallSession);
assertTrue("Call is not in Active State", (moCall.getDetails().getState()
== Call.STATE_ACTIVE));
moCall.disconnect();
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
isCallDisconnected(moCall, moCallSession);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
waitForUnboundService();
}
@Test
public void testOutGoingIncomingMultiCallAcceptTerminate() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
}
bindImsService();
mServiceCallBack = new ServiceCallBack();
InCallServiceStateValidator.setCallbacks(mServiceCallBack);
TelecomManager telecomManager = (TelecomManager) InstrumentationRegistry
.getInstrumentation().getContext().getSystemService(Context.TELECOM_SERVICE);
final Uri imsUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, String.valueOf(++sCounter), null);
Bundle extras = new Bundle();
// Place outgoing call
telecomManager.placeCall(imsUri, extras);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_ADDED, WAIT_FOR_CALL_STATE));
Call moCall = getCall(mCurrentCallId);
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DIALING, WAIT_FOR_CALL_STATE));
TestImsCallSessionImpl moCallSession = sServiceConnector.getCarrierService()
.getMmTelFeature().getImsCallsession();
isCallActive(moCall, moCallSession);
assertTrue("Call is not in Active State", (moCall.getDetails().getState()
== Call.STATE_ACTIVE));
extras.putBoolean("android.telephony.ims.feature.extra.IS_USSD", false);
extras.putBoolean("android.telephony.ims.feature.extra.IS_UNKNOWN_CALL", false);
extras.putString("android:imsCallID", String.valueOf(++sCounter));
extras.putLong("android:phone_id", 123456);
sServiceConnector.getCarrierService().getMmTelFeature().onIncomingCallReceived(extras);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_ADDED, WAIT_FOR_CALL_STATE));
TestImsCallSessionImpl mtCallSession = sServiceConnector.getCarrierService()
.getMmTelFeature().getImsCallsession();
// do not generate an auto hold response here, need to simulate a timing issue.
moCallSession.addTestType(TestImsCallSessionImpl.TEST_TYPE_HOLD_NO_RESPONSE);
Call mtCall = null;
if (mCurrentCallId != null) {
mtCall = getCall(mCurrentCallId);
if (mtCall.getDetails().getState() == Call.STATE_RINGING) {
mtCall.answer(0);
}
}
// simulate user hanging up the MT call at the same time as accept.
mtCallSession.terminateIncomingCall();
isCallDisconnected(mtCall, mtCallSession);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
// then send hold response, which should be reversed, since MT call was disconnected.
moCallSession.sendHoldResponse();
// MO call should move back to active.
isCallActive(moCall, moCallSession);
assertTrue("Call is not in Active State", (moCall.getDetails().getState()
== Call.STATE_ACTIVE));
moCall.disconnect();
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
isCallDisconnected(moCall, moCallSession);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
waitForUnboundService();
}
@Test
public void testOutGoingIncomingMultiCallHoldFailedTerminateByRemote() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
}
bindImsService();
mServiceCallBack = new ServiceCallBack();
InCallServiceStateValidator.setCallbacks(mServiceCallBack);
TelecomManager telecomManager = (TelecomManager) InstrumentationRegistry
.getInstrumentation().getContext().getSystemService(Context.TELECOM_SERVICE);
final Uri imsUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, String.valueOf(++sCounter), null);
Bundle extras = new Bundle();
telecomManager.placeCall(imsUri, extras);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_ADDED, WAIT_FOR_CALL_STATE));
Call moCall = getCall(mCurrentCallId);
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DIALING, WAIT_FOR_CALL_STATE));
TestImsCallSessionImpl moCallSession = sServiceConnector.getCarrierService()
.getMmTelFeature().getImsCallsession();
isCallActive(moCall, moCallSession);
assertTrue("Call is not in Active State", (moCall.getDetails().getState()
== Call.STATE_ACTIVE));
sServiceConnector.getCarrierService().getMmTelFeature().onIncomingCallReceived(extras);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_ADDED, WAIT_FOR_CALL_STATE));
TestImsCallSessionImpl mtCallSession = sServiceConnector.getCarrierService()
.getMmTelFeature().getImsCallsession();
moCallSession.addTestType(TestImsCallSessionImpl.TEST_TYPE_HOLD_NO_RESPONSE);
Call mtCall = null;
if (mCurrentCallId != null) {
mtCall = getCall(mCurrentCallId);
if (mtCall.getDetails().getState() == Call.STATE_RINGING) {
mtCall.answer(0);
}
}
ImsUtils.waitInCurrentState(WAIT_IN_CURRENT_STATE);
// received holdFailed because the other party of the outgoing call terminated the call
moCallSession.sendHoldFailRemoteTerminated();
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
isCallDisconnected(moCall, moCallSession);
// incoming call accept again
mtCall.answer(0);
isCallActive(mtCall, mtCallSession);
assertTrue("Call is not in Active State", (mtCall.getDetails().getState()
== Call.STATE_ACTIVE));
mtCall.disconnect();
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
isCallDisconnected(mtCall, mtCallSession);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
waitForUnboundService();
}
@Test
public void testOutGoingCallSwap() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
}
bindImsService();
mServiceCallBack = new ServiceCallBack();
InCallServiceStateValidator.setCallbacks(mServiceCallBack);
addOutgoingCalls();
// Swap the call
ImsUtils.waitInCurrentState(WAIT_IN_CURRENT_STATE);
mCall1.unhold();
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_HOLDING, WAIT_FOR_CALL_STATE));
assertTrue("Call is not in Hold State", (mCall2.getDetails().getState()
== Call.STATE_HOLDING));
isCallActive(mCall1, mCallSession1);
// After successful call swap disconnect the call
mCall1.disconnect();
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
isCallDisconnected(mCall1, mCallSession1);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
//Wait till second call is in active state
waitUntilConditionIsTrueOrTimeout(
new Condition() {
@Override
public Object expected() {
return true;
}
@Override
public Object actual() {
return (mCall2.getDetails().getState() == Call.STATE_ACTIVE)
? true : false;
}
}, WAIT_FOR_CALL_STATE_ACTIVE, "Call in Active State");
isCallActive(mCall2, mCallSession2);
mCall2.disconnect();
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
isCallDisconnected(mCall2, mCallSession2);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
waitForUnboundService();
}
@Test
public void testOutGoingCallSwapFail() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
}
bindImsService();
mServiceCallBack = new ServiceCallBack();
InCallServiceStateValidator.setCallbacks(mServiceCallBack);
addOutgoingCalls();
mCallSession1.addTestType(TestImsCallSessionImpl.TEST_TYPE_RESUME_FAILED);
// Swap the call
ImsUtils.waitInCurrentState(WAIT_IN_CURRENT_STATE);
mCall1.unhold();
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_HOLDING, WAIT_FOR_CALL_STATE));
assertTrue("Call is not in Hold State", (mCall1.getDetails().getState()
== Call.STATE_HOLDING));
// Wait till second call is in active state
waitUntilConditionIsTrueOrTimeout(
new Condition() {
@Override
public Object expected() {
return true;
}
@Override
public Object actual() {
return (mCall2.getDetails().getState() == Call.STATE_ACTIVE)
? true : false;
}
}, WAIT_FOR_CALL_STATE_ACTIVE, "Call in Active State");
isCallActive(mCall2, mCallSession2);
mCallSession1.removeTestType(TestImsCallSessionImpl.TEST_TYPE_RESUME_FAILED);
mCall2.disconnect();
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
isCallDisconnected(mCall2, mCallSession2);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
// Wait till second call is in active state
isCallActive(mCall1, mCallSession1);
mCall1.disconnect();
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
isCallDisconnected(mCall1, mCallSession1);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
waitForUnboundService();
}
@Test
public void testConferenceCall() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
}
Log.i(LOG_TAG, "testConference ");
bindImsService();
mServiceCallBack = new ServiceCallBack();
InCallServiceStateValidator.setCallbacks(mServiceCallBack);
makeConferenceCall();
//Disconnect the conference call.
mConferenceCall.disconnect();
//Verify conference participant connections are disconnected.
assertParticiapantAddedToConference(0);
isCallDisconnected(mConferenceCall, mConfCallSession);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
waitForUnboundService();
}
@Test
public void testConferenceCallFailure() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
}
Log.i(LOG_TAG, "testConferenceCallFailure ");
bindImsService();
mServiceCallBack = new ServiceCallBack();
InCallServiceStateValidator.setCallbacks(mServiceCallBack);
addOutgoingCalls();
mCallSession2.addTestType(TestImsCallSessionImpl.TEST_TYPE_CONFERENCE_FAILED);
addConferenceCall(mCall1, mCall2);
ImsUtils.waitInCurrentState(WAIT_IN_CURRENT_STATE);
//Verify foreground call is in Active state after merge failed.
assertTrue("Call is not in Active State", (mCall2.getDetails().getState()
== Call.STATE_ACTIVE));
//Verify background call is in Hold state after merge failed.
assertTrue("Call is not in Holding State", (mCall1.getDetails().getState()
== Call.STATE_HOLDING));
mCall2.disconnect();
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
isCallDisconnected(mCall2, mCallSession2);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
//Wait till background call is in active state
isCallActive(mCall1, mCallSession1);
mCall1.disconnect();
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
isCallDisconnected(mCall1, mCallSession1);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
waitForUnboundService();
}
@Test
public void testConferenceCallFailureByRemoteTerminated() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
}
bindImsService();
mServiceCallBack = new ServiceCallBack();
InCallServiceStateValidator.setCallbacks(mServiceCallBack);
addOutgoingCalls();
mCallSession2.addTestType(
TestImsCallSessionImpl.TEST_TYPE_CONFERENCE_FAILED_REMOTE_TERMINATED);
addConferenceCall(mCall1, mCall2);
ImsUtils.waitInCurrentState(WAIT_IN_CURRENT_STATE);
// first call is terminated by remote
mCallSession1.sendTerminatedByRemote();
// received mergeFailed due to terminated first call
mCallSession2.sendMergedFailed();
ImsUtils.waitInCurrentState(WAIT_IN_CURRENT_STATE);
// verify foreground call is in Active state after merge failed.
assertTrue("Call is not in Active State", (mCall2.getDetails().getState()
== Call.STATE_ACTIVE));
// verify background call is in Disconnected state.
isCallDisconnected(mCall1, mCallSession1);
assertTrue("Call is not in Disconnected State", (mCall1.getDetails().getState()
== Call.STATE_DISCONNECTED));
mCall2.disconnect();
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
isCallDisconnected(mCall2, mCallSession2);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
waitForUnboundService();
}
@Test
public void testCallJoinExistingConferenceCall() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
}
bindImsService();
mServiceCallBack = new ServiceCallBack();
InCallServiceStateValidator.setCallbacks(mServiceCallBack);
makeConferenceCall();
// add third outgoing call, third call : active , conference call : hold
addThirdOutgoingCall();
mCallSession3.addTestType(TestImsCallSessionImpl.TEST_TYPE_JOIN_EXIST_CONFERENCE);
mCall3.conference(mConferenceCall);
isCallActive(mConferenceCall, mConfCallSession);
ImsUtils.waitInCurrentState(WAIT_IN_CURRENT_STATE);
// verify third call disconnected after conference Merge success
assertParticiapantDisconnected(mCall3);
// verify conference participant connections are connected.
assertParticiapantAddedToConference(3);
mConferenceCall.disconnect();
assertParticiapantAddedToConference(0);
isCallDisconnected(mConferenceCall, mConfCallSession);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
waitForUnboundService();
}
@Test
public void testCallJoinExistingConferenceCallAfterCallSwap() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
}
bindImsService();
mServiceCallBack = new ServiceCallBack();
InCallServiceStateValidator.setCallbacks(mServiceCallBack);
makeConferenceCall();
// add third outgoing call, third call : active , conference call : hold
addThirdOutgoingCall();
// swap the call
ImsUtils.waitInCurrentState(WAIT_IN_CURRENT_STATE);
mConferenceCall.unhold();
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_HOLDING, WAIT_FOR_CALL_STATE));
assertTrue("Call is not in Hold State", (mCall3.getDetails().getState()
== Call.STATE_HOLDING));
isCallActive(mConferenceCall, mConfCallSession);
mConfCallSession.addTestType(
TestImsCallSessionImpl.TEST_TYPE_JOIN_EXIST_CONFERENCE_AFTER_SWAP);
// merge call
mConferenceCall.conference(mCall3);
isCallActive(mConferenceCall, mConfCallSession);
// verify third call disconnected after conference Merge success
assertParticiapantDisconnected(mCall3);
// verify conference participant connections are connected.
assertParticiapantAddedToConference(3);
// disconnect the conference call.
mConferenceCall.disconnect();
// verify conference participant connections are disconnected.
assertParticiapantAddedToConference(0);
isCallDisconnected(mConferenceCall, mConfCallSession);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
waitForUnboundService();
}
@Test
public void testCallJoinExistingConferenceCallAfterCallSwapFail() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
}
bindImsService();
mServiceCallBack = new ServiceCallBack();
InCallServiceStateValidator.setCallbacks(mServiceCallBack);
makeConferenceCall();
// add third outgoing call, third call : active , conference call : hold
addThirdOutgoingCall();
// swap the call
ImsUtils.waitInCurrentState(WAIT_IN_CURRENT_STATE);
mConferenceCall.unhold();
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_HOLDING, WAIT_FOR_CALL_STATE));
assertTrue("Call is not in Hold State", (mCall3.getDetails().getState()
== Call.STATE_HOLDING));
isCallActive(mConferenceCall, mConfCallSession);
// fail to merge
mConfCallSession.addTestType(
TestImsCallSessionImpl.TEST_TYPE_JOIN_EXIST_CONFERENCE_FAILED_AFTER_SWAP);
mConferenceCall.conference(mCall3);
ImsUtils.waitInCurrentState(WAIT_IN_CURRENT_STATE);
// verify foreground call is in Active state after merge failed.
assertTrue("Call is not in Active State", (mConferenceCall.getDetails().getState()
== Call.STATE_ACTIVE));
// verify background call is in Hold state after merge failed.
assertTrue("Call is not in Holding State", (mCall3.getDetails().getState()
== Call.STATE_HOLDING));
// disconnect the conference call.
mConferenceCall.disconnect();
// verify conference participant connections are disconnected.
assertParticiapantAddedToConference(0);
isCallDisconnected(mConferenceCall, mConfCallSession);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
// verify third call is active
isCallActive(mCall3, mCallSession3);
mCall3.disconnect();
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
isCallDisconnected(mCall3, mCallSession3);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
waitForUnboundService();
}
@Test
public void testSetCallAudioHandler() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
}
bindImsService();
mServiceCallBack = new ServiceCallBack();
InCallServiceStateValidator.setCallbacks(mServiceCallBack);
TelecomManager telecomManager = (TelecomManager) InstrumentationRegistry
.getInstrumentation().getContext().getSystemService(Context.TELECOM_SERVICE);
AudioManager mAudioManager = (AudioManager) InstrumentationRegistry
.getInstrumentation().getContext().getSystemService(Context.AUDIO_SERVICE);
final Uri imsUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, String.valueOf(++sCounter), null);
Bundle extras = new Bundle();
// Place outgoing call
telecomManager.placeCall(imsUri, extras);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_ADDED, WAIT_FOR_CALL_STATE));
Call call = getCall(mCurrentCallId);
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DIALING, WAIT_FOR_CALL_STATE));
TestImsCallSessionImpl callSession = sServiceConnector.getCarrierService().getMmTelFeature()
.getImsCallsession();
isCallActive(call, callSession);
sServiceConnector.getCarrierService().getMmTelFeature()
.setCallAudioHandler(MmTelFeature.AUDIO_HANDLER_ANDROID);
sServiceConnector.getCarrierService().getMmTelFeature()
.getTerminalBasedCallWaitingLatch().await(WAIT_UPDATE_TIMEOUT_MS,
TimeUnit.MILLISECONDS);
assertEquals(AudioManager.MODE_IN_COMMUNICATION, mAudioManager.getMode());
sServiceConnector.getCarrierService().getMmTelFeature()
.setCallAudioHandler(MmTelFeature.AUDIO_HANDLER_BASEBAND);
sServiceConnector.getCarrierService().getMmTelFeature()
.getTerminalBasedCallWaitingLatch().await(WAIT_UPDATE_TIMEOUT_MS,
TimeUnit.MILLISECONDS);
assertEquals(AudioManager.MODE_IN_CALL, mAudioManager.getMode());
call.disconnect();
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
isCallDisconnected(call, callSession);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
waitForUnboundService();
}
@Test
public void testNotifyMediaCallStatusChanged() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
}
bindImsService();
mServiceCallBack = new ServiceCallBack();
InCallServiceStateValidator.setCallbacks(mServiceCallBack);
TelecomManager telecomManager = (TelecomManager) InstrumentationRegistry
.getInstrumentation().getContext().getSystemService(Context.TELECOM_SERVICE);
final Uri imsUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, String.valueOf(++sCounter), null);
Bundle extras = new Bundle();
// Place outgoing call
telecomManager.placeCall(imsUri, extras);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_ADDED, WAIT_FOR_CALL_STATE));
Call call = getCall(mCurrentCallId);
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DIALING, WAIT_FOR_CALL_STATE));
TestImsCallSessionImpl callSession = sServiceConnector.getCarrierService().getMmTelFeature()
.getImsCallsession();
isCallActive(call, callSession);
String callSessionId = callSession.getCallId();
LinkedBlockingQueue<MediaQualityStatus> queue = new LinkedBlockingQueue<>();
ImsCallingTest.TestTelephonyCallback testCb =
new ImsCallingTest.TestTelephonyCallback(queue);
TelephonyManager telephonyManager = getContext().getSystemService(TelephonyManager.class);
//test registration without permission
try {
telephonyManager.registerTelephonyCallback(getContext().getMainExecutor(), testCb);
fail("registerTelephonyCallback requires READ_PRECISE_PHONE_STATE permission.");
} catch (SecurityException e) {
//expected
}
final UiAutomation automan = InstrumentationRegistry.getInstrumentation().getUiAutomation();
try {
automan.adoptShellPermissionIdentity();
telephonyManager.registerTelephonyCallback(getContext().getMainExecutor(), testCb);
} finally {
automan.dropShellPermissionIdentity();
}
//Expect to receive cached media quality status retrieved by #queryMediaQualityStatus.
MediaQualityStatus status = queue.poll(ImsUtils.TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
assertNotNull(status);
assertEquals(callSessionId, status.getCallSessionId());
assertEquals(MediaQualityStatus.MEDIA_SESSION_TYPE_AUDIO, status.getMediaSessionType());
assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, status.getTransportType());
assertEquals(0, status.getRtpPacketLossRate());
assertEquals(0, status.getRtpJitterMillis());
assertEquals(0, status.getRtpInactivityMillis());
//Notify a new media quality status.
sServiceConnector.getCarrierService().getMmTelFeature()
.notifyMediaQualityStatusChanged(new MediaQualityStatus
.Builder(callSessionId,
MediaQualityStatus.MEDIA_SESSION_TYPE_AUDIO,
AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
.setRtpPacketLossRate(TEST_RTP_THRESHOLD_PACKET_LOSS_RATE)
.setRtpJitterMillis(TEST_RTP_THRESHOLD_JITTER_MILLIS)
.setRtpInactivityMillis(TEST_RTP_THRESHOLD_INACTIVITY_TIME_MILLIS).build());
status = queue.poll(ImsUtils.TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
assertNotNull(status);
assertEquals(callSessionId, status.getCallSessionId());
assertEquals(MediaQualityStatus.MEDIA_SESSION_TYPE_AUDIO, status.getMediaSessionType());
assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, status.getTransportType());
assertEquals(TEST_RTP_THRESHOLD_PACKET_LOSS_RATE, status.getRtpPacketLossRate());
assertEquals(TEST_RTP_THRESHOLD_JITTER_MILLIS, status.getRtpJitterMillis());
assertEquals(TEST_RTP_THRESHOLD_INACTIVITY_TIME_MILLIS, status.getRtpInactivityMillis());
call.disconnect();
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
isCallDisconnected(call, callSession);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
waitForUnboundService();
}
private class TestTelephonyCallback extends TelephonyCallback
implements TelephonyCallback.MediaQualityStatusChangedListener {
LinkedBlockingQueue<MediaQualityStatus> mTestMediaQualityStatusQueue;
TestTelephonyCallback(LinkedBlockingQueue<MediaQualityStatus> queue) {
mTestMediaQualityStatusQueue = queue;
}
@Override
public void onMediaQualityStatusChanged(@NonNull MediaQualityStatus status) {
mTestMediaQualityStatusQueue.offer(status);
}
}
void addConferenceCall(Call call1, Call call2) {
InCallServiceStateValidator inCallService = mServiceCallBack.getService();
// Verify that the calls have each other on their conferenceable list before proceeding
List<Call> callConfList = new ArrayList<>();
callConfList.add(call2);
assertCallConferenceableList(call1, callConfList);
callConfList.clear();
callConfList.add(call1);
assertCallConferenceableList(call2, callConfList);
call2.conference(call1);
}
void assertCallConferenceableList(final Call call, final List<Call> conferenceableList) {
waitUntilConditionIsTrueOrTimeout(
new Condition() {
@Override
public Object expected() {
return conferenceableList;
}
@Override
public Object actual() {
return call.getConferenceableCalls();
}
}, WAIT_FOR_CONDITION,
"Call: " + call + " does not have the correct conferenceable call list."
);
}
private void assertParticiapantDisconnected(Call call) {
waitUntilConditionIsTrueOrTimeout(
new Condition() {
@Override
public Object expected() {
return true;
}
@Override
public Object actual() {
return ((call.getState() == Call.STATE_DISCONNECTED)) ? true : false;
}
}, WAIT_FOR_CONDITION, "Call Disconnected");
}
private void assertParticiapantAddedToConference(int count) {
waitUntilConditionIsTrueOrTimeout(
new Condition() {
@Override
public Object expected() {
return true;
}
@Override
public Object actual() {
return (mParticipantCount == count) ? true : false;
}
}, WAIT_FOR_CONDITION, "Call Added");
}
private void addOutgoingCalls() throws Exception {
TelecomManager telecomManager = (TelecomManager) InstrumentationRegistry
.getInstrumentation().getContext().getSystemService(Context.TELECOM_SERVICE);
// Place first outgoing call
final Uri imsUri1 = Uri.fromParts(PhoneAccount.SCHEME_TEL, String.valueOf(++sCounter),
null);
Bundle extras1 = new Bundle();
telecomManager.placeCall(imsUri1, extras1);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_ADDED, WAIT_FOR_CALL_STATE));
mCall1 = getCall(mCurrentCallId);
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DIALING, WAIT_FOR_CALL_STATE));
mCallSession1 = sServiceConnector.getCarrierService().getMmTelFeature().getImsCallsession();
isCallActive(mCall1, mCallSession1);
assertTrue("Call is not in Active State", (mCall1.getDetails().getState()
== Call.STATE_ACTIVE));
// Place second outgoing call
final Uri imsUri2 = Uri.fromParts(PhoneAccount.SCHEME_TEL, String.valueOf(++sCounter),
null);
Bundle extras2 = new Bundle();
telecomManager.placeCall(imsUri2, extras2);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_ADDED, WAIT_FOR_CALL_STATE));
mCall2 = getCall(mCurrentCallId);
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DIALING, WAIT_FOR_CALL_STATE));
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_HOLDING, WAIT_FOR_CALL_STATE));
assertTrue("Call is not in Hold State", (mCall1.getDetails().getState()
== Call.STATE_HOLDING));
//Wait till the object of TestImsCallSessionImpl for second call created.
waitUntilConditionIsTrueOrTimeout(
new Condition() {
@Override
public Object expected() {
return true;
}
@Override
public Object actual() {
TestMmTelFeature mmtelfeatue = sServiceConnector.getCarrierService()
.getMmTelFeature();
return (mmtelfeatue.getImsCallsession() != mCallSession1) ? true : false;
}
}, WAIT_FOR_CONDITION, "CallSession Created");
mCallSession2 = sServiceConnector.getCarrierService().getMmTelFeature().getImsCallsession();
isCallActive(mCall2, mCallSession2);
assertTrue("Call is not in Active State", (mCall2.getDetails().getState()
== Call.STATE_ACTIVE));
}
private void addThirdOutgoingCall() {
// add a third outgoing call when a conference call already exists.
TelecomManager telecomManager = (TelecomManager) InstrumentationRegistry
.getInstrumentation().getContext().getSystemService(Context.TELECOM_SERVICE);
final Uri imsUri3 = Uri.fromParts(PhoneAccount.SCHEME_TEL, String.valueOf(++sCounter),
null);
Bundle extras3 = new Bundle();
telecomManager.placeCall(imsUri3, extras3);
ImsUtils.waitInCurrentState(WAIT_IN_CURRENT_STATE);
callingTestLatchCountdown(LATCH_IS_ON_CALL_ADDED, WAIT_FOR_CALL_STATE);
mCall3 = getCall(mCurrentCallId);
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DIALING, WAIT_FOR_CALL_STATE));
assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_HOLDING, WAIT_FOR_CALL_STATE));
assertTrue("Call is not in Hold State", (mConferenceCall.getDetails().getState()
== Call.STATE_HOLDING));
waitNewCallCreated(mCallSession2);
mCallSession3 =
sServiceConnector.getCarrierService().getMmTelFeature().getImsCallsession();
isCallActive(mCall3, mCallSession3);
assertTrue("Call is not in Active State", (mCall3.getDetails().getState()
== Call.STATE_ACTIVE));
}
private void waitNewCallCreated(TestImsCallSessionImpl previousCallSession) {
waitUntilConditionIsTrueOrTimeout(
new Condition() {
@Override
public Object expected() {
return true;
}
@Override
public Object actual() {
TestMmTelFeature mmtelfeatue = sServiceConnector.getCarrierService()
.getMmTelFeature();
return (mmtelfeatue.getImsCallsession() != previousCallSession) ? true
: false;
}
}, WAIT_FOR_CONDITION, "CallSession Created");
}
private void makeConferenceCall() throws Exception {
addOutgoingCalls();
addConferenceCall(mCall1, mCall2);
assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_ADDED, WAIT_FOR_CALL_STATE));
// Wait to add participants in conference
ImsUtils.waitInCurrentState(WAIT_IN_CURRENT_STATE);
assertTrue("Conference call is not added", mServiceCallBack.getService()
.getConferenceCallCount() > 0);
mConferenceCall = mServiceCallBack.getService().getLastConferenceCall();
assertNotNull("Unable to add conference call, its null", mConferenceCall);
ConferenceHelper confHelper = sServiceConnector.getCarrierService().getMmTelFeature()
.getConferenceHelper();
mConfCallSession = confHelper.getConferenceSession();
isCallActive(mConferenceCall, mConfCallSession);
assertTrue("Conference call is not Active", mConfCallSession.isInCall());
//Verify mCall1 and mCall2 disconnected after conference Merge success
assertParticiapantDisconnected(mCall1);
assertParticiapantDisconnected(mCall2);
//Verify conference participant connections are connected.
assertParticiapantAddedToConference(2);
// Since the conference call has been made, remove session1&2 from the confHelper session.
confHelper.removeSession(mCallSession1);
confHelper.removeSession(mCallSession2);
}
private void resetCallSessionObjects() {
mCall1 = mCall2 = mCall3 = mConferenceCall = null;
mCallSession1 = mCallSession2 = mCallSession3 = mConfCallSession = null;
ConferenceHelper confHelper = sServiceConnector.getCarrierService().getMmTelFeature()
.getConferenceHelper();
if (confHelper != null) {
confHelper.clearSessions();
}
}
}