blob: 0b166c8dc3ea6077cc24f6841824ee5bf1ebcee5 [file] [log] [blame]
/*
* Copyright (C) 2018 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.cts.TestUtils.TEST_HANDOVER_DEST_PHONE_ACCOUNT_HANDLE;
import static android.telecom.cts.TestUtils.TEST_HANDOVER_SRC_PHONE_ACCOUNT_HANDLE;
import static android.telecom.cts.TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS;
import android.net.Uri;
import android.os.Bundle;
import android.telecom.Call;
import android.telecom.Connection;
import android.telecom.ConnectionRequest;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
/**
* Tests the Telecom handover APIs.
*/
public class HandoverTest extends BaseTelecomTestWithMockServices {
@Override
protected void setUp() throws Exception {
super.setUp();
mContext = getInstrumentation().getContext();
if (mShouldTestTelecom) {
setupConnectionService(null, FLAG_REGISTER | FLAG_ENABLE);
// Test handover source is a managed ConnectionService
mTelecomManager.registerPhoneAccount(TestUtils.TEST_PHONE_ACCOUNT_HANDOVER_SRC);
TestUtils.enablePhoneAccount(getInstrumentation(),
TestUtils.TEST_HANDOVER_SRC_PHONE_ACCOUNT_HANDLE);
assertPhoneAccountEnabled(TestUtils.TEST_HANDOVER_SRC_PHONE_ACCOUNT_HANDLE);
// Test handover destination is a self-managed ConnectionService.
mTelecomManager.registerPhoneAccount(TestUtils.TEST_PHONE_ACCOUNT_HANDOVER_DEST);
}
}
@Override
protected void tearDown() throws Exception {
CtsSelfManagedConnectionService connectionService =
CtsSelfManagedConnectionService.getConnectionService();
if (connectionService != null) {
connectionService.tearDown();
mTelecomManager.unregisterPhoneAccount(
TestUtils.TEST_HANDOVER_SRC_PHONE_ACCOUNT_HANDLE);
mTelecomManager.unregisterPhoneAccount(
TestUtils.TEST_HANDOVER_DEST_PHONE_ACCOUNT_HANDLE);
}
super.tearDown();
}
/**
* Ensures a call handover cannot be initiated for a {@link android.telecom.PhoneAccount} which
* does not declare {@link android.telecom.PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.
*/
public void testHandoverSourceFailed() {
if (!mShouldTestTelecom) {
return;
}
placeAndVerifyCall();
Call call = mInCallCallbacks.getService().getLastCall();
call.handoverTo(TestUtils.TEST_SELF_MANAGED_HANDLE_1, VideoProfile.STATE_BIDIRECTIONAL,
null);
// Expect the handover failed callback to be called.
mOnHandoverFailedCounter.waitForCount(WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
Call callbackCall = (Call) mOnHandoverFailedCounter.getArgs(0)[0];
int failureReason = (int) mOnHandoverFailedCounter.getArgs(0)[1];
assertEquals(call, callbackCall);
assertEquals(Call.Callback.HANDOVER_FAILURE_NOT_SUPPORTED, failureReason);
call.disconnect();
}
/**
* Ensures a call handover cannot be initiated to a {@link android.telecom.PhoneAccount} which
* does not declare {@link android.telecom.PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.
*/
public void testHandoverDestinationFailed() {
if (!mShouldTestTelecom) {
return;
}
startSourceCall();
Call call = mInCallCallbacks.getService().getLastCall();
// Now try to handover to an account which does not support handover.
call.handoverTo(TestUtils.TEST_SELF_MANAGED_HANDLE_1, VideoProfile.STATE_BIDIRECTIONAL,
null);
// Expect the handover failed callback to be called.
mOnHandoverFailedCounter.waitForCount(WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
Call callbackCall = (Call) mOnHandoverFailedCounter.getArgs(0)[0];
int failureReason = (int) mOnHandoverFailedCounter.getArgs(0)[1];
assertEquals(call, callbackCall);
assertEquals(Call.Callback.HANDOVER_FAILURE_NOT_SUPPORTED, failureReason);
call.disconnect();
}
/**
* Ensures that when the source and destination both support handover that an outgoing handover
* request will be successfully relayed.
*/
public void testOutgoingHandoverRequestValid() {
if (!mShouldTestTelecom) {
return;
}
// Begin our source call on the CS which supports handover from it.
startSourceCall();
final Call call = mInCallCallbacks.getService().getLastCall();
// Now try to handover to an account which does support handover to it.
call.handoverTo(TestUtils.TEST_HANDOVER_DEST_PHONE_ACCOUNT_HANDLE,
VideoProfile.STATE_BIDIRECTIONAL, null);
// Ensure Telecom bound to the self managed CS
if (!CtsSelfManagedConnectionService.waitForBinding()) {
fail("Could not bind to Self-Managed ConnectionService");
}
// Wait for binding to self managed CS and invocation of outgoing handover method.
TestUtils.InvokeCounter counter =
CtsSelfManagedConnectionService.getConnectionService()
.getOnCreateOutgoingHandoverConnectionCounter();
counter.waitForCount(WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
SelfManagedConnection connection = TestUtils.waitForAndGetConnection(
call.getDetails().getHandle());
// Verify the from handle is as expected.
PhoneAccountHandle fromHandle = (PhoneAccountHandle) counter.getArgs(0)[0];
assertEquals(TEST_HANDOVER_SRC_PHONE_ACCOUNT_HANDLE, fromHandle);
// Verify the to handle is as expected.
ConnectionRequest request = (ConnectionRequest) counter.getArgs(0)[1];
assertEquals(TEST_HANDOVER_DEST_PHONE_ACCOUNT_HANDLE, request.getAccountHandle());
completeHandoverAndVerify(call, connection);
}
/**
* Tests use of the
* {@link android.telecom.TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} API on
* the receiving side of the handover.
*/
public void testIncomingHandoverRequestValid() {
if (!mShouldTestTelecom) {
return;
}
// Begin our source call on the CS which supports handover from it.
startSourceCall();
final Call call = mInCallCallbacks.getService().getLastCall();
// Request to accept handover of that call to another app.
mTelecomManager.acceptHandover(call.getDetails().getHandle(),
VideoProfile.STATE_BIDIRECTIONAL, TEST_HANDOVER_DEST_PHONE_ACCOUNT_HANDLE);
// Ensure Telecom bound to the self managed CS
if (!CtsSelfManagedConnectionService.waitForBinding()) {
fail("Could not bind to Self-Managed ConnectionService");
}
// Wait for binding to self managed CS and invocation of incoming handover method.
TestUtils.InvokeCounter counter =
CtsSelfManagedConnectionService.getConnectionService()
.getOnCreateIncomingHandoverConnectionCounter();
counter.waitForCount(WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
SelfManagedConnection connection = TestUtils.waitForAndGetConnection(
call.getDetails().getHandle());
// Verify the from handle is as expected.
PhoneAccountHandle fromHandle = (PhoneAccountHandle) counter.getArgs(0)[0];
assertEquals(TEST_HANDOVER_SRC_PHONE_ACCOUNT_HANDLE, fromHandle);
// Verify the to handle is as expected.
ConnectionRequest request = (ConnectionRequest) counter.getArgs(0)[1];
assertEquals(TEST_HANDOVER_DEST_PHONE_ACCOUNT_HANDLE, request.getAccountHandle());
// The original call's address should match the address of the handover request.
assertEquals(call.getDetails().getHandle(), request.getAddress());
completeHandoverAndVerify(call, connection);
}
/**
* Begins a call which will be the source of a handover.
*/
private void startSourceCall() {
// Ensure the ongoing account is on a PhoneAccount which supports handover from.
Bundle extras = new Bundle();
extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
TEST_HANDOVER_SRC_PHONE_ACCOUNT_HANDLE);
placeAndVerifyCall(extras);
Connection connection = verifyConnectionForOutgoingCall();
connection.setActive();
Call call = mInCallCallbacks.getService().getLastCall();
assertCallState(call, Call.STATE_ACTIVE);
}
/**
* Complete the a call handover and verify that it was successfully reported.
* @param call
* @param connection
*/
private void completeHandoverAndVerify(final Call call, SelfManagedConnection connection) {
// Make the connection active, indicating that the user has accepted the handover.
connection.setActive();
// Expect the original call to have been informed of handover completion.
mOnHandoverCompleteCounter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
assertTrue("mOnHandoverCompleteCounter is zero",
mOnHandoverCompleteCounter.getInvokeCount() >= 1);
// Also expect the connection to be informed of handover completion.
connection.getHandoverCompleteCounter().waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
assertTrue("connection's handoverCompleteCounter is zero",
connection.getHandoverCompleteCounter().getInvokeCount() >= 1);
// Now, we expect that the original connection will get disconnected.
waitUntilConditionIsTrueOrTimeout(new Condition() {
@Override
public Object expected() {
return Call.STATE_DISCONNECTED;
}
@Override
public Object actual() {
return call.getState();
}
},
WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
"Expected original call to be disconnected."
);
}
}