diff options
author | Tyler Gunn <tgunn@google.com> | 2016-03-14 15:18:07 -0700 |
---|---|---|
committer | Tyler Gunn <tgunn@google.com> | 2016-03-14 23:26:34 +0000 |
commit | 876dbfb4767da4a2ba5459d5b78fb6eb55e4516f (patch) | |
tree | 163ef4c1fc05a90706df68b25d02ac51489bd6ec | |
parent | 791a1546484f643e98a4bb245c3b7c302b894f78 (diff) |
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
20 files changed, 493 insertions, 22 deletions
diff --git a/api/current.txt b/api/current.txt index 9e0af763ef56..2a3aa59b5a5e 100644 --- a/api/current.txt +++ b/api/current.txt @@ -30762,6 +30762,7 @@ package android.provider { 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 @@ package android.provider { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 00cf3573c71e..9056a89ead4e 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -33114,6 +33114,7 @@ package android.provider { 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 @@ package android.provider { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 9aed5e940d52..566a574c6ee6 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -30832,6 +30832,7 @@ package android.provider { 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 @@ package android.provider { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 @@ package android.telecom { 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 e7c4a075cf72..e2ae133cf6e9 100644 --- a/core/java/android/provider/CallLog.java +++ b/core/java/android/provider/CallLog.java @@ -179,6 +179,7 @@ public class CallLog { * <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 class CallLog { 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 @@ public class CallLog { /** 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 10808da8785e..afb7d9394679 100644 --- a/telecomm/java/android/telecom/Call.java +++ b/telecomm/java/android/telecom/Call.java @@ -95,6 +95,19 @@ public final class Call { 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 final class Call { */ 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 final class Call { */ 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 @@ public final class Call { 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 @@ public final class Call { 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 @@ public final class Call { * 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 @@ public final class Call { } /** + * 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 @@ public final class Call { } } + /** {@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 @@ public final class Call { } /** + * 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 4547c6a6c153..5c34bd8244d9 100644 --- a/telecomm/java/android/telecom/Connection.java +++ b/telecomm/java/android/telecom/Connection.java @@ -93,6 +93,15 @@ public abstract class Connection extends Conferenceable { 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 abstract class Connection extends Conferenceable { */ 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 abstract class Connection extends Conferenceable { 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 @@ public abstract class Connection extends Conferenceable { 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 abstract class Connection extends Conferenceable { 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 abstract class Connection extends Conferenceable { */ 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 @@ public abstract class Connection extends Conferenceable { } /** - * 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 5b62e03350b1..d18b31725aaa 100644 --- a/telecomm/java/android/telecom/ConnectionService.java +++ b/telecomm/java/android/telecom/ConnectionService.java @@ -103,6 +103,8 @@ public abstract class ConnectionService extends Service { 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 @@ public abstract class ConnectionService extends Service { 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 @@ public abstract class ConnectionService extends Service { } 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 @@ public abstract class ConnectionService extends Service { } @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 @@ public abstract class ConnectionService extends Service { } } + /** + * 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 30fc5ad1e4b6..e91128f1f7bc 100644 --- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java +++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java @@ -418,12 +418,13 @@ final class ConnectionServiceAdapter implements DeathRecipient { * * @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 6a8c1cb281ba..4b15e541d0dc 100644 --- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java +++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java @@ -245,7 +245,8 @@ final class ConnectionServiceAdapterServant { 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 @@ final class ConnectionServiceAdapterServant { } @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 2eef7eeb6bd8..cf73d4f1453e 100644 --- a/telecomm/java/android/telecom/DisconnectCause.java +++ b/telecomm/java/android/telecom/DisconnectCause.java @@ -64,6 +64,17 @@ public final class DisconnectCause implements Parcelable { */ 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 0cf7212ba55b..52ef4a705e05 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 @@ public final class InCallAdapter { } /** + * 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 671399b6f842..df6715d41a3f 100644 --- a/telecomm/java/android/telecom/InCallService.java +++ b/telecomm/java/android/telecom/InCallService.java @@ -22,6 +22,7 @@ import android.app.Service; 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 @@ public abstract class InCallService extends Service { 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 @@ public abstract class InCallService extends Service { 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 abstract class InCallService extends Service { 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 @@ public abstract class InCallService extends Service { } /** + * 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 d45938cb9b85..a4ef5601e551 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 @@ public final class Phone { 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 01858080d7d7..5b602eb49dca 100644 --- a/telecomm/java/android/telecom/RemoteConnection.java +++ b/telecomm/java/android/telecom/RemoteConnection.java @@ -212,12 +212,14 @@ public final class RemoteConnection { /** * 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 @@ public final class RemoteConnection { } /** + * 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 @@ public final class RemoteConnection { } /** @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 b85382feae60..fa7183acc350 100644 --- a/telecomm/java/android/telecom/RemoteConnectionService.java +++ b/telecomm/java/android/telecom/RemoteConnectionService.java @@ -332,9 +332,10 @@ final class RemoteConnectionService { } @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 8afb4556b97d..4fa8fe96a6a9 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -317,6 +317,18 @@ public class TelecomManager { "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 8a54addcf06e..3ee0e9f94443 100644 --- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl +++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl @@ -75,4 +75,8 @@ oneway interface IConnectionService { 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 569c24469368..dff1b1138741 100644 --- a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl +++ b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl @@ -87,5 +87,5 @@ oneway interface IConnectionServiceAdapter { 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 863fff29d560..0678fe2c0aa4 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 @@ oneway interface IInCallAdapter { 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 0088e0cf6b64..3e43fe22cdfb 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 @@ oneway interface IInCallService { void onCanAddCallChanged(boolean canAddCall); void silenceRinger(); + + void onConnectionEvent(String callId, String event, in Bundle extras); } |