Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License
     15  */
     16 
     17 package com.android.server.telecom.tests;
     18 
     19 import static com.android.server.telecom.tests.TelecomSystemTest.TEST_TIMEOUT;
     20 
     21 import android.content.ComponentName;
     22 import android.graphics.drawable.Icon;
     23 import android.net.Uri;
     24 import android.os.Binder;
     25 import android.telecom.DisconnectCause;
     26 import android.telecom.PhoneAccount;
     27 import android.telecom.PhoneAccountHandle;
     28 import android.test.suitebuilder.annotation.SmallTest;
     29 
     30 import com.android.server.telecom.Call;
     31 import com.android.server.telecom.CallIdMapper;
     32 import com.android.server.telecom.ConnectionServiceFocusManager;
     33 import com.android.server.telecom.ConnectionServiceRepository;
     34 import com.android.server.telecom.ConnectionServiceWrapper;
     35 import com.android.server.telecom.CreateConnectionProcessor;
     36 import com.android.server.telecom.CreateConnectionResponse;
     37 import com.android.server.telecom.PhoneAccountRegistrar;
     38 
     39 import org.junit.After;
     40 import org.junit.Before;
     41 import org.junit.Test;
     42 import org.junit.runner.RunWith;
     43 import org.junit.runners.JUnit4;
     44 import org.mockito.Mock;
     45 import org.mockito.MockitoAnnotations;
     46 import org.mockito.invocation.InvocationOnMock;
     47 import org.mockito.stubbing.Answer;
     48 
     49 import java.util.ArrayList;
     50 import java.util.Arrays;
     51 
     52 import static org.mockito.ArgumentMatchers.nullable;
     53 import static org.mockito.Matchers.any;
     54 import static org.mockito.Matchers.eq;
     55 import static org.mockito.Mockito.doAnswer;
     56 import static org.mockito.Mockito.mock;
     57 import static org.mockito.Mockito.never;
     58 import static org.mockito.Mockito.reset;
     59 import static org.mockito.Mockito.timeout;
     60 import static org.mockito.Mockito.verify;
     61 import static org.mockito.Mockito.when;
     62 
     63 /**
     64  * Unit testing for CreateConnectionProcessor as well as CreateConnectionTimeout classes.
     65  */
     66 @RunWith(JUnit4.class)
     67 public class CreateConnectionProcessorTest extends TelecomTestCase {
     68 
     69     private static final String TEST_PACKAGE = "com.android.server.telecom.tests";
     70     private static final String TEST_CLASS =
     71             "com.android.server.telecom.tests.MockConnectionService";
     72 
     73     @Mock
     74     ConnectionServiceRepository mMockConnectionServiceRepository;
     75     @Mock
     76     PhoneAccountRegistrar mMockAccountRegistrar;
     77     @Mock
     78     CreateConnectionResponse mMockCreateConnectionResponse;
     79     @Mock
     80     Call mMockCall;
     81     @Mock
     82     ConnectionServiceFocusManager mConnectionServiceFocusManager;
     83 
     84     CreateConnectionProcessor mTestCreateConnectionProcessor;
     85 
     86     @Override
     87     @Before
     88     public void setUp() throws Exception {
     89         super.setUp();
     90         MockitoAnnotations.initMocks(this);
     91         mContext = mComponentContextFixture.getTestDouble().getApplicationContext();
     92 
     93         when(mMockCall.getConnectionServiceFocusManager()).thenReturn(
     94                 mConnectionServiceFocusManager);
     95         doAnswer(new Answer<Void>() {
     96                      @Override
     97                      public Void answer(InvocationOnMock invocation) {
     98                          Object[] args = invocation.getArguments();
     99                          ConnectionServiceFocusManager.CallFocus focus =
    100                                  (ConnectionServiceFocusManager.CallFocus) args[0];
    101                          ConnectionServiceFocusManager.RequestFocusCallback callback =
    102                                  (ConnectionServiceFocusManager.RequestFocusCallback) args[1];
    103                          callback.onRequestFocusDone(focus);
    104                          return null;
    105                      }
    106                  }
    107                 ).when(mConnectionServiceFocusManager).requestFocus(any(), any());
    108 
    109         mTestCreateConnectionProcessor = new CreateConnectionProcessor(mMockCall,
    110                 mMockConnectionServiceRepository, mMockCreateConnectionResponse,
    111                 mMockAccountRegistrar, mContext);
    112     }
    113 
    114     @Override
    115     @After
    116     public void tearDown() throws Exception {
    117         mTestCreateConnectionProcessor = null;
    118         super.tearDown();
    119     }
    120 
    121     @SmallTest
    122     @Test
    123     public void testSimPhoneAccountSuccess() throws Exception {
    124         PhoneAccountHandle pAHandle = getNewTargetPhoneAccountHandle("tel_acct");
    125         when(mMockCall.isEmergencyCall()).thenReturn(false);
    126         // No Connection Manager in this case
    127         when(mMockAccountRegistrar.getSimCallManagerFromCall(any(Call.class))).thenReturn(null);
    128         ConnectionServiceWrapper service = makeConnectionServiceWrapper();
    129 
    130         mTestCreateConnectionProcessor.process();
    131 
    132         verify(mMockCall).setConnectionManagerPhoneAccount(eq(pAHandle));
    133         verify(mMockCall).setTargetPhoneAccount(eq(pAHandle));
    134         verify(mMockCall).setConnectionService(eq(service));
    135         verify(service).createConnection(eq(mMockCall), any(CreateConnectionResponse.class));
    136         // Notify successful connection to call
    137         CallIdMapper mockCallIdMapper = mock(CallIdMapper.class);
    138         mTestCreateConnectionProcessor.handleCreateConnectionSuccess(mockCallIdMapper, null);
    139         verify(mMockCreateConnectionResponse).handleCreateConnectionSuccess(mockCallIdMapper, null);
    140     }
    141 
    142     @SmallTest
    143     @Test
    144     public void testbadPhoneAccount() throws Exception {
    145         PhoneAccountHandle pAHandle = null;
    146         when(mMockCall.isEmergencyCall()).thenReturn(false);
    147         when(mMockCall.getTargetPhoneAccount()).thenReturn(pAHandle);
    148         givePhoneAccountBindPermission(pAHandle);
    149         // No Connection Manager in this case
    150         when(mMockAccountRegistrar.getSimCallManagerFromCall(any(Call.class))).thenReturn(null);
    151         ConnectionServiceWrapper service = makeConnectionServiceWrapper();
    152 
    153         mTestCreateConnectionProcessor.process();
    154 
    155         verify(service, never()).createConnection(eq(mMockCall),
    156                 any(CreateConnectionResponse.class));
    157         verify(mMockCreateConnectionResponse).handleCreateConnectionFailure(
    158                 eq(new DisconnectCause(DisconnectCause.ERROR)));
    159     }
    160 
    161     @SmallTest
    162     @Test
    163     public void testConnectionManagerSuccess() throws Exception {
    164         PhoneAccountHandle pAHandle = getNewTargetPhoneAccountHandle("tel_acct");
    165         when(mMockCall.isEmergencyCall()).thenReturn(false);
    166         // Include a Connection Manager
    167         PhoneAccountHandle callManagerPAHandle = getNewConnectionMangerHandle("cm_acct");
    168         ConnectionServiceWrapper service = makeConnectionServiceWrapper();
    169         // Make sure the target phone account has the correct permissions
    170         PhoneAccount mFakeTargetPhoneAccount = makeQuickAccount("cm_acct",
    171                 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION);
    172         when(mMockAccountRegistrar.getPhoneAccountUnchecked(pAHandle)).thenReturn(
    173                 mFakeTargetPhoneAccount);
    174 
    175         mTestCreateConnectionProcessor.process();
    176 
    177         verify(mMockCall).setConnectionManagerPhoneAccount(eq(callManagerPAHandle));
    178         verify(mMockCall).setTargetPhoneAccount(eq(pAHandle));
    179         verify(mMockCall).setConnectionService(eq(service));
    180         verify(service).createConnection(eq(mMockCall),
    181                 any(CreateConnectionResponse.class));
    182         // Notify successful connection to call
    183         CallIdMapper mockCallIdMapper = mock(CallIdMapper.class);
    184         mTestCreateConnectionProcessor.handleCreateConnectionSuccess(mockCallIdMapper, null);
    185         verify(mMockCreateConnectionResponse).handleCreateConnectionSuccess(mockCallIdMapper, null);
    186     }
    187 
    188     @SmallTest
    189     @Test
    190     public void testConnectionManagerFailedFallToSim() throws Exception {
    191         PhoneAccountHandle pAHandle = getNewTargetPhoneAccountHandle("tel_acct");
    192         when(mMockCall.isEmergencyCall()).thenReturn(false);
    193         // Include a Connection Manager
    194         PhoneAccountHandle callManagerPAHandle = getNewConnectionMangerHandle("cm_acct");
    195         ConnectionServiceWrapper service = makeConnectionServiceWrapper();
    196         when(mMockCall.getConnectionManagerPhoneAccount()).thenReturn(callManagerPAHandle);
    197         PhoneAccount mFakeTargetPhoneAccount = makeQuickAccount("cm_acct",
    198                 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION);
    199         when(mMockAccountRegistrar.getPhoneAccountUnchecked(pAHandle)).thenReturn(
    200                 mFakeTargetPhoneAccount);
    201         when(mMockCall.getConnectionService()).thenReturn(service);
    202         // Put CreateConnectionProcessor in correct state to fail with ConnectionManager
    203         mTestCreateConnectionProcessor.process();
    204         reset(mMockCall);
    205         reset(service);
    206 
    207         when(mMockCall.getConnectionServiceFocusManager()).thenReturn(
    208                 mConnectionServiceFocusManager);
    209         // Notify that the ConnectionManager has denied the call.
    210         when(mMockCall.getConnectionManagerPhoneAccount()).thenReturn(callManagerPAHandle);
    211         when(mMockCall.getConnectionService()).thenReturn(service);
    212         mTestCreateConnectionProcessor.handleCreateConnectionFailure(
    213                 new DisconnectCause(DisconnectCause.CONNECTION_MANAGER_NOT_SUPPORTED));
    214 
    215         // Verify that the Sim Phone Account is used correctly
    216         verify(mMockCall).setConnectionManagerPhoneAccount(eq(pAHandle));
    217         verify(mMockCall).setTargetPhoneAccount(eq(pAHandle));
    218         verify(mMockCall).setConnectionService(eq(service));
    219         verify(service).createConnection(eq(mMockCall), any(CreateConnectionResponse.class));
    220         // Notify successful connection to call
    221         CallIdMapper mockCallIdMapper = mock(CallIdMapper.class);
    222         mTestCreateConnectionProcessor.handleCreateConnectionSuccess(mockCallIdMapper, null);
    223         verify(mMockCreateConnectionResponse).handleCreateConnectionSuccess(mockCallIdMapper, null);
    224     }
    225 
    226     @SmallTest
    227     @Test
    228     public void testConnectionManagerFailedDoNotFallToSim() throws Exception {
    229         PhoneAccountHandle pAHandle = getNewTargetPhoneAccountHandle("tel_acct");
    230         when(mMockCall.isEmergencyCall()).thenReturn(false);
    231         // Include a Connection Manager
    232         PhoneAccountHandle callManagerPAHandle = getNewConnectionMangerHandle("cm_acct");
    233         ConnectionServiceWrapper service = makeConnectionServiceWrapper();
    234         when(mMockCall.getConnectionManagerPhoneAccount()).thenReturn(callManagerPAHandle);
    235         PhoneAccount mFakeTargetPhoneAccount = makeQuickAccount("cm_acct",
    236                 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION);
    237         when(mMockAccountRegistrar.getPhoneAccountUnchecked(pAHandle)).thenReturn(
    238                 mFakeTargetPhoneAccount);
    239         when(mMockCall.getConnectionService()).thenReturn(service);
    240         // Put CreateConnectionProcessor in correct state to fail with ConnectionManager
    241         mTestCreateConnectionProcessor.process();
    242         reset(mMockCall);
    243         reset(service);
    244 
    245         when(mMockCall.getConnectionServiceFocusManager()).thenReturn(
    246                 mConnectionServiceFocusManager);
    247         // Notify that the ConnectionManager has rejected the call.
    248         when(mMockCall.getConnectionManagerPhoneAccount()).thenReturn(callManagerPAHandle);
    249         when(mMockCall.getConnectionService()).thenReturn(service);
    250         when(service.isServiceValid("createConnection")).thenReturn(true);
    251         mTestCreateConnectionProcessor.handleCreateConnectionFailure(
    252                 new DisconnectCause(DisconnectCause.OTHER));
    253 
    254         // Verify call connection rejected
    255         verify(mMockCreateConnectionResponse).handleCreateConnectionFailure(
    256                 new DisconnectCause(DisconnectCause.OTHER));
    257     }
    258 
    259     @SmallTest
    260     @Test
    261     public void testEmergencyCallToSim() throws Exception {
    262         when(mMockCall.isEmergencyCall()).thenReturn(true);
    263         // Put in a regular phone account to be sure it doesn't call that
    264         PhoneAccountHandle pAHandle = getNewTargetPhoneAccountHandle("tel_acct");
    265         // Include a Connection Manager to be sure it doesn't call that
    266         PhoneAccount callManagerPA = getNewConnectionManagerPhoneAccount("cm_acct", 0);
    267         ConnectionServiceWrapper service = makeConnectionServiceWrapper();
    268         PhoneAccount emergencyPhoneAccount = makeEmergencyPhoneAccount("tel_emer");
    269         PhoneAccountHandle emergencyPhoneAccountHandle = emergencyPhoneAccount.getAccountHandle();
    270 
    271         mTestCreateConnectionProcessor.process();
    272 
    273         verify(mMockCall).setConnectionManagerPhoneAccount(eq(emergencyPhoneAccountHandle));
    274         verify(mMockCall).setTargetPhoneAccount(eq(emergencyPhoneAccountHandle));
    275         verify(mMockCall).setConnectionService(eq(service));
    276         verify(service).createConnection(eq(mMockCall), any(CreateConnectionResponse.class));
    277         // Notify successful connection to call
    278         CallIdMapper mockCallIdMapper = mock(CallIdMapper.class);
    279         mTestCreateConnectionProcessor.handleCreateConnectionSuccess(mockCallIdMapper, null);
    280         verify(mMockCreateConnectionResponse).handleCreateConnectionSuccess(mockCallIdMapper, null);
    281     }
    282 
    283     @SmallTest
    284     @Test
    285     public void testEmergencyCallSimFailToConnectionManager() throws Exception {
    286         when(mMockCall.isEmergencyCall()).thenReturn(true);
    287         when(mMockCall.getHandle()).thenReturn(Uri.parse(""));
    288         // Put in a regular phone account to be sure it doesn't call that
    289         PhoneAccountHandle pAHandle = getNewTargetPhoneAccountHandle("tel_acct");
    290         when(mMockAccountRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
    291                 nullable(String.class))).thenReturn(pAHandle);
    292         // Include a normal Connection Manager to be sure it doesn't call that
    293         PhoneAccount callManagerPA = getNewConnectionManagerPhoneAccount("cm_acct", 0);
    294         // Include a connection Manager for the user with the capability to make calls
    295         PhoneAccount emerCallManagerPA = getNewEmergencyConnectionManagerPhoneAccount("cm_acct",
    296                 PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS);
    297         ConnectionServiceWrapper service = makeConnectionServiceWrapper();
    298         PhoneAccount emergencyPhoneAccount = makeEmergencyPhoneAccount("tel_emer");
    299         mTestCreateConnectionProcessor.process();
    300         reset(mMockCall);
    301         reset(service);
    302 
    303         when(mMockCall.getConnectionServiceFocusManager()).thenReturn(
    304                 mConnectionServiceFocusManager);
    305         when(mMockCall.isEmergencyCall()).thenReturn(true);
    306 
    307         // When Notify SIM connection fails, fall back to connection manager
    308         mTestCreateConnectionProcessor.handleCreateConnectionFailure(new DisconnectCause(
    309                 DisconnectCause.REJECTED));
    310 
    311         verify(mMockCall).setConnectionManagerPhoneAccount(
    312                 eq(emerCallManagerPA.getAccountHandle()));
    313         verify(mMockCall).setTargetPhoneAccount(eq(pAHandle));
    314         verify(mMockCall).setConnectionService(eq(service));
    315         verify(service).createConnection(eq(mMockCall), any(CreateConnectionResponse.class));
    316     }
    317 
    318     private PhoneAccount makeEmergencyPhoneAccount(String id) {
    319         final PhoneAccount emergencyPhoneAccount = makeQuickAccount(id,
    320                 PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS |
    321                         PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION);
    322         PhoneAccountHandle emergencyPhoneAccountHandle = emergencyPhoneAccount.getAccountHandle();
    323         givePhoneAccountBindPermission(emergencyPhoneAccountHandle);
    324         ArrayList<PhoneAccount> phoneAccounts = new ArrayList<PhoneAccount>() {{
    325             add(emergencyPhoneAccount);
    326         }};
    327         when(mMockAccountRegistrar.getAllPhoneAccountsOfCurrentUser()).thenReturn(phoneAccounts);
    328         return emergencyPhoneAccount;
    329     }
    330 
    331     private void givePhoneAccountBindPermission(PhoneAccountHandle handle) {
    332         when(mMockAccountRegistrar.phoneAccountRequiresBindPermission(eq(handle))).thenReturn(true);
    333     }
    334 
    335     private PhoneAccountHandle getNewConnectionMangerHandle(String id) {
    336         PhoneAccountHandle callManagerPAHandle = makeQuickAccountHandle(id);
    337         when(mMockAccountRegistrar.getSimCallManagerFromCall(any(Call.class))).thenReturn(
    338                 callManagerPAHandle);
    339         givePhoneAccountBindPermission(callManagerPAHandle);
    340         return callManagerPAHandle;
    341     }
    342 
    343     private PhoneAccountHandle getNewTargetPhoneAccountHandle(String id) {
    344         PhoneAccountHandle pAHandle = makeQuickAccountHandle(id);
    345         when(mMockCall.getTargetPhoneAccount()).thenReturn(pAHandle);
    346         givePhoneAccountBindPermission(pAHandle);
    347         return pAHandle;
    348     }
    349 
    350     private PhoneAccount getNewConnectionManagerPhoneAccount(String id, int capability) {
    351         PhoneAccount callManagerPA = makeQuickAccount(id, capability);
    352         when(mMockAccountRegistrar.getSimCallManagerFromCall(any(Call.class))).thenReturn(
    353                 callManagerPA.getAccountHandle());
    354         givePhoneAccountBindPermission(callManagerPA.getAccountHandle());
    355         when(mMockAccountRegistrar.getPhoneAccountUnchecked(
    356                 callManagerPA.getAccountHandle())).thenReturn(callManagerPA);
    357         return callManagerPA;
    358     }
    359 
    360     private PhoneAccount getNewEmergencyConnectionManagerPhoneAccount(String id, int capability) {
    361         PhoneAccount callManagerPA = makeQuickAccount(id, capability);
    362         when(mMockAccountRegistrar.getSimCallManagerOfCurrentUser()).thenReturn(
    363                 callManagerPA.getAccountHandle());
    364         givePhoneAccountBindPermission(callManagerPA.getAccountHandle());
    365         when(mMockAccountRegistrar.getPhoneAccountUnchecked(
    366                 callManagerPA.getAccountHandle())).thenReturn(callManagerPA);
    367         return callManagerPA;
    368     }
    369 
    370     private static ComponentName makeQuickConnectionServiceComponentName() {
    371         return new ComponentName(TEST_PACKAGE, TEST_CLASS);
    372     }
    373 
    374     private ConnectionServiceWrapper makeConnectionServiceWrapper() {
    375         ConnectionServiceWrapper wrapper = mock(ConnectionServiceWrapper.class);
    376         when(mMockConnectionServiceRepository.getService(
    377                 eq(makeQuickConnectionServiceComponentName()),
    378                 eq(Binder.getCallingUserHandle()))).thenReturn(wrapper);
    379         return wrapper;
    380     }
    381 
    382     private static PhoneAccountHandle makeQuickAccountHandle(String id) {
    383         return new PhoneAccountHandle(makeQuickConnectionServiceComponentName(), id,
    384                 Binder.getCallingUserHandle());
    385     }
    386 
    387     private PhoneAccount.Builder makeQuickAccountBuilder(String id, int idx) {
    388         return new PhoneAccount.Builder(makeQuickAccountHandle(id), "label" + idx);
    389     }
    390 
    391     private PhoneAccount makeQuickAccount(String id, int idx) {
    392         return makeQuickAccountBuilder(id, idx)
    393                 .setAddress(Uri.parse("http://foo.com/" + idx))
    394                 .setSubscriptionAddress(Uri.parse("tel:555-000" + idx))
    395                 .setCapabilities(idx)
    396                 .setIcon(Icon.createWithResource(
    397                         "com.android.server.telecom.tests", R.drawable.stat_sys_phone_call))
    398                 .setShortDescription("desc" + idx)
    399                 .setIsEnabled(true)
    400                 .build();
    401     }
    402 }