blob: 48319adac7996e0d9d4b5271a6c8876869ac1e43 [file] [log] [blame]
/*
* 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 com.android.server.telecom.tests;
import static com.android.server.telecom.tests.TelecomSystemTest.TEST_TIMEOUT;
import android.content.ComponentName;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Binder;
import android.telecom.DisconnectCause;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.server.telecom.Call;
import com.android.server.telecom.CallIdMapper;
import com.android.server.telecom.ConnectionServiceFocusManager;
import com.android.server.telecom.ConnectionServiceRepository;
import com.android.server.telecom.ConnectionServiceWrapper;
import com.android.server.telecom.CreateConnectionProcessor;
import com.android.server.telecom.CreateConnectionResponse;
import com.android.server.telecom.PhoneAccountRegistrar;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import java.util.ArrayList;
import java.util.Arrays;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* Unit testing for CreateConnectionProcessor as well as CreateConnectionTimeout classes.
*/
@RunWith(JUnit4.class)
public class CreateConnectionProcessorTest extends TelecomTestCase {
private static final String TEST_PACKAGE = "com.android.server.telecom.tests";
private static final String TEST_CLASS =
"com.android.server.telecom.tests.MockConnectionService";
@Mock
ConnectionServiceRepository mMockConnectionServiceRepository;
@Mock
PhoneAccountRegistrar mMockAccountRegistrar;
@Mock
CreateConnectionResponse mMockCreateConnectionResponse;
@Mock
Call mMockCall;
@Mock
ConnectionServiceFocusManager mConnectionServiceFocusManager;
CreateConnectionProcessor mTestCreateConnectionProcessor;
@Override
@Before
public void setUp() throws Exception {
super.setUp();
MockitoAnnotations.initMocks(this);
mContext = mComponentContextFixture.getTestDouble().getApplicationContext();
when(mMockCall.getConnectionServiceFocusManager()).thenReturn(
mConnectionServiceFocusManager);
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
ConnectionServiceFocusManager.CallFocus focus =
(ConnectionServiceFocusManager.CallFocus) args[0];
ConnectionServiceFocusManager.RequestFocusCallback callback =
(ConnectionServiceFocusManager.RequestFocusCallback) args[1];
callback.onRequestFocusDone(focus);
return null;
}
}
).when(mConnectionServiceFocusManager).requestFocus(any(), any());
mTestCreateConnectionProcessor = new CreateConnectionProcessor(mMockCall,
mMockConnectionServiceRepository, mMockCreateConnectionResponse,
mMockAccountRegistrar, mContext);
}
@Override
@After
public void tearDown() throws Exception {
mTestCreateConnectionProcessor = null;
super.tearDown();
}
@SmallTest
@Test
public void testSimPhoneAccountSuccess() throws Exception {
PhoneAccountHandle pAHandle = getNewTargetPhoneAccountHandle("tel_acct");
when(mMockCall.isEmergencyCall()).thenReturn(false);
// No Connection Manager in this case
when(mMockAccountRegistrar.getSimCallManagerFromCall(any(Call.class))).thenReturn(null);
ConnectionServiceWrapper service = makeConnectionServiceWrapper();
mTestCreateConnectionProcessor.process();
verify(mMockCall).setConnectionManagerPhoneAccount(eq(pAHandle));
verify(mMockCall).setTargetPhoneAccount(eq(pAHandle));
verify(mMockCall).setConnectionService(eq(service));
verify(service).createConnection(eq(mMockCall), any(CreateConnectionResponse.class));
// Notify successful connection to call
CallIdMapper mockCallIdMapper = mock(CallIdMapper.class);
mTestCreateConnectionProcessor.handleCreateConnectionSuccess(mockCallIdMapper, null);
verify(mMockCreateConnectionResponse).handleCreateConnectionSuccess(mockCallIdMapper, null);
}
@SmallTest
@Test
public void testbadPhoneAccount() throws Exception {
PhoneAccountHandle pAHandle = null;
when(mMockCall.isEmergencyCall()).thenReturn(false);
when(mMockCall.getTargetPhoneAccount()).thenReturn(pAHandle);
givePhoneAccountBindPermission(pAHandle);
// No Connection Manager in this case
when(mMockAccountRegistrar.getSimCallManagerFromCall(any(Call.class))).thenReturn(null);
ConnectionServiceWrapper service = makeConnectionServiceWrapper();
mTestCreateConnectionProcessor.process();
verify(service, never()).createConnection(eq(mMockCall),
any(CreateConnectionResponse.class));
verify(mMockCreateConnectionResponse).handleCreateConnectionFailure(
eq(new DisconnectCause(DisconnectCause.ERROR)));
}
@SmallTest
@Test
public void testConnectionManagerSuccess() throws Exception {
PhoneAccountHandle pAHandle = getNewTargetPhoneAccountHandle("tel_acct");
when(mMockCall.isEmergencyCall()).thenReturn(false);
// Include a Connection Manager
PhoneAccountHandle callManagerPAHandle = getNewConnectionMangerHandle("cm_acct");
ConnectionServiceWrapper service = makeConnectionServiceWrapper();
// Make sure the target phone account has the correct permissions
PhoneAccount mFakeTargetPhoneAccount = makeQuickAccount("cm_acct",
PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION);
when(mMockAccountRegistrar.getPhoneAccountUnchecked(pAHandle)).thenReturn(
mFakeTargetPhoneAccount);
mTestCreateConnectionProcessor.process();
verify(mMockCall).setConnectionManagerPhoneAccount(eq(callManagerPAHandle));
verify(mMockCall).setTargetPhoneAccount(eq(pAHandle));
verify(mMockCall).setConnectionService(eq(service));
verify(service).createConnection(eq(mMockCall),
any(CreateConnectionResponse.class));
// Notify successful connection to call
CallIdMapper mockCallIdMapper = mock(CallIdMapper.class);
mTestCreateConnectionProcessor.handleCreateConnectionSuccess(mockCallIdMapper, null);
verify(mMockCreateConnectionResponse).handleCreateConnectionSuccess(mockCallIdMapper, null);
}
@SmallTest
@Test
public void testConnectionManagerFailedFallToSim() throws Exception {
PhoneAccountHandle pAHandle = getNewTargetPhoneAccountHandle("tel_acct");
when(mMockCall.isEmergencyCall()).thenReturn(false);
// Include a Connection Manager
PhoneAccountHandle callManagerPAHandle = getNewConnectionMangerHandle("cm_acct");
ConnectionServiceWrapper service = makeConnectionServiceWrapper();
when(mMockCall.getConnectionManagerPhoneAccount()).thenReturn(callManagerPAHandle);
PhoneAccount mFakeTargetPhoneAccount = makeQuickAccount("cm_acct",
PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION);
when(mMockAccountRegistrar.getPhoneAccountUnchecked(pAHandle)).thenReturn(
mFakeTargetPhoneAccount);
when(mMockCall.getConnectionService()).thenReturn(service);
// Put CreateConnectionProcessor in correct state to fail with ConnectionManager
mTestCreateConnectionProcessor.process();
reset(mMockCall);
reset(service);
when(mMockCall.getConnectionServiceFocusManager()).thenReturn(
mConnectionServiceFocusManager);
// Notify that the ConnectionManager has denied the call.
when(mMockCall.getConnectionManagerPhoneAccount()).thenReturn(callManagerPAHandle);
when(mMockCall.getConnectionService()).thenReturn(service);
mTestCreateConnectionProcessor.handleCreateConnectionFailure(
new DisconnectCause(DisconnectCause.CONNECTION_MANAGER_NOT_SUPPORTED));
// Verify that the Sim Phone Account is used correctly
verify(mMockCall).setConnectionManagerPhoneAccount(eq(pAHandle));
verify(mMockCall).setTargetPhoneAccount(eq(pAHandle));
verify(mMockCall).setConnectionService(eq(service));
verify(service).createConnection(eq(mMockCall), any(CreateConnectionResponse.class));
// Notify successful connection to call
CallIdMapper mockCallIdMapper = mock(CallIdMapper.class);
mTestCreateConnectionProcessor.handleCreateConnectionSuccess(mockCallIdMapper, null);
verify(mMockCreateConnectionResponse).handleCreateConnectionSuccess(mockCallIdMapper, null);
}
@SmallTest
@Test
public void testConnectionManagerFailedDoNotFallToSim() throws Exception {
PhoneAccountHandle pAHandle = getNewTargetPhoneAccountHandle("tel_acct");
when(mMockCall.isEmergencyCall()).thenReturn(false);
// Include a Connection Manager
PhoneAccountHandle callManagerPAHandle = getNewConnectionMangerHandle("cm_acct");
ConnectionServiceWrapper service = makeConnectionServiceWrapper();
when(mMockCall.getConnectionManagerPhoneAccount()).thenReturn(callManagerPAHandle);
PhoneAccount mFakeTargetPhoneAccount = makeQuickAccount("cm_acct",
PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION);
when(mMockAccountRegistrar.getPhoneAccountUnchecked(pAHandle)).thenReturn(
mFakeTargetPhoneAccount);
when(mMockCall.getConnectionService()).thenReturn(service);
// Put CreateConnectionProcessor in correct state to fail with ConnectionManager
mTestCreateConnectionProcessor.process();
reset(mMockCall);
reset(service);
when(mMockCall.getConnectionServiceFocusManager()).thenReturn(
mConnectionServiceFocusManager);
// Notify that the ConnectionManager has rejected the call.
when(mMockCall.getConnectionManagerPhoneAccount()).thenReturn(callManagerPAHandle);
when(mMockCall.getConnectionService()).thenReturn(service);
when(service.isServiceValid("createConnection")).thenReturn(true);
mTestCreateConnectionProcessor.handleCreateConnectionFailure(
new DisconnectCause(DisconnectCause.OTHER));
// Verify call connection rejected
verify(mMockCreateConnectionResponse).handleCreateConnectionFailure(
new DisconnectCause(DisconnectCause.OTHER));
}
@SmallTest
@Test
public void testEmergencyCallToSim() throws Exception {
when(mMockCall.isEmergencyCall()).thenReturn(true);
// Put in a regular phone account to be sure it doesn't call that
PhoneAccountHandle pAHandle = getNewTargetPhoneAccountHandle("tel_acct");
// Include a Connection Manager to be sure it doesn't call that
PhoneAccount callManagerPA = getNewConnectionManagerPhoneAccount("cm_acct", 0);
ConnectionServiceWrapper service = makeConnectionServiceWrapper();
PhoneAccount emergencyPhoneAccount = makeEmergencyPhoneAccount("tel_emer");
PhoneAccountHandle emergencyPhoneAccountHandle = emergencyPhoneAccount.getAccountHandle();
mTestCreateConnectionProcessor.process();
verify(mMockCall).setConnectionManagerPhoneAccount(eq(emergencyPhoneAccountHandle));
verify(mMockCall).setTargetPhoneAccount(eq(emergencyPhoneAccountHandle));
verify(mMockCall).setConnectionService(eq(service));
verify(service).createConnection(eq(mMockCall), any(CreateConnectionResponse.class));
// Notify successful connection to call
CallIdMapper mockCallIdMapper = mock(CallIdMapper.class);
mTestCreateConnectionProcessor.handleCreateConnectionSuccess(mockCallIdMapper, null);
verify(mMockCreateConnectionResponse).handleCreateConnectionSuccess(mockCallIdMapper, null);
}
@SmallTest
@Test
public void testEmergencyCallSimFailToConnectionManager() throws Exception {
when(mMockCall.isEmergencyCall()).thenReturn(true);
when(mMockCall.getHandle()).thenReturn(Uri.parse(""));
// Put in a regular phone account to be sure it doesn't call that
PhoneAccountHandle pAHandle = getNewTargetPhoneAccountHandle("tel_acct");
when(mMockAccountRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
nullable(String.class))).thenReturn(pAHandle);
// Include a normal Connection Manager to be sure it doesn't call that
PhoneAccount callManagerPA = getNewConnectionManagerPhoneAccount("cm_acct", 0);
// Include a connection Manager for the user with the capability to make calls
PhoneAccount emerCallManagerPA = getNewEmergencyConnectionManagerPhoneAccount("cm_acct",
PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS);
ConnectionServiceWrapper service = makeConnectionServiceWrapper();
PhoneAccount emergencyPhoneAccount = makeEmergencyPhoneAccount("tel_emer");
mTestCreateConnectionProcessor.process();
reset(mMockCall);
reset(service);
when(mMockCall.getConnectionServiceFocusManager()).thenReturn(
mConnectionServiceFocusManager);
when(mMockCall.isEmergencyCall()).thenReturn(true);
// When Notify SIM connection fails, fall back to connection manager
mTestCreateConnectionProcessor.handleCreateConnectionFailure(new DisconnectCause(
DisconnectCause.REJECTED));
verify(mMockCall).setConnectionManagerPhoneAccount(
eq(emerCallManagerPA.getAccountHandle()));
verify(mMockCall).setTargetPhoneAccount(eq(pAHandle));
verify(mMockCall).setConnectionService(eq(service));
verify(service).createConnection(eq(mMockCall), any(CreateConnectionResponse.class));
}
private PhoneAccount makeEmergencyPhoneAccount(String id) {
final PhoneAccount emergencyPhoneAccount = makeQuickAccount(id,
PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS |
PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION);
PhoneAccountHandle emergencyPhoneAccountHandle = emergencyPhoneAccount.getAccountHandle();
givePhoneAccountBindPermission(emergencyPhoneAccountHandle);
ArrayList<PhoneAccount> phoneAccounts = new ArrayList<PhoneAccount>() {{
add(emergencyPhoneAccount);
}};
when(mMockAccountRegistrar.getAllPhoneAccountsOfCurrentUser()).thenReturn(phoneAccounts);
return emergencyPhoneAccount;
}
private void givePhoneAccountBindPermission(PhoneAccountHandle handle) {
when(mMockAccountRegistrar.phoneAccountRequiresBindPermission(eq(handle))).thenReturn(true);
}
private PhoneAccountHandle getNewConnectionMangerHandle(String id) {
PhoneAccountHandle callManagerPAHandle = makeQuickAccountHandle(id);
when(mMockAccountRegistrar.getSimCallManagerFromCall(any(Call.class))).thenReturn(
callManagerPAHandle);
givePhoneAccountBindPermission(callManagerPAHandle);
return callManagerPAHandle;
}
private PhoneAccountHandle getNewTargetPhoneAccountHandle(String id) {
PhoneAccountHandle pAHandle = makeQuickAccountHandle(id);
when(mMockCall.getTargetPhoneAccount()).thenReturn(pAHandle);
givePhoneAccountBindPermission(pAHandle);
return pAHandle;
}
private PhoneAccount getNewConnectionManagerPhoneAccount(String id, int capability) {
PhoneAccount callManagerPA = makeQuickAccount(id, capability);
when(mMockAccountRegistrar.getSimCallManagerFromCall(any(Call.class))).thenReturn(
callManagerPA.getAccountHandle());
givePhoneAccountBindPermission(callManagerPA.getAccountHandle());
when(mMockAccountRegistrar.getPhoneAccountUnchecked(
callManagerPA.getAccountHandle())).thenReturn(callManagerPA);
return callManagerPA;
}
private PhoneAccount getNewEmergencyConnectionManagerPhoneAccount(String id, int capability) {
PhoneAccount callManagerPA = makeQuickAccount(id, capability);
when(mMockAccountRegistrar.getSimCallManagerOfCurrentUser()).thenReturn(
callManagerPA.getAccountHandle());
givePhoneAccountBindPermission(callManagerPA.getAccountHandle());
when(mMockAccountRegistrar.getPhoneAccountUnchecked(
callManagerPA.getAccountHandle())).thenReturn(callManagerPA);
return callManagerPA;
}
private static ComponentName makeQuickConnectionServiceComponentName() {
return new ComponentName(TEST_PACKAGE, TEST_CLASS);
}
private ConnectionServiceWrapper makeConnectionServiceWrapper() {
ConnectionServiceWrapper wrapper = mock(ConnectionServiceWrapper.class);
when(mMockConnectionServiceRepository.getService(
eq(makeQuickConnectionServiceComponentName()),
eq(Binder.getCallingUserHandle()))).thenReturn(wrapper);
return wrapper;
}
private static PhoneAccountHandle makeQuickAccountHandle(String id) {
return new PhoneAccountHandle(makeQuickConnectionServiceComponentName(), id,
Binder.getCallingUserHandle());
}
private PhoneAccount.Builder makeQuickAccountBuilder(String id, int idx) {
return new PhoneAccount.Builder(makeQuickAccountHandle(id), "label" + idx);
}
private PhoneAccount makeQuickAccount(String id, int idx) {
return makeQuickAccountBuilder(id, idx)
.setAddress(Uri.parse("http://foo.com/" + idx))
.setSubscriptionAddress(Uri.parse("tel:555-000" + idx))
.setCapabilities(idx)
.setIcon(Icon.createWithResource(
"com.android.server.telecom.tests", R.drawable.stat_sys_phone_call))
.setShortDescription("desc" + idx)
.setIsEnabled(true)
.build();
}
}