Add API support for multi-endpoint.
This CL includes changes required to support multi-endpoint (see the
design doc linked off the bug).
Main changes include:
- support for indicating if a call/connection is "external" to the device.
- support for indicating if an external call can be pulled from the
remote device to the local device.
- API used to initiate a pull of a call external to the current device to
the current device.
- Made the "connection event" API public (was previously @hide); this will
be used to support passing some error events involving pulling calls to
the incall ui.
- Added new InCallService metadata which will be used to determine if an
InCallService wants to be informed of external calls.
- New disconnect causes which will be used to expose the fact that a
multi-endpoint call was answered elsewhere and that a call ended because
it was pulled to another device.
- New call log call types to indicate if calls were answered elsewhere
or pulled to another device.
Bug: 27458894
Change-Id: I423f64ff965b5e50194635a51868c327782db2a1
diff --git a/api/current.txt b/api/current.txt
index 9e0af76..2a3aa59 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -30762,6 +30762,7 @@
public static class CallLog.Calls implements android.provider.BaseColumns {
ctor public CallLog.Calls();
method public static java.lang.String getLastOutgoingCall(android.content.Context);
+ field public static final int ANSWERED_EXTERNALLY_TYPE = 7; // 0x7
field public static final int BLOCKED_TYPE = 6; // 0x6
field public static final java.lang.String CACHED_FORMATTED_NUMBER = "formatted_number";
field public static final java.lang.String CACHED_LOOKUP_URI = "lookup_uri";
@@ -30784,6 +30785,7 @@
field public static final java.lang.String DURATION = "duration";
field public static final java.lang.String EXTRA_CALL_TYPE_FILTER = "android.provider.extra.CALL_TYPE_FILTER";
field public static final java.lang.String FEATURES = "features";
+ field public static final int FEATURES_PULLED_EXTERNALLY = 2; // 0x2
field public static final int FEATURES_VIDEO = 1; // 0x1
field public static final java.lang.String GEOCODED_LOCATION = "geocoded_location";
field public static final int INCOMING_TYPE = 1; // 0x1
@@ -36058,9 +36060,11 @@
method public void phoneAccountSelected(android.telecom.PhoneAccountHandle, boolean);
method public void playDtmfTone(char);
method public void postDialContinue(boolean);
+ method public void pullExternalCall();
method public void registerCallback(android.telecom.Call.Callback);
method public void registerCallback(android.telecom.Call.Callback, android.os.Handler);
method public void reject(boolean, java.lang.String);
+ method public void sendCallEvent(java.lang.String, android.os.Bundle);
method public void splitFromConference();
method public void stopDtmfTone();
method public void swapConference();
@@ -36074,6 +36078,7 @@
field public static final int STATE_DISCONNECTING = 10; // 0xa
field public static final int STATE_HOLDING = 3; // 0x3
field public static final int STATE_NEW = 0; // 0x0
+ field public static final int STATE_PULLING_CALL = 11; // 0xb
field public static final int STATE_RINGING = 2; // 0x2
field public static final int STATE_SELECT_PHONE_ACCOUNT = 8; // 0x8
}
@@ -36084,6 +36089,7 @@
method public void onCannedTextResponsesLoaded(android.telecom.Call, java.util.List<java.lang.String>);
method public void onChildrenChanged(android.telecom.Call, java.util.List<android.telecom.Call>);
method public void onConferenceableCallsChanged(android.telecom.Call, java.util.List<android.telecom.Call>);
+ method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle);
method public void onDetailsChanged(android.telecom.Call, android.telecom.Call.Details);
method public void onParentChanged(android.telecom.Call, android.telecom.Call);
method public void onPostDialWait(android.telecom.Call, java.lang.String);
@@ -36114,6 +36120,7 @@
method public static java.lang.String propertiesToString(int);
field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 4194304; // 0x400000
field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
+ field public static final int CAPABILITY_CAN_PULL_CALL = 8388608; // 0x800000
field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000
field public static final int CAPABILITY_HOLD = 1; // 0x1
field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80
@@ -36133,6 +36140,7 @@
field public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 4; // 0x4
field public static final int PROPERTY_GENERIC_CONFERENCE = 2; // 0x2
field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10
+ field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40
field public static final int PROPERTY_WIFI = 8; // 0x8
field public static final int PROPERTY_WORK_CALL = 32; // 0x20
}
@@ -36247,15 +36255,18 @@
method public void onAnswer(int);
method public void onAnswer();
method public void onCallAudioStateChanged(android.telecom.CallAudioState);
+ method public void onCallEvent(java.lang.String, android.os.Bundle);
method public void onDisconnect();
method public void onHold();
method public void onPlayDtmfTone(char);
method public void onPostDialContinue(boolean);
+ method public void onPullExternalCall();
method public void onReject();
method public void onSeparate();
method public void onStateChanged(int);
method public void onStopDtmfTone();
method public void onUnhold();
+ method public void sendConnectionEvent(java.lang.String, android.os.Bundle);
method public final void setActive();
method public final void setAddress(android.net.Uri, int);
method public final void setAudioModeIsVoip(boolean);
@@ -36279,9 +36290,11 @@
method public static java.lang.String stateToString(int);
field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 8388608; // 0x800000
field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
+ field public static final int CAPABILITY_CAN_PULL_CALL = 33554432; // 0x2000000
field public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 524288; // 0x80000
field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000
field public static final int CAPABILITY_HOLD = 1; // 0x1
+ field public static final int CAPABILITY_IS_EXTERNAL_CALL = 16777216; // 0x1000000
field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80
field public static final int CAPABILITY_MERGE_CONFERENCE = 4; // 0x4
field public static final int CAPABILITY_MUTE = 64; // 0x40
@@ -36295,6 +36308,7 @@
field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 2048; // 0x800
field public static final int CAPABILITY_SUPPORT_HOLD = 2; // 0x2
field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8
+ field public static final java.lang.String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED";
field public static final java.lang.String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT";
field public static final java.lang.String EXTRA_CHILD_ADDRESS = "android.telecom.extra.CHILD_ADDRESS";
field public static final java.lang.String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER";
@@ -36304,6 +36318,7 @@
field public static final int STATE_HOLDING = 5; // 0x5
field public static final int STATE_INITIALIZING = 0; // 0x0
field public static final int STATE_NEW = 1; // 0x1
+ field public static final int STATE_PULLING_CALL = 7; // 0x7
field public static final int STATE_RINGING = 2; // 0x2
}
@@ -36381,7 +36396,9 @@
method public java.lang.String getReason();
method public int getTone();
method public void writeToParcel(android.os.Parcel, int);
+ field public static final int ANSWERED_ELSEWHERE = 11; // 0xb
field public static final int BUSY = 7; // 0x7
+ field public static final int CALL_PULLED = 12; // 0xc
field public static final int CANCELED = 4; // 0x4
field public static final int CONNECTION_MANAGER_NOT_SUPPORTED = 10; // 0xa
field public static final android.os.Parcelable.Creator<android.telecom.DisconnectCause> CREATOR;
@@ -36417,6 +36434,7 @@
method public void onCallAudioStateChanged(android.telecom.CallAudioState);
method public void onCallRemoved(android.telecom.Call);
method public void onCanAddCallChanged(boolean);
+ method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle);
method public void onSilenceRinger();
method public final void setAudioRoute(int);
method public final void setMuted(boolean);
@@ -36567,6 +36585,7 @@
method public boolean isVoipAudioMode();
method public void playDtmfTone(char);
method public void postDialContinue(boolean);
+ method public void pullExternalCall();
method public void registerCallback(android.telecom.RemoteConnection.Callback);
method public void registerCallback(android.telecom.RemoteConnection.Callback, android.os.Handler);
method public void reject();
@@ -36583,6 +36602,7 @@
method public void onConferenceChanged(android.telecom.RemoteConnection, android.telecom.RemoteConference);
method public void onConferenceableConnectionsChanged(android.telecom.RemoteConnection, java.util.List<android.telecom.RemoteConnection>);
method public void onConnectionCapabilitiesChanged(android.telecom.RemoteConnection, int);
+ method public void onConnectionEvent(android.telecom.RemoteConnection, java.lang.String, android.os.Bundle);
method public void onDestroyed(android.telecom.RemoteConnection);
method public void onDisconnected(android.telecom.RemoteConnection, android.telecom.DisconnectCause);
method public void onExtrasChanged(android.telecom.RemoteConnection, android.os.Bundle);
@@ -36680,6 +36700,7 @@
field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS";
field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE";
+ field public static final java.lang.String METADATA_INCLUDE_EXTERNAL_CALLS = "android.telecom.INCLUDE_EXTERNAL_CALLS";
field public static final java.lang.String METADATA_IN_CALL_SERVICE_RINGING = "android.telecom.IN_CALL_SERVICE_RINGING";
field public static final java.lang.String METADATA_IN_CALL_SERVICE_UI = "android.telecom.IN_CALL_SERVICE_UI";
field public static final int PRESENTATION_ALLOWED = 1; // 0x1
diff --git a/api/system-current.txt b/api/system-current.txt
index 00cf357..9056a89 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -33114,6 +33114,7 @@
public static class CallLog.Calls implements android.provider.BaseColumns {
ctor public CallLog.Calls();
method public static java.lang.String getLastOutgoingCall(android.content.Context);
+ field public static final int ANSWERED_EXTERNALLY_TYPE = 7; // 0x7
field public static final int BLOCKED_TYPE = 6; // 0x6
field public static final java.lang.String CACHED_FORMATTED_NUMBER = "formatted_number";
field public static final java.lang.String CACHED_LOOKUP_URI = "lookup_uri";
@@ -33136,6 +33137,7 @@
field public static final java.lang.String DURATION = "duration";
field public static final java.lang.String EXTRA_CALL_TYPE_FILTER = "android.provider.extra.CALL_TYPE_FILTER";
field public static final java.lang.String FEATURES = "features";
+ field public static final int FEATURES_PULLED_EXTERNALLY = 2; // 0x2
field public static final int FEATURES_VIDEO = 1; // 0x1
field public static final java.lang.String GEOCODED_LOCATION = "geocoded_location";
field public static final int INCOMING_TYPE = 1; // 0x1
@@ -38658,10 +38660,12 @@
method public void phoneAccountSelected(android.telecom.PhoneAccountHandle, boolean);
method public void playDtmfTone(char);
method public void postDialContinue(boolean);
+ method public void pullExternalCall();
method public void registerCallback(android.telecom.Call.Callback);
method public void registerCallback(android.telecom.Call.Callback, android.os.Handler);
method public void reject(boolean, java.lang.String);
method public deprecated void removeListener(android.telecom.Call.Listener);
+ method public void sendCallEvent(java.lang.String, android.os.Bundle);
method public void splitFromConference();
method public void stopDtmfTone();
method public void swapConference();
@@ -38676,6 +38680,7 @@
field public static final int STATE_HOLDING = 3; // 0x3
field public static final int STATE_NEW = 0; // 0x0
field public static final deprecated int STATE_PRE_DIAL_WAIT = 8; // 0x8
+ field public static final int STATE_PULLING_CALL = 11; // 0xb
field public static final int STATE_RINGING = 2; // 0x2
field public static final int STATE_SELECT_PHONE_ACCOUNT = 8; // 0x8
}
@@ -38686,6 +38691,7 @@
method public void onCannedTextResponsesLoaded(android.telecom.Call, java.util.List<java.lang.String>);
method public void onChildrenChanged(android.telecom.Call, java.util.List<android.telecom.Call>);
method public void onConferenceableCallsChanged(android.telecom.Call, java.util.List<android.telecom.Call>);
+ method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle);
method public void onDetailsChanged(android.telecom.Call, android.telecom.Call.Details);
method public void onParentChanged(android.telecom.Call, android.telecom.Call);
method public void onPostDialWait(android.telecom.Call, java.lang.String);
@@ -38716,6 +38722,7 @@
method public static java.lang.String propertiesToString(int);
field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 4194304; // 0x400000
field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
+ field public static final int CAPABILITY_CAN_PULL_CALL = 8388608; // 0x800000
field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000
field public static final int CAPABILITY_HOLD = 1; // 0x1
field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80
@@ -38735,6 +38742,7 @@
field public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 4; // 0x4
field public static final int PROPERTY_GENERIC_CONFERENCE = 2; // 0x2
field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10
+ field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40
field public static final int PROPERTY_WIFI = 8; // 0x8
field public static final int PROPERTY_WORK_CALL = 32; // 0x20
}
@@ -38860,15 +38868,18 @@
method public void onAnswer();
method public deprecated void onAudioStateChanged(android.telecom.AudioState);
method public void onCallAudioStateChanged(android.telecom.CallAudioState);
+ method public void onCallEvent(java.lang.String, android.os.Bundle);
method public void onDisconnect();
method public void onHold();
method public void onPlayDtmfTone(char);
method public void onPostDialContinue(boolean);
+ method public void onPullExternalCall();
method public void onReject();
method public void onSeparate();
method public void onStateChanged(int);
method public void onStopDtmfTone();
method public void onUnhold();
+ method public void sendConnectionEvent(java.lang.String, android.os.Bundle);
method public final void setActive();
method public final void setAddress(android.net.Uri, int);
method public final void setAudioModeIsVoip(boolean);
@@ -38892,9 +38903,11 @@
method public static java.lang.String stateToString(int);
field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 8388608; // 0x800000
field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
+ field public static final int CAPABILITY_CAN_PULL_CALL = 33554432; // 0x2000000
field public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 524288; // 0x80000
field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000
field public static final int CAPABILITY_HOLD = 1; // 0x1
+ field public static final int CAPABILITY_IS_EXTERNAL_CALL = 16777216; // 0x1000000
field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80
field public static final int CAPABILITY_MERGE_CONFERENCE = 4; // 0x4
field public static final int CAPABILITY_MUTE = 64; // 0x40
@@ -38908,6 +38921,7 @@
field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 2048; // 0x800
field public static final int CAPABILITY_SUPPORT_HOLD = 2; // 0x2
field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8
+ field public static final java.lang.String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED";
field public static final java.lang.String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT";
field public static final java.lang.String EXTRA_CHILD_ADDRESS = "android.telecom.extra.CHILD_ADDRESS";
field public static final java.lang.String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER";
@@ -38917,6 +38931,7 @@
field public static final int STATE_HOLDING = 5; // 0x5
field public static final int STATE_INITIALIZING = 0; // 0x0
field public static final int STATE_NEW = 1; // 0x1
+ field public static final int STATE_PULLING_CALL = 7; // 0x7
field public static final int STATE_RINGING = 2; // 0x2
}
@@ -38994,7 +39009,9 @@
method public java.lang.String getReason();
method public int getTone();
method public void writeToParcel(android.os.Parcel, int);
+ field public static final int ANSWERED_ELSEWHERE = 11; // 0xb
field public static final int BUSY = 7; // 0x7
+ field public static final int CALL_PULLED = 12; // 0xc
field public static final int CANCELED = 4; // 0x4
field public static final int CONNECTION_MANAGER_NOT_SUPPORTED = 10; // 0xa
field public static final android.os.Parcelable.Creator<android.telecom.DisconnectCause> CREATOR;
@@ -39031,6 +39048,7 @@
method public void onCallAudioStateChanged(android.telecom.CallAudioState);
method public void onCallRemoved(android.telecom.Call);
method public void onCanAddCallChanged(boolean);
+ method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle);
method public deprecated void onPhoneCreated(android.telecom.Phone);
method public deprecated void onPhoneDestroyed(android.telecom.Phone);
method public void onSilenceRinger();
@@ -39236,6 +39254,7 @@
method public boolean isVoipAudioMode();
method public void playDtmfTone(char);
method public void postDialContinue(boolean);
+ method public void pullExternalCall();
method public void registerCallback(android.telecom.RemoteConnection.Callback);
method public void registerCallback(android.telecom.RemoteConnection.Callback, android.os.Handler);
method public void reject();
@@ -39253,6 +39272,7 @@
method public void onConferenceChanged(android.telecom.RemoteConnection, android.telecom.RemoteConference);
method public void onConferenceableConnectionsChanged(android.telecom.RemoteConnection, java.util.List<android.telecom.RemoteConnection>);
method public void onConnectionCapabilitiesChanged(android.telecom.RemoteConnection, int);
+ method public void onConnectionEvent(android.telecom.RemoteConnection, java.lang.String, android.os.Bundle);
method public void onDestroyed(android.telecom.RemoteConnection);
method public void onDisconnected(android.telecom.RemoteConnection, android.telecom.DisconnectCause);
method public void onExtrasChanged(android.telecom.RemoteConnection, android.os.Bundle);
@@ -39377,6 +39397,7 @@
field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS";
field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE";
+ field public static final java.lang.String METADATA_INCLUDE_EXTERNAL_CALLS = "android.telecom.INCLUDE_EXTERNAL_CALLS";
field public static final java.lang.String METADATA_IN_CALL_SERVICE_RINGING = "android.telecom.IN_CALL_SERVICE_RINGING";
field public static final java.lang.String METADATA_IN_CALL_SERVICE_UI = "android.telecom.IN_CALL_SERVICE_UI";
field public static final int PRESENTATION_ALLOWED = 1; // 0x1
diff --git a/api/test-current.txt b/api/test-current.txt
index 9aed5e9..566a574 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -30832,6 +30832,7 @@
public static class CallLog.Calls implements android.provider.BaseColumns {
ctor public CallLog.Calls();
method public static java.lang.String getLastOutgoingCall(android.content.Context);
+ field public static final int ANSWERED_EXTERNALLY_TYPE = 7; // 0x7
field public static final int BLOCKED_TYPE = 6; // 0x6
field public static final java.lang.String CACHED_FORMATTED_NUMBER = "formatted_number";
field public static final java.lang.String CACHED_LOOKUP_URI = "lookup_uri";
@@ -30854,6 +30855,7 @@
field public static final java.lang.String DURATION = "duration";
field public static final java.lang.String EXTRA_CALL_TYPE_FILTER = "android.provider.extra.CALL_TYPE_FILTER";
field public static final java.lang.String FEATURES = "features";
+ field public static final int FEATURES_PULLED_EXTERNALLY = 2; // 0x2
field public static final int FEATURES_VIDEO = 1; // 0x1
field public static final java.lang.String GEOCODED_LOCATION = "geocoded_location";
field public static final int INCOMING_TYPE = 1; // 0x1
@@ -36130,9 +36132,11 @@
method public void phoneAccountSelected(android.telecom.PhoneAccountHandle, boolean);
method public void playDtmfTone(char);
method public void postDialContinue(boolean);
+ method public void pullExternalCall();
method public void registerCallback(android.telecom.Call.Callback);
method public void registerCallback(android.telecom.Call.Callback, android.os.Handler);
method public void reject(boolean, java.lang.String);
+ method public void sendCallEvent(java.lang.String, android.os.Bundle);
method public void splitFromConference();
method public void stopDtmfTone();
method public void swapConference();
@@ -36146,6 +36150,7 @@
field public static final int STATE_DISCONNECTING = 10; // 0xa
field public static final int STATE_HOLDING = 3; // 0x3
field public static final int STATE_NEW = 0; // 0x0
+ field public static final int STATE_PULLING_CALL = 11; // 0xb
field public static final int STATE_RINGING = 2; // 0x2
field public static final int STATE_SELECT_PHONE_ACCOUNT = 8; // 0x8
}
@@ -36156,6 +36161,7 @@
method public void onCannedTextResponsesLoaded(android.telecom.Call, java.util.List<java.lang.String>);
method public void onChildrenChanged(android.telecom.Call, java.util.List<android.telecom.Call>);
method public void onConferenceableCallsChanged(android.telecom.Call, java.util.List<android.telecom.Call>);
+ method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle);
method public void onDetailsChanged(android.telecom.Call, android.telecom.Call.Details);
method public void onParentChanged(android.telecom.Call, android.telecom.Call);
method public void onPostDialWait(android.telecom.Call, java.lang.String);
@@ -36186,6 +36192,7 @@
method public static java.lang.String propertiesToString(int);
field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 4194304; // 0x400000
field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
+ field public static final int CAPABILITY_CAN_PULL_CALL = 8388608; // 0x800000
field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000
field public static final int CAPABILITY_HOLD = 1; // 0x1
field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80
@@ -36205,6 +36212,7 @@
field public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 4; // 0x4
field public static final int PROPERTY_GENERIC_CONFERENCE = 2; // 0x2
field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10
+ field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40
field public static final int PROPERTY_WIFI = 8; // 0x8
field public static final int PROPERTY_WORK_CALL = 32; // 0x20
}
@@ -36319,15 +36327,18 @@
method public void onAnswer(int);
method public void onAnswer();
method public void onCallAudioStateChanged(android.telecom.CallAudioState);
+ method public void onCallEvent(java.lang.String, android.os.Bundle);
method public void onDisconnect();
method public void onHold();
method public void onPlayDtmfTone(char);
method public void onPostDialContinue(boolean);
+ method public void onPullExternalCall();
method public void onReject();
method public void onSeparate();
method public void onStateChanged(int);
method public void onStopDtmfTone();
method public void onUnhold();
+ method public void sendConnectionEvent(java.lang.String, android.os.Bundle);
method public final void setActive();
method public final void setAddress(android.net.Uri, int);
method public final void setAudioModeIsVoip(boolean);
@@ -36351,9 +36362,11 @@
method public static java.lang.String stateToString(int);
field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 8388608; // 0x800000
field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
+ field public static final int CAPABILITY_CAN_PULL_CALL = 33554432; // 0x2000000
field public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 524288; // 0x80000
field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000
field public static final int CAPABILITY_HOLD = 1; // 0x1
+ field public static final int CAPABILITY_IS_EXTERNAL_CALL = 16777216; // 0x1000000
field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80
field public static final int CAPABILITY_MERGE_CONFERENCE = 4; // 0x4
field public static final int CAPABILITY_MUTE = 64; // 0x40
@@ -36367,6 +36380,7 @@
field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 2048; // 0x800
field public static final int CAPABILITY_SUPPORT_HOLD = 2; // 0x2
field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8
+ field public static final java.lang.String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED";
field public static final java.lang.String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT";
field public static final java.lang.String EXTRA_CHILD_ADDRESS = "android.telecom.extra.CHILD_ADDRESS";
field public static final java.lang.String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER";
@@ -36376,6 +36390,7 @@
field public static final int STATE_HOLDING = 5; // 0x5
field public static final int STATE_INITIALIZING = 0; // 0x0
field public static final int STATE_NEW = 1; // 0x1
+ field public static final int STATE_PULLING_CALL = 7; // 0x7
field public static final int STATE_RINGING = 2; // 0x2
}
@@ -36453,7 +36468,9 @@
method public java.lang.String getReason();
method public int getTone();
method public void writeToParcel(android.os.Parcel, int);
+ field public static final int ANSWERED_ELSEWHERE = 11; // 0xb
field public static final int BUSY = 7; // 0x7
+ field public static final int CALL_PULLED = 12; // 0xc
field public static final int CANCELED = 4; // 0x4
field public static final int CONNECTION_MANAGER_NOT_SUPPORTED = 10; // 0xa
field public static final android.os.Parcelable.Creator<android.telecom.DisconnectCause> CREATOR;
@@ -36489,6 +36506,7 @@
method public void onCallAudioStateChanged(android.telecom.CallAudioState);
method public void onCallRemoved(android.telecom.Call);
method public void onCanAddCallChanged(boolean);
+ method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle);
method public void onSilenceRinger();
method public final void setAudioRoute(int);
method public final void setMuted(boolean);
@@ -36639,6 +36657,7 @@
method public boolean isVoipAudioMode();
method public void playDtmfTone(char);
method public void postDialContinue(boolean);
+ method public void pullExternalCall();
method public void registerCallback(android.telecom.RemoteConnection.Callback);
method public void registerCallback(android.telecom.RemoteConnection.Callback, android.os.Handler);
method public void reject();
@@ -36655,6 +36674,7 @@
method public void onConferenceChanged(android.telecom.RemoteConnection, android.telecom.RemoteConference);
method public void onConferenceableConnectionsChanged(android.telecom.RemoteConnection, java.util.List<android.telecom.RemoteConnection>);
method public void onConnectionCapabilitiesChanged(android.telecom.RemoteConnection, int);
+ method public void onConnectionEvent(android.telecom.RemoteConnection, java.lang.String, android.os.Bundle);
method public void onDestroyed(android.telecom.RemoteConnection);
method public void onDisconnected(android.telecom.RemoteConnection, android.telecom.DisconnectCause);
method public void onExtrasChanged(android.telecom.RemoteConnection, android.os.Bundle);
@@ -36752,6 +36772,7 @@
field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS";
field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE";
+ field public static final java.lang.String METADATA_INCLUDE_EXTERNAL_CALLS = "android.telecom.INCLUDE_EXTERNAL_CALLS";
field public static final java.lang.String METADATA_IN_CALL_SERVICE_RINGING = "android.telecom.IN_CALL_SERVICE_RINGING";
field public static final java.lang.String METADATA_IN_CALL_SERVICE_UI = "android.telecom.IN_CALL_SERVICE_UI";
field public static final int PRESENTATION_ALLOWED = 1; // 0x1
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index e7c4a07..e2ae133 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -179,6 +179,7 @@
* <li>{@link #VOICEMAIL_TYPE}</li>
* <li>{@link #REJECTED_TYPE}</li>
* <li>{@link #BLOCKED_TYPE}</li>
+ * <li>{@link #ANSWERED_EXTERNALLY_TYPE}</li>
* </ul>
* </p>
*/
@@ -196,6 +197,12 @@
public static final int REJECTED_TYPE = 5;
/** Call log type for calls blocked automatically. */
public static final int BLOCKED_TYPE = 6;
+ /**
+ * Call log type for a call which was answered on another device. Used in situations where
+ * a call rings on multiple devices simultaneously and it ended up being answered on a
+ * device other than the current one.
+ */
+ public static final int ANSWERED_EXTERNALLY_TYPE = 7;
/**
* Bit-mask describing features of the call (e.g. video).
@@ -207,6 +214,9 @@
/** Call had video. */
public static final int FEATURES_VIDEO = 0x1;
+ /** Call was pulled externally. */
+ public static final int FEATURES_PULLED_EXTERNALLY = 0x2;
+
/**
* The phone number as the user entered it.
* <P>Type: TEXT</P>
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 10808da..afb7d93 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -95,6 +95,19 @@
public static final int STATE_DISCONNECTING = 10;
/**
+ * The state of an external call which is in the process of being pulled from a remote device to
+ * the local device.
+ * <p>
+ * A call can only be in this state if the {@link Details#PROPERTY_IS_EXTERNAL_CALL} property
+ * and {@link Details#CAPABILITY_CAN_PULL_CALL} capability are set on the call.
+ * <p>
+ * An {@link InCallService} will only see this state if it has the
+ * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} in its
+ * manifest.
+ */
+ public static final int STATE_PULLING_CALL = 11;
+
+ /**
* The key to retrieve the optional {@code PhoneAccount}s Telecom can bundle with its Call
* extras. Used to pass the phone accounts to display on the front end to the user in order to
* select phone accounts to (for example) place a call.
@@ -226,8 +239,23 @@
*/
public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 0x00400000;
+ /**
+ * When set for an external call, indicates that this {@code Call} can be pulled from a
+ * remote device to the current device.
+ * <p>
+ * Should only be set on a {@code Call} where {@link #PROPERTY_IS_EXTERNAL_CALL} is set.
+ * <p>
+ * An {@link InCallService} will only see calls with this capability if it has the
+ * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
+ * in its manifest.
+ * <p>
+ * See {@link Connection#CAPABILITY_CAN_PULL_CALL} and
+ * {@link Connection#CAPABILITY_IS_EXTERNAL_CALL}.
+ */
+ public static final int CAPABILITY_CAN_PULL_CALL = 0x00800000;
+
//******************************************************************************************
- // Next CAPABILITY value: 0x00800000
+ // Next CAPABILITY value: 0x01000000
//******************************************************************************************
/**
@@ -261,8 +289,25 @@
*/
public static final int PROPERTY_WORK_CALL = 0x00000020;
+ /**
+ * When set, indicates that this {@code Call} does not actually exist locally for the
+ * {@link ConnectionService}.
+ * <p>
+ * Consider, for example, a scenario where a user has two phones with the same phone number.
+ * When a user places a call on one device, the telephony stack can represent that call on
+ * the other device by adding it to the {@link ConnectionService} with the
+ * {@link Connection#CAPABILITY_IS_EXTERNAL_CALL} capability set.
+ * <p>
+ * An {@link InCallService} will only see calls with this property if it has the
+ * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
+ * in its manifest.
+ * <p>
+ * See {@link Connection#CAPABILITY_IS_EXTERNAL_CALL}.
+ */
+ public static final int PROPERTY_IS_EXTERNAL_CALL = 0x00000040;
+
//******************************************************************************************
- // Next PROPERTY value: 0x00000040
+ // Next PROPERTY value: 0x00000100
//******************************************************************************************
private final String mTelecomCallId;
@@ -362,6 +407,9 @@
if (can(capabilities, CAPABILITY_CAN_PAUSE_VIDEO)) {
builder.append(" CAPABILITY_CAN_PAUSE_VIDEO");
}
+ if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) {
+ builder.append(" CAPABILITY_CAN_PULL_CALL");
+ }
builder.append("]");
return builder.toString();
}
@@ -411,6 +459,9 @@
if (hasProperty(properties, PROPERTY_EMERGENCY_CALLBACK_MODE)) {
builder.append(" PROPERTY_EMERGENCY_CALLBACK_MODE");
}
+ if (hasProperty(properties, PROPERTY_IS_EXTERNAL_CALL)) {
+ builder.append(" PROPERTY_IS_EXTERNAL_CALL");
+ }
builder.append("]");
return builder.toString();
}
@@ -723,6 +774,17 @@
* conferenced.
*/
public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {}
+
+ /**
+ * Invoked when a call receives an event from its associated {@link Connection}.
+ * <p>
+ * See {@link Connection#sendConnectionEvent(String, Bundle)}.
+ *
+ * @param call The {@code Call} receiving the event.
+ * @param event The event.
+ * @param extras Extras associated with the connection event.
+ */
+ public void onConnectionEvent(Call call, String event, Bundle extras) {}
}
/**
@@ -889,6 +951,43 @@
}
/**
+ * Initiates a request to the {@link ConnectionService} to pull an external call to the local
+ * device.
+ * <p>
+ * Calls to this method are ignored if the call does not have the
+ * {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} property set.
+ * <p>
+ * An {@link InCallService} will only see calls which support this method if it has the
+ * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
+ * in its manifest.
+ */
+ public void pullExternalCall() {
+ // If this isn't an external call, ignore the request.
+ if (!mDetails.hasProperty(Details.PROPERTY_IS_EXTERNAL_CALL)) {
+ return;
+ }
+
+ mInCallAdapter.pullExternalCall(mTelecomCallId);
+ }
+
+ /**
+ * Sends a {@code Call} event from this {@code Call} to the associated {@link Connection} in
+ * the {@link ConnectionService}.
+ * <p>
+ * Events are exposed to {@link ConnectionService} implementations via
+ * {@link android.telecom.Connection#onCallEvent(String, Bundle)}.
+ * <p>
+ * No assumptions should be made as to how a {@link ConnectionService} will handle these events.
+ * Events should be fully qualified (e.g., com.example.event.MY_EVENT) to avoid conflicts.
+ *
+ * @param event The connection event.
+ * @param extras Bundle containing extra information associated with the event.
+ */
+ public void sendCallEvent(String event, Bundle extras) {
+ mInCallAdapter.sendCallEvent(mTelecomCallId, event, extras);
+ }
+
+ /**
* Obtains the parent of this {@code Call} in a conference, if any.
*
* @return The parent {@code Call}, or {@code null} if this {@code Call} is not a
@@ -1211,6 +1310,11 @@
}
}
+ /** {@hide} */
+ final void internalOnConnectionEvent(String event, Bundle extras) {
+ fireOnConnectionEvent(event, extras);
+ }
+
private void fireStateChanged(final int newState) {
for (CallbackRecord<Callback> record : mCallbackRecords) {
final Call call = this;
@@ -1358,6 +1462,27 @@
}
/**
+ * Notifies listeners of an incoming connection event.
+ * <p>
+ * Connection events are issued via {@link Connection#sendConnectionEvent(String, Bundle)}.
+ *
+ * @param event
+ * @param extras
+ */
+ private void fireOnConnectionEvent(final String event, final Bundle extras) {
+ for (CallbackRecord<Callback> record : mCallbackRecords) {
+ final Call call = this;
+ final Callback callback = record.getCallback();
+ record.getHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ callback.onConnectionEvent(call, event, extras);
+ }
+ });
+ }
+ }
+
+ /**
* Determines if two bundles are equal.
*
* @param bundle The original bundle.
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 4547c6a..5c34bd8 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -93,6 +93,15 @@
public static final int STATE_DISCONNECTED = 6;
/**
+ * The state of an external connection which is in the process of being pulled from a remote
+ * device to the local device.
+ * <p>
+ * A connection can only be in this state if the {@link #CAPABILITY_IS_EXTERNAL_CALL} and
+ * {@link #CAPABILITY_CAN_PULL_CALL} capability bits are set on the connection.
+ */
+ public static final int STATE_PULLING_CALL = 7;
+
+ /**
* Connection can currently be put on hold or unheld. This is distinct from
* {@link #CAPABILITY_SUPPORT_HOLD} in that although a connection may support 'hold' most times,
* it does not at the moment support the function. This can be true while the call is in the
@@ -270,8 +279,33 @@
*/
public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 0x00800000;
+ /**
+ * When set, indicates that the {@code Connection} does not actually exist locally for the
+ * {@link ConnectionService}.
+ * <p>
+ * Consider, for example, a scenario where a user has two devices with the same phone number.
+ * When a user places a call on one devices, the telephony stack can represent that call on the
+ * other device by adding is to the {@link ConnectionService} with the
+ * {@code CAPABILITY_IS_EXTERNAL_CALL} capability set.
+ * <p>
+ * An {@link ConnectionService} should not assume that all {@link InCallService}s will handle
+ * external connections. Only those {@link InCallService}s which have the
+ * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} in its
+ * manifest will see external connections.
+ */
+ public static final int CAPABILITY_IS_EXTERNAL_CALL = 0x01000000;
+
+ /**
+ * When set for an external connection, indicates that this {@code Connection} can be pulled
+ * from a remote device to the current device.
+ * <p>
+ * Should only be set on a {@code Connection} where {@link #CAPABILITY_IS_EXTERNAL_CALL}
+ * is set.
+ */
+ public static final int CAPABILITY_CAN_PULL_CALL = 0x02000000;
+
//**********************************************************************************************
- // Next CAPABILITY value: 0x01000000
+ // Next CAPABILITY value: 0x04000000
//**********************************************************************************************
/**
@@ -315,6 +349,18 @@
public static final String EVENT_ON_HOLD_TONE_END =
"android.telecom.event.ON_HOLD_TONE_END";
+ /**
+ * Connection event used to inform {@link InCallService}s when pulling of an external call has
+ * failed. The user interface should inform the user of the error.
+ * <p>
+ * Expected to be used by the {@link ConnectionService} when the {@link Call#pullExternalCall()}
+ * API is called on a {@link Call} with the properties
+ * {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} and
+ * {@link Call.Details#CAPABILITY_CAN_PULL_CALL}, but the {@link ConnectionService} could not
+ * pull the external call due to an error condition.
+ */
+ public static final String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED";
+
// Flag controlling whether PII is emitted into the logs
private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG);
@@ -434,6 +480,12 @@
if (can(capabilities, CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION)) {
builder.append(" CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION");
}
+ if (can(capabilities, CAPABILITY_IS_EXTERNAL_CALL)) {
+ builder.append(" CAPABILITY_IS_EXTERNAL_CALL");
+ }
+ if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) {
+ builder.append(" CAPABILITY_CAN_PULL_CALL");
+ }
builder.append("]");
return builder.toString();
@@ -465,8 +517,7 @@
public void onConferenceStarted() {}
public void onConferenceMergeFailed(Connection c) {}
public void onExtrasChanged(Connection c, Bundle extras) {}
- /** @hide */
- public void onConnectionEvent(Connection c, String event) {}
+ public void onConnectionEvent(Connection c, String event, Bundle extras) {}
}
/**
@@ -1854,6 +1905,31 @@
*/
public void onPostDialContinue(boolean proceed) {}
+ /**
+ * Notifies this Connection of a request to pull an external call to the local device.
+ * <p>
+ * The {@link InCallService} issues a request to pull an external call to the local device via
+ * {@link Call#pullExternalCall()}.
+ * <p>
+ * For a Connection to be pulled, both the {@link Connection#CAPABILITY_CAN_PULL_CALL} and
+ * {@link Connection#CAPABILITY_IS_EXTERNAL_CALL} capability bits must be set.
+ * <p>
+ * For more information on external calls, see {@link Connection#CAPABILITY_IS_EXTERNAL_CALL}.
+ */
+ public void onPullExternalCall() {}
+
+ /**
+ * Notifies this Connection of a {@link Call} event initiated from an {@link InCallService}.
+ * <p>
+ * The {@link InCallService} issues a Call event via {@link Call#sendCallEvent(String, Bundle)}.
+ * <p>
+ * See also {@link Call#sendCallEvent(String, Bundle)}.
+ *
+ * @param event The call event.
+ * @param extras Extras associated with the call event.
+ */
+ public void onCallEvent(String event, Bundle extras) {}
+
static String toLogSafePhoneNumber(String number) {
// For unknown number, log empty string.
if (number == null) {
@@ -2008,14 +2084,20 @@
}
/**
- * Sends a connection event to Telecom.
+ * Sends an event associated with this {@code Connection}, with associated event extras.
+ *
+ * Events are exposed to {@link InCallService} implementations via the
+ * {@link Call.Callback#onConnectionEvent(Call, String, Bundle)} API.
+ *
+ * No assumptions should be made as to how an In-Call UI or service will handle these events.
+ * Events should be fully qualified (e.g., com.example.event.MY_EVENT) to avoid conflicts.
*
* @param event The connection event.
- * @hide
+ * @param extras Bundle containing extra information associated with the event.
*/
- protected void sendConnectionEvent(String event) {
+ public void sendConnectionEvent(String event, Bundle extras) {
for (Listener l : mListeners) {
- l.onConnectionEvent(this, event);
+ l.onConnectionEvent(this, event, null);
}
}
}
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 5b62e03..d18b317 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -103,6 +103,8 @@
private static final int MSG_SWAP_CONFERENCE = 19;
private static final int MSG_REJECT_WITH_MESSAGE = 20;
private static final int MSG_SILENCE = 21;
+ private static final int MSG_PULL_EXTERNAL_CALL = 22;
+ private static final int MSG_SEND_CALL_EVENT = 23;
private static Connection sNullConnection;
@@ -245,6 +247,20 @@
args.argi1 = proceed ? 1 : 0;
mHandler.obtainMessage(MSG_ON_POST_DIAL_CONTINUE, args).sendToTarget();
}
+
+ @Override
+ public void pullExternalCall(String callId) {
+ mHandler.obtainMessage(MSG_PULL_EXTERNAL_CALL, callId).sendToTarget();
+ }
+
+ @Override
+ public void sendCallEvent(String callId, String event, Bundle extras) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = callId;
+ args.arg2 = event;
+ args.arg3 = extras;
+ mHandler.obtainMessage(MSG_SEND_CALL_EVENT, args).sendToTarget();
+ }
};
private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@@ -382,6 +398,22 @@
}
break;
}
+ case MSG_PULL_EXTERNAL_CALL: {
+ pullExternalCall((String) msg.obj);
+ break;
+ }
+ case MSG_SEND_CALL_EVENT: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ try {
+ String callId = (String) args.arg1;
+ String event = (String) args.arg2;
+ Bundle extras = (Bundle) args.arg3;
+ sendCallEvent(callId, event, extras);
+ } finally {
+ args.recycle();
+ }
+ break;
+ }
default:
break;
}
@@ -615,10 +647,10 @@
}
@Override
- public void onConnectionEvent(Connection connection, String event) {
+ public void onConnectionEvent(Connection connection, String event, Bundle extras) {
String id = mIdByConnection.get(connection);
if (id != null) {
- mAdapter.onConnectionEvent(id, event);
+ mAdapter.onConnectionEvent(id, event, extras);
}
}
};
@@ -864,6 +896,39 @@
}
}
+ /**
+ * Notifies a {@link Connection} of a request to pull an external call.
+ *
+ * See {@link Call#pullExternalCall()}.
+ *
+ * @param callId The ID of the call to pull.
+ */
+ private void pullExternalCall(String callId) {
+ Log.d(this, "pullExternalCall(%s)", callId);
+ Connection connection = findConnectionForAction(callId, "pullExternalCall");
+ if (connection != null) {
+ connection.onPullExternalCall();
+ }
+ }
+
+ /**
+ * Notifies a {@link Connection} of a call event.
+ *
+ * See {@link Call#sendCallEvent(String, Bundle)}.
+ *
+ * @param callId The ID of the call receiving the event.
+ * @param event The event.
+ * @param extras Extras associated with the event.
+ */
+ private void sendCallEvent(String callId, String event, Bundle extras) {
+ Log.d(this, "sendCallEvent(%s, %s)", callId, event);
+ Connection connection = findConnectionForAction(callId, "sendCallEvent");
+ if (connection != null) {
+ connection.onCallEvent(event, extras);
+ }
+
+ }
+
private void onPostDialContinue(String callId, boolean proceed) {
Log.d(this, "onPostDialContinue(%s)", callId);
findConnectionForAction(callId, "stopDtmfTone").onPostDialContinue(proceed);
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapter.java b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
index 30fc5ad..e91128f 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
@@ -418,12 +418,13 @@
*
* @param callId The unique ID of the call.
* @param event The event.
+ * @param extras Extras associated with the event.
*/
- void onConnectionEvent(String callId, String event) {
+ void onConnectionEvent(String callId, String event, Bundle extras) {
Log.v(this, "onConnectionEvent: %s", event);
for (IConnectionServiceAdapter adapter : mAdapters) {
try {
- adapter.onConnectionEvent(callId, event);
+ adapter.onConnectionEvent(callId, event, extras);
} catch (RemoteException ignored) {
}
}
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
index 6a8c1cb..4b15e54 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
@@ -245,7 +245,8 @@
case MSG_ON_CONNECTION_EVENT: {
SomeArgs args = (SomeArgs) msg.obj;
try {
- mDelegate.onConnectionEvent((String) args.arg1, (String) args.arg2);
+ mDelegate.onConnectionEvent((String) args.arg1, (String) args.arg2,
+ (Bundle) args.arg3);
} finally {
args.recycle();
}
@@ -432,10 +433,11 @@
}
@Override
- public final void onConnectionEvent(String connectionId, String event) {
+ public final void onConnectionEvent(String connectionId, String event, Bundle extras) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = connectionId;
args.arg2 = event;
+ args.arg3 = extras;
mHandler.obtainMessage(MSG_ON_CONNECTION_EVENT, args).sendToTarget();
}
};
diff --git a/telecomm/java/android/telecom/DisconnectCause.java b/telecomm/java/android/telecom/DisconnectCause.java
index 2eef7ee..cf73d4f 100644
--- a/telecomm/java/android/telecom/DisconnectCause.java
+++ b/telecomm/java/android/telecom/DisconnectCause.java
@@ -64,6 +64,17 @@
*/
public static final int CONNECTION_MANAGER_NOT_SUPPORTED = 10;
+ /**
+ * Disconnected because the user did not locally answer the incoming call, but it was answered
+ * on another device where the call was ringing.
+ */
+ public static final int ANSWERED_ELSEWHERE = 11;
+
+ /**
+ * Disconnected because the call was pulled from the current device to another device.
+ */
+ public static final int CALL_PULLED = 12;
+
private int mDisconnectCode;
private CharSequence mDisconnectLabel;
private CharSequence mDisconnectDescription;
diff --git a/telecomm/java/android/telecom/InCallAdapter.java b/telecomm/java/android/telecom/InCallAdapter.java
index 0cf7212b..52ef4a7 100644
--- a/telecomm/java/android/telecom/InCallAdapter.java
+++ b/telecomm/java/android/telecom/InCallAdapter.java
@@ -16,6 +16,7 @@
package android.telecom;
+import android.os.Bundle;
import android.os.RemoteException;
import com.android.internal.telecom.IInCallAdapter;
@@ -251,6 +252,32 @@
}
/**
+ * Instructs Telecom to pull an external call to the local device.
+ *
+ * @param callId The callId to pull.
+ */
+ public void pullExternalCall(String callId) {
+ try {
+ mAdapter.pullExternalCall(callId);
+ } catch (RemoteException ignored) {
+ }
+ }
+
+ /**
+ * Intructs Telecom to send a call event.
+ *
+ * @param callId The callId to send the event for.
+ * @param event The event.
+ * @param extras Extras associated with the event.
+ */
+ public void sendCallEvent(String callId, String event, Bundle extras) {
+ try {
+ mAdapter.sendCallEvent(callId, event, extras);
+ } catch (RemoteException ignored) {
+ }
+ }
+
+ /**
* Instructs Telecom to turn the proximity sensor on.
*/
public void turnProximitySensorOn() {
diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java
index 671399b..df6715d 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -22,6 +22,7 @@
import android.content.Intent;
import android.hardware.camera2.CameraManager;
import android.net.Uri;
+import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -74,6 +75,7 @@
private static final int MSG_BRING_TO_FOREGROUND = 6;
private static final int MSG_ON_CAN_ADD_CALL_CHANGED = 7;
private static final int MSG_SILENCE_RINGER = 8;
+ private static final int MSG_ON_CONNECTION_EVENT = 9;
/** Default Handler used to consolidate binder method calls onto a single thread. */
private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@@ -118,6 +120,18 @@
case MSG_SILENCE_RINGER:
mPhone.internalSilenceRinger();
break;
+ case MSG_ON_CONNECTION_EVENT: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ try {
+ String callId = (String) args.arg1;
+ String event = (String) args.arg2;
+ Bundle extras = (Bundle) args.arg3;
+ mPhone.internalOnConnectionEvent(callId, event, extras);
+ } finally {
+ args.recycle();
+ }
+ break;
+ }
default:
break;
}
@@ -174,6 +188,15 @@
public void silenceRinger() {
mHandler.obtainMessage(MSG_SILENCE_RINGER).sendToTarget();
}
+
+ @Override
+ public void onConnectionEvent(String callId, String event, Bundle extras) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = callId;
+ args.arg2 = event;
+ args.arg3 = extras;
+ mHandler.obtainMessage(MSG_ON_CONNECTION_EVENT, args).sendToTarget();
+ }
}
private Phone.Listener mPhoneListener = new Phone.Listener() {
@@ -426,6 +449,19 @@
}
/**
+ * Called when a {@link Call} has received a connection event issued by the
+ * {@link ConnectionService}.
+ * <p>
+ * See {@link Connection#sendConnectionEvent(String, Bundle)}.
+ *
+ * @param call The call the event is associated with.
+ * @param event The event.
+ * @param extras Any associated extras.
+ */
+ public void onConnectionEvent(Call call, String event, Bundle extras) {
+ }
+
+ /**
* Used to issue commands to the {@link Connection.VideoProvider} associated with a
* {@link Call}.
*/
diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java
index d45938c..a4ef560 100644
--- a/telecomm/java/android/telecom/Phone.java
+++ b/telecomm/java/android/telecom/Phone.java
@@ -17,6 +17,7 @@
package android.telecom;
import android.annotation.SystemApi;
+import android.os.Bundle;
import android.util.ArrayMap;
import java.util.Collections;
@@ -190,6 +191,13 @@
fireSilenceRinger();
}
+ final void internalOnConnectionEvent(String telecomId, String event, Bundle extras) {
+ Call call = mCallByTelecomCallId.get(telecomId);
+ if (call != null) {
+ call.internalOnConnectionEvent(event, extras);
+ }
+ }
+
/**
* Called to destroy the phone and cleanup any lingering calls.
*/
diff --git a/telecomm/java/android/telecom/RemoteConnection.java b/telecomm/java/android/telecom/RemoteConnection.java
index 0185808..5b602eb 100644
--- a/telecomm/java/android/telecom/RemoteConnection.java
+++ b/telecomm/java/android/telecom/RemoteConnection.java
@@ -212,12 +212,14 @@
/**
* Handles a connection event propagated to this {@link RemoteConnection}.
+ * <p>
+ * Connection events originate from {@link Connection#sendConnectionEvent(String, Bundle)}.
*
* @param connection The {@code RemoteConnection} invoking this method.
* @param event The connection event.
- * @hide
+ * @param extras Extras associated with the event.
*/
- public void onConnectionEvent(RemoteConnection connection, String event) {}
+ public void onConnectionEvent(RemoteConnection connection, String event, Bundle extras) {}
}
/**
@@ -962,6 +964,20 @@
}
/**
+ * Instructs this {@link RemoteConnection} to pull itself to the local device.
+ * <p>
+ * See {@link Call#pullExternalCall()} for more information.
+ */
+ public void pullExternalCall() {
+ try {
+ if (mConnected) {
+ mConnectionService.pullExternalCall(mConnectionId);
+ }
+ } catch (RemoteException ignored) {
+ }
+ }
+
+ /**
* Set the audio state of this {@code RemoteConnection}.
*
* @param state The audio state of this {@code RemoteConnection}.
@@ -1301,14 +1317,14 @@
}
/** @hide */
- void onConnectionEvent(final String event) {
+ void onConnectionEvent(final String event, final Bundle extras) {
for (CallbackRecord record : mCallbackRecords) {
final RemoteConnection connection = this;
final Callback callback = record.getCallback();
record.getHandler().post(new Runnable() {
@Override
public void run() {
- callback.onConnectionEvent(connection, event);
+ callback.onConnectionEvent(connection, event, extras);
}
});
}
diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java
index b85382f..fa7183a 100644
--- a/telecomm/java/android/telecom/RemoteConnectionService.java
+++ b/telecomm/java/android/telecom/RemoteConnectionService.java
@@ -332,9 +332,10 @@
}
@Override
- public void onConnectionEvent(String callId, String event) {
+ public void onConnectionEvent(String callId, String event, Bundle extras) {
if (mConnectionById.containsKey(callId)) {
- findConnectionForAction(callId, "onConnectionEvent").onConnectionEvent(event);
+ findConnectionForAction(callId, "onConnectionEvent").onConnectionEvent(event,
+ extras);
}
}
};
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 8afb455..4fa8fe9 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -317,6 +317,18 @@
"android.telecom.IN_CALL_SERVICE_RINGING";
/**
+ * A boolean meta-data value indicating whether an {@link InCallService} wants to be informed of
+ * calls which have the {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} property. An external
+ * call is one which a {@link ConnectionService} knows about, but is not connected to directly.
+ * Dialer implementations (see {@link #getDefaultDialerPackage()}) which would like to be
+ * informed of external calls should set this meta-data to {@code true} in the manifest
+ * registration of their {@link InCallService}. By default, the {@link InCallService} will NOT
+ * be informed of external calls.
+ */
+ public static final String METADATA_INCLUDE_EXTERNAL_CALLS =
+ "android.telecom.INCLUDE_EXTERNAL_CALLS";
+
+ /**
* The dual tone multi-frequency signaling character sent to indicate the dialing system should
* pause for a predefined period.
*/
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
index 8a54add..3ee0e9f 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
@@ -75,4 +75,8 @@
void swapConference(String conferenceCallId);
void onPostDialContinue(String callId, boolean proceed);
+
+ void pullExternalCall(String callId);
+
+ void sendCallEvent(String callId, String event, in Bundle extras);
}
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
index 569c244..dff1b11 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
@@ -87,5 +87,5 @@
void setExtras(String callId, in Bundle extras);
- void onConnectionEvent(String callId, String event);
+ void onConnectionEvent(String callId, String event, in Bundle extras);
}
diff --git a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
index 863fff2..0678fe2 100644
--- a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
@@ -16,6 +16,7 @@
package com.android.internal.telecom;
+import android.os.Bundle;
import android.telecom.PhoneAccountHandle;
/**
@@ -60,4 +61,8 @@
void turnOnProximitySensor();
void turnOffProximitySensor(boolean screenOnImmediately);
+
+ void pullExternalCall(String callId);
+
+ void sendCallEvent(String callId, String event, in Bundle extras);
}
diff --git a/telecomm/java/com/android/internal/telecom/IInCallService.aidl b/telecomm/java/com/android/internal/telecom/IInCallService.aidl
index 0088e0c..3e43fe2 100644
--- a/telecomm/java/com/android/internal/telecom/IInCallService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IInCallService.aidl
@@ -17,6 +17,7 @@
package com.android.internal.telecom;
import android.app.PendingIntent;
+import android.os.Bundle;
import android.telecom.CallAudioState;
import android.telecom.ParcelableCall;
@@ -47,4 +48,6 @@
void onCanAddCallChanged(boolean canAddCall);
void silenceRinger();
+
+ void onConnectionEvent(String callId, String event, in Bundle extras);
}