summaryrefslogtreecommitdiff
path: root/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java')
-rw-r--r--src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java142
1 files changed, 114 insertions, 28 deletions
diff --git a/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java b/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
index 3b402b1aa..6070baa5f 100644
--- a/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
+++ b/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
@@ -16,6 +16,7 @@
package com.android.server.telecom;
+import android.Manifest;
import android.app.Activity;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
@@ -37,6 +38,7 @@ import android.telephony.TelephonyManager;
import android.text.TextUtils;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.telecom.flags.FeatureFlags;
import com.android.server.telecom.callredirection.CallRedirectionProcessor;
// TODO: Needed for move to system service: import com.android.internal.R;
@@ -77,6 +79,7 @@ public class NewOutgoingCallIntentBroadcaster {
private final TelecomSystem.SyncRoot mLock;
private final DefaultDialerCache mDefaultDialerCache;
private final MmiUtils mMmiUtils;
+ private final FeatureFlags mFeatureFlags;
/*
* Whether or not the outgoing call intent originated from the default phone application. If
@@ -100,7 +103,8 @@ public class NewOutgoingCallIntentBroadcaster {
@VisibleForTesting
public NewOutgoingCallIntentBroadcaster(Context context, CallsManager callsManager,
Intent intent, PhoneNumberUtilsAdapter phoneNumberUtilsAdapter,
- boolean isDefaultPhoneApp, DefaultDialerCache defaultDialerCache, MmiUtils mmiUtils) {
+ boolean isDefaultPhoneApp, DefaultDialerCache defaultDialerCache, MmiUtils mmiUtils,
+ FeatureFlags featureFlags) {
mContext = context;
mCallsManager = callsManager;
mIntent = intent;
@@ -109,6 +113,7 @@ public class NewOutgoingCallIntentBroadcaster {
mLock = mCallsManager.getLock();
mDefaultDialerCache = defaultDialerCache;
mMmiUtils = mmiUtils;
+ mFeatureFlags = featureFlags;
}
/**
@@ -128,7 +133,8 @@ public class NewOutgoingCallIntentBroadcaster {
// 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(this, "Received new-outgoing-call-broadcast for %s with data %s", mCall,
+ Log.i(NewOutgoingCallIntentBroadcaster.this,
+ "Received new-outgoing-call-broadcast for %s with data %s", mCall,
Log.pii(resultNumber));
boolean endEarly = false;
@@ -320,6 +326,7 @@ public class NewOutgoingCallIntentBroadcaster {
String scheme = mPhoneNumberUtilsAdapter.isUriNumber(number)
? PhoneAccount.SCHEME_SIP : PhoneAccount.SCHEME_TEL;
result.callingAddress = Uri.fromParts(scheme, number, null);
+
return result;
}
@@ -351,14 +358,57 @@ 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.
+ if (disposition.requestRedirection && !disposition.callImmediately) {
+ 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));
+ /**
+ * 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 no redirection was kicked off, place the call now.
+ if (!callRedirectionWithService) {
+ callImmediately(disposition);
+ }
+
+ // Finally, send the non-blocking broadcast if we're supposed to (ie for any non-voip call).
+ if (disposition.sendBroadcast) {
+ UserHandle targetUser = mCall.getAssociatedUser();
+ broadcastIntent(mIntent, disposition.number, false /* receiverRequired */, targetUser);
+ }
+ }
+
+ /**
+ * 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) {
- boolean speakerphoneOn = mIntent.getBooleanExtra(
- TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, false);
- int videoState = mIntent.getIntExtra(
- TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
- VideoProfile.STATE_AUDIO_ONLY);
- placeOutgoingCallImmediately(mCall, disposition.callingAddress, null,
- speakerphoneOn, videoState);
+ 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
@@ -390,13 +440,26 @@ public class NewOutgoingCallIntentBroadcaster {
if (disposition.sendBroadcast) {
UserHandle targetUser = mCall.getAssociatedUser();
- Log.i(this, "Sending NewOutgoingCallBroadcast for %s to %s", mCall, targetUser);
broadcastIntent(mIntent, disposition.number,
!disposition.callImmediately && !callRedirectionWithService, targetUser);
}
}
/**
+ * Place a call immediately.
+ * @param disposition The disposition; used for retrieving the address of the call.
+ */
+ private void callImmediately(CallDisposition disposition) {
+ boolean speakerphoneOn = mIntent.getBooleanExtra(
+ TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, false);
+ int videoState = mIntent.getIntExtra(
+ TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
+ VideoProfile.STATE_AUDIO_ONLY);
+ placeOutgoingCallImmediately(mCall, disposition.callingAddress, null,
+ speakerphoneOn, videoState);
+ }
+
+ /**
* Sends a new outgoing call ordered broadcast so that third party apps can cancel the
* placement of the call or redirect it to a different number.
*
@@ -415,28 +478,51 @@ public class NewOutgoingCallIntentBroadcaster {
if (number != null) {
broadcastIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, number);
}
-
- // 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);
Log.v(this, "Broadcasting intent: %s.", broadcastIntent);
checkAndCopyProviderExtras(originalCallIntent, broadcastIntent);
- final BroadcastOptions options = BroadcastOptions.makeBasic();
- options.setBackgroundActivityStartsAllowed(true);
- 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
+ if (mFeatureFlags.isNewOutgoingCallBroadcastUnblocking()) {
+ // Where 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(),
+ targetUser);
+ if (mFeatureFlags.telecomResolveHiddenDependencies()) {
+ mContext.sendBroadcastAsUser(
+ broadcastIntent,
+ targetUser,
+ Manifest.permission.PROCESS_OUTGOING_CALLS);
+ } else {
+ mContext.sendBroadcastAsUser(
+ broadcastIntent,
+ targetUser,
+ 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
+ }
}
/**