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 android.Manifest; 20 import android.app.Activity; 21 import android.app.AppOpsManager; 22 import android.content.BroadcastReceiver; 23 import android.content.ComponentName; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.net.Uri; 27 import android.os.Bundle; 28 import android.os.Handler; 29 import android.os.UserHandle; 30 import android.telecom.GatewayInfo; 31 import android.telecom.TelecomManager; 32 import android.telecom.VideoProfile; 33 import android.telephony.DisconnectCause; 34 import android.test.suitebuilder.annotation.SmallTest; 35 36 import com.android.server.telecom.Call; 37 import com.android.server.telecom.CallsManager; 38 import com.android.server.telecom.NewOutgoingCallIntentBroadcaster; 39 import com.android.server.telecom.PhoneNumberUtilsAdapter; 40 import com.android.server.telecom.PhoneNumberUtilsAdapterImpl; 41 42 import org.mockito.ArgumentCaptor; 43 import org.mockito.Mock; 44 45 import static org.mockito.Matchers.any; 46 import static org.mockito.Matchers.anyBoolean; 47 import static org.mockito.Matchers.anyInt; 48 import static org.mockito.Matchers.anyString; 49 import static org.mockito.Matchers.eq; 50 import static org.mockito.Matchers.isNotNull; 51 import static org.mockito.Matchers.isNull; 52 import static org.mockito.Mockito.doReturn; 53 import static org.mockito.Mockito.never; 54 import static org.mockito.Mockito.spy; 55 import static org.mockito.Mockito.verify; 56 import static org.mockito.Mockito.when; 57 58 public class NewOutgoingCallIntentBroadcasterTest extends TelecomTestCase { 59 private static class ReceiverIntentPair { 60 public BroadcastReceiver receiver; 61 public Intent intent; 62 63 public ReceiverIntentPair(BroadcastReceiver receiver, Intent intent) { 64 this.receiver = receiver; 65 this.intent = intent; 66 } 67 } 68 69 @Mock private CallsManager mCallsManager; 70 @Mock private Call mCall; 71 72 private PhoneNumberUtilsAdapter mPhoneNumberUtilsAdapterSpy; 73 74 @Override 75 public void setUp() throws Exception { 76 super.setUp(); 77 mContext = mComponentContextFixture.getTestDouble().getApplicationContext(); 78 mPhoneNumberUtilsAdapterSpy = spy(new PhoneNumberUtilsAdapterImpl()); 79 when(mCall.getInitiatingUser()).thenReturn(UserHandle.CURRENT); 80 } 81 82 @SmallTest 83 public void testNullHandle() { 84 Intent intent = new Intent(Intent.ACTION_CALL, null); 85 int result = processIntent(intent, true); 86 assertEquals(DisconnectCause.INVALID_NUMBER, result); 87 verifyNoBroadcastSent(); 88 verifyNoCallPlaced(); 89 } 90 91 @SmallTest 92 public void testVoicemailCall() { 93 String voicemailNumber = "voicemail:18005551234"; 94 Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse(voicemailNumber)); 95 intent.putExtra(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, true); 96 97 int result = processIntent(intent, true); 98 99 assertEquals(DisconnectCause.NOT_DISCONNECTED, result); 100 verify(mCallsManager).placeOutgoingCall(eq(mCall), eq(Uri.parse(voicemailNumber)), 101 any(GatewayInfo.class), eq(true), eq(VideoProfile.STATE_AUDIO_ONLY)); 102 } 103 104 @SmallTest 105 public void testVoicemailCallWithBadAction() { 106 badCallActionHelper(Uri.parse("voicemail:18005551234"), DisconnectCause.OUTGOING_CANCELED); 107 } 108 109 @SmallTest 110 public void testTelCallWithBadCallAction() { 111 badCallActionHelper(Uri.parse("tel:6505551234"), DisconnectCause.INVALID_NUMBER); 112 } 113 114 @SmallTest 115 public void testSipCallWithBadCallAction() { 116 badCallActionHelper(Uri.parse("sip:testuser (at) testsite.com"), DisconnectCause.INVALID_NUMBER); 117 } 118 119 private void badCallActionHelper(Uri handle, int expectedCode) { 120 Intent intent = new Intent(Intent.ACTION_ALARM_CHANGED, handle); 121 122 int result = processIntent(intent, true); 123 124 assertEquals(expectedCode, result); 125 verifyNoBroadcastSent(); 126 verifyNoCallPlaced(); 127 } 128 129 @SmallTest 130 public void testAlreadyDisconnectedCall() { 131 Uri handle = Uri.parse("tel:6505551234"); 132 doReturn(true).when(mCall).isDisconnected(); 133 Intent callIntent = buildIntent(handle, Intent.ACTION_CALL, null); 134 ReceiverIntentPair result = regularCallTestHelper(callIntent, null); 135 136 result.receiver.setResultData( 137 result.intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER)); 138 139 result.receiver.onReceive(mContext, result.intent); 140 verifyNoCallPlaced(); 141 } 142 143 @SmallTest 144 public void testNoNumberSupplied() { 145 Uri handle = Uri.parse("tel:"); 146 Intent intent = new Intent(Intent.ACTION_CALL, handle); 147 148 int result = processIntent(intent, true); 149 150 assertEquals(DisconnectCause.NO_PHONE_NUMBER_SUPPLIED, result); 151 verifyNoBroadcastSent(); 152 verifyNoCallPlaced(); 153 } 154 155 @SmallTest 156 public void testEmergencyCallWithNonDefaultDialer() { 157 Uri handle = Uri.parse("tel:6505551911"); 158 doReturn(true).when(mPhoneNumberUtilsAdapterSpy).isPotentialLocalEmergencyNumber( 159 any(Context.class), eq(handle.getSchemeSpecificPart())); 160 Intent intent = new Intent(Intent.ACTION_CALL, handle); 161 162 String ui_package_string = "sample_string_1"; 163 String dialer_default_class_string = "sample_string_2"; 164 mComponentContextFixture.putResource(R.string.ui_default_package, ui_package_string); 165 mComponentContextFixture.putResource(R.string.dialer_default_class, 166 dialer_default_class_string); 167 168 int result = processIntent(intent, false); 169 170 assertEquals(DisconnectCause.OUTGOING_CANCELED, result); 171 verifyNoBroadcastSent(); 172 verifyNoCallPlaced(); 173 174 ArgumentCaptor<Intent> dialerIntentCaptor = ArgumentCaptor.forClass(Intent.class); 175 verify(mContext).startActivityAsUser(dialerIntentCaptor.capture(), any(UserHandle.class)); 176 Intent dialerIntent = dialerIntentCaptor.getValue(); 177 assertEquals(new ComponentName(ui_package_string, dialer_default_class_string), 178 dialerIntent.getComponent()); 179 assertEquals(Intent.ACTION_DIAL, dialerIntent.getAction()); 180 assertEquals(handle, dialerIntent.getData()); 181 assertEquals(Intent.FLAG_ACTIVITY_NEW_TASK, dialerIntent.getFlags()); 182 } 183 184 @SmallTest 185 public void testActionCallEmergencyCall() { 186 Uri handle = Uri.parse("tel:6505551911"); 187 Intent intent = buildIntent(handle, Intent.ACTION_CALL, null); 188 emergencyCallTestHelper(intent, null); 189 } 190 191 @SmallTest 192 public void testActionEmergencyWithEmergencyNumber() { 193 Uri handle = Uri.parse("tel:6505551911"); 194 Intent intent = buildIntent(handle, Intent.ACTION_CALL_EMERGENCY, null); 195 emergencyCallTestHelper(intent, null); 196 } 197 198 @SmallTest 199 public void testActionPrivCallWithEmergencyNumber() { 200 Uri handle = Uri.parse("tel:6505551911"); 201 Intent intent = buildIntent(handle, Intent.ACTION_CALL_PRIVILEGED, null); 202 emergencyCallTestHelper(intent, null); 203 } 204 205 @SmallTest 206 public void testEmergencyCallWithGatewayExtras() { 207 Uri handle = Uri.parse("tel:6505551911"); 208 Bundle gatewayExtras = new Bundle(); 209 gatewayExtras.putString(NewOutgoingCallIntentBroadcaster.EXTRA_GATEWAY_PROVIDER_PACKAGE, 210 "sample1"); 211 gatewayExtras.putString(NewOutgoingCallIntentBroadcaster.EXTRA_GATEWAY_URI, "sample2"); 212 213 Intent intent = buildIntent(handle, Intent.ACTION_CALL, gatewayExtras); 214 emergencyCallTestHelper(intent, gatewayExtras); 215 } 216 217 @SmallTest 218 public void testActionEmergencyWithNonEmergencyNumber() { 219 Uri handle = Uri.parse("tel:6505551911"); 220 doReturn(false).when(mPhoneNumberUtilsAdapterSpy).isPotentialLocalEmergencyNumber( 221 any(Context.class), eq(handle.getSchemeSpecificPart())); 222 Intent intent = new Intent(Intent.ACTION_CALL_EMERGENCY, handle); 223 int result = processIntent(intent, true); 224 225 assertEquals(DisconnectCause.OUTGOING_CANCELED, result); 226 verifyNoCallPlaced(); 227 verifyNoBroadcastSent(); 228 } 229 230 private void emergencyCallTestHelper(Intent intent, Bundle expectedAdditionalExtras) { 231 Uri handle = intent.getData(); 232 int videoState = VideoProfile.STATE_BIDIRECTIONAL; 233 boolean isSpeakerphoneOn = true; 234 doReturn(true).when(mPhoneNumberUtilsAdapterSpy).isPotentialLocalEmergencyNumber( 235 any(Context.class), eq(handle.getSchemeSpecificPart())); 236 intent.putExtra(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, isSpeakerphoneOn); 237 intent.putExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, videoState); 238 int result = processIntent(intent, true); 239 240 assertEquals(DisconnectCause.NOT_DISCONNECTED, result); 241 verify(mCallsManager).placeOutgoingCall(eq(mCall), eq(handle), isNull(GatewayInfo.class), 242 eq(isSpeakerphoneOn), eq(videoState)); 243 244 Bundle expectedExtras = createNumberExtras(handle.getSchemeSpecificPart()); 245 if (expectedAdditionalExtras != null) { 246 expectedExtras.putAll(expectedAdditionalExtras); 247 } 248 BroadcastReceiver receiver = verifyBroadcastSent(handle.getSchemeSpecificPart(), 249 expectedExtras).receiver; 250 assertNull(receiver); 251 } 252 253 @SmallTest 254 public void testUnmodifiedRegularCall() { 255 Uri handle = Uri.parse("tel:6505551234"); 256 Intent callIntent = buildIntent(handle, Intent.ACTION_CALL, null); 257 ReceiverIntentPair result = regularCallTestHelper(callIntent, null); 258 259 result.receiver.setResultData( 260 result.intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER)); 261 262 result.receiver.onReceive(mContext, result.intent); 263 264 verify(mCallsManager).placeOutgoingCall(eq(mCall), eq(handle), isNull(GatewayInfo.class), 265 eq(true), eq(VideoProfile.STATE_BIDIRECTIONAL)); 266 } 267 268 @SmallTest 269 public void testUnmodifiedSipCall() { 270 Uri handle = Uri.parse("sip:test (at) test.com"); 271 Intent callIntent = buildIntent(handle, Intent.ACTION_CALL, null); 272 ReceiverIntentPair result = regularCallTestHelper(callIntent, null); 273 274 result.receiver.setResultData( 275 result.intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER)); 276 277 result.receiver.onReceive(mContext, result.intent); 278 279 Uri encHandle = Uri.fromParts(handle.getScheme(), 280 handle.getSchemeSpecificPart(), null); 281 verify(mCallsManager).placeOutgoingCall(eq(mCall), eq(encHandle), isNull(GatewayInfo.class), 282 eq(true), eq(VideoProfile.STATE_BIDIRECTIONAL)); 283 } 284 285 @SmallTest 286 public void testCallWithGatewayInfo() { 287 Uri handle = Uri.parse("tel:6505551234"); 288 Intent callIntent = buildIntent(handle, Intent.ACTION_CALL, null); 289 290 callIntent.putExtra(NewOutgoingCallIntentBroadcaster 291 .EXTRA_GATEWAY_PROVIDER_PACKAGE, "sample1"); 292 callIntent.putExtra(NewOutgoingCallIntentBroadcaster.EXTRA_GATEWAY_URI, "sample2"); 293 ReceiverIntentPair result = regularCallTestHelper(callIntent, callIntent.getExtras()); 294 295 result.receiver.setResultData( 296 result.intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER)); 297 298 result.receiver.onReceive(mContext, result.intent); 299 300 verify(mCallsManager).placeOutgoingCall(eq(mCall), eq(handle), 301 isNotNull(GatewayInfo.class), eq(true), eq(VideoProfile.STATE_BIDIRECTIONAL)); 302 } 303 304 @SmallTest 305 public void testCallNumberModifiedToNull() { 306 Uri handle = Uri.parse("tel:6505551234"); 307 Intent callIntent = buildIntent(handle, Intent.ACTION_CALL, null); 308 ReceiverIntentPair result = regularCallTestHelper(callIntent, null); 309 310 result.receiver.setResultData(null); 311 312 result.receiver.onReceive(mContext, result.intent); 313 verifyNoCallPlaced(); 314 verify(mCall).disconnect(true); 315 } 316 317 @SmallTest 318 public void testCallModifiedToEmergency() { 319 Uri handle = Uri.parse("tel:6505551234"); 320 Intent callIntent = buildIntent(handle, Intent.ACTION_CALL, null); 321 ReceiverIntentPair result = regularCallTestHelper(callIntent, null); 322 323 String newEmergencyNumber = "1234567890"; 324 result.receiver.setResultData(newEmergencyNumber); 325 326 doReturn(true).when(mPhoneNumberUtilsAdapterSpy).isPotentialLocalEmergencyNumber( 327 any(Context.class), eq(newEmergencyNumber)); 328 result.receiver.onReceive(mContext, result.intent); 329 verify(mCall).disconnect(true); 330 } 331 332 private ReceiverIntentPair regularCallTestHelper(Intent intent, 333 Bundle expectedAdditionalExtras) { 334 Uri handle = intent.getData(); 335 int videoState = VideoProfile.STATE_BIDIRECTIONAL; 336 boolean isSpeakerphoneOn = true; 337 intent.putExtra(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, isSpeakerphoneOn); 338 intent.putExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, videoState); 339 340 int result = processIntent(intent, true); 341 342 assertEquals(DisconnectCause.NOT_DISCONNECTED, result); 343 Bundle expectedExtras = createNumberExtras(handle.getSchemeSpecificPart()); 344 if (expectedAdditionalExtras != null) { 345 expectedExtras.putAll(expectedAdditionalExtras); 346 } 347 return verifyBroadcastSent(handle.getSchemeSpecificPart(), expectedExtras); 348 } 349 350 private Intent buildIntent(Uri handle, String action, Bundle extras) { 351 Intent i = new Intent(action, handle); 352 if (extras != null) { 353 i.putExtras(extras); 354 } 355 return i; 356 } 357 358 private int processIntent(Intent intent, 359 boolean isDefaultPhoneApp) { 360 NewOutgoingCallIntentBroadcaster b = new NewOutgoingCallIntentBroadcaster( 361 mContext, mCallsManager, mCall, intent, mPhoneNumberUtilsAdapterSpy, 362 isDefaultPhoneApp); 363 return b.processIntent(); 364 } 365 366 private ReceiverIntentPair verifyBroadcastSent(String number, Bundle expectedExtras) { 367 ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); 368 ArgumentCaptor<BroadcastReceiver> receiverCaptor = 369 ArgumentCaptor.forClass(BroadcastReceiver.class); 370 371 verify(mContext).sendOrderedBroadcastAsUser( 372 intentCaptor.capture(), 373 eq(UserHandle.CURRENT), 374 eq(Manifest.permission.PROCESS_OUTGOING_CALLS), 375 eq(AppOpsManager.OP_PROCESS_OUTGOING_CALLS), 376 receiverCaptor.capture(), 377 isNull(Handler.class), 378 eq(Activity.RESULT_OK), 379 eq(number), 380 isNull(Bundle.class)); 381 382 Intent capturedIntent = intentCaptor.getValue(); 383 assertEquals(Intent.ACTION_NEW_OUTGOING_CALL, capturedIntent.getAction()); 384 assertEquals(Intent.FLAG_RECEIVER_FOREGROUND, capturedIntent.getFlags()); 385 assertTrue(areBundlesEqual(expectedExtras, capturedIntent.getExtras())); 386 387 BroadcastReceiver receiver = receiverCaptor.getValue(); 388 if (receiver != null) { 389 receiver.setPendingResult( 390 new BroadcastReceiver.PendingResult(0, "", null, 0, true, false, null, 0, 0)); 391 } 392 393 return new ReceiverIntentPair(receiver, capturedIntent); 394 } 395 396 private Bundle createNumberExtras(String number) { 397 Bundle b = new Bundle(); 398 b.putString(Intent.EXTRA_PHONE_NUMBER, number); 399 return b; 400 } 401 402 private void verifyNoCallPlaced() { 403 verify(mCallsManager, never()).placeOutgoingCall(any(Call.class), any(Uri.class), 404 any(GatewayInfo.class), anyBoolean(), anyInt()); 405 } 406 407 private void verifyNoBroadcastSent() { 408 verify(mContext, never()).sendOrderedBroadcastAsUser( 409 any(Intent.class), 410 any(UserHandle.class), 411 anyString(), 412 anyInt(), 413 any(BroadcastReceiver.class), 414 any(Handler.class), 415 anyInt(), 416 anyString(), 417 any(Bundle.class)); 418 } 419 420 private static boolean areBundlesEqual(Bundle b1, Bundle b2) { 421 for (String key1 : b1.keySet()) { 422 if (!b1.get(key1).equals(b2.get(key1))) { 423 return false; 424 } 425 } 426 427 for (String key2 : b2.keySet()) { 428 if (!b2.get(key2).equals(b1.get(key2))) { 429 return false; 430 } 431 } 432 return true; 433 } 434 } 435