Loading flags/telecom_broadcast_flags.aconfig +1 −7 Original line number Diff line number Diff line package: "com.android.server.telecom.flags" container: "system" # OWNER=tgunn TARGET=24Q3 flag { name: "is_new_outgoing_call_broadcast_unblocking" namespace: "telecom" description: "When set, the ACTION_NEW_OUTGOING_CALL broadcast is unblocking." bug: "224550864" } No newline at end of file # This file intentionally left blank to avoid compilation errors due to removed flag. src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java +12 −169 Original line number Diff line number Diff line Loading @@ -115,88 +115,6 @@ public class NewOutgoingCallIntentBroadcaster { mFeatureFlags = featureFlags; } /** * Processes the result of the outgoing call broadcast intent, and performs callbacks to * the OutgoingCallIntentBroadcasterListener as necessary. */ public class NewOutgoingCallBroadcastIntentReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { try { Log.startSession("NOCBIR.oR"); synchronized (mLock) { Log.v(this, "onReceive: %s", intent); // Once the NEW_OUTGOING_CALL broadcast is finished, the resultData is // used as the actual number to call. (If null, no call will be placed.) String resultNumber = getResultData(); Log.i(NewOutgoingCallIntentBroadcaster.this, "Received new-outgoing-call-broadcast for %s with data %s", mCall, Log.pii(resultNumber)); boolean endEarly = false; long disconnectTimeout = Timeouts.getNewOutgoingCallCancelMillis(mContext, mFeatureFlags); if (resultNumber == null) { Log.v(this, "Call cancelled (null number), returning..."); disconnectTimeout = getDisconnectTimeoutFromApp( getResultExtras(false), disconnectTimeout); endEarly = true; } else if (isEmergencyNumber(resultNumber)) { Log.w(this, "Cannot modify outgoing call to emergency number %s.", resultNumber); disconnectTimeout = 0; endEarly = true; } if (endEarly) { if (mCall != null) { mCall.disconnect(disconnectTimeout); } return; } // If this call is already disconnected then we have nothing more to do. if (mCall.isDisconnected()) { Log.w(this, "Call has already been disconnected," + " ignore the broadcast Call %s", mCall); return; } // TODO: Remove the assumption that phone numbers are either SIP or TEL. // This does not impact self-managed ConnectionServices as they do not use the // NewOutgoingCallIntentBroadcaster. Uri resultHandleUri = Uri.fromParts( mPhoneNumberUtilsAdapter.isUriNumber(resultNumber) ? PhoneAccount.SCHEME_SIP : PhoneAccount.SCHEME_TEL, resultNumber, null); Uri originalUri = mIntent.getData(); if (originalUri.getSchemeSpecificPart().equals(resultNumber)) { Log.v(this, "Call number unmodified after" + " new outgoing call intent broadcast."); } else { Log.v(this, "Retrieved modified handle after outgoing call intent" + " broadcast: Original: %s, Modified: %s", Log.pii(originalUri), Log.pii(resultHandleUri)); } GatewayInfo gatewayInfo = getGateWayInfoFromIntent(intent, resultHandleUri); placeOutgoingCallImmediately(mCall, resultHandleUri, gatewayInfo, mIntent.getBooleanExtra( TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, false), mIntent.getIntExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, VideoProfile.STATE_AUDIO_ONLY)); } } finally { Log.endSession(); } } } /** * Processes the supplied intent and starts the outgoing call broadcast process relevant to the * intent. Loading Loading @@ -355,13 +273,6 @@ public class NewOutgoingCallIntentBroadcaster { public void processCall(Call call, CallDisposition disposition) { mCall = call; // If the new outgoing call broadast doesn't block, trigger the legacy process call // behavior and exit out here. if (!mFeatureFlags.isNewOutgoingCallBroadcastUnblocking()) { legacyProcessCall(disposition); return; } boolean callRedirectionWithService = false; // Only try to do redirection if it was requested and we're not calling immediately. // We can expect callImmediately to be true for emergency calls and voip calls. Loading Loading @@ -398,50 +309,6 @@ public class NewOutgoingCallIntentBroadcaster { } } /** * The legacy non-flagged version of processing a call. Although there is some code duplication * if makes the new flow cleaner to read. * @param disposition */ private void legacyProcessCall(CallDisposition disposition) { if (disposition.callImmediately) { callImmediately(disposition); // Don't return but instead continue and send the ACTION_NEW_OUTGOING_CALL broadcast // so that third parties can still inspect (but not intercept) the outgoing call. When // the broadcast finally reaches the OutgoingCallBroadcastReceiver, we'll know not to // initiate the call again because of the presence of the EXTRA_ALREADY_CALLED extra. } boolean callRedirectionWithService = false; if (disposition.requestRedirection) { CallRedirectionProcessor callRedirectionProcessor = new CallRedirectionProcessor( mContext, mCallsManager, mCall, disposition.callingAddress, mCallsManager.getPhoneAccountRegistrar(), getGateWayInfoFromIntent(mIntent, mIntent.getData()), mIntent.getBooleanExtra(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, false), mIntent.getIntExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, VideoProfile.STATE_AUDIO_ONLY), mFeatureFlags); /** * If there is an available {@link android.telecom.CallRedirectionService}, use the * {@link CallRedirectionProcessor} to perform call redirection instead of using * broadcasting. */ callRedirectionWithService = callRedirectionProcessor .canMakeCallRedirectionWithServiceAsUser(mCall.getAssociatedUser()); if (callRedirectionWithService) { callRedirectionProcessor.performCallRedirection(mCall.getAssociatedUser()); } } if (disposition.sendBroadcast) { UserHandle targetUser = mCall.getAssociatedUser(); broadcastIntent(mIntent, disposition.number, !disposition.callImmediately && !callRedirectionWithService, targetUser); } } /** * Place a call immediately. * @param disposition The disposition; used for retrieving the address of the call. Loading Loading @@ -479,8 +346,7 @@ public class NewOutgoingCallIntentBroadcaster { checkAndCopyProviderExtras(originalCallIntent, broadcastIntent); if (mFeatureFlags.isNewOutgoingCallBroadcastUnblocking()) { // Where the new outgoing call broadcast is unblocking, do not give receiver FG priority // The new outgoing call broadcast is unblocking, do not give receiver FG priority // and do not allow background activity starts. broadcastIntent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); Log.i(this, "broadcastIntent: Sending non-blocking for %s to %s", mCall.getId(), Loading @@ -497,29 +363,6 @@ public class NewOutgoingCallIntentBroadcaster { android.Manifest.permission.PROCESS_OUTGOING_CALLS, AppOpsManager.OP_PROCESS_OUTGOING_CALLS); // initialExtras } } else { Log.i(this, "broadcastIntent: Sending ordered for %s to %s, waitForResult=%b", mCall.getId(), targetUser, receiverRequired); final BroadcastOptions options = BroadcastOptions.makeBasic(); options.setBackgroundActivityStartsAllowed(true); // Force receivers of this broadcast intent to run at foreground priority because we // want to finish processing the broadcast intent as soon as possible. broadcastIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); mContext.sendOrderedBroadcastAsUser( broadcastIntent, targetUser, android.Manifest.permission.PROCESS_OUTGOING_CALLS, AppOpsManager.OP_PROCESS_OUTGOING_CALLS, options.toBundle(), receiverRequired ? new NewOutgoingCallBroadcastIntentReceiver() : null, null, // scheduler Activity.RESULT_OK, // initialCode number, // initialData: initial value for the result data (number to be // modified) null); // initialExtras } } /** Loading tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java +18 −208 Original line number Diff line number Diff line Loading @@ -78,16 +78,6 @@ import org.mockito.Mock; public class NewOutgoingCallIntentBroadcasterTest extends TelecomTestCase { private static final Uri TEST_URI = Uri.parse("tel:16505551212"); private static class ReceiverIntentPair { public BroadcastReceiver receiver; public Intent intent; public ReceiverIntentPair(BroadcastReceiver receiver, Intent intent) { this.receiver = receiver; this.intent = intent; } } @Mock private CallsManager mCallsManager; @Mock private Call mCall; @Mock private SystemStateHelper mSystemStateHelper; Loading Loading @@ -117,7 +107,6 @@ public class NewOutgoingCallIntentBroadcasterTest extends TelecomTestCase { any(PhoneAccountHandle.class))).thenReturn(mPhoneAccount); when(mPhoneAccount.isSelfManaged()).thenReturn(true); when(mSystemStateHelper.isCarModeOrProjectionActive()).thenReturn(false); when(mFeatureFlags.isNewOutgoingCallBroadcastUnblocking()).thenReturn(false); } @Override Loading Loading @@ -193,21 +182,6 @@ public class NewOutgoingCallIntentBroadcasterTest extends TelecomTestCase { verifyNoCallPlaced(); } @SmallTest @Test public void testAlreadyDisconnectedCall() { Uri handle = Uri.parse("tel:6505551234"); doReturn(true).when(mCall).isDisconnected(); Intent callIntent = buildIntent(handle, Intent.ACTION_CALL, null); ReceiverIntentPair result = regularCallTestHelper(callIntent, null); result.receiver.setResultData( result.intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER)); result.receiver.onReceive(mContext, result.intent); verifyNoCallPlaced(); } @SmallTest @Test public void testNoNumberSupplied() { Loading Loading @@ -392,170 +366,15 @@ public class NewOutgoingCallIntentBroadcasterTest extends TelecomTestCase { if (expectedAdditionalExtras != null) { expectedExtras.putAll(expectedAdditionalExtras); } BroadcastReceiver receiver = verifyBroadcastSent(handle.getSchemeSpecificPart(), expectedExtras).receiver; assertNull(receiver); } @SmallTest @Test public void testUnmodifiedRegularCall() { Uri handle = Uri.parse("tel:6505551234"); Intent callIntent = buildIntent(handle, Intent.ACTION_CALL, null); ReceiverIntentPair result = regularCallTestHelper(callIntent, null); result.receiver.setResultData( result.intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER)); result.receiver.onReceive(mContext, result.intent); verify(mCallsManager).placeOutgoingCall(eq(mCall), eq(handle), isNull(), eq(true), eq(VideoProfile.STATE_BIDIRECTIONAL)); } @SmallTest @Test public void testUnmodifiedSipCall() { Uri handle = Uri.parse("sip:test@test.com"); Intent callIntent = buildIntent(handle, Intent.ACTION_CALL, null); ReceiverIntentPair result = regularCallTestHelper(callIntent, null); result.receiver.setResultData( result.intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER)); result.receiver.onReceive(mContext, result.intent); Uri encHandle = Uri.fromParts(handle.getScheme(), handle.getSchemeSpecificPart(), null); verify(mCallsManager).placeOutgoingCall(eq(mCall), eq(encHandle), isNull(), eq(true), eq(VideoProfile.STATE_BIDIRECTIONAL)); } @SmallTest @Test public void testCallWithGatewayInfo() { Uri handle = Uri.parse("tel:6505551234"); Intent callIntent = buildIntent(handle, Intent.ACTION_CALL, null); callIntent.putExtra(NewOutgoingCallIntentBroadcaster .EXTRA_GATEWAY_PROVIDER_PACKAGE, "sample1"); callIntent.putExtra(NewOutgoingCallIntentBroadcaster.EXTRA_GATEWAY_URI, "sample2"); ReceiverIntentPair result = regularCallTestHelper(callIntent, callIntent.getExtras()); result.receiver.setResultData( result.intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER)); result.receiver.onReceive(mContext, result.intent); verify(mCallsManager).placeOutgoingCall(eq(mCall), eq(handle), isNotNull(), eq(true), eq(VideoProfile.STATE_BIDIRECTIONAL)); } @SmallTest @Test public void testCallNumberModifiedToNull() { Uri handle = Uri.parse("tel:6505551234"); Intent callIntent = buildIntent(handle, Intent.ACTION_CALL, null); ReceiverIntentPair result = regularCallTestHelper(callIntent, null); result.receiver.setResultData(null); result.receiver.onReceive(mContext, result.intent); verifyNoCallPlaced(); ArgumentCaptor<Long> timeoutCaptor = ArgumentCaptor.forClass(Long.class); verify(mCall).disconnect(timeoutCaptor.capture()); assertTrue(timeoutCaptor.getValue() > 0); } @SmallTest @Test public void testCallNumberModifiedToNullWithLongCustomTimeout() { Uri handle = Uri.parse("tel:6505551234"); Intent callIntent = buildIntent(handle, Intent.ACTION_CALL, null); ReceiverIntentPair result = regularCallTestHelper(callIntent, null); long customTimeout = 100000000; Bundle bundle = new Bundle(); bundle.putLong(TelecomManager.EXTRA_NEW_OUTGOING_CALL_CANCEL_TIMEOUT, customTimeout); result.receiver.setResultData(null); result.receiver.setResultExtras(bundle); result.receiver.onReceive(mContext, result.intent); verifyNoCallPlaced(); ArgumentCaptor<Long> timeoutCaptor = ArgumentCaptor.forClass(Long.class); verify(mCall).disconnect(timeoutCaptor.capture()); assertTrue(timeoutCaptor.getValue() < customTimeout); } @SmallTest @Test public void testCallModifiedToEmergency() { Uri handle = Uri.parse("tel:6505551234"); Intent callIntent = buildIntent(handle, Intent.ACTION_CALL, null); ReceiverIntentPair result = regularCallTestHelper(callIntent, null); String newEmergencyNumber = "1234567890"; result.receiver.setResultData(newEmergencyNumber); doReturn(true).when(mComponentContextFixture.getTelephonyManager()) .isEmergencyNumber(eq(newEmergencyNumber)); result.receiver.onReceive(mContext, result.intent); verify(mCall).disconnect(eq(0L)); } /** * Ensure if {@link TelephonyManager#isPotentialEmergencyNumber(String)} throws an exception of * any sort that we don't crash Telecom. */ @SmallTest @Test public void testThrowOnIsPotentialEmergencyNumber() { doThrow(new IllegalStateException()).when(mComponentContextFixture.getTelephonyManager()) .isPotentialEmergencyNumber(anyString()); testUnmodifiedRegularCall(); } /** * Where the flag `isNewOutgoingCallBroadcastUnblocking` is off, verify that we sent an ordered * broadcast and did not try to start the call immediately (legacy behavior). */ @SmallTest @Test public void testSendBroadcastBlocking() { when(mFeatureFlags.isNewOutgoingCallBroadcastUnblocking()).thenReturn(false); Intent intent = new Intent(Intent.ACTION_CALL, TEST_URI); NewOutgoingCallIntentBroadcaster nocib = new NewOutgoingCallIntentBroadcaster( mContext, mCallsManager, intent, mPhoneNumberUtilsAdapter, true /* isDefaultPhoneApp */, mDefaultDialerCache, mMmiUtils, mFeatureFlags); NewOutgoingCallIntentBroadcaster.CallDisposition disposition = nocib.evaluateCall(); nocib.processCall(mCall, disposition); // We should not have not short-circuited to place the outgoing call directly. verify(mCall, never()).setNewOutgoingCallIntentBroadcastIsDone(); verify(mCallsManager, never()).placeOutgoingCall(any(Call.class), any(Uri.class), any(GatewayInfo.class), anyBoolean(), anyInt()); // Ensure we did send the broadcast ordered verifyBroadcastSent(TEST_URI.getSchemeSpecificPart(), createNumberExtras(TEST_URI.getSchemeSpecificPart())); // Ensure we did not try to directly send the broadcast unordered. verify(mContext, never()).sendBroadcastAsUser( any(Intent.class), eq(UserHandle.CURRENT), eq(android.Manifest.permission.PROCESS_OUTGOING_CALLS)); verifyBroadcastSent(handle.getSchemeSpecificPart(), expectedExtras); } /** * Where the flag `isNewOutgoingCallBroadcastUnblocking` is off, verify that we sent an ordered * broadcast and did not try to start the call immediately. Also ensure that the broadcast * flags are correct. * Verify that the new outgoing call broadcast is not ordered. */ @SmallTest @Test public void testSendBroadcastNonBlocking() { when(mFeatureFlags.isNewOutgoingCallBroadcastUnblocking()).thenReturn(true); Intent intent = new Intent(Intent.ACTION_CALL, TEST_URI); NewOutgoingCallIntentBroadcaster nocib = new NewOutgoingCallIntentBroadcaster( mContext, mCallsManager, intent, mPhoneNumberUtilsAdapter, Loading Loading @@ -593,7 +412,7 @@ public class NewOutgoingCallIntentBroadcasterTest extends TelecomTestCase { assertEquals(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, capturedIntent.getFlags()); } private ReceiverIntentPair regularCallTestHelper(Intent intent, private void regularCallTestHelper(Intent intent, Bundle expectedAdditionalExtras) { Uri handle = intent.getData(); int videoState = VideoProfile.STATE_BIDIRECTIONAL; Loading @@ -610,7 +429,7 @@ public class NewOutgoingCallIntentBroadcasterTest extends TelecomTestCase { if (expectedAdditionalExtras != null) { expectedExtras.putAll(expectedAdditionalExtras); } return verifyBroadcastSent(handle.getSchemeSpecificPart(), expectedExtras); verifyBroadcastSent(handle.getSchemeSpecificPart(), expectedExtras); } private Intent buildIntent(Uri handle, String action, Bundle extras) { Loading @@ -633,36 +452,27 @@ public class NewOutgoingCallIntentBroadcasterTest extends TelecomTestCase { return cd; } private ReceiverIntentPair verifyBroadcastSent(String number, Bundle expectedExtras) { private void verifyBroadcastSent(String number, Bundle expectedExtras) { ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); ArgumentCaptor<BroadcastReceiver> receiverCaptor = ArgumentCaptor.forClass(BroadcastReceiver.class); verify(mContext).sendOrderedBroadcastAsUser( if (mFeatureFlags.telecomResolveHiddenDependencies()) { verify(mContext).sendBroadcastAsUser( intentCaptor.capture(), eq(UserHandle.CURRENT), eq(Manifest.permission.PROCESS_OUTGOING_CALLS)); } else { verify(mContext).sendBroadcastAsUser( intentCaptor.capture(), eq(UserHandle.CURRENT), eq(Manifest.permission.PROCESS_OUTGOING_CALLS), eq(AppOpsManager.OP_PROCESS_OUTGOING_CALLS), any(Bundle.class), receiverCaptor.capture(), isNull(), eq(Activity.RESULT_OK), eq(number), isNull()); anyInt()); } Intent capturedIntent = intentCaptor.getValue(); assertEquals(Intent.ACTION_NEW_OUTGOING_CALL, capturedIntent.getAction()); assertEquals(Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, assertEquals(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, capturedIntent.getFlags()); assertTrue(areBundlesEqual(expectedExtras, capturedIntent.getExtras())); BroadcastReceiver receiver = receiverCaptor.getValue(); if (receiver != null) { receiver.setPendingResult( new BroadcastReceiver.PendingResult(0, "", null, 0, true, false, null, 0, 0)); } return new ReceiverIntentPair(receiver, capturedIntent); } private Bundle createNumberExtras(String number) { Loading tests/src/com/android/server/telecom/tests/TelecomSystemTest.java +20 −27 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
flags/telecom_broadcast_flags.aconfig +1 −7 Original line number Diff line number Diff line package: "com.android.server.telecom.flags" container: "system" # OWNER=tgunn TARGET=24Q3 flag { name: "is_new_outgoing_call_broadcast_unblocking" namespace: "telecom" description: "When set, the ACTION_NEW_OUTGOING_CALL broadcast is unblocking." bug: "224550864" } No newline at end of file # This file intentionally left blank to avoid compilation errors due to removed flag.
src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java +12 −169 Original line number Diff line number Diff line Loading @@ -115,88 +115,6 @@ public class NewOutgoingCallIntentBroadcaster { mFeatureFlags = featureFlags; } /** * Processes the result of the outgoing call broadcast intent, and performs callbacks to * the OutgoingCallIntentBroadcasterListener as necessary. */ public class NewOutgoingCallBroadcastIntentReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { try { Log.startSession("NOCBIR.oR"); synchronized (mLock) { Log.v(this, "onReceive: %s", intent); // Once the NEW_OUTGOING_CALL broadcast is finished, the resultData is // used as the actual number to call. (If null, no call will be placed.) String resultNumber = getResultData(); Log.i(NewOutgoingCallIntentBroadcaster.this, "Received new-outgoing-call-broadcast for %s with data %s", mCall, Log.pii(resultNumber)); boolean endEarly = false; long disconnectTimeout = Timeouts.getNewOutgoingCallCancelMillis(mContext, mFeatureFlags); if (resultNumber == null) { Log.v(this, "Call cancelled (null number), returning..."); disconnectTimeout = getDisconnectTimeoutFromApp( getResultExtras(false), disconnectTimeout); endEarly = true; } else if (isEmergencyNumber(resultNumber)) { Log.w(this, "Cannot modify outgoing call to emergency number %s.", resultNumber); disconnectTimeout = 0; endEarly = true; } if (endEarly) { if (mCall != null) { mCall.disconnect(disconnectTimeout); } return; } // If this call is already disconnected then we have nothing more to do. if (mCall.isDisconnected()) { Log.w(this, "Call has already been disconnected," + " ignore the broadcast Call %s", mCall); return; } // TODO: Remove the assumption that phone numbers are either SIP or TEL. // This does not impact self-managed ConnectionServices as they do not use the // NewOutgoingCallIntentBroadcaster. Uri resultHandleUri = Uri.fromParts( mPhoneNumberUtilsAdapter.isUriNumber(resultNumber) ? PhoneAccount.SCHEME_SIP : PhoneAccount.SCHEME_TEL, resultNumber, null); Uri originalUri = mIntent.getData(); if (originalUri.getSchemeSpecificPart().equals(resultNumber)) { Log.v(this, "Call number unmodified after" + " new outgoing call intent broadcast."); } else { Log.v(this, "Retrieved modified handle after outgoing call intent" + " broadcast: Original: %s, Modified: %s", Log.pii(originalUri), Log.pii(resultHandleUri)); } GatewayInfo gatewayInfo = getGateWayInfoFromIntent(intent, resultHandleUri); placeOutgoingCallImmediately(mCall, resultHandleUri, gatewayInfo, mIntent.getBooleanExtra( TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, false), mIntent.getIntExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, VideoProfile.STATE_AUDIO_ONLY)); } } finally { Log.endSession(); } } } /** * Processes the supplied intent and starts the outgoing call broadcast process relevant to the * intent. Loading Loading @@ -355,13 +273,6 @@ public class NewOutgoingCallIntentBroadcaster { public void processCall(Call call, CallDisposition disposition) { mCall = call; // If the new outgoing call broadast doesn't block, trigger the legacy process call // behavior and exit out here. if (!mFeatureFlags.isNewOutgoingCallBroadcastUnblocking()) { legacyProcessCall(disposition); return; } boolean callRedirectionWithService = false; // Only try to do redirection if it was requested and we're not calling immediately. // We can expect callImmediately to be true for emergency calls and voip calls. Loading Loading @@ -398,50 +309,6 @@ public class NewOutgoingCallIntentBroadcaster { } } /** * The legacy non-flagged version of processing a call. Although there is some code duplication * if makes the new flow cleaner to read. * @param disposition */ private void legacyProcessCall(CallDisposition disposition) { if (disposition.callImmediately) { callImmediately(disposition); // Don't return but instead continue and send the ACTION_NEW_OUTGOING_CALL broadcast // so that third parties can still inspect (but not intercept) the outgoing call. When // the broadcast finally reaches the OutgoingCallBroadcastReceiver, we'll know not to // initiate the call again because of the presence of the EXTRA_ALREADY_CALLED extra. } boolean callRedirectionWithService = false; if (disposition.requestRedirection) { CallRedirectionProcessor callRedirectionProcessor = new CallRedirectionProcessor( mContext, mCallsManager, mCall, disposition.callingAddress, mCallsManager.getPhoneAccountRegistrar(), getGateWayInfoFromIntent(mIntent, mIntent.getData()), mIntent.getBooleanExtra(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, false), mIntent.getIntExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, VideoProfile.STATE_AUDIO_ONLY), mFeatureFlags); /** * If there is an available {@link android.telecom.CallRedirectionService}, use the * {@link CallRedirectionProcessor} to perform call redirection instead of using * broadcasting. */ callRedirectionWithService = callRedirectionProcessor .canMakeCallRedirectionWithServiceAsUser(mCall.getAssociatedUser()); if (callRedirectionWithService) { callRedirectionProcessor.performCallRedirection(mCall.getAssociatedUser()); } } if (disposition.sendBroadcast) { UserHandle targetUser = mCall.getAssociatedUser(); broadcastIntent(mIntent, disposition.number, !disposition.callImmediately && !callRedirectionWithService, targetUser); } } /** * Place a call immediately. * @param disposition The disposition; used for retrieving the address of the call. Loading Loading @@ -479,8 +346,7 @@ public class NewOutgoingCallIntentBroadcaster { checkAndCopyProviderExtras(originalCallIntent, broadcastIntent); if (mFeatureFlags.isNewOutgoingCallBroadcastUnblocking()) { // Where the new outgoing call broadcast is unblocking, do not give receiver FG priority // The new outgoing call broadcast is unblocking, do not give receiver FG priority // and do not allow background activity starts. broadcastIntent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); Log.i(this, "broadcastIntent: Sending non-blocking for %s to %s", mCall.getId(), Loading @@ -497,29 +363,6 @@ public class NewOutgoingCallIntentBroadcaster { android.Manifest.permission.PROCESS_OUTGOING_CALLS, AppOpsManager.OP_PROCESS_OUTGOING_CALLS); // initialExtras } } else { Log.i(this, "broadcastIntent: Sending ordered for %s to %s, waitForResult=%b", mCall.getId(), targetUser, receiverRequired); final BroadcastOptions options = BroadcastOptions.makeBasic(); options.setBackgroundActivityStartsAllowed(true); // Force receivers of this broadcast intent to run at foreground priority because we // want to finish processing the broadcast intent as soon as possible. broadcastIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); mContext.sendOrderedBroadcastAsUser( broadcastIntent, targetUser, android.Manifest.permission.PROCESS_OUTGOING_CALLS, AppOpsManager.OP_PROCESS_OUTGOING_CALLS, options.toBundle(), receiverRequired ? new NewOutgoingCallBroadcastIntentReceiver() : null, null, // scheduler Activity.RESULT_OK, // initialCode number, // initialData: initial value for the result data (number to be // modified) null); // initialExtras } } /** Loading
tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java +18 −208 Original line number Diff line number Diff line Loading @@ -78,16 +78,6 @@ import org.mockito.Mock; public class NewOutgoingCallIntentBroadcasterTest extends TelecomTestCase { private static final Uri TEST_URI = Uri.parse("tel:16505551212"); private static class ReceiverIntentPair { public BroadcastReceiver receiver; public Intent intent; public ReceiverIntentPair(BroadcastReceiver receiver, Intent intent) { this.receiver = receiver; this.intent = intent; } } @Mock private CallsManager mCallsManager; @Mock private Call mCall; @Mock private SystemStateHelper mSystemStateHelper; Loading Loading @@ -117,7 +107,6 @@ public class NewOutgoingCallIntentBroadcasterTest extends TelecomTestCase { any(PhoneAccountHandle.class))).thenReturn(mPhoneAccount); when(mPhoneAccount.isSelfManaged()).thenReturn(true); when(mSystemStateHelper.isCarModeOrProjectionActive()).thenReturn(false); when(mFeatureFlags.isNewOutgoingCallBroadcastUnblocking()).thenReturn(false); } @Override Loading Loading @@ -193,21 +182,6 @@ public class NewOutgoingCallIntentBroadcasterTest extends TelecomTestCase { verifyNoCallPlaced(); } @SmallTest @Test public void testAlreadyDisconnectedCall() { Uri handle = Uri.parse("tel:6505551234"); doReturn(true).when(mCall).isDisconnected(); Intent callIntent = buildIntent(handle, Intent.ACTION_CALL, null); ReceiverIntentPair result = regularCallTestHelper(callIntent, null); result.receiver.setResultData( result.intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER)); result.receiver.onReceive(mContext, result.intent); verifyNoCallPlaced(); } @SmallTest @Test public void testNoNumberSupplied() { Loading Loading @@ -392,170 +366,15 @@ public class NewOutgoingCallIntentBroadcasterTest extends TelecomTestCase { if (expectedAdditionalExtras != null) { expectedExtras.putAll(expectedAdditionalExtras); } BroadcastReceiver receiver = verifyBroadcastSent(handle.getSchemeSpecificPart(), expectedExtras).receiver; assertNull(receiver); } @SmallTest @Test public void testUnmodifiedRegularCall() { Uri handle = Uri.parse("tel:6505551234"); Intent callIntent = buildIntent(handle, Intent.ACTION_CALL, null); ReceiverIntentPair result = regularCallTestHelper(callIntent, null); result.receiver.setResultData( result.intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER)); result.receiver.onReceive(mContext, result.intent); verify(mCallsManager).placeOutgoingCall(eq(mCall), eq(handle), isNull(), eq(true), eq(VideoProfile.STATE_BIDIRECTIONAL)); } @SmallTest @Test public void testUnmodifiedSipCall() { Uri handle = Uri.parse("sip:test@test.com"); Intent callIntent = buildIntent(handle, Intent.ACTION_CALL, null); ReceiverIntentPair result = regularCallTestHelper(callIntent, null); result.receiver.setResultData( result.intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER)); result.receiver.onReceive(mContext, result.intent); Uri encHandle = Uri.fromParts(handle.getScheme(), handle.getSchemeSpecificPart(), null); verify(mCallsManager).placeOutgoingCall(eq(mCall), eq(encHandle), isNull(), eq(true), eq(VideoProfile.STATE_BIDIRECTIONAL)); } @SmallTest @Test public void testCallWithGatewayInfo() { Uri handle = Uri.parse("tel:6505551234"); Intent callIntent = buildIntent(handle, Intent.ACTION_CALL, null); callIntent.putExtra(NewOutgoingCallIntentBroadcaster .EXTRA_GATEWAY_PROVIDER_PACKAGE, "sample1"); callIntent.putExtra(NewOutgoingCallIntentBroadcaster.EXTRA_GATEWAY_URI, "sample2"); ReceiverIntentPair result = regularCallTestHelper(callIntent, callIntent.getExtras()); result.receiver.setResultData( result.intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER)); result.receiver.onReceive(mContext, result.intent); verify(mCallsManager).placeOutgoingCall(eq(mCall), eq(handle), isNotNull(), eq(true), eq(VideoProfile.STATE_BIDIRECTIONAL)); } @SmallTest @Test public void testCallNumberModifiedToNull() { Uri handle = Uri.parse("tel:6505551234"); Intent callIntent = buildIntent(handle, Intent.ACTION_CALL, null); ReceiverIntentPair result = regularCallTestHelper(callIntent, null); result.receiver.setResultData(null); result.receiver.onReceive(mContext, result.intent); verifyNoCallPlaced(); ArgumentCaptor<Long> timeoutCaptor = ArgumentCaptor.forClass(Long.class); verify(mCall).disconnect(timeoutCaptor.capture()); assertTrue(timeoutCaptor.getValue() > 0); } @SmallTest @Test public void testCallNumberModifiedToNullWithLongCustomTimeout() { Uri handle = Uri.parse("tel:6505551234"); Intent callIntent = buildIntent(handle, Intent.ACTION_CALL, null); ReceiverIntentPair result = regularCallTestHelper(callIntent, null); long customTimeout = 100000000; Bundle bundle = new Bundle(); bundle.putLong(TelecomManager.EXTRA_NEW_OUTGOING_CALL_CANCEL_TIMEOUT, customTimeout); result.receiver.setResultData(null); result.receiver.setResultExtras(bundle); result.receiver.onReceive(mContext, result.intent); verifyNoCallPlaced(); ArgumentCaptor<Long> timeoutCaptor = ArgumentCaptor.forClass(Long.class); verify(mCall).disconnect(timeoutCaptor.capture()); assertTrue(timeoutCaptor.getValue() < customTimeout); } @SmallTest @Test public void testCallModifiedToEmergency() { Uri handle = Uri.parse("tel:6505551234"); Intent callIntent = buildIntent(handle, Intent.ACTION_CALL, null); ReceiverIntentPair result = regularCallTestHelper(callIntent, null); String newEmergencyNumber = "1234567890"; result.receiver.setResultData(newEmergencyNumber); doReturn(true).when(mComponentContextFixture.getTelephonyManager()) .isEmergencyNumber(eq(newEmergencyNumber)); result.receiver.onReceive(mContext, result.intent); verify(mCall).disconnect(eq(0L)); } /** * Ensure if {@link TelephonyManager#isPotentialEmergencyNumber(String)} throws an exception of * any sort that we don't crash Telecom. */ @SmallTest @Test public void testThrowOnIsPotentialEmergencyNumber() { doThrow(new IllegalStateException()).when(mComponentContextFixture.getTelephonyManager()) .isPotentialEmergencyNumber(anyString()); testUnmodifiedRegularCall(); } /** * Where the flag `isNewOutgoingCallBroadcastUnblocking` is off, verify that we sent an ordered * broadcast and did not try to start the call immediately (legacy behavior). */ @SmallTest @Test public void testSendBroadcastBlocking() { when(mFeatureFlags.isNewOutgoingCallBroadcastUnblocking()).thenReturn(false); Intent intent = new Intent(Intent.ACTION_CALL, TEST_URI); NewOutgoingCallIntentBroadcaster nocib = new NewOutgoingCallIntentBroadcaster( mContext, mCallsManager, intent, mPhoneNumberUtilsAdapter, true /* isDefaultPhoneApp */, mDefaultDialerCache, mMmiUtils, mFeatureFlags); NewOutgoingCallIntentBroadcaster.CallDisposition disposition = nocib.evaluateCall(); nocib.processCall(mCall, disposition); // We should not have not short-circuited to place the outgoing call directly. verify(mCall, never()).setNewOutgoingCallIntentBroadcastIsDone(); verify(mCallsManager, never()).placeOutgoingCall(any(Call.class), any(Uri.class), any(GatewayInfo.class), anyBoolean(), anyInt()); // Ensure we did send the broadcast ordered verifyBroadcastSent(TEST_URI.getSchemeSpecificPart(), createNumberExtras(TEST_URI.getSchemeSpecificPart())); // Ensure we did not try to directly send the broadcast unordered. verify(mContext, never()).sendBroadcastAsUser( any(Intent.class), eq(UserHandle.CURRENT), eq(android.Manifest.permission.PROCESS_OUTGOING_CALLS)); verifyBroadcastSent(handle.getSchemeSpecificPart(), expectedExtras); } /** * Where the flag `isNewOutgoingCallBroadcastUnblocking` is off, verify that we sent an ordered * broadcast and did not try to start the call immediately. Also ensure that the broadcast * flags are correct. * Verify that the new outgoing call broadcast is not ordered. */ @SmallTest @Test public void testSendBroadcastNonBlocking() { when(mFeatureFlags.isNewOutgoingCallBroadcastUnblocking()).thenReturn(true); Intent intent = new Intent(Intent.ACTION_CALL, TEST_URI); NewOutgoingCallIntentBroadcaster nocib = new NewOutgoingCallIntentBroadcaster( mContext, mCallsManager, intent, mPhoneNumberUtilsAdapter, Loading Loading @@ -593,7 +412,7 @@ public class NewOutgoingCallIntentBroadcasterTest extends TelecomTestCase { assertEquals(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, capturedIntent.getFlags()); } private ReceiverIntentPair regularCallTestHelper(Intent intent, private void regularCallTestHelper(Intent intent, Bundle expectedAdditionalExtras) { Uri handle = intent.getData(); int videoState = VideoProfile.STATE_BIDIRECTIONAL; Loading @@ -610,7 +429,7 @@ public class NewOutgoingCallIntentBroadcasterTest extends TelecomTestCase { if (expectedAdditionalExtras != null) { expectedExtras.putAll(expectedAdditionalExtras); } return verifyBroadcastSent(handle.getSchemeSpecificPart(), expectedExtras); verifyBroadcastSent(handle.getSchemeSpecificPart(), expectedExtras); } private Intent buildIntent(Uri handle, String action, Bundle extras) { Loading @@ -633,36 +452,27 @@ public class NewOutgoingCallIntentBroadcasterTest extends TelecomTestCase { return cd; } private ReceiverIntentPair verifyBroadcastSent(String number, Bundle expectedExtras) { private void verifyBroadcastSent(String number, Bundle expectedExtras) { ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); ArgumentCaptor<BroadcastReceiver> receiverCaptor = ArgumentCaptor.forClass(BroadcastReceiver.class); verify(mContext).sendOrderedBroadcastAsUser( if (mFeatureFlags.telecomResolveHiddenDependencies()) { verify(mContext).sendBroadcastAsUser( intentCaptor.capture(), eq(UserHandle.CURRENT), eq(Manifest.permission.PROCESS_OUTGOING_CALLS)); } else { verify(mContext).sendBroadcastAsUser( intentCaptor.capture(), eq(UserHandle.CURRENT), eq(Manifest.permission.PROCESS_OUTGOING_CALLS), eq(AppOpsManager.OP_PROCESS_OUTGOING_CALLS), any(Bundle.class), receiverCaptor.capture(), isNull(), eq(Activity.RESULT_OK), eq(number), isNull()); anyInt()); } Intent capturedIntent = intentCaptor.getValue(); assertEquals(Intent.ACTION_NEW_OUTGOING_CALL, capturedIntent.getAction()); assertEquals(Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, assertEquals(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, capturedIntent.getFlags()); assertTrue(areBundlesEqual(expectedExtras, capturedIntent.getExtras())); BroadcastReceiver receiver = receiverCaptor.getValue(); if (receiver != null) { receiver.setPendingResult( new BroadcastReceiver.PendingResult(0, "", null, 0, true, false, null, 0, 0)); } return new ReceiverIntentPair(receiver, capturedIntent); } private Bundle createNumberExtras(String number) { Loading
tests/src/com/android/server/telecom/tests/TelecomSystemTest.java +20 −27 File changed.Preview size limit exceeded, changes collapsed. Show changes