TelecomSystemTest.java revision b63b57e2c35c4769e756f47131c7ebbc0af42c59
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 com.android.internal.telecom.IInCallAdapter; 20import com.android.server.telecom.CallsManager; 21import com.android.server.telecom.HeadsetMediaButton; 22import com.android.server.telecom.HeadsetMediaButtonFactory; 23import com.android.server.telecom.InCallWakeLockController; 24import com.android.server.telecom.InCallWakeLockControllerFactory; 25import com.android.server.telecom.MissedCallNotifier; 26import com.android.server.telecom.ProximitySensorManager; 27import com.android.server.telecom.ProximitySensorManagerFactory; 28import com.android.server.telecom.TelecomSystem; 29 30import org.mockito.ArgumentCaptor; 31import org.mockito.Mock; 32 33import android.annotation.TargetApi; 34import android.content.BroadcastReceiver; 35import android.content.ComponentName; 36import android.content.Context; 37import android.content.Intent; 38import android.net.Uri; 39import android.os.Bundle; 40import android.os.Handler; 41import android.os.UserHandle; 42import android.telecom.CallState; 43import android.telecom.ConnectionRequest; 44import android.telecom.DisconnectCause; 45import android.telecom.ParcelableCall; 46import android.telecom.PhoneAccount; 47import android.telecom.PhoneAccountHandle; 48import android.telecom.TelecomManager; 49import android.telephony.TelephonyManager; 50 51import static org.mockito.Matchers.anyBoolean; 52import static org.mockito.Matchers.anyInt; 53import static org.mockito.Mockito.any; 54import static org.mockito.Mockito.anyString; 55import static org.mockito.Mockito.eq; 56import static org.mockito.Mockito.mock; 57import static org.mockito.Mockito.timeout; 58import static org.mockito.Mockito.verify; 59import static org.mockito.Mockito.when; 60 61public class TelecomSystemTest extends TelecomTestCase { 62 63 static final int TEST_TIMEOUT = 1000; // milliseconds 64 65 @Mock MissedCallNotifier mMissedCallNotifier; 66 @Mock HeadsetMediaButton mHeadsetMediaButton; 67 @Mock ProximitySensorManager mProximitySensorManager; 68 @Mock InCallWakeLockController mInCallWakeLockController; 69 70 final ComponentName mInCallServiceComponentNameX = 71 new ComponentName( 72 "incall-service-package-X", 73 "incall-service-class-X"); 74 final ComponentName mInCallServiceComponentNameY = 75 new ComponentName( 76 "incall-service-package-Y", 77 "incall-service-class-Y"); 78 79 InCallServiceFixture mInCallServiceFixtureX; 80 InCallServiceFixture mInCallServiceFixtureY; 81 82 final ComponentName mConnectionServiceComponentNameA = 83 new ComponentName( 84 "connection-service-package-A", 85 "connection-service-class-A"); 86 final ComponentName mConnectionServiceComponentNameB = 87 new ComponentName( 88 "connection-service-package-B", 89 "connection-service-class-B"); 90 91 final PhoneAccount mPhoneAccountA0 = 92 PhoneAccount.builder( 93 new PhoneAccountHandle( 94 mConnectionServiceComponentNameA, 95 "id A 0"), 96 "Phone account service A ID 0") 97 .addSupportedUriScheme("tel") 98 .setCapabilities( 99 PhoneAccount.CAPABILITY_CALL_PROVIDER | 100 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) 101 .build(); 102 final PhoneAccount mPhoneAccountA1 = 103 PhoneAccount.builder( 104 new PhoneAccountHandle( 105 mConnectionServiceComponentNameA, 106 "id A 1"), 107 "Phone account service A ID 1") 108 .addSupportedUriScheme("tel") 109 .setCapabilities( 110 PhoneAccount.CAPABILITY_CALL_PROVIDER | 111 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) 112 .build(); 113 final PhoneAccount mPhoneAccountB0 = 114 PhoneAccount.builder( 115 new PhoneAccountHandle( 116 mConnectionServiceComponentNameA, 117 "id B 0"), 118 "Phone account service B ID 0") 119 .addSupportedUriScheme("tel") 120 .setCapabilities( 121 PhoneAccount.CAPABILITY_CALL_PROVIDER | 122 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) 123 .build(); 124 125 ConnectionServiceFixture mConnectionServiceFixtureA; 126 ConnectionServiceFixture mConnectionServiceFixtureB; 127 128 TelecomSystem mTelecomSystem; 129 130 @Override 131 public void setUp() throws Exception { 132 super.setUp(); 133 134 // First set up information about the In-Call services in the mock Context, since 135 // Telecom will search for these as soon as it is instantiated 136 setupInCallServices(); 137 138 // Next, create the TelecomSystem, our system under test 139 setupTelecomSystem(); 140 141 // Finally, register the ConnectionServices with the PhoneAccountRegistrar of the 142 // now-running TelecomSystem 143 setupConnectionServices(); 144 } 145 146 @Override 147 public void tearDown() throws Exception { 148 mTelecomSystem = null; 149 super.tearDown(); 150 } 151 152 private void setupTelecomSystem() throws Exception { 153 HeadsetMediaButtonFactory headsetMediaButtonFactory = 154 mock(HeadsetMediaButtonFactory.class); 155 ProximitySensorManagerFactory proximitySensorManagerFactory = 156 mock(ProximitySensorManagerFactory.class); 157 InCallWakeLockControllerFactory inCallWakeLockControllerFactory = 158 mock(InCallWakeLockControllerFactory.class); 159 160 when(headsetMediaButtonFactory.create( 161 any(Context.class), 162 any(CallsManager.class))) 163 .thenReturn(mHeadsetMediaButton); 164 when(proximitySensorManagerFactory.create( 165 any(Context.class), 166 any(CallsManager.class))) 167 .thenReturn(mProximitySensorManager); 168 when(inCallWakeLockControllerFactory.create( 169 any(Context.class), 170 any(CallsManager.class))) 171 .thenReturn(mInCallWakeLockController); 172 173 mTelecomSystem = new TelecomSystem( 174 mComponentContextFixture.getTestDouble(), 175 mMissedCallNotifier, 176 headsetMediaButtonFactory, 177 proximitySensorManagerFactory, 178 inCallWakeLockControllerFactory); 179 180 verify(headsetMediaButtonFactory).create( 181 eq(mComponentContextFixture.getTestDouble().getApplicationContext()), 182 any(CallsManager.class)); 183 verify(proximitySensorManagerFactory).create( 184 eq(mComponentContextFixture.getTestDouble().getApplicationContext()), 185 any(CallsManager.class)); 186 verify(inCallWakeLockControllerFactory).create( 187 eq(mComponentContextFixture.getTestDouble().getApplicationContext()), 188 any(CallsManager.class)); 189 } 190 191 private void setupConnectionServices() throws Exception { 192 mConnectionServiceFixtureA = new ConnectionServiceFixture(); 193 mConnectionServiceFixtureB = new ConnectionServiceFixture(); 194 195 mComponentContextFixture.addConnectionService( 196 mConnectionServiceComponentNameA, 197 mConnectionServiceFixtureA.getTestDouble()); 198 mComponentContextFixture.addConnectionService( 199 mConnectionServiceComponentNameB, 200 mConnectionServiceFixtureB.getTestDouble()); 201 202 mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountA0); 203 mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountA1); 204 mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountB0); 205 } 206 207 private void setupInCallServices() throws Exception { 208 mComponentContextFixture.putResource( 209 com.android.server.telecom.R.string.ui_default_package, 210 mInCallServiceComponentNameX.getPackageName()); 211 mComponentContextFixture.putResource( 212 com.android.server.telecom.R.string.incall_default_class, 213 mInCallServiceComponentNameX.getClassName()); 214 215 mInCallServiceFixtureX = new InCallServiceFixture(); 216 mInCallServiceFixtureY = new InCallServiceFixture(); 217 218 mComponentContextFixture.addInCallService( 219 mInCallServiceComponentNameX, 220 mInCallServiceFixtureX.getTestDouble()); 221 mComponentContextFixture.addInCallService( 222 mInCallServiceComponentNameY, 223 mInCallServiceFixtureY.getTestDouble()); 224 } 225 226 private String startOutgoingPhoneCall( 227 String number, 228 PhoneAccountHandle phoneAccountHandle, 229 ConnectionServiceFixture connectionServiceFixture) throws Exception { 230 Intent actionCallIntent = new Intent(); 231 actionCallIntent.setData(Uri.parse("tel:" + number)); 232 actionCallIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, number); 233 actionCallIntent.setAction(Intent.ACTION_CALL); 234 if (phoneAccountHandle != null) { 235 actionCallIntent.putExtra( 236 TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, 237 phoneAccountHandle); 238 } 239 240 mTelecomSystem.getCallIntentProcessor().processIntent(actionCallIntent); 241 242 ArgumentCaptor<Intent> newOutgoingCallIntent = 243 ArgumentCaptor.forClass(Intent.class); 244 ArgumentCaptor<BroadcastReceiver> newOutgoingCallReceiver = 245 ArgumentCaptor.forClass(BroadcastReceiver.class); 246 247 verify(mComponentContextFixture.getTestDouble().getApplicationContext()) 248 .sendOrderedBroadcastAsUser( 249 newOutgoingCallIntent.capture(), 250 any(UserHandle.class), 251 anyString(), 252 newOutgoingCallReceiver.capture(), 253 any(Handler.class), 254 anyInt(), 255 anyString(), 256 any(Bundle.class)); 257 258 assertNotNull(mInCallServiceFixtureX.mInCallAdapter); 259 assertNotNull(mInCallServiceFixtureY.mInCallAdapter); 260 261 // Pass on the new outgoing call Intent 262 // Set a dummy PendingResult so the BroadcastReceiver agrees to accept onReceive() 263 newOutgoingCallReceiver.getValue().setPendingResult( 264 new BroadcastReceiver.PendingResult(0, "", null, 0, true, false, null, 0)); 265 newOutgoingCallReceiver.getValue().setResultData( 266 newOutgoingCallIntent.getValue().getStringExtra(Intent.EXTRA_PHONE_NUMBER)); 267 newOutgoingCallReceiver.getValue().onReceive( 268 mComponentContextFixture.getTestDouble(), 269 newOutgoingCallIntent.getValue()); 270 271 verify(connectionServiceFixture.getTestDouble()).createConnection( 272 eq(phoneAccountHandle), 273 anyString(), 274 any(ConnectionRequest.class), 275 anyBoolean(), 276 anyBoolean()); 277 278 String id = connectionServiceFixture.mLatestConnectionId; 279 280 connectionServiceFixture.sendHandleCreateConnectionComplete(id); 281 282 return id; 283 } 284 285 private String startIncomingPhoneCall( 286 String number, 287 PhoneAccountHandle phoneAccountHandle, 288 ConnectionServiceFixture connectionServiceFixture) throws Exception { 289 Bundle extras = new Bundle(); 290 extras.putParcelable( 291 TelephonyManager.EXTRA_INCOMING_NUMBER, 292 Uri.fromParts(PhoneAccount.SCHEME_TEL, number, null)); 293 mTelecomSystem.getTelecomServiceImpl().getBinder() 294 .addNewIncomingCall(phoneAccountHandle, extras); 295 296 verify(connectionServiceFixture.getTestDouble()).createConnection( 297 any(PhoneAccountHandle.class), 298 anyString(), 299 any(ConnectionRequest.class), 300 eq(true), 301 eq(false)); 302 303 String id = connectionServiceFixture.mLatestConnectionId; 304 305 connectionServiceFixture.sendHandleCreateConnectionComplete(id); 306 connectionServiceFixture.sendSetRinging(id); 307 308 // For the case of incoming calls, Telecom connecting the InCall services and adding the 309 // Call is triggered by the async completion of the CallerInfoAsyncQuery. Once the Call 310 // is added, future interactions as triggered by the ConnectionService, through the various 311 // test fixtures, will be synchronous. 312 313 verify( 314 mInCallServiceFixtureX.getTestDouble(), 315 timeout(TEST_TIMEOUT)) 316 .setInCallAdapter( 317 any(IInCallAdapter.class)); 318 verify( 319 mInCallServiceFixtureY.getTestDouble(), 320 timeout(TEST_TIMEOUT)) 321 .setInCallAdapter( 322 any(IInCallAdapter.class)); 323 324 assertNotNull(mInCallServiceFixtureX.mInCallAdapter); 325 assertNotNull(mInCallServiceFixtureY.mInCallAdapter); 326 327 verify( 328 mInCallServiceFixtureX.getTestDouble(), 329 timeout(TEST_TIMEOUT)) 330 .addCall( 331 any(ParcelableCall.class)); 332 verify( 333 mInCallServiceFixtureY.getTestDouble(), 334 timeout(TEST_TIMEOUT)) 335 .addCall( 336 any(ParcelableCall.class)); 337 338 return id; 339 } 340 341 // A simple outgoing call, verifying that the appropriate connection service is contacted, 342 // the proper lifecycle is followed, and both In-Call Services are updated correctly. 343 public void testSingleOutgoingCall() throws Exception { 344 String connectionId = startOutgoingPhoneCall( 345 "650-555-1212", 346 mPhoneAccountA0.getAccountHandle(), 347 mConnectionServiceFixtureA); 348 349 assertEquals(1, mConnectionServiceFixtureA.mConnectionServiceAdapters.size()); 350 assertEquals(1, mConnectionServiceFixtureA.mConnectionById.size()); 351 352 mConnectionServiceFixtureA.sendSetDialing(connectionId); 353 354 assertEquals(1, mInCallServiceFixtureX.mCallById.size()); 355 String callId = mInCallServiceFixtureX.mLatestCallId; 356 357 assertEquals(CallState.DIALING, mInCallServiceFixtureX.getCall(callId).getState()); 358 assertEquals(CallState.DIALING, mInCallServiceFixtureY.getCall(callId).getState()); 359 360 mConnectionServiceFixtureA.sendSetActive(connectionId); 361 assertEquals(CallState.ACTIVE, mInCallServiceFixtureX.getCall(callId).getState()); 362 assertEquals(CallState.ACTIVE, mInCallServiceFixtureY.getCall(callId).getState()); 363 364 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(callId);; 365 assertEquals(CallState.ACTIVE, mInCallServiceFixtureX.getCall(callId).getState()); 366 assertEquals(CallState.ACTIVE, mInCallServiceFixtureY.getCall(callId).getState()); 367 368 mConnectionServiceFixtureA.sendSetDisconnected(connectionId, DisconnectCause.LOCAL); 369 assertEquals(CallState.DISCONNECTED, mInCallServiceFixtureX.getCall(callId).getState()); 370 assertEquals(CallState.DISCONNECTED, mInCallServiceFixtureY.getCall(callId).getState()); 371 } 372 373 // A simple incoming call, similar in scope to the previous test 374 public void testSingleIncomingCall() throws Exception { 375 String connectionId = startIncomingPhoneCall( 376 "650-555-1212", 377 mPhoneAccountA0.getAccountHandle(), 378 mConnectionServiceFixtureA); 379 380 assertEquals(1, mConnectionServiceFixtureA.mConnectionServiceAdapters.size()); 381 assertEquals(1, mConnectionServiceFixtureA.mConnectionById.size()); 382 383 assertEquals(1, mInCallServiceFixtureX.mCallById.size()); 384 String callId = mInCallServiceFixtureX.mLatestCallId; 385 386 assertEquals(CallState.RINGING, mInCallServiceFixtureX.getCall(callId).getState()); 387 assertEquals(CallState.RINGING, mInCallServiceFixtureY.getCall(callId).getState()); 388 389 mConnectionServiceFixtureA.sendSetActive(connectionId); 390 assertEquals(CallState.ACTIVE, mInCallServiceFixtureX.getCall(callId).getState()); 391 assertEquals(CallState.ACTIVE, mInCallServiceFixtureY.getCall(callId).getState()); 392 393 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(callId);; 394 assertEquals(CallState.ACTIVE, mInCallServiceFixtureX.getCall(callId).getState()); 395 assertEquals(CallState.ACTIVE, mInCallServiceFixtureY.getCall(callId).getState()); 396 397 mConnectionServiceFixtureA.sendSetDisconnected(connectionId, DisconnectCause.LOCAL); 398 assertEquals(CallState.DISCONNECTED, mInCallServiceFixtureX.getCall(callId).getState()); 399 assertEquals(CallState.DISCONNECTED, mInCallServiceFixtureY.getCall(callId).getState()); 400 } 401} 402