Reduce latency for InCallUI by adding an intermediate state
Immediately add a call to Telecomm before the outgoing call broadcast
intent returns, this will reduce the latency for the InCallUI by
allowing the InCallActivity to start before Telecomm has responded.
Bug: 16396523
Change-Id: I4edd533083d3d7edb7a14d179c174223374a4282
diff --git a/src/com/android/telecomm/Call.java b/src/com/android/telecomm/Call.java
index 16dc323..82827ad 100644
--- a/src/com/android/telecomm/Call.java
+++ b/src/com/android/telecomm/Call.java
@@ -188,7 +188,7 @@
* that the user is attempting to connect to via the gateway, the actual handle to dial in
* order to connect the call via the gateway, as well as the package name of the gateway
* service. */
- private final GatewayInfo mGatewayInfo;
+ private GatewayInfo mGatewayInfo;
private PhoneAccountHandle mConnectionManagerPhoneAccountHandle;
@@ -307,7 +307,7 @@
boolean isConference) {
mState = isConference ? CallState.ACTIVE : CallState.NEW;
mRepository = repository;
- setHandle(handle, CallPropertyPresentation.ALLOWED);
+ setHandle(handle);
mGatewayInfo = gatewayInfo;
mConnectionManagerPhoneAccountHandle = connectionManagerPhoneAccountHandle;
mTargetPhoneAccountHandle = targetPhoneAccountHandle;
@@ -383,6 +383,11 @@
return mHandlePresentation;
}
+
+ void setHandle(Uri handle) {
+ setHandle(handle, CallPropertyPresentation.ALLOWED);
+ }
+
void setHandle(Uri handle, int presentation) {
if (!Objects.equals(handle, mHandle) || presentation != mHandlePresentation) {
mHandle = handle;
@@ -466,6 +471,10 @@
return mGatewayInfo;
}
+ void setGatewayInfo(GatewayInfo gatewayInfo) {
+ mGatewayInfo = gatewayInfo;
+ }
+
PhoneAccountHandle getConnectionManagerPhoneAccount() {
return mConnectionManagerPhoneAccountHandle;
}
diff --git a/src/com/android/telecomm/CallActivity.java b/src/com/android/telecomm/CallActivity.java
index 607d994..0e231b0 100644
--- a/src/com/android/telecomm/CallActivity.java
+++ b/src/com/android/telecomm/CallActivity.java
@@ -21,10 +21,12 @@
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
+import android.net.Uri;
import android.os.Bundle;
import android.telecomm.PhoneAccountHandle;
import android.telecomm.TelecommManager;
import android.telecomm.TelecommManager;
+import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
/**
@@ -105,8 +107,17 @@
* @param intent Call intent containing data about the handle to call.
*/
private void processOutgoingCallIntent(Intent intent) {
+ String uriString = intent.getData().getSchemeSpecificPart();
+ Uri handle = Uri.fromParts(
+ PhoneNumberUtils.isUriNumber(uriString) ? "sip" : "tel", uriString, null);
+ PhoneAccountHandle phoneAccountHandle = intent.getParcelableExtra(
+ TelecommManager.EXTRA_PHONE_ACCOUNT_HANDLE);
+
+ // Send to CallsManager to ensure the InCallUI gets kicked off before the broadcast returns
+ Call call = mCallsManager.startOutgoingCall(handle, phoneAccountHandle);
+
NewOutgoingCallIntentBroadcaster broadcaster = new NewOutgoingCallIntentBroadcaster(
- mCallsManager, intent, isDefaultDialer());
+ mCallsManager, call, intent, isDefaultDialer());
final boolean success = broadcaster.processIntent();
setResult(success ? RESULT_OK : RESULT_CANCELED);
}
diff --git a/src/com/android/telecomm/CallsManager.java b/src/com/android/telecomm/CallsManager.java
index e75a9a1..b7cc233 100644
--- a/src/com/android/telecomm/CallsManager.java
+++ b/src/com/android/telecomm/CallsManager.java
@@ -259,7 +259,7 @@
* Starts the process to attach the call to a connection service.
*
* @param phoneAccountHandle The phone account which contains the component name of the connection
- * serivce to use for this call.
+ * service to use for this call.
* @param extras The optional extras Bundle passed with the intent used for the incoming call.
*/
void processIncomingCallIntent(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
@@ -281,6 +281,43 @@
call.startCreateConnection();
}
+
+ /**
+ * Kicks off the first steps to creating an outgoing call so that InCallUI can launch.
+ *
+ * NOTE: emergency calls will never pass through this because they call
+ * placeOutgoingCall directly.
+ *
+ */
+ Call startOutgoingCall(Uri handle, PhoneAccountHandle phoneAccountHandle) {
+ // We only allow a single outgoing call at any given time. Before placing a call, make sure
+ // there doesn't already exist another outgoing call.
+ Call call = getFirstCallWithState(CallState.NEW, CallState.DIALING);
+
+ if (call != null) {
+ Log.i(this, "Canceling simultaneous outgoing call.");
+ return null;
+ }
+
+ // Create a call with original handle. The handle may be changed when the call is attached
+ // to a connection service, but in most cases will remain the same.
+ call = new Call(
+ mConnectionServiceRepository,
+ handle,
+ null /* gatewayInfo */,
+ null /* connectionManagerPhoneAccount */,
+ phoneAccountHandle,
+ false /* isIncoming */,
+ false /* isConference */);
+ call.setState(CallState.CONNECTING);
+
+ // TODO: Move this to be a part of addCall()
+ call.addListener(this);
+ addCall(call);
+
+ return call;
+ }
+
/**
* Attempts to issue/connect the specified call.
*
@@ -290,14 +327,11 @@
* @param speakerphoneOn Whether or not to turn the speakerphone on once the call connects.
* @param videoState The desired video state for the outgoing call.
*/
- void placeOutgoingCall(Uri handle, GatewayInfo gatewayInfo, PhoneAccountHandle accountHandle,
- boolean speakerphoneOn, int videoState) {
-
- // We only allow a single outgoing call at any given time. Before placing a call, make sure
- // there doesn't already exist another outgoing call.
- Call currentOutgoing = getFirstCallWithState(CallState.NEW, CallState.DIALING);
- if (currentOutgoing != null) {
- Log.i(this, "Canceling simultaneous outgoing call.");
+ void placeOutgoingCall(Call call, Uri handle, GatewayInfo gatewayInfo,
+ PhoneAccountHandle accountHandle, boolean speakerphoneOn, int videoState) {
+ if (call == null) {
+ // don't do anything if the call no longer exists
+ Log.i(this, "Canceling unknown call.");
return;
}
@@ -311,6 +345,9 @@
Log.pii(uriHandle), Log.pii(handle));
}
+ //TODO: phone account is already set in {@link #startOutgoingCall}, refactor so this is
+ // not redundant.
+ //
// Only dial with the requested phoneAccount if it is still valid. Otherwise treat this call
// as if a phoneAccount was not specified (does the default behavior instead).
if (accountHandle != null) {
@@ -321,27 +358,19 @@
}
}
- Call call = new Call(
- mConnectionServiceRepository,
- uriHandle,
- gatewayInfo,
- null /* connectionManagerPhoneAccount */,
- accountHandle,
- false /* isIncoming */,
- false /* isConference */);
+ call.setHandle(uriHandle);
+ call.setGatewayInfo(gatewayInfo);
call.setStartWithSpeakerphoneOn(speakerphoneOn);
call.setVideoState(videoState);
- // TODO: Move this to be a part of addCall()
- call.addListener(this);
- addCall(call);
-
// This block of code will attempt to pre-determine a phone account
final boolean emergencyCall = TelephonyUtil.shouldProcessAsEmergency(app, call.getHandle());
if (emergencyCall) {
// Emergency -- CreateConnectionProcessor will choose accounts automatically
call.setTargetPhoneAccount(null);
} else if (accountHandle != null) {
+ // NOTE: this is currently not an option because no feature currently exists to
+ // preset a phone account
Log.d(this, "CALL with phone account: " + accountHandle);
call.setTargetPhoneAccount(accountHandle);
} else {
diff --git a/src/com/android/telecomm/NewOutgoingCallIntentBroadcaster.java b/src/com/android/telecomm/NewOutgoingCallIntentBroadcaster.java
index 410cbfd..71d8a96 100644
--- a/src/com/android/telecomm/NewOutgoingCallIntentBroadcaster.java
+++ b/src/com/android/telecomm/NewOutgoingCallIntentBroadcaster.java
@@ -69,6 +69,7 @@
private static final String SCHEME_SIP = "sip";
private final CallsManager mCallsManager;
+ private final Call mCall;
private final Intent mIntent;
/*
* Whether or not the outgoing call intent originated from the default phone application. If
@@ -76,9 +77,10 @@
*/
private final boolean mIsDefaultOrSystemPhoneApp;
- NewOutgoingCallIntentBroadcaster(CallsManager callsManager, Intent intent,
+ NewOutgoingCallIntentBroadcaster(CallsManager callsManager, Call call, Intent intent,
boolean isDefaultPhoneApp) {
mCallsManager = callsManager;
+ mCall = call;
mIntent = intent;
mIsDefaultOrSystemPhoneApp = isDefaultPhoneApp;
}
@@ -124,7 +126,7 @@
GatewayInfo gatewayInfo = getGateWayInfoFromIntent(intent, resultHandleUri);
PhoneAccountHandle accountHandle = getAccountHandleFromIntent(intent);
- mCallsManager.placeOutgoingCall(resultHandleUri, gatewayInfo, accountHandle,
+ mCallsManager.placeOutgoingCall(mCall, resultHandleUri, gatewayInfo, accountHandle,
mIntent.getBooleanExtra(TelecommManager.EXTRA_START_CALL_WITH_SPEAKERPHONE,
false),
mIntent.getIntExtra(TelecommManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
@@ -205,8 +207,8 @@
int videoState = mIntent.getIntExtra(
TelecommManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
VideoCallProfile.VideoState.AUDIO_ONLY);
- mCallsManager.placeOutgoingCall(
- Uri.fromParts(scheme, handle, null), null, null, speakerphoneOn, videoState);
+ mCallsManager.placeOutgoingCall(mCall, Uri.fromParts(scheme, handle, null), null, null,
+ speakerphoneOn, videoState);
// 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