blob: 5ace9fff55728c3ca6768c8af6b4b3d6e4d834a5 [file] [log] [blame]
/*
* Copyright (C) 2017 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 android.net.Uri;
import android.os.Bundle;
import android.telecom.CallAudioState;
import android.telecom.PhoneAccount;
import android.telecom.TelecomManager;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import static android.telecom.cts.TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS;
import static android.telecom.cts.TestUtils.waitOnAllHandlers;
/**
* CTS tests for the self-managed {@link android.telecom.ConnectionService} APIs.
* For more information about these APIs, see {@link android.telecom}, and
* {@link android.telecom.PhoneAccount#CAPABILITY_SELF_MANAGED}.
*/
public class SelfManagedConnectionServiceTest extends BaseTelecomTestWithMockServices {
private Uri TEST_ADDRESS_1 = Uri.fromParts("sip", "call1@test.com", null);
private Uri TEST_ADDRESS_2 = Uri.fromParts("sip", "call2@test.com", null);
@Override
protected void setUp() throws Exception {
super.setUp();
mContext = getInstrumentation().getContext();
if (mShouldTestTelecom) {
// Register and enable the CTS ConnectionService; we want to be able to test a managed
// ConnectionService alongside a self-managed ConnectionService.
setupConnectionService(null, FLAG_REGISTER | FLAG_ENABLE);
mTelecomManager.registerPhoneAccount(TestUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_1);
mTelecomManager.registerPhoneAccount(TestUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_2);
}
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
CtsSelfManagedConnectionService connectionService =
CtsSelfManagedConnectionService.getConnectionService();
if (connectionService != null) {
connectionService.tearDown();
mTelecomManager.unregisterPhoneAccount(TestUtils.TEST_SELF_MANAGED_HANDLE_1);
mTelecomManager.unregisterPhoneAccount(TestUtils.TEST_SELF_MANAGED_HANDLE_2);
}
}
/**
* Tests the ability to successfully register a self-managed
* {@link android.telecom.PhoneAccount}.
*/
public void testRegisterSelfManagedConnectionService() {
if (!mShouldTestTelecom) {
return;
}
// The phone account is registered in the setup method.
assertPhoneAccountRegistered(TestUtils.TEST_SELF_MANAGED_HANDLE_1);
assertPhoneAccountEnabled(TestUtils.TEST_SELF_MANAGED_HANDLE_1);
PhoneAccount registeredAccount = mTelecomManager.getPhoneAccount(
TestUtils.TEST_SELF_MANAGED_HANDLE_1);
// It should exist and be the same as the previously registered one.
assertNotNull(registeredAccount);
// We cannot just check for equality of the PhoneAccount since the one we registered is not
// enabled, and the one we get back after registration is.
assertPhoneAccountEquals(TestUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_1, registeredAccount);
// An important asumption is that self-managed PhoneAccounts are automatically
// enabled by default.
assertTrue("Self-managed PhoneAccounts must be enabled by default.",
registeredAccount.isEnabled());
}
/**
* This test ensures that a {@link android.telecom.PhoneAccount} declared as self-managed cannot
* but is also registered as a call provider is not permitted.
*
* A self-managed {@link android.telecom.PhoneAccount} cannot also be a call provider.
*/
public void testRegisterCallCapableSelfManagedConnectionService() {
if (!mShouldTestTelecom) {
return;
}
// Attempt to register both a call provider and self-managed account.
PhoneAccount toRegister = TestUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_1.toBuilder()
.setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED |
PhoneAccount.CAPABILITY_CALL_PROVIDER)
.build();
registerAndExpectFailure(toRegister);
}
/**
* This test ensures that a {@link android.telecom.PhoneAccount} declared as self-managed cannot
* but is also registered as a sim subscription is not permitted.
*
* A self-managed {@link android.telecom.PhoneAccount} cannot also be a SIM subscription.
*/
public void testRegisterSimSelfManagedConnectionService() {
if (!mShouldTestTelecom) {
return;
}
// Attempt to register both a call provider and self-managed account.
PhoneAccount toRegister = TestUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_1.toBuilder()
.setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED |
PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
.build();
registerAndExpectFailure(toRegister);
}
/**
* This test ensures that a {@link android.telecom.PhoneAccount} declared as self-managed cannot
* but is also registered as a connection manager is not permitted.
*
* A self-managed {@link android.telecom.PhoneAccount} cannot also be a connection manager.
*/
public void testRegisterConnectionManagerSelfManagedConnectionService() {
if (!mShouldTestTelecom) {
return;
}
// Attempt to register both a call provider and self-managed account.
PhoneAccount toRegister = TestUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_1.toBuilder()
.setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED |
PhoneAccount.CAPABILITY_CONNECTION_MANAGER)
.build();
registerAndExpectFailure(toRegister);
}
/**
* Attempts to register a {@link android.telecom.PhoneAccount}, expecting a security exception
* which indicates that invalid capabilities were specified.
*
* @param toRegister The PhoneAccount to register.
*/
private void registerAndExpectFailure(PhoneAccount toRegister) {
try {
mTelecomManager.registerPhoneAccount(toRegister);
} catch (SecurityException se) {
assertEquals("Self-managed ConnectionServices cannot also be call capable, " +
"connection managers, or SIM accounts.", se.getMessage());
return;
}
fail("Expected SecurityException");
}
/**
* Tests ability to add a new self-managed incoming connection.
*/
public void testAddSelfManagedIncomingConnection() throws Exception {
if (!mShouldTestTelecom) {
return;
}
TestUtils.addIncomingCall(getInstrumentation(), mTelecomManager,
TestUtils.TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_1);
// Ensure Telecom bound to the self managed CS
if (!CtsSelfManagedConnectionService.waitForBinding()) {
fail("Could not bind to Self-Managed ConnectionService");
}
SelfManagedConnection connection = TestUtils.waitForAndGetConnection(TEST_ADDRESS_1);
// Expect callback indicating that UI should be shown.
connection.getOnShowIncomingUiInvokeCounter().waitForCount(1);
setActiveAndVerify(connection);
// Expect there to be no managed calls at the moment.
assertFalse(mTelecomManager.isInManagedCall());
setDisconnectedAndVerify(connection);
}
/**
* Tests ability to add a new self-managed outgoing connection.
*/
public void testAddSelfManagedOutgoingConnection() throws Exception {
if (!mShouldTestTelecom) {
return;
}
TestUtils.placeOutgoingCall(getInstrumentation(), mTelecomManager,
TestUtils.TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_1);
// Ensure Telecom bound to the self managed CS
if (!CtsSelfManagedConnectionService.waitForBinding()) {
fail("Could not bind to Self-Managed ConnectionService");
}
SelfManagedConnection connection = TestUtils.waitForAndGetConnection(TEST_ADDRESS_1);
assert(!connection.isIncomingCall());
assertEquals(connection.getOnShowIncomingUiInvokeCounter().getInvokeCount(), 0);
setActiveAndVerify(connection);
// Expect there to be no managed calls at the moment.
assertFalse(mTelecomManager.isInManagedCall());
setDisconnectedAndVerify(connection);
}
/**
* Tests ability to change the audio route via the
* {@link android.telecom.Connection#setAudioRoute(int)} API.
*/
public void testAudioRoute() throws Exception {
if (!mShouldTestTelecom) {
return;
}
TestUtils.placeOutgoingCall(getInstrumentation(), mTelecomManager,
TestUtils.TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_1);
SelfManagedConnection connection = TestUtils.waitForAndGetConnection(TEST_ADDRESS_1);
setActiveAndVerify(connection);
TestUtils.InvokeCounter counter = connection.getCallAudioStateChangedInvokeCounter();
connection.setAudioRoute(CallAudioState.ROUTE_SPEAKER);
counter.waitForPredicate(new Predicate<CallAudioState>() {
@Override
public boolean test(CallAudioState cas) {
return cas.getRoute() == CallAudioState.ROUTE_SPEAKER;
}
}, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
connection.setAudioRoute(CallAudioState.ROUTE_EARPIECE);
counter.waitForPredicate(new Predicate<CallAudioState>() {
@Override
public boolean test(CallAudioState cas) {
return cas.getRoute() == CallAudioState.ROUTE_EARPIECE;
}
}, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
setDisconnectedAndVerify(connection);
}
/**
* Tests that Telecom will disallow an outgoing call when there is already an ongoing call in
* another third-party app.
* @throws Exception
*/
public void testDisallowOutgoingCall() throws Exception {
if (!mShouldTestTelecom) {
return;
}
// Create an ongoing call in the first self-managed PhoneAccount.
TestUtils.placeOutgoingCall(getInstrumentation(), mTelecomManager,
TestUtils.TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_1);
SelfManagedConnection connection = TestUtils.waitForAndGetConnection(TEST_ADDRESS_1);
setActiveAndVerify(connection);
// Attempt to create a new outgoing call for the other PhoneAccount; it should fail.
TestUtils.placeOutgoingCall(getInstrumentation(), mTelecomManager,
TestUtils.TEST_SELF_MANAGED_HANDLE_2, TEST_ADDRESS_2);
assertTrue("Expected onCreateOutgoingConnectionFailed callback",
CtsSelfManagedConnectionService.getConnectionService().waitForUpdate(
CtsSelfManagedConnectionService.CREATE_OUTGOING_CONNECTION_FAILED_LOCK));
setDisconnectedAndVerify(connection);
}
/**
* Tests that Telecom will disallow an outgoing call when there is already an ongoing call in
* another third-party app.
* @throws Exception
*/
public void testIncomingWhileOngoing() throws Exception {
if (!mShouldTestTelecom) {
return;
}
// Create an ongoing call in the first self-managed PhoneAccount.
TestUtils.placeOutgoingCall(getInstrumentation(), mTelecomManager,
TestUtils.TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_1);
SelfManagedConnection connection = TestUtils.waitForAndGetConnection(TEST_ADDRESS_1);
setActiveAndVerify(connection);
// Attempt to create a new outgoing call for the other PhoneAccount; it should succeed.
TestUtils.addIncomingCall(getInstrumentation(), mTelecomManager,
TestUtils.TEST_SELF_MANAGED_HANDLE_2, TEST_ADDRESS_2);
SelfManagedConnection connection2 = TestUtils.waitForAndGetConnection(TEST_ADDRESS_2);
connection2.disconnectAndDestroy();
setDisconnectedAndVerify(connection);
}
/**
* Tests that Telecom enforces a maximum number of calls for a self-managed ConnectionService.
*
* @throws Exception
*/
public void testCallLimit() throws Exception {
if (!mShouldTestTelecom) {
return;
}
List<SelfManagedConnection> connections = new ArrayList<>();
// Create 10 calls; they should succeed.
for (int ix = 0; ix < 10; ix++) {
Uri address = Uri.fromParts("sip", "test" + ix + "@test.com", null);
// Create an ongoing call in the first self-managed PhoneAccount.
TestUtils.placeOutgoingCall(getInstrumentation(), mTelecomManager,
TestUtils.TEST_SELF_MANAGED_HANDLE_1, address);
SelfManagedConnection connection = TestUtils.waitForAndGetConnection(address);
setActiveAndVerify(connection);
connections.add(connection);
}
// Try adding an 11th. It should fail to be created.
TestUtils.addIncomingCall(getInstrumentation(), mTelecomManager,
TestUtils.TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_2);
assertTrue("Expected onCreateIncomingConnectionFailed callback",
CtsSelfManagedConnectionService.getConnectionService().waitForUpdate(
CtsSelfManagedConnectionService.CREATE_INCOMING_CONNECTION_FAILED_LOCK));
connections.forEach((selfManagedConnection) ->
selfManagedConnection.disconnectAndDestroy());
waitOnAllHandlers(getInstrumentation());
}
public void testEmergencyCallOngoing() throws Exception {
if (!mShouldTestTelecom) {
return;
}
// Set 555-1212 as a test emergency number.
TestUtils.executeShellCommand(getInstrumentation(),
"setprop ril.ecclist 5551212");
Bundle extras = new Bundle();
extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
TestUtils.TEST_PHONE_ACCOUNT_HANDLE);
mTelecomManager.placeCall(Uri.fromParts(PhoneAccount.SCHEME_TEL, "5551212", null), extras);
assertIsInCall(true);
assertIsInManagedCall(true);
try {
TestUtils.waitOnAllHandlers(getInstrumentation());
} catch (Exception e) {
fail("Failed to wait on handlers " + e);
}
// Try adding a self managed call. It should fail to be created.
TestUtils.addIncomingCall(getInstrumentation(), mTelecomManager,
TestUtils.TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_1);
assertTrue("Expected onCreateIncomingConnectionFailed callback",
CtsSelfManagedConnectionService.getConnectionService().waitForUpdate(
CtsSelfManagedConnectionService.CREATE_INCOMING_CONNECTION_FAILED_LOCK));
}
/**
* Sets a connection active, and verifies TelecomManager thinks we're in call but not in a
* managed call.
* @param connection The connection.
*/
private void setActiveAndVerify(SelfManagedConnection connection) throws Exception {
// Set the connection active.
connection.setActive();
// Check with Telecom if we're in a call.
assertIsInCall(true);
assertIsInManagedCall(false);
}
/**
* Sets a connection to be disconnected, and then waits until the TelecomManager reports it is
* no longer in a call.
*
* @param connection The connection to disconnect/destroy.
*/
private void setDisconnectedAndVerify(SelfManagedConnection connection) {
// Now, disconnect call and clean it up.
connection.disconnectAndDestroy();
assertIsInCall(false);
assertIsInManagedCall(false);
}
}