| /* |
| * 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 android.content.ComponentName; |
| import android.graphics.drawable.Icon; |
| import android.net.Uri; |
| import android.os.Binder; |
| import android.os.Debug; |
| 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.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.mockito.Mock; |
| import org.mockito.MockitoAnnotations; |
| |
| import java.util.ArrayList; |
| |
| import static org.mockito.Matchers.any; |
| import static org.mockito.Matchers.eq; |
| import static org.mockito.Mockito.mock; |
| import static org.mockito.Mockito.never; |
| import static org.mockito.Mockito.reset; |
| import static org.mockito.Mockito.verify; |
| import static org.mockito.Mockito.when; |
| |
| /** |
| * Unit testing for CreateConnectionProcessor as well as CreateConnectionTimeout classes. |
| */ |
| 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; |
| |
| CreateConnectionProcessor mTestCreateConnectionProcessor; |
| |
| @Override |
| public void setUp() throws Exception { |
| super.setUp(); |
| MockitoAnnotations.initMocks(this); |
| mContext = mComponentContextFixture.getTestDouble().getApplicationContext(); |
| |
| mTestCreateConnectionProcessor = new CreateConnectionProcessor(mMockCall, |
| mMockConnectionServiceRepository, mMockCreateConnectionResponse, |
| mMockAccountRegistrar, mContext); |
| } |
| |
| @Override |
| public void tearDown() throws Exception { |
| mTestCreateConnectionProcessor = null; |
| super.tearDown(); |
| } |
| |
| @SmallTest |
| 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 |
| 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 |
| 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 |
| 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); |
| |
| // 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 |
| 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); |
| |
| // 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 |
| 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 |
| 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( |
| any(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.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(); |
| } |
| } |