| /* |
| * 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.content.Context; |
| 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.telephony.SubscriptionManager; |
| 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.HashMap; |
| import java.util.List; |
| |
| import static org.mockito.ArgumentMatchers.anyList; |
| 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.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; |
| |
| private ArrayList<PhoneAccount> phoneAccounts; |
| private HashMap<Integer,Integer> mSubToSlot; |
| private HashMap<PhoneAccount,Integer> mAccountToSub; |
| |
| @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); |
| |
| mAccountToSub = new HashMap<>(); |
| phoneAccounts = new ArrayList<>(); |
| mSubToSlot = new HashMap<>(); |
| mTestCreateConnectionProcessor.setTelephonyManagerAdapter( |
| new CreateConnectionProcessor.ITelephonyManagerAdapter() { |
| @Override |
| public int getSubIdForPhoneAccount(Context context, PhoneAccount account) { |
| return mAccountToSub.getOrDefault(account, |
| SubscriptionManager.INVALID_SIM_SLOT_INDEX); |
| } |
| |
| @Override |
| public int getSlotIndex(int subId) { |
| return mSubToSlot.getOrDefault(subId, |
| SubscriptionManager.INVALID_SIM_SLOT_INDEX); |
| } |
| }); |
| when(mMockAccountRegistrar.getAllPhoneAccountsOfCurrentUser()).thenReturn(phoneAccounts); |
| } |
| |
| @Override |
| @After |
| public void tearDown() throws Exception { |
| mTestCreateConnectionProcessor = null; |
| super.tearDown(); |
| } |
| |
| @SmallTest |
| @Test |
| public void testSimPhoneAccountSuccess() throws Exception { |
| PhoneAccountHandle pAHandle = getNewTargetPhoneAccountHandle("tel_acct"); |
| setTargetPhoneAccount(mMockCall, pAHandle); |
| 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"); |
| setTargetPhoneAccount(mMockCall, pAHandle); |
| when(mMockCall.isEmergencyCall()).thenReturn(false); |
| // Include a Connection Manager |
| PhoneAccountHandle callManagerPAHandle = getNewConnectionMangerHandleForCall(mMockCall, |
| "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"); |
| setTargetPhoneAccount(mMockCall, pAHandle); |
| when(mMockCall.isEmergencyCall()).thenReturn(false); |
| // Include a Connection Manager |
| PhoneAccountHandle callManagerPAHandle = getNewConnectionMangerHandleForCall(mMockCall, |
| "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"); |
| setTargetPhoneAccount(mMockCall, pAHandle); |
| when(mMockCall.isEmergencyCall()).thenReturn(false); |
| // Include a Connection Manager |
| PhoneAccountHandle callManagerPAHandle = getNewConnectionMangerHandleForCall(mMockCall, |
| "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)); |
| } |
| |
| /** |
| * Ensure that when a test emergency number is being dialed and we restrict the usable |
| * PhoneAccounts using {@link PhoneAccountRegistrar#filterRestrictedPhoneAccounts(List)}, the |
| * test emergency call is sent on the filtered PhoneAccount. |
| */ |
| @SmallTest |
| @Test |
| public void testFakeEmergencyNumber() throws Exception { |
| when(mMockCall.isEmergencyCall()).thenReturn(true); |
| when(mMockCall.isTestEmergencyCall()).thenReturn(true); |
| // Put in a regular phone account as the target and make sure it calls that. |
| PhoneAccount regularAccount = makeEmergencyTestPhoneAccount("tel_acct1", 0); |
| PhoneAccountHandle regularAccountHandle = regularAccount.getAccountHandle(); |
| List<PhoneAccount> filteredList = new ArrayList<>(); |
| filteredList.add(regularAccount); |
| when(mMockAccountRegistrar.filterRestrictedPhoneAccounts(anyList())) |
| .thenReturn(filteredList); |
| mapToSubSlot(regularAccount, 1 /*subId*/, 0 /*slotId*/); |
| setTargetPhoneAccount(mMockCall, regularAccount.getAccountHandle()); |
| phoneAccounts.add(regularAccount); |
| // Do not use this account, even though it is a SIM subscription and can place emergency |
| // calls |
| ConnectionServiceWrapper service = makeConnectionServiceWrapper(); |
| PhoneAccount emergencyPhoneAccount = makeEmergencyPhoneAccount("tel_emer", 0); |
| mapToSubSlot(emergencyPhoneAccount, 2 /*subId*/, 1 /*slotId*/); |
| phoneAccounts.add(emergencyPhoneAccount); |
| |
| mTestCreateConnectionProcessor.process(); |
| |
| verify(mMockCall).setConnectionManagerPhoneAccount(eq(regularAccountHandle)); |
| verify(mMockCall).setTargetPhoneAccount(eq(regularAccountHandle)); |
| 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); |
| } |
| |
| /** |
| * Ensure that the non-emergency capable PhoneAccount and the SIM manager is not chosen to place |
| * the emergency call if there is an emergency capable PhoneAccount available as well. |
| */ |
| @SmallTest |
| @Test |
| public void testEmergencyCall() throws Exception { |
| when(mMockCall.isEmergencyCall()).thenReturn(true); |
| when(mMockCall.isTestEmergencyCall()).thenReturn(false); |
| // Put in a regular phone account as the target to be sure it doesn't call that |
| PhoneAccount regularAccount = makePhoneAccount("tel_acct1", |
| PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION); |
| mapToSubSlot(regularAccount, 1 /*subId*/, 0 /*slotId*/); |
| setTargetPhoneAccount(mMockCall, regularAccount.getAccountHandle()); |
| phoneAccounts.add(regularAccount); |
| // Include a Connection Manager to be sure it doesn't call that |
| PhoneAccount callManagerPA = createNewConnectionManagerPhoneAccountForCall(mMockCall, |
| "cm_acct", 0); |
| phoneAccounts.add(callManagerPA); |
| ConnectionServiceWrapper service = makeConnectionServiceWrapper(); |
| PhoneAccount emergencyPhoneAccount = makeEmergencyPhoneAccount("tel_emer", 0); |
| mapToSubSlot(emergencyPhoneAccount, 2 /*subId*/, 1 /*slotId*/); |
| phoneAccounts.add(emergencyPhoneAccount); |
| 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); |
| } |
| |
| /** |
| * 1) Ensure that if there is a non-SIM PhoneAccount, it is not chosen as the Phone Account to |
| * dial the emergency call. |
| * 2) Register multiple emergency capable PhoneAccounts. Since there is not preference, we |
| * default to sending on the lowest slot. |
| */ |
| @SmallTest |
| @Test |
| public void testEmergencyCallMultiSimNoPreferred() throws Exception { |
| when(mMockCall.isEmergencyCall()).thenReturn(true); |
| when(mMockCall.isTestEmergencyCall()).thenReturn(false); |
| // Put in a non-SIM phone account as the target to be sure it doesn't call that. |
| PhoneAccount regularAccount = makePhoneAccount("tel_acct1", 0); |
| setTargetPhoneAccount(mMockCall, regularAccount.getAccountHandle()); |
| // Include a Connection Manager to be sure it doesn't call that |
| PhoneAccount callManagerPA = createNewConnectionManagerPhoneAccountForCall(mMockCall, |
| "cm_acct", 0); |
| phoneAccounts.add(callManagerPA); |
| ConnectionServiceWrapper service = makeConnectionServiceWrapper(); |
| PhoneAccount emergencyPhoneAccount1 = makeEmergencyPhoneAccount("tel_emer1", 0); |
| phoneAccounts.add(emergencyPhoneAccount1); |
| mapToSubSlot(emergencyPhoneAccount1, 1 /*subId*/, 1 /*slotId*/); |
| PhoneAccount emergencyPhoneAccount2 = makeEmergencyPhoneAccount("tel_emer2", 0); |
| phoneAccounts.add(emergencyPhoneAccount2); |
| mapToSubSlot(emergencyPhoneAccount2, 2 /*subId*/, 0 /*slotId*/); |
| PhoneAccountHandle emergencyPhoneAccountHandle2 = emergencyPhoneAccount2.getAccountHandle(); |
| |
| mTestCreateConnectionProcessor.process(); |
| |
| // We did not set a preference |
| verify(mMockCall).setConnectionManagerPhoneAccount(eq(emergencyPhoneAccountHandle2)); |
| verify(mMockCall).setTargetPhoneAccount(eq(emergencyPhoneAccountHandle2)); |
| 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); |
| } |
| |
| /** |
| * Ensure that the call goes out on the PhoneAccount that has the CAPABILITY_EMERGENCY_PREFERRED |
| * capability, even if the user specifically chose the other emergency capable PhoneAccount. |
| */ |
| @SmallTest |
| @Test |
| public void testEmergencyCallMultiSimTelephonyPreferred() throws Exception { |
| when(mMockCall.isEmergencyCall()).thenReturn(true); |
| when(mMockCall.isTestEmergencyCall()).thenReturn(false); |
| ConnectionServiceWrapper service = makeConnectionServiceWrapper(); |
| PhoneAccount emergencyPhoneAccount1 = makeEmergencyPhoneAccount("tel_emer1", 0); |
| mapToSubSlot(emergencyPhoneAccount1, 1 /*subId*/, 0 /*slotId*/); |
| setTargetPhoneAccount(mMockCall, emergencyPhoneAccount1.getAccountHandle()); |
| phoneAccounts.add(emergencyPhoneAccount1); |
| PhoneAccount emergencyPhoneAccount2 = makeEmergencyPhoneAccount("tel_emer2", |
| PhoneAccount.CAPABILITY_EMERGENCY_PREFERRED); |
| mapToSubSlot(emergencyPhoneAccount2, 2 /*subId*/, 1 /*slotId*/); |
| phoneAccounts.add(emergencyPhoneAccount2); |
| PhoneAccountHandle emergencyPhoneAccountHandle2 = emergencyPhoneAccount2.getAccountHandle(); |
| |
| mTestCreateConnectionProcessor.process(); |
| |
| // Make sure the telephony preferred SIM is the one that is chosen. |
| verify(mMockCall).setConnectionManagerPhoneAccount(eq(emergencyPhoneAccountHandle2)); |
| verify(mMockCall).setTargetPhoneAccount(eq(emergencyPhoneAccountHandle2)); |
| 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); |
| } |
| |
| /** |
| * If there is no phone account with CAPABILITY_EMERGENCY_PREFERRED capability, choose the user |
| * chosen target account. |
| */ |
| @SmallTest |
| @Test |
| public void testEmergencyCallMultiSimUserPreferred() throws Exception { |
| when(mMockCall.isEmergencyCall()).thenReturn(true); |
| when(mMockCall.isTestEmergencyCall()).thenReturn(false); |
| // Include a Connection Manager to be sure it doesn't call that |
| PhoneAccount callManagerPA = createNewConnectionManagerPhoneAccountForCall(mMockCall, |
| "cm_acct", 0); |
| phoneAccounts.add(callManagerPA); |
| ConnectionServiceWrapper service = makeConnectionServiceWrapper(); |
| PhoneAccount emergencyPhoneAccount1 = makeEmergencyPhoneAccount("tel_emer1", 0); |
| mapToSubSlot(emergencyPhoneAccount1, 1 /*subId*/, 0 /*slotId*/); |
| phoneAccounts.add(emergencyPhoneAccount1); |
| PhoneAccount emergencyPhoneAccount2 = makeEmergencyPhoneAccount("tel_emer2", 0); |
| // Make this the user preferred account |
| mapToSubSlot(emergencyPhoneAccount2, 2 /*subId*/, 1 /*slotId*/); |
| setTargetPhoneAccount(mMockCall, emergencyPhoneAccount2.getAccountHandle()); |
| phoneAccounts.add(emergencyPhoneAccount2); |
| PhoneAccountHandle emergencyPhoneAccountHandle2 = emergencyPhoneAccount2.getAccountHandle(); |
| |
| mTestCreateConnectionProcessor.process(); |
| |
| // Make sure the user preferred SIM is the one that is chosen. |
| verify(mMockCall).setConnectionManagerPhoneAccount(eq(emergencyPhoneAccountHandle2)); |
| verify(mMockCall).setTargetPhoneAccount(eq(emergencyPhoneAccountHandle2)); |
| 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); |
| } |
| |
| /** |
| * If the user preferred PhoneAccount is associated with an invalid slot, place on the other, |
| * valid slot. |
| */ |
| @SmallTest |
| @Test |
| public void testEmergencyCallMultiSimUserPreferredInvalidSlot() throws Exception { |
| when(mMockCall.isEmergencyCall()).thenReturn(true); |
| when(mMockCall.isTestEmergencyCall()).thenReturn(false); |
| // Include a Connection Manager to be sure it doesn't call that |
| PhoneAccount callManagerPA = createNewConnectionManagerPhoneAccountForCall(mMockCall, |
| "cm_acct", 0); |
| phoneAccounts.add(callManagerPA); |
| ConnectionServiceWrapper service = makeConnectionServiceWrapper(); |
| PhoneAccount emergencyPhoneAccount1 = makeEmergencyPhoneAccount("tel_emer1", 0); |
| // make this the user preferred account |
| setTargetPhoneAccount(mMockCall, emergencyPhoneAccount1.getAccountHandle()); |
| mapToSubSlot(emergencyPhoneAccount1, 1 /*subId*/, |
| SubscriptionManager.INVALID_SIM_SLOT_INDEX /*slotId*/); |
| phoneAccounts.add(emergencyPhoneAccount1); |
| PhoneAccount emergencyPhoneAccount2 = makeEmergencyPhoneAccount("tel_emer2", 0); |
| mapToSubSlot(emergencyPhoneAccount2, 2 /*subId*/, 1 /*slotId*/); |
| phoneAccounts.add(emergencyPhoneAccount2); |
| PhoneAccountHandle emergencyPhoneAccountHandle2 = emergencyPhoneAccount2.getAccountHandle(); |
| |
| mTestCreateConnectionProcessor.process(); |
| |
| // Make sure the valid SIM is the one that is chosen. |
| verify(mMockCall).setConnectionManagerPhoneAccount(eq(emergencyPhoneAccountHandle2)); |
| verify(mMockCall).setTargetPhoneAccount(eq(emergencyPhoneAccountHandle2)); |
| 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); |
| } |
| |
| /** |
| * If a PhoneAccount is associated with an invalid slot, place on the other, valid slot. |
| */ |
| @SmallTest |
| @Test |
| public void testEmergencyCallMultiSimNoPreferenceInvalidSlot() throws Exception { |
| when(mMockCall.isEmergencyCall()).thenReturn(true); |
| when(mMockCall.isTestEmergencyCall()).thenReturn(false); |
| // Include a Connection Manager to be sure it doesn't call that |
| PhoneAccount callManagerPA = createNewConnectionManagerPhoneAccountForCall(mMockCall, |
| "cm_acct", 0); |
| phoneAccounts.add(callManagerPA); |
| ConnectionServiceWrapper service = makeConnectionServiceWrapper(); |
| PhoneAccount emergencyPhoneAccount1 = makeEmergencyPhoneAccount("tel_emer1", 0); |
| mapToSubSlot(emergencyPhoneAccount1, 1 /*subId*/, |
| SubscriptionManager.INVALID_SIM_SLOT_INDEX /*slotId*/); |
| phoneAccounts.add(emergencyPhoneAccount1); |
| PhoneAccount emergencyPhoneAccount2 = makeEmergencyPhoneAccount("tel_emer2", 0); |
| mapToSubSlot(emergencyPhoneAccount2, 2 /*subId*/, 1 /*slotId*/); |
| phoneAccounts.add(emergencyPhoneAccount2); |
| PhoneAccountHandle emergencyPhoneAccountHandle2 = emergencyPhoneAccount2.getAccountHandle(); |
| |
| mTestCreateConnectionProcessor.process(); |
| |
| // Make sure the valid SIM is the one that is chosen. |
| verify(mMockCall).setConnectionManagerPhoneAccount(eq(emergencyPhoneAccountHandle2)); |
| verify(mMockCall).setTargetPhoneAccount(eq(emergencyPhoneAccountHandle2)); |
| 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.isTestEmergencyCall()).thenReturn(false); |
| when(mMockCall.getHandle()).thenReturn(Uri.parse("")); |
| // Put in a regular phone account to be sure it doesn't call that |
| PhoneAccount regularAccount = makePhoneAccount("tel_acct1", |
| PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION); |
| mapToSubSlot(regularAccount, 1 /*subId*/, 0 /*slotId*/); |
| setTargetPhoneAccount(mMockCall, regularAccount.getAccountHandle()); |
| phoneAccounts.add(regularAccount); |
| when(mMockAccountRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser( |
| nullable(String.class))).thenReturn(regularAccount.getAccountHandle()); |
| // Include a normal Connection Manager to be sure it doesn't call that |
| PhoneAccount callManagerPA = createNewConnectionManagerPhoneAccountForCall(mMockCall, |
| "cm_acct", 0); |
| phoneAccounts.add(callManagerPA); |
| // 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", 0); |
| phoneAccounts.add(emergencyPhoneAccount); |
| mapToSubSlot(regularAccount, 2 /*subId*/, 1 /*slotId*/); |
| 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(regularAccount.getAccountHandle())); |
| verify(mMockCall).setConnectionService(eq(service)); |
| verify(service).createConnection(eq(mMockCall), any(CreateConnectionResponse.class)); |
| } |
| |
| private PhoneAccount makeEmergencyTestPhoneAccount(String id, int capabilities) { |
| final PhoneAccount emergencyPhoneAccount = makeQuickAccount(id, capabilities | |
| PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS); |
| PhoneAccountHandle emergencyPhoneAccountHandle = emergencyPhoneAccount.getAccountHandle(); |
| givePhoneAccountBindPermission(emergencyPhoneAccountHandle); |
| when(mMockAccountRegistrar.getPhoneAccountUnchecked(emergencyPhoneAccountHandle)) |
| .thenReturn(emergencyPhoneAccount); |
| return emergencyPhoneAccount; |
| } |
| |
| private PhoneAccount makeEmergencyPhoneAccount(String id, int capabilities) { |
| final PhoneAccount emergencyPhoneAccount = makeQuickAccount(id, capabilities | |
| PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS | |
| PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION); |
| PhoneAccountHandle emergencyPhoneAccountHandle = emergencyPhoneAccount.getAccountHandle(); |
| givePhoneAccountBindPermission(emergencyPhoneAccountHandle); |
| when(mMockAccountRegistrar.getPhoneAccountUnchecked(emergencyPhoneAccountHandle)) |
| .thenReturn(emergencyPhoneAccount); |
| return emergencyPhoneAccount; |
| } |
| |
| private PhoneAccount makePhoneAccount(String id, int capabilities) { |
| final PhoneAccount phoneAccount = makeQuickAccount(id, capabilities); |
| PhoneAccountHandle phoneAccountHandle = phoneAccount.getAccountHandle(); |
| givePhoneAccountBindPermission(phoneAccountHandle); |
| when(mMockAccountRegistrar.getPhoneAccountUnchecked( |
| phoneAccount.getAccountHandle())).thenReturn(phoneAccount); |
| return phoneAccount; |
| } |
| |
| private void mapToSubSlot(PhoneAccount account, int subId, int slotId) { |
| mAccountToSub.put(account, subId); |
| mSubToSlot.put(subId, slotId); |
| } |
| |
| private void givePhoneAccountBindPermission(PhoneAccountHandle handle) { |
| when(mMockAccountRegistrar.phoneAccountRequiresBindPermission(eq(handle))).thenReturn(true); |
| } |
| |
| private PhoneAccountHandle getNewConnectionMangerHandleForCall(Call call, String id) { |
| PhoneAccountHandle callManagerPAHandle = makeQuickAccountHandle(id); |
| when(mMockAccountRegistrar.getSimCallManagerFromCall(eq(call))).thenReturn( |
| callManagerPAHandle); |
| givePhoneAccountBindPermission(callManagerPAHandle); |
| return callManagerPAHandle; |
| } |
| |
| private PhoneAccountHandle getNewTargetPhoneAccountHandle(String id) { |
| PhoneAccountHandle pAHandle = makeQuickAccountHandle(id); |
| givePhoneAccountBindPermission(pAHandle); |
| return pAHandle; |
| } |
| |
| private void setTargetPhoneAccount(Call call, PhoneAccountHandle pAHandle) { |
| when(call.getTargetPhoneAccount()).thenReturn(pAHandle); |
| } |
| |
| private PhoneAccount createNewConnectionManagerPhoneAccountForCall(Call call, String id, |
| int capability) { |
| PhoneAccount callManagerPA = makeQuickAccount(id, capability); |
| when(mMockAccountRegistrar.getSimCallManagerFromCall(eq(call))).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(); |
| } |
| } |