Remote incoming calls: Telephony
Change-Id: Ie8091aacfd9be36d63db02eb8a0a4935753d657f
diff --git a/sip/src/com/android/services/telephony/sip/SipConnection.java b/sip/src/com/android/services/telephony/sip/SipConnection.java
index 5b065fd..5bca97b 100644
--- a/sip/src/com/android/services/telephony/sip/SipConnection.java
+++ b/sip/src/com/android/services/telephony/sip/SipConnection.java
@@ -40,7 +40,7 @@
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_PRECISE_CALL_STATE_CHANGED:
- updateState();
+ updateState(false);
break;
}
}
@@ -210,14 +210,14 @@
call.getEarliestConnection() == mOriginalConnection;
}
- private void updateState() {
+ private void updateState(boolean force) {
if (mOriginalConnection == null) {
return;
}
Call.State newState = mOriginalConnection.getState();
if (VERBOSE) log("updateState, " + mOriginalConnectionState + " -> " + newState);
- if (mOriginalConnectionState != newState) {
+ if (force || mOriginalConnectionState != newState) {
mOriginalConnectionState = newState;
switch (newState) {
case IDLE:
@@ -243,7 +243,7 @@
case DISCONNECTING:
break;
}
- updateCallCapabilities();
+ updateCallCapabilities(force);
}
}
@@ -255,16 +255,17 @@
return capabilities;
}
- void updateCallCapabilities() {
+ void updateCallCapabilities(boolean force) {
int newCallCapabilities = buildCallCapabilities();
- if (getCallCapabilities() != newCallCapabilities) {
+ if (force || getCallCapabilities() != newCallCapabilities) {
setCallCapabilities(newCallCapabilities);
}
}
void onAddedToCallService() {
if (VERBOSE) log("onAddedToCallService");
- updateCallCapabilities();
+ updateState(true);
+ updateCallCapabilities(true);
setAudioModeIsVoip(true);
if (mOriginalConnection != null) {
setCallerDisplayName(mOriginalConnection.getCnapName(),
diff --git a/sip/src/com/android/services/telephony/sip/SipConnectionService.java b/sip/src/com/android/services/telephony/sip/SipConnectionService.java
index 3c32604..a46180d 100644
--- a/sip/src/com/android/services/telephony/sip/SipConnectionService.java
+++ b/sip/src/com/android/services/telephony/sip/SipConnectionService.java
@@ -54,15 +54,15 @@
}
@Override
- protected void onCreateConnections(
+ protected void onCreateOutgoingConnection(
final ConnectionRequest request,
- final OutgoingCallResponse<Connection> response) {
- if (VERBOSE) log("onCreateConnections, request: " + request);
+ final CreateConnectionResponse<Connection> response) {
+ if (VERBOSE) log("onCreateOutgoingConnection, request: " + request);
SipProfileChooser.Callback callback = new SipProfileChooser.Callback() {
@Override
public void onSipChosen(SipProfile profile) {
- if (VERBOSE) log("onCreateConnections, onSipChosen: " + profile);
+ if (VERBOSE) log("onCreateOutgoingConnection, onSipChosen: " + profile);
SipConnection connection = createConnectionForProfile(profile, request);
if (connection == null) {
response.onCancel(request);
@@ -73,13 +73,13 @@
@Override
public void onSipNotChosen() {
- if (VERBOSE) log("onCreateConnections, onSipNotChosen");
+ if (VERBOSE) log("onCreateOutgoingConnection, onSipNotChosen");
response.onFailure(request, DisconnectCause.ERROR_UNSPECIFIED, null);
}
@Override
public void onCancelCall() {
- if (VERBOSE) log("onCreateConnections, onCancelCall");
+ if (VERBOSE) log("onCreateOutgoingConnection, onCancelCall");
response.onCancel(request);
}
};
@@ -99,14 +99,20 @@
@Override
protected void onCreateIncomingConnection(
ConnectionRequest request,
- Response<ConnectionRequest, Connection> response) {
+ CreateConnectionResponse<Connection> response) {
if (VERBOSE) log("onCreateIncomingConnection, request: " + request);
+ if (request.getExtras() == null) {
+ if (VERBOSE) log("onCreateIncomingConnection, no extras");
+ response.onFailure(request, DisconnectCause.ERROR_UNSPECIFIED, null);
+ return;
+ }
+
Intent sipIntent = (Intent) request.getExtras().getParcelable(
SipUtil.EXTRA_INCOMING_CALL_INTENT);
if (sipIntent == null) {
if (VERBOSE) log("onCreateIncomingConnection, no SIP intent");
- response.onError(request, DisconnectCause.ERROR_UNSPECIFIED, null);
+ response.onFailure(request, DisconnectCause.ERROR_UNSPECIFIED, null);
return;
}
@@ -114,8 +120,8 @@
try {
sipAudioCall = SipManager.newInstance(this).takeAudioCall(sipIntent, null);
} catch (SipException e) {
- log("onCreateConferenceConnection, takeAudioCall exception: " + e);
- response.onError(request, DisconnectCause.ERROR_UNSPECIFIED, null);
+ log("onCreateIncomingConnection, takeAudioCall exception: " + e);
+ response.onCancel(request);
return;
}
@@ -129,11 +135,11 @@
if (VERBOSE) log("onCreateIncomingConnection, new connection: " + originalConnection);
if (originalConnection != null) {
SipConnection connection = new SipConnection(originalConnection);
- response.onResult(getConnectionRequestForIncomingCall(request, originalConnection),
+ response.onSuccess(getConnectionRequestForIncomingCall(request, originalConnection),
connection);
} else {
if (VERBOSE) log("onCreateIncomingConnection, takingIncomingCall failed");
- response.onError(request, DisconnectCause.ERROR_UNSPECIFIED, null);
+ response.onCancel(request);
}
}
}
diff --git a/src/com/android/phone/CallFeaturesSetting.java b/src/com/android/phone/CallFeaturesSetting.java
index 95d648c..c3d0191 100644
--- a/src/com/android/phone/CallFeaturesSetting.java
+++ b/src/com/android/phone/CallFeaturesSetting.java
@@ -2251,7 +2251,7 @@
CharSequence label = mConnectionServiceLabelByComponentName.get(
value == null ? mConnectionService.getValue() : value);
if (label == null) {
- Log.wtf(LOG_TAG, "Unknown default connection service entry " +
+ Log.w(LOG_TAG, "Unknown default connection service entry " +
mConnectionService.getValue());
mConnectionService.setSummary("");
}
diff --git a/src/com/android/services/telephony/GsmConnection.java b/src/com/android/services/telephony/GsmConnection.java
index f34cf27..8b02b52 100644
--- a/src/com/android/services/telephony/GsmConnection.java
+++ b/src/com/android/services/telephony/GsmConnection.java
@@ -51,7 +51,7 @@
void setIsConferenceCapable(boolean isConferenceCapable) {
if (mIsConferenceCapable != isConferenceCapable) {
mIsConferenceCapable = isConferenceCapable;
- updateCallCapabilities();
+ updateCallCapabilities(false);
}
}
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 4662536..5886ef2 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -16,6 +16,7 @@
package com.android.services.telephony;
+import android.net.Uri;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Message;
@@ -29,6 +30,7 @@
import android.telecomm.Connection;
import java.util.List;
+import java.util.Objects;
/**
* Base class for CDMA and GSM connections.
@@ -40,21 +42,20 @@
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
- // TODO: This code assumes that there is only one connection in the foreground call,
- // in other words, it punts on network-mediated conference calling.
- if (getOriginalConnection() != getForegroundConnection()) {
- Log.v(TelephonyConnection.this, "handleMessage, original connection is not " +
- "foreground connection, skipping");
- return;
- }
-
switch (msg.what) {
case MSG_PRECISE_CALL_STATE_CHANGED:
Log.v(TelephonyConnection.this, "MSG_PRECISE_CALL_STATE_CHANGED");
- updateState();
+ updateState(false);
break;
case MSG_RINGBACK_TONE:
Log.v(TelephonyConnection.this, "MSG_RINGBACK_TONE");
+ // TODO: This code assumes that there is only one connection in the foreground
+ // call, in other words, it punts on network-mediated conference calling.
+ if (getOriginalConnection() != getForegroundConnection()) {
+ Log.v(TelephonyConnection.this, "handleMessage, original connection is " +
+ "not foreground connection, skipping");
+ return;
+ }
setRequestingRingback((Boolean) ((AsyncResult) msg.obj).result);
break;
}
@@ -81,7 +82,6 @@
mHandler, MSG_PRECISE_CALL_STATE_CHANGED, null);
getPhone().registerForRingbackTone(mHandler, MSG_RINGBACK_TONE, null);
mOriginalConnection.addPostDialListener(mPostDialListener);
- updateState();
}
@Override
@@ -223,23 +223,40 @@
protected abstract int buildCallCapabilities();
- final void updateCallCapabilities() {
+ protected final void updateCallCapabilities(boolean force) {
int newCallCapabilities = buildCallCapabilities();
- if (getCallCapabilities() != newCallCapabilities) {
+ if (force || getCallCapabilities() != newCallCapabilities) {
setCallCapabilities(newCallCapabilities);
}
}
- void onAddedToCallService() {
- updateCallCapabilities();
+ protected final void updateHandle(boolean force) {
if (mOriginalConnection != null) {
- setCallerDisplayName(
- mOriginalConnection.getCnapName(),
- mOriginalConnection.getCnapNamePresentation());
+ Uri handle = TelephonyConnectionService.getHandleFromAddress(
+ mOriginalConnection.getAddress());
+ int presentation = mOriginalConnection.getNumberPresentation();
+ if (force || !Objects.equals(handle, getHandle()) ||
+ presentation != getHandlePresentation()) {
+ Log.v(this, "updateHandle, handle changed");
+ setHandle(handle, presentation);
+ }
+
+ String name = mOriginalConnection.getCnapName();
+ int namePresentation = mOriginalConnection.getCnapNamePresentation();
+ if (force || !Objects.equals(name, getCallerDisplayName()) ||
+ namePresentation != getCallerDisplayNamePresentation()) {
+ Log.v(this, "updateHandle, caller display name changed");
+ setCallerDisplayName(name, namePresentation);
+ }
}
}
+ void onAddedToCallService() {
+ updateState(false);
+ }
+
void onRemovedFromCallService() {
+ // Subclass can override this to do cleanup.
}
private void hangup(int disconnectCause) {
@@ -313,14 +330,14 @@
return true;
}
- private void updateState() {
+ private void updateState(boolean force) {
if (mOriginalConnection == null) {
return;
}
Call.State newState = mOriginalConnection.getState();
Log.v(this, "Update state from %s to %s for %s", mOriginalConnectionState, newState, this);
- if (mOriginalConnectionState != newState) {
+ if (force || mOriginalConnectionState != newState) {
mOriginalConnectionState = newState;
switch (newState) {
case IDLE:
@@ -341,12 +358,14 @@
break;
case DISCONNECTED:
setDisconnected(mOriginalConnection.getDisconnectCause(), null);
+ close();
break;
case DISCONNECTING:
break;
}
- updateCallCapabilities();
}
+ updateCallCapabilities(force);
+ updateHandle(force);
}
private void close() {
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 782f864..626244e 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -53,20 +53,21 @@
}
@Override
- protected void onCreateConnections(
+ protected void onCreateOutgoingConnection(
final ConnectionRequest request,
- final OutgoingCallResponse<Connection> response) {
- Log.v(this, "onCreateConnections, request: " + request);
+ final CreateConnectionResponse<Connection> response) {
+ Log.v(this, "onCreateOutgoingConnection, request: " + request);
Uri handle = request.getHandle();
if (handle == null) {
- Log.d(this, "onCreateConnections, handle is null");
+ Log.d(this, "onCreateOutgoingConnection, handle is null");
response.onFailure(request, DisconnectCause.NO_PHONE_NUMBER_SUPPLIED, "Handle is null");
return;
}
if (!SCHEME_TEL.equals(handle.getScheme())) {
- Log.d(this, "onCreateConnections, Handle %s is not type tel", handle.getScheme());
+ Log.d(this, "onCreateOutgoingConnection, Handle %s is not type tel",
+ handle.getScheme());
response.onFailure(request, DisconnectCause.ERROR_UNSPECIFIED,
"Handle scheme is not type tel");
return;
@@ -74,14 +75,14 @@
final String number = handle.getSchemeSpecificPart();
if (TextUtils.isEmpty(number)) {
- Log.d(this, "onCreateConnections, unable to parse number");
+ Log.d(this, "onCreateOutgoingConnection, unable to parse number");
response.onFailure(request, DisconnectCause.INVALID_NUMBER, "Unable to parse number");
return;
}
final Phone phone = PhoneFactory.getDefaultPhone();
if (phone == null) {
- Log.d(this, "onCreateConnections, phone is null");
+ Log.d(this, "onCreateOutgoingConnection, phone is null");
response.onFailure(request, DisconnectCause.ERROR_UNSPECIFIED, "Phone is null");
return;
}
@@ -105,15 +106,16 @@
"ServiceState.STATE_POWER_OFF");
return;
default:
- Log.d(this, "onCreateConnections, Unrecognized service state: %d", state);
+ Log.d(this, "onCreateOutgoingConnection, unkown service state: %d", state);
response.onFailure(request, DisconnectCause.ERROR_UNSPECIFIED,
- "Unrecognized service state " + state);
+ "Unkown service state " + state);
return;
}
}
if (isEmergencyNumber) {
- Log.d(this, "onCreateConnections, doing startTurnOnRadioSequence for emergency number");
+ Log.d(this, "onCreateOutgoingConnection, doing startTurnOnRadioSequence for " +
+ "emergency number");
if (mEmergencyCallHelper == null) {
mEmergencyCallHelper = new EmergencyCallHelper(this);
}
@@ -124,7 +126,7 @@
if (isRadioReady) {
startOutgoingCall(request, response, phone, number);
} else {
- Log.d(this, "onCreateConnections, failed to turn on radio");
+ Log.d(this, "onCreateOutgoingConnection, failed to turn on radio");
response.onFailure(request, DisconnectCause.POWER_OFF,
"Failed to turn on radio.");
}
@@ -153,22 +155,21 @@
@Override
protected void onCreateIncomingConnection(
ConnectionRequest request,
- Response<ConnectionRequest, Connection> response) {
+ CreateConnectionResponse<Connection> response) {
Log.v(this, "onCreateIncomingConnection, request: " + request);
Phone phone = PhoneFactory.getDefaultPhone();
Call call = phone.getRingingCall();
if (!call.getState().isRinging()) {
Log.v(this, "onCreateIncomingConnection, no ringing call");
- response.onError(request, DisconnectCause.INCOMING_MISSED, "Found no ringing call");
+ response.onFailure(request, DisconnectCause.INCOMING_MISSED, "Found no ringing call");
return;
}
com.android.internal.telephony.Connection originalConnection = call.getEarliestConnection();
if (isOriginalConnectionKnown(originalConnection)) {
Log.v(this, "onCreateIncomingConnection, original connection already registered");
- response.onError(request, DisconnectCause.ERROR_UNSPECIFIED,
- "Connection already registered");
+ response.onCancel(request);
return;
}
@@ -182,11 +183,11 @@
request.getVideoState());
if (phone.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) {
- response.onResult(telephonyRequest, new GsmConnection(originalConnection));
+ response.onSuccess(telephonyRequest, new GsmConnection(originalConnection));
} else if (phone.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) {
- response.onResult(telephonyRequest, new CdmaConnection(originalConnection));
+ response.onSuccess(telephonyRequest, new CdmaConnection(originalConnection));
} else {
- response.onError(request, DisconnectCause.ERROR_UNSPECIFIED, "Invalid phone type");
+ response.onCancel(request);
}
}
@@ -208,7 +209,7 @@
private void startOutgoingCall(
ConnectionRequest request,
- OutgoingCallResponse<Connection> response,
+ CreateConnectionResponse<Connection> response,
Phone phone,
String number) {
Log.v(this, "startOutgoingCall");
@@ -258,7 +259,7 @@
return false;
}
- private static Uri getHandleFromAddress(String address) {
+ static Uri getHandleFromAddress(String address) {
// Address can be null for blocked calls.
if (address == null) {
address = "";