CreateConnectionProcessorTest.java revision f19000764f6b93dfa15561342cbdd9c1aa1d3e22
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 17package com.android.server.telecom.tests; 18 19import android.content.ComponentName; 20import android.graphics.drawable.Icon; 21import android.net.Uri; 22import android.os.Binder; 23import android.os.Debug; 24import android.telecom.DisconnectCause; 25import android.telecom.PhoneAccount; 26import android.telecom.PhoneAccountHandle; 27 28import com.android.server.telecom.Call; 29import com.android.server.telecom.CallIdMapper; 30import com.android.server.telecom.ConnectionServiceRepository; 31import com.android.server.telecom.ConnectionServiceWrapper; 32import com.android.server.telecom.CreateConnectionProcessor; 33import com.android.server.telecom.CreateConnectionResponse; 34import com.android.server.telecom.PhoneAccountRegistrar; 35 36import org.mockito.Mock; 37import org.mockito.MockitoAnnotations; 38 39import java.util.ArrayList; 40 41import static org.mockito.Matchers.any; 42import static org.mockito.Matchers.eq; 43import static org.mockito.Mockito.mock; 44import static org.mockito.Mockito.never; 45import static org.mockito.Mockito.reset; 46import static org.mockito.Mockito.verify; 47import static org.mockito.Mockito.when; 48 49/** 50 * Unit testing for CreateConnectionProcessor as well as CreateConnectionTimeout classes. 51 */ 52public class CreateConnectionProcessorTest extends TelecomTestCase { 53 54 private static final String TEST_PACKAGE = "com.android.server.telecom.tests"; 55 private static final String TEST_CLASS = 56 "com.android.server.telecom.tests.MockConnectionService"; 57 58 @Mock 59 ConnectionServiceRepository mMockConnectionServiceRepository; 60 @Mock 61 PhoneAccountRegistrar mMockAccountRegistrar; 62 @Mock 63 CreateConnectionResponse mMockCreateConnectionResponse; 64 @Mock 65 Call mMockCall; 66 67 CreateConnectionProcessor mTestCreateConnectionProcessor; 68 69 @Override 70 public void setUp() throws Exception { 71 super.setUp(); 72 MockitoAnnotations.initMocks(this); 73 mContext = mComponentContextFixture.getTestDouble().getApplicationContext(); 74 75 mTestCreateConnectionProcessor = new CreateConnectionProcessor(mMockCall, 76 mMockConnectionServiceRepository, mMockCreateConnectionResponse, 77 mMockAccountRegistrar, mContext); 78 } 79 80 @Override 81 public void tearDown() throws Exception { 82 mTestCreateConnectionProcessor = null; 83 super.tearDown(); 84 } 85 86 public void testSimPhoneAccountSuccess() throws Exception { 87 PhoneAccountHandle pAHandle = getNewTargetPhoneAccountHandle("tel_acct"); 88 when(mMockCall.isEmergencyCall()).thenReturn(false); 89 // No Connection Manager in this case 90 when(mMockAccountRegistrar.getSimCallManagerFromCall(any(Call.class))).thenReturn(null); 91 ConnectionServiceWrapper service = makeConnectionServiceWrapper(); 92 93 mTestCreateConnectionProcessor.process(); 94 95 verify(mMockCall).setConnectionManagerPhoneAccount(eq(pAHandle)); 96 verify(mMockCall).setTargetPhoneAccount(eq(pAHandle)); 97 verify(mMockCall).setConnectionService(eq(service)); 98 verify(service).createConnection(eq(mMockCall), any(CreateConnectionResponse.class)); 99 // Notify successful connection to call 100 CallIdMapper mockCallIdMapper = mock(CallIdMapper.class); 101 mTestCreateConnectionProcessor.handleCreateConnectionSuccess(mockCallIdMapper, null); 102 verify(mMockCreateConnectionResponse).handleCreateConnectionSuccess(mockCallIdMapper, null); 103 } 104 105 public void testbadPhoneAccount() throws Exception { 106 PhoneAccountHandle pAHandle = null; 107 when(mMockCall.isEmergencyCall()).thenReturn(false); 108 when(mMockCall.getTargetPhoneAccount()).thenReturn(pAHandle); 109 givePhoneAccountBindPermission(pAHandle); 110 // No Connection Manager in this case 111 when(mMockAccountRegistrar.getSimCallManagerFromCall(any(Call.class))).thenReturn(null); 112 ConnectionServiceWrapper service = makeConnectionServiceWrapper(); 113 114 mTestCreateConnectionProcessor.process(); 115 116 verify(service, never()).createConnection(eq(mMockCall), 117 any(CreateConnectionResponse.class)); 118 verify(mMockCreateConnectionResponse).handleCreateConnectionFailure( 119 eq(new DisconnectCause(DisconnectCause.ERROR))); 120 } 121 122 public void testConnectionManagerSuccess() throws Exception { 123 PhoneAccountHandle pAHandle = getNewTargetPhoneAccountHandle("tel_acct"); 124 when(mMockCall.isEmergencyCall()).thenReturn(false); 125 // Include a Connection Manager 126 PhoneAccountHandle callManagerPAHandle = getNewConnectionMangerHandle("cm_acct"); 127 ConnectionServiceWrapper service = makeConnectionServiceWrapper(); 128 // Make sure the target phone account has the correct permissions 129 PhoneAccount mFakeTargetPhoneAccount = makeQuickAccount("cm_acct", 130 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION); 131 when(mMockAccountRegistrar.getPhoneAccountUnchecked(pAHandle)).thenReturn( 132 mFakeTargetPhoneAccount); 133 134 mTestCreateConnectionProcessor.process(); 135 136 verify(mMockCall).setConnectionManagerPhoneAccount(eq(callManagerPAHandle)); 137 verify(mMockCall).setTargetPhoneAccount(eq(pAHandle)); 138 verify(mMockCall).setConnectionService(eq(service)); 139 verify(service).createConnection(eq(mMockCall), any(CreateConnectionResponse.class)); 140 // Notify successful connection to call 141 CallIdMapper mockCallIdMapper = mock(CallIdMapper.class); 142 mTestCreateConnectionProcessor.handleCreateConnectionSuccess(mockCallIdMapper, null); 143 verify(mMockCreateConnectionResponse).handleCreateConnectionSuccess(mockCallIdMapper, null); 144 } 145 146 public void testConnectionManagerFailedFallToSim() throws Exception { 147 PhoneAccountHandle pAHandle = getNewTargetPhoneAccountHandle("tel_acct"); 148 when(mMockCall.isEmergencyCall()).thenReturn(false); 149 // Include a Connection Manager 150 PhoneAccountHandle callManagerPAHandle = getNewConnectionMangerHandle("cm_acct"); 151 ConnectionServiceWrapper service = makeConnectionServiceWrapper(); 152 when(mMockCall.getConnectionManagerPhoneAccount()).thenReturn(callManagerPAHandle); 153 PhoneAccount mFakeTargetPhoneAccount = makeQuickAccount("cm_acct", 154 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION); 155 when(mMockAccountRegistrar.getPhoneAccountUnchecked(pAHandle)).thenReturn( 156 mFakeTargetPhoneAccount); 157 when(mMockCall.getConnectionService()).thenReturn(service); 158 // Put CreateConnectionProcessor in correct state to fail with ConnectionManager 159 mTestCreateConnectionProcessor.process(); 160 reset(mMockCall); 161 reset(service); 162 163 // Notify that the ConnectionManager has denied the call. 164 when(mMockCall.getConnectionManagerPhoneAccount()).thenReturn(callManagerPAHandle); 165 when(mMockCall.getConnectionService()).thenReturn(service); 166 mTestCreateConnectionProcessor.handleCreateConnectionFailure( 167 new DisconnectCause(DisconnectCause.CONNECTION_MANAGER_NOT_SUPPORTED)); 168 169 // Verify that the Sim Phone Account is used correctly 170 verify(mMockCall).setConnectionManagerPhoneAccount(eq(pAHandle)); 171 verify(mMockCall).setTargetPhoneAccount(eq(pAHandle)); 172 verify(mMockCall).setConnectionService(eq(service)); 173 verify(service).createConnection(eq(mMockCall), any(CreateConnectionResponse.class)); 174 // Notify successful connection to call 175 CallIdMapper mockCallIdMapper = mock(CallIdMapper.class); 176 mTestCreateConnectionProcessor.handleCreateConnectionSuccess(mockCallIdMapper, null); 177 verify(mMockCreateConnectionResponse).handleCreateConnectionSuccess(mockCallIdMapper, null); 178 } 179 180 public void testConnectionManagerFailedDoNotFallToSim() throws Exception { 181 PhoneAccountHandle pAHandle = getNewTargetPhoneAccountHandle("tel_acct"); 182 when(mMockCall.isEmergencyCall()).thenReturn(false); 183 // Include a Connection Manager 184 PhoneAccountHandle callManagerPAHandle = getNewConnectionMangerHandle("cm_acct"); 185 ConnectionServiceWrapper service = makeConnectionServiceWrapper(); 186 when(mMockCall.getConnectionManagerPhoneAccount()).thenReturn(callManagerPAHandle); 187 PhoneAccount mFakeTargetPhoneAccount = makeQuickAccount("cm_acct", 188 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION); 189 when(mMockAccountRegistrar.getPhoneAccountUnchecked(pAHandle)).thenReturn( 190 mFakeTargetPhoneAccount); 191 when(mMockCall.getConnectionService()).thenReturn(service); 192 // Put CreateConnectionProcessor in correct state to fail with ConnectionManager 193 mTestCreateConnectionProcessor.process(); 194 reset(mMockCall); 195 reset(service); 196 197 // Notify that the ConnectionManager has rejected the call. 198 when(mMockCall.getConnectionManagerPhoneAccount()).thenReturn(callManagerPAHandle); 199 when(mMockCall.getConnectionService()).thenReturn(service); 200 when(service.isServiceValid("createConnection")).thenReturn(true); 201 mTestCreateConnectionProcessor.handleCreateConnectionFailure( 202 new DisconnectCause(DisconnectCause.OTHER)); 203 204 // Verify call connection rejected 205 verify(mMockCreateConnectionResponse).handleCreateConnectionFailure( 206 new DisconnectCause(DisconnectCause.OTHER)); 207 } 208 209 public void testEmergencyCallToSim() throws Exception { 210 when(mMockCall.isEmergencyCall()).thenReturn(true); 211 // Put in a regular phone account to be sure it doesn't call that 212 PhoneAccountHandle pAHandle = getNewTargetPhoneAccountHandle("tel_acct"); 213 // Include a Connection Manager to be sure it doesn't call that 214 PhoneAccount callManagerPA = getNewConnectionManagerPhoneAccount("cm_acct", 0); 215 ConnectionServiceWrapper service = makeConnectionServiceWrapper(); 216 PhoneAccount emergencyPhoneAccount = makeEmergencyPhoneAccount("tel_emer"); 217 PhoneAccountHandle emergencyPhoneAccountHandle = emergencyPhoneAccount.getAccountHandle(); 218 219 mTestCreateConnectionProcessor.process(); 220 221 verify(mMockCall).setConnectionManagerPhoneAccount(eq(emergencyPhoneAccountHandle)); 222 verify(mMockCall).setTargetPhoneAccount(eq(emergencyPhoneAccountHandle)); 223 verify(mMockCall).setConnectionService(eq(service)); 224 verify(service).createConnection(eq(mMockCall), any(CreateConnectionResponse.class)); 225 // Notify successful connection to call 226 CallIdMapper mockCallIdMapper = mock(CallIdMapper.class); 227 mTestCreateConnectionProcessor.handleCreateConnectionSuccess(mockCallIdMapper, null); 228 verify(mMockCreateConnectionResponse).handleCreateConnectionSuccess(mockCallIdMapper, null); 229 } 230 231 public void testEmergencyCallSimFailToConnectionManager() throws Exception { 232 when(mMockCall.isEmergencyCall()).thenReturn(true); 233 when(mMockCall.getHandle()).thenReturn(Uri.parse("")); 234 // Put in a regular phone account to be sure it doesn't call that 235 PhoneAccountHandle pAHandle = getNewTargetPhoneAccountHandle("tel_acct"); 236 when(mMockAccountRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser( 237 any(String.class))).thenReturn(pAHandle); 238 // Include a normal Connection Manager to be sure it doesn't call that 239 PhoneAccount callManagerPA = getNewConnectionManagerPhoneAccount("cm_acct", 0); 240 // Include a connection Manager for the user with the capability to make calls 241 PhoneAccount emerCallManagerPA = getNewEmergencyConnectionManagerPhoneAccount("cm_acct", 242 PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS); 243 ConnectionServiceWrapper service = makeConnectionServiceWrapper(); 244 PhoneAccount emergencyPhoneAccount = makeEmergencyPhoneAccount("tel_emer"); 245 mTestCreateConnectionProcessor.process(); 246 reset(mMockCall); 247 reset(service); 248 when(mMockCall.isEmergencyCall()).thenReturn(true); 249 250 // When Notify SIM connection fails, fall back to connection manager 251 mTestCreateConnectionProcessor.handleCreateConnectionFailure(new DisconnectCause( 252 DisconnectCause.REJECTED)); 253 254 verify(mMockCall).setConnectionManagerPhoneAccount( 255 eq(emerCallManagerPA.getAccountHandle())); 256 verify(mMockCall).setTargetPhoneAccount(eq(pAHandle)); 257 verify(mMockCall).setConnectionService(eq(service)); 258 verify(service).createConnection(eq(mMockCall), any(CreateConnectionResponse.class)); 259 } 260 261 private PhoneAccount makeEmergencyPhoneAccount(String id) { 262 final PhoneAccount emergencyPhoneAccount = makeQuickAccount(id, 263 PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS | 264 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION); 265 PhoneAccountHandle emergencyPhoneAccountHandle = emergencyPhoneAccount.getAccountHandle(); 266 givePhoneAccountBindPermission(emergencyPhoneAccountHandle); 267 ArrayList<PhoneAccount> phoneAccounts = new ArrayList<PhoneAccount>() {{ 268 add(emergencyPhoneAccount); 269 }}; 270 when(mMockAccountRegistrar.getAllPhoneAccountsOfCurrentUser()).thenReturn(phoneAccounts); 271 return emergencyPhoneAccount; 272 } 273 274 private void givePhoneAccountBindPermission(PhoneAccountHandle handle) { 275 when(mMockAccountRegistrar.phoneAccountRequiresBindPermission(eq(handle))).thenReturn(true); 276 } 277 278 private PhoneAccountHandle getNewConnectionMangerHandle(String id) { 279 PhoneAccountHandle callManagerPAHandle = makeQuickAccountHandle(id); 280 when(mMockAccountRegistrar.getSimCallManagerFromCall(any(Call.class))).thenReturn( 281 callManagerPAHandle); 282 givePhoneAccountBindPermission(callManagerPAHandle); 283 return callManagerPAHandle; 284 } 285 286 private PhoneAccountHandle getNewTargetPhoneAccountHandle(String id) { 287 PhoneAccountHandle pAHandle = makeQuickAccountHandle(id); 288 when(mMockCall.getTargetPhoneAccount()).thenReturn(pAHandle); 289 givePhoneAccountBindPermission(pAHandle); 290 return pAHandle; 291 } 292 293 private PhoneAccount getNewConnectionManagerPhoneAccount(String id, int capability) { 294 PhoneAccount callManagerPA = makeQuickAccount(id, capability); 295 when(mMockAccountRegistrar.getSimCallManagerFromCall(any(Call.class))).thenReturn( 296 callManagerPA.getAccountHandle()); 297 givePhoneAccountBindPermission(callManagerPA.getAccountHandle()); 298 when(mMockAccountRegistrar.getPhoneAccountUnchecked( 299 callManagerPA.getAccountHandle())).thenReturn(callManagerPA); 300 return callManagerPA; 301 } 302 303 private PhoneAccount getNewEmergencyConnectionManagerPhoneAccount(String id, int capability) { 304 PhoneAccount callManagerPA = makeQuickAccount(id, capability); 305 when(mMockAccountRegistrar.getSimCallManagerOfCurrentUser()).thenReturn( 306 callManagerPA.getAccountHandle()); 307 givePhoneAccountBindPermission(callManagerPA.getAccountHandle()); 308 when(mMockAccountRegistrar.getPhoneAccountUnchecked( 309 callManagerPA.getAccountHandle())).thenReturn(callManagerPA); 310 return callManagerPA; 311 } 312 313 private static ComponentName makeQuickConnectionServiceComponentName() { 314 return new ComponentName(TEST_PACKAGE, TEST_CLASS); 315 } 316 317 private ConnectionServiceWrapper makeConnectionServiceWrapper() { 318 ConnectionServiceWrapper wrapper = mock(ConnectionServiceWrapper.class); 319 when(mMockConnectionServiceRepository.getService( 320 eq(makeQuickConnectionServiceComponentName()), 321 eq(Binder.getCallingUserHandle()))).thenReturn(wrapper); 322 return wrapper; 323 } 324 325 private static PhoneAccountHandle makeQuickAccountHandle(String id) { 326 return new PhoneAccountHandle(makeQuickConnectionServiceComponentName(), id, 327 Binder.getCallingUserHandle()); 328 } 329 330 private PhoneAccount.Builder makeQuickAccountBuilder(String id, int idx) { 331 return new PhoneAccount.Builder(makeQuickAccountHandle(id), "label" + idx); 332 } 333 334 private PhoneAccount makeQuickAccount(String id, int idx) { 335 return makeQuickAccountBuilder(id, idx) 336 .setAddress(Uri.parse("http://foo.com/" + idx)) 337 .setSubscriptionAddress(Uri.parse("tel:555-000" + idx)) 338 .setCapabilities(idx) 339 .setIcon(Icon.createWithResource( 340 "com.android.server.telecom.tests", R.drawable.stat_sys_phone_call)) 341 .setShortDescription("desc" + idx) 342 .setIsEnabled(true) 343 .build(); 344 } 345}