diff options
Diffstat (limited to 'telecomm/java')
26 files changed, 1724 insertions, 403 deletions
diff --git a/telecomm/java/android/telecom/AudioState.java b/telecomm/java/android/telecom/AudioState.java index fc2fff4..bd63e00 100644 --- a/telecomm/java/android/telecom/AudioState.java +++ b/telecomm/java/android/telecom/AudioState.java @@ -23,7 +23,8 @@ import android.os.Parcelable; import java.util.Locale; /** - * Encapsulates all audio states during a call. + * Encapsulates the telecom audio state, including the current audio routing, supported audio + * routing and mute. * @hide */ @SystemApi @@ -53,25 +54,25 @@ public final class AudioState implements Parcelable { public static final int ROUTE_ALL = ROUTE_EARPIECE | ROUTE_BLUETOOTH | ROUTE_WIRED_HEADSET | ROUTE_SPEAKER; - /** True if the call is muted, false otherwise. */ - public final boolean isMuted; + /** @hide */ + @Deprecated public final boolean isMuted; - /** The route to use for the audio stream. */ - public final int route; + /** @hide */ + @Deprecated public final int route; - /** Bit vector of all routes supported by this call. */ - public final int supportedRouteMask; + /** @hide */ + @Deprecated public final int supportedRouteMask; - public AudioState(boolean isMuted, int route, int supportedRouteMask) { - this.isMuted = isMuted; + public AudioState(boolean muted, int route, int supportedRouteMask) { + this.isMuted = muted; this.route = route; this.supportedRouteMask = supportedRouteMask; } public AudioState(AudioState state) { - isMuted = state.isMuted; - route = state.route; - supportedRouteMask = state.supportedRouteMask; + isMuted = state.isMuted(); + route = state.getRoute(); + supportedRouteMask = state.getSupportedRouteMask(); } @Override @@ -83,15 +84,17 @@ public final class AudioState implements Parcelable { return false; } AudioState state = (AudioState) obj; - return isMuted == state.isMuted && route == state.route && - supportedRouteMask == state.supportedRouteMask; + return isMuted() == state.isMuted() && getRoute() == state.getRoute() && + getSupportedRouteMask() == state.getSupportedRouteMask(); } @Override public String toString() { return String.format(Locale.US, "[AudioState isMuted: %b, route; %s, supportedRouteMask: %s]", - isMuted, audioRouteToString(route), audioRouteToString(supportedRouteMask)); + isMuted, + audioRouteToString(route), + audioRouteToString(supportedRouteMask)); } /** @hide */ @@ -161,4 +164,25 @@ public final class AudioState implements Parcelable { destination.writeInt(route); destination.writeInt(supportedRouteMask); } + + /** + * @return {@code true} if the call is muted, false otherwise. + */ + public boolean isMuted() { + return isMuted; + } + + /** + * @return The current audio route being used. + */ + public int getRoute() { + return route; + } + + /** + * @return Bit mask of all routes supported by this call. + */ + public int getSupportedRouteMask() { + return supportedRouteMask; + } } diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java index 354fa2e..bbf3384 100644 --- a/telecomm/java/android/telecom/Call.java +++ b/telecomm/java/android/telecom/Call.java @@ -97,6 +97,91 @@ public final class Call { public static final String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts"; public static class Details { + + /** Call can currently be put on hold or unheld. */ + public static final int CAPABILITY_HOLD = 0x00000001; + + /** Call supports the hold feature. */ + public static final int CAPABILITY_SUPPORT_HOLD = 0x00000002; + + /** + * Calls within a conference can be merged. A {@link ConnectionService} has the option to + * add a {@link Conference} call before the child {@link Connection}s are merged. This is how + * CDMA-based {@link Connection}s are implemented. For these unmerged {@link Conference}s, this + * capability allows a merge button to be shown while the conference call is in the foreground + * of the in-call UI. + * <p> + * This is only intended for use by a {@link Conference}. + */ + public static final int CAPABILITY_MERGE_CONFERENCE = 0x00000004; + + /** + * Calls within a conference can be swapped between foreground and background. + * See {@link #CAPABILITY_MERGE_CONFERENCE} for additional information. + * <p> + * This is only intended for use by a {@link Conference}. + */ + public static final int CAPABILITY_SWAP_CONFERENCE = 0x00000008; + + /** + * @hide + */ + public static final int CAPABILITY_UNUSED = 0x00000010; + + /** Call supports responding via text option. */ + public static final int CAPABILITY_RESPOND_VIA_TEXT = 0x00000020; + + /** Call can be muted. */ + public static final int CAPABILITY_MUTE = 0x00000040; + + /** + * Call supports conference call management. This capability only applies to {@link Conference} + * calls which can have {@link Connection}s as children. + */ + public static final int CAPABILITY_MANAGE_CONFERENCE = 0x00000080; + + /** + * Local device supports video telephony. + * @hide + */ + public static final int CAPABILITY_SUPPORTS_VT_LOCAL = 0x00000100; + + /** + * Remote device supports video telephony. + * @hide + */ + public static final int CAPABILITY_SUPPORTS_VT_REMOTE = 0x00000200; + + /** + * Call is using high definition audio. + * @hide + */ + public static final int CAPABILITY_HIGH_DEF_AUDIO = 0x00000400; + + /** + * Call is using voice over WIFI. + * @hide + */ + public static final int CAPABILITY_VoWIFI = 0x00000800; + + /** + * Call is able to be separated from its parent {@code Conference}, if any. + */ + public static final int CAPABILITY_SEPARATE_FROM_CONFERENCE = 0x00001000; + + /** + * Call is able to be individually disconnected when in a {@code Conference}. + */ + public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 0x00002000; + + /** + * Whether the call is a generic conference, where we do not know the precise state of + * participants in the conference (eg. on CDMA). + * + * @hide + */ + public static final int CAPABILITY_GENERIC_CONFERENCE = 0x00004000; + private final Uri mHandle; private final int mHandlePresentation; private final String mCallerDisplayName; @@ -112,6 +197,78 @@ public final class Call { private final Bundle mExtras; /** + * Whether the supplied capabilities supports the specified capability. + * + * @param capabilities A bit field of capabilities. + * @param capability The capability to check capabilities for. + * @return Whether the specified capability is supported. + * @hide + */ + public static boolean can(int capabilities, int capability) { + return (capabilities & capability) != 0; + } + + /** + * Whether the capabilities of this {@code Details} supports the specified capability. + * + * @param capability The capability to check capabilities for. + * @return Whether the specified capability is supported. + * @hide + */ + public boolean can(int capability) { + return can(mCallCapabilities, capability); + } + + /** + * Render a set of capability bits ({@code CAPABILITY_*}) as a human readable string. + * + * @param capabilities A capability bit field. + * @return A human readable string representation. + */ + public static String capabilitiesToString(int capabilities) { + StringBuilder builder = new StringBuilder(); + builder.append("[Capabilities:"); + if (can(capabilities, CAPABILITY_HOLD)) { + builder.append(" CAPABILITY_HOLD"); + } + if (can(capabilities, CAPABILITY_SUPPORT_HOLD)) { + builder.append(" CAPABILITY_SUPPORT_HOLD"); + } + if (can(capabilities, CAPABILITY_MERGE_CONFERENCE)) { + builder.append(" CAPABILITY_MERGE_CONFERENCE"); + } + if (can(capabilities, CAPABILITY_SWAP_CONFERENCE)) { + builder.append(" CAPABILITY_SWAP_CONFERENCE"); + } + if (can(capabilities, CAPABILITY_RESPOND_VIA_TEXT)) { + builder.append(" CAPABILITY_RESPOND_VIA_TEXT"); + } + if (can(capabilities, CAPABILITY_MUTE)) { + builder.append(" CAPABILITY_MUTE"); + } + if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) { + builder.append(" CAPABILITY_MANAGE_CONFERENCE"); + } + if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL)) { + builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL"); + } + if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE)) { + builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE"); + } + if (can(capabilities, CAPABILITY_HIGH_DEF_AUDIO)) { + builder.append(" CAPABILITY_HIGH_DEF_AUDIO"); + } + if (can(capabilities, CAPABILITY_VoWIFI)) { + builder.append(" CAPABILITY_VoWIFI"); + } + if (can(capabilities, CAPABILITY_GENERIC_CONFERENCE)) { + builder.append(" CAPABILITY_GENERIC_CONFERENCE"); + } + builder.append("]"); + return builder.toString(); + } + + /** * @return The handle (e.g., phone number) to which the {@code Call} is currently * connected. */ @@ -151,8 +308,8 @@ public final class Call { } /** - * @return A bitmask of the capabilities of the {@code Call}, as defined in - * {@link PhoneCapabilities}. + * @return A bitmask of the capabilities of the {@code Call}, as defined by the various + * {@code CAPABILITY_*} constants in this class. */ public int getCallCapabilities() { return mCallCapabilities; @@ -511,14 +668,14 @@ public final class Call { } /** - * Merges the calls within this conference. See {@link PhoneCapabilities#MERGE_CONFERENCE}. + * Merges the calls within this conference. See {@link Details#CAPABILITY_MERGE_CONFERENCE}. */ public void mergeConference() { mInCallAdapter.mergeConference(mTelecomCallId); } /** - * Swaps the calls within this conference. See {@link PhoneCapabilities#SWAP_CONFERENCE}. + * Swaps the calls within this conference. See {@link Details#CAPABILITY_SWAP_CONFERENCE}. */ public void swapConference() { mInCallAdapter.swapConference(mTelecomCallId); diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java index b7b98bf..5371481 100644 --- a/telecomm/java/android/telecom/Conference.java +++ b/telecomm/java/android/telecom/Conference.java @@ -30,7 +30,7 @@ import java.util.concurrent.CopyOnWriteArraySet; * @hide */ @SystemApi -public abstract class Conference { +public abstract class Conference implements IConferenceable { /** @hide */ public abstract static class Listener { @@ -41,7 +41,8 @@ public abstract class Conference { public void onConferenceableConnectionsChanged( Conference conference, List<Connection> conferenceableConnections) {} public void onDestroyed(Conference conference) {} - public void onCapabilitiesChanged(Conference conference, int capabilities) {} + public void onConnectionCapabilitiesChanged( + Conference conference, int connectionCapabilities) {} } private final Set<Listener> mListeners = new CopyOnWriteArraySet<>(); @@ -56,7 +57,7 @@ public abstract class Conference { private AudioState mAudioState; private int mState = Connection.STATE_NEW; private DisconnectCause mDisconnectCause; - private int mCapabilities; + private int mConnectionCapabilities; private String mDisconnectMessage; private final Connection.Listener mConnectionDeathListener = new Connection.Listener() { @@ -104,13 +105,62 @@ public abstract class Conference { return mState; } + /** @hide */ + @Deprecated public final int getCapabilities() { + return getConnectionCapabilities(); + } + + /** + * Returns the capabilities of a conference. See {@code CAPABILITY_*} constants in class + * {@link Connection} for valid values. + * + * @return A bitmask of the capabilities of the conference call. + */ + public final int getConnectionCapabilities() { + return mConnectionCapabilities; + } + + /** + * Whether the given capabilities support the specified capability. + * + * @param capabilities A capability bit field. + * @param capability The capability to check capabilities for. + * @return Whether the specified capability is supported. + * @hide + */ + public static boolean can(int capabilities, int capability) { + return (capabilities & capability) != 0; + } + + /** + * Whether the capabilities of this {@code Connection} supports the specified capability. + * + * @param capability The capability to check capabilities for. + * @return Whether the specified capability is supported. + * @hide + */ + public boolean can(int capability) { + return can(mConnectionCapabilities, capability); + } + + /** + * Removes the specified capability from the set of capabilities of this {@code Conference}. + * + * @param capability The capability to remove from the set. + * @hide + */ + public void removeCapability(int capability) { + mConnectionCapabilities &= ~capability; + } + /** - * Returns the capabilities of a conference. See {@link PhoneCapabilities} for valid values. + * Adds the specified capability to the set of capabilities of this {@code Conference}. * - * @return A bitmask of the {@code PhoneCapabilities} of the conference call. + * @param capability The capability to add to the set. + * @hide */ - public final int getCapabilities() { - return mCapabilities; + public void addCapability(int capability) { + mConnectionCapabilities |= capability; } /** @@ -153,13 +203,13 @@ public abstract class Conference { /** * Invoked when the child calls should be merged. Only invoked if the conference contains the - * capability {@link PhoneCapabilities#MERGE_CONFERENCE}. + * capability {@link Connection#CAPABILITY_MERGE_CONFERENCE}. */ public void onMerge() {} /** * Invoked when the child calls should be swapped. Only invoked if the conference contains the - * capability {@link PhoneCapabilities#SWAP_CONFERENCE}. + * capability {@link Connection#CAPABILITY_SWAP_CONFERENCE}. */ public void onSwap() {} @@ -183,6 +233,13 @@ public abstract class Conference { public void onAudioStateChanged(AudioState state) {} /** + * Notifies this conference that a connection has been added to it. + * + * @param connection The newly added connection. + */ + public void onConnectionAdded(Connection connection) {} + + /** * Sets state to be on hold. */ public final void setOnHold() { @@ -211,16 +268,29 @@ public abstract class Conference { } /** - * Sets the capabilities of a conference. See {@link PhoneCapabilities} for valid values. + * @return The {@link DisconnectCause} for this connection. + */ + public final DisconnectCause getDisconnectCause() { + return mDisconnectCause; + } + + /** @hide */ + @Deprecated public final void setCapabilities(int connectionCapabilities) { + setConnectionCapabilities(connectionCapabilities); + } + + /** + * Sets the capabilities of a conference. See {@code CAPABILITY_*} constants of class + * {@link Connection} for valid values. * - * @param capabilities A bitmask of the {@code PhoneCapabilities} of the conference call. + * @param connectionCapabilities A bitmask of the {@code PhoneCapabilities} of the conference call. */ - public final void setCapabilities(int capabilities) { - if (capabilities != mCapabilities) { - mCapabilities = capabilities; + public final void setConnectionCapabilities(int connectionCapabilities) { + if (connectionCapabilities != mConnectionCapabilities) { + mConnectionCapabilities = connectionCapabilities; for (Listener l : mListeners) { - l.onCapabilitiesChanged(this, mCapabilities); + l.onConnectionCapabilitiesChanged(this, mConnectionCapabilities); } } } @@ -235,6 +305,7 @@ public abstract class Conference { if (connection != null && !mChildConnections.contains(connection)) { if (connection.setConference(this)) { mChildConnections.add(connection); + onConnectionAdded(connection); for (Listener l : mListeners) { l.onConnectionAdded(this, connection); } @@ -338,6 +409,19 @@ public abstract class Conference { } /** + * Retrieves the primary connection associated with the conference. The primary connection is + * the connection from which the conference will retrieve its current state. + * + * @return The primary connection. + */ + public Connection getPrimaryConnection() { + if (mUnmodifiableChildConnections == null || mUnmodifiableChildConnections.isEmpty()) { + return null; + } + return mUnmodifiableChildConnections.get(0); + } + + /** * Inform this Conference that the state of its audio output has been changed externally. * * @param state The new audio state. diff --git a/telecomm/java/android/telecom/ConferenceParticipant.aidl b/telecomm/java/android/telecom/ConferenceParticipant.aidl new file mode 100644 index 0000000..020c923 --- /dev/null +++ b/telecomm/java/android/telecom/ConferenceParticipant.aidl @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package android.telecom; + +/** + * {@hide} + */ +parcelable ConferenceParticipant; diff --git a/telecomm/java/android/telecom/ConferenceParticipant.java b/telecomm/java/android/telecom/ConferenceParticipant.java new file mode 100644 index 0000000..db0f151 --- /dev/null +++ b/telecomm/java/android/telecom/ConferenceParticipant.java @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package android.telecom; + +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Parcelable representation of a participant's state in a conference call. + * @hide + */ +public class ConferenceParticipant implements Parcelable { + + /** + * The conference participant's handle (e.g., phone number). + */ + private final Uri mHandle; + + /** + * The display name for the participant. + */ + private final String mDisplayName; + + /** + * The endpoint Uri which uniquely identifies this conference participant. E.g. for an IMS + * conference call, this is the endpoint URI for the participant on the IMS conference server. + */ + private final Uri mEndpoint; + + /** + * The state of the participant in the conference. + * + * @see android.telecom.Connection + */ + private final int mState; + + /** + * Creates an instance of {@code ConferenceParticipant}. + * + * @param handle The conference participant's handle (e.g., phone number). + * @param displayName The display name for the participant. + * @param endpoint The enpoint Uri which uniquely identifies this conference participant. + * @param state The state of the participant in the conference. + */ + public ConferenceParticipant(Uri handle, String displayName, Uri endpoint, int state) { + mHandle = handle; + mDisplayName = displayName; + mEndpoint = endpoint; + mState = state; + } + + /** + * Responsible for creating {@code ConferenceParticipant} objects for deserialized Parcels. + */ + public static final Parcelable.Creator<ConferenceParticipant> CREATOR = + new Parcelable.Creator<ConferenceParticipant>() { + + @Override + public ConferenceParticipant createFromParcel(Parcel source) { + ClassLoader classLoader = ParcelableCall.class.getClassLoader(); + Uri handle = source.readParcelable(classLoader); + String displayName = source.readString(); + Uri endpoint = source.readParcelable(classLoader); + int state = source.readInt(); + return new ConferenceParticipant(handle, displayName, endpoint, state); + } + + @Override + public ConferenceParticipant[] newArray(int size) { + return new ConferenceParticipant[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + /** + * Writes the {@code ConferenceParticipant} to a parcel. + * + * @param dest The Parcel in which the object should be written. + * @param flags Additional flags about how the object should be written. + */ + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeParcelable(mHandle, 0); + dest.writeString(mDisplayName); + dest.writeParcelable(mEndpoint, 0); + dest.writeInt(mState); + } + + /** + * Builds a string representation of this instance. + * + * @return String representing the conference participant. + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("[ConferenceParticipant Handle: "); + sb.append(mHandle); + sb.append(" DisplayName: "); + sb.append(mDisplayName); + sb.append(" Endpoint: "); + sb.append(mEndpoint); + sb.append(" State: "); + sb.append(mState); + sb.append("]"); + return sb.toString(); + } + + /** + * The conference participant's handle (e.g., phone number). + */ + public Uri getHandle() { + return mHandle; + } + + /** + * The display name for the participant. + */ + public String getDisplayName() { + return mDisplayName; + } + + /** + * The enpoint Uri which uniquely identifies this conference participant. E.g. for an IMS + * conference call, this is the endpoint URI for the participant on the IMS conference server. + */ + public Uri getEndpoint() { + return mEndpoint; + } + + /** + * The state of the participant in the conference. + * + * @see android.telecom.Connection + */ + public int getState() { + return mState; + } +} diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java index 4c1f75f..04274c7 100644 --- a/telecomm/java/android/telecom/Connection.java +++ b/telecomm/java/android/telecom/Connection.java @@ -47,7 +47,7 @@ import java.util.concurrent.ConcurrentHashMap; * @hide */ @SystemApi -public abstract class Connection { +public abstract class Connection implements IConferenceable { public static final int STATE_INITIALIZING = 0; @@ -63,9 +63,180 @@ public abstract class Connection { public static final int STATE_DISCONNECTED = 6; + /** Connection can currently be put on hold or unheld. */ + public static final int CAPABILITY_HOLD = 0x00000001; + + /** Connection supports the hold feature. */ + public static final int CAPABILITY_SUPPORT_HOLD = 0x00000002; + + /** + * Connections within a conference can be merged. A {@link ConnectionService} has the option to + * add a {@link Conference} before the child {@link Connection}s are merged. This is how + * CDMA-based {@link Connection}s are implemented. For these unmerged {@link Conference}s, this + * capability allows a merge button to be shown while the conference is in the foreground + * of the in-call UI. + * <p> + * This is only intended for use by a {@link Conference}. + */ + public static final int CAPABILITY_MERGE_CONFERENCE = 0x00000004; + + /** + * Connections within a conference can be swapped between foreground and background. + * See {@link #CAPABILITY_MERGE_CONFERENCE} for additional information. + * <p> + * This is only intended for use by a {@link Conference}. + */ + public static final int CAPABILITY_SWAP_CONFERENCE = 0x00000008; + + /** + * @hide + */ + public static final int CAPABILITY_UNUSED = 0x00000010; + + /** Connection supports responding via text option. */ + public static final int CAPABILITY_RESPOND_VIA_TEXT = 0x00000020; + + /** Connection can be muted. */ + public static final int CAPABILITY_MUTE = 0x00000040; + + /** + * Connection supports conference management. This capability only applies to + * {@link Conference}s which can have {@link Connection}s as children. + */ + public static final int CAPABILITY_MANAGE_CONFERENCE = 0x00000080; + + /** + * Local device supports video telephony. + * @hide + */ + public static final int CAPABILITY_SUPPORTS_VT_LOCAL = 0x00000100; + + /** + * Remote device supports video telephony. + * @hide + */ + public static final int CAPABILITY_SUPPORTS_VT_REMOTE = 0x00000200; + + /** + * Connection is using high definition audio. + * @hide + */ + public static final int CAPABILITY_HIGH_DEF_AUDIO = 0x00000400; + + /** + * Connection is using voice over WIFI. + * @hide + */ + public static final int CAPABILITY_VoWIFI = 0x00000800; + + /** + * Connection is able to be separated from its parent {@code Conference}, if any. + */ + public static final int CAPABILITY_SEPARATE_FROM_CONFERENCE = 0x00001000; + + /** + * Connection is able to be individually disconnected when in a {@code Conference}. + */ + public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 0x00002000; + + /** + * Whether the call is a generic conference, where we do not know the precise state of + * participants in the conference (eg. on CDMA). + * + * @hide + */ + public static final int CAPABILITY_GENERIC_CONFERENCE = 0x00004000; + // Flag controlling whether PII is emitted into the logs private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG); + /** + * Whether the given capabilities support the specified capability. + * + * @param capabilities A capability bit field. + * @param capability The capability to check capabilities for. + * @return Whether the specified capability is supported. + * @hide + */ + public static boolean can(int capabilities, int capability) { + return (capabilities & capability) != 0; + } + + /** + * Whether the capabilities of this {@code Connection} supports the specified capability. + * + * @param capability The capability to check capabilities for. + * @return Whether the specified capability is supported. + * @hide + */ + public boolean can(int capability) { + return can(mConnectionCapabilities, capability); + } + + /** + * Removes the specified capability from the set of capabilities of this {@code Connection}. + * + * @param capability The capability to remove from the set. + * @hide + */ + public void removeCapability(int capability) { + mConnectionCapabilities &= ~capability; + } + + /** + * Adds the specified capability to the set of capabilities of this {@code Connection}. + * + * @param capability The capability to add to the set. + * @hide + */ + public void addCapability(int capability) { + mConnectionCapabilities |= capability; + } + + + public static String capabilitiesToString(int capabilities) { + StringBuilder builder = new StringBuilder(); + builder.append("[Capabilities:"); + if (can(capabilities, CAPABILITY_HOLD)) { + builder.append(" CAPABILITY_HOLD"); + } + if (can(capabilities, CAPABILITY_SUPPORT_HOLD)) { + builder.append(" CAPABILITY_SUPPORT_HOLD"); + } + if (can(capabilities, CAPABILITY_MERGE_CONFERENCE)) { + builder.append(" CAPABILITY_MERGE_CONFERENCE"); + } + if (can(capabilities, CAPABILITY_SWAP_CONFERENCE)) { + builder.append(" CAPABILITY_SWAP_CONFERENCE"); + } + if (can(capabilities, CAPABILITY_RESPOND_VIA_TEXT)) { + builder.append(" CAPABILITY_RESPOND_VIA_TEXT"); + } + if (can(capabilities, CAPABILITY_MUTE)) { + builder.append(" CAPABILITY_MUTE"); + } + if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) { + builder.append(" CAPABILITY_MANAGE_CONFERENCE"); + } + if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL)) { + builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL"); + } + if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE)) { + builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE"); + } + if (can(capabilities, CAPABILITY_HIGH_DEF_AUDIO)) { + builder.append(" CAPABILITY_HIGH_DEF_AUDIO"); + } + if (can(capabilities, CAPABILITY_VoWIFI)) { + builder.append(" CAPABILITY_VoWIFI"); + } + if (can(capabilities, CAPABILITY_GENERIC_CONFERENCE)) { + builder.append(" CAPABILITY_GENERIC_CONFERENCE"); + } + builder.append("]"); + return builder.toString(); + } + /** @hide */ public abstract static class Listener { public void onStateChanged(Connection c, int state) {} @@ -77,14 +248,17 @@ public abstract class Connection { public void onPostDialWait(Connection c, String remaining) {} public void onRingbackRequested(Connection c, boolean ringback) {} public void onDestroyed(Connection c) {} - public void onCallCapabilitiesChanged(Connection c, int callCapabilities) {} + public void onConnectionCapabilitiesChanged(Connection c, int capabilities) {} public void onVideoProviderChanged( Connection c, VideoProvider videoProvider) {} public void onAudioModeIsVoipChanged(Connection c, boolean isVoip) {} public void onStatusHintsChanged(Connection c, StatusHints statusHints) {} - public void onConferenceableConnectionsChanged( - Connection c, List<Connection> conferenceableConnections) {} + public void onConferenceablesChanged( + Connection c, List<IConferenceable> conferenceables) {} public void onConferenceChanged(Connection c, Conference conference) {} + /** @hide */ + public void onConferenceParticipantsChanged(Connection c, + List<ConferenceParticipant> participants) {} } /** @hide */ @@ -149,7 +323,7 @@ public abstract class Connection { private static final int MSG_SEND_SESSION_MODIFY_REQUEST = 7; private static final int MSG_SEND_SESSION_MODIFY_RESPONSE = 8; private static final int MSG_REQUEST_CAMERA_CAPABILITIES = 9; - private static final int MSG_REQUEST_CALL_DATA_USAGE = 10; + private static final int MSG_REQUEST_CONNECTION_DATA_USAGE = 10; private static final int MSG_SET_PAUSE_IMAGE = 11; private final VideoProvider.VideoProviderHandler @@ -191,8 +365,8 @@ public abstract class Connection { case MSG_REQUEST_CAMERA_CAPABILITIES: onRequestCameraCapabilities(); break; - case MSG_REQUEST_CALL_DATA_USAGE: - onRequestCallDataUsage(); + case MSG_REQUEST_CONNECTION_DATA_USAGE: + onRequestConnectionDataUsage(); break; case MSG_SET_PAUSE_IMAGE: onSetPauseImage((String) msg.obj); @@ -247,7 +421,7 @@ public abstract class Connection { } public void requestCallDataUsage() { - mMessageHandler.obtainMessage(MSG_REQUEST_CALL_DATA_USAGE).sendToTarget(); + mMessageHandler.obtainMessage(MSG_REQUEST_CONNECTION_DATA_USAGE).sendToTarget(); } public void setPauseImage(String uri) { @@ -268,7 +442,7 @@ public abstract class Connection { } /** - * Sets the camera to be used for video recording in a video call. + * Sets the camera to be used for video recording in a video connection. * * @param cameraId The id of the camera. */ @@ -308,19 +482,19 @@ public abstract class Connection { /** * Issues a request to modify the properties of the current session. The request is * sent to the remote device where it it handled by the In-Call UI. - * Some examples of session modification requests: upgrade call from audio to video, - * downgrade call from video to audio, pause video. + * Some examples of session modification requests: upgrade connection from audio to video, + * downgrade connection from video to audio, pause video. * - * @param requestProfile The requested call video properties. + * @param requestProfile The requested connection video properties. */ public abstract void onSendSessionModifyRequest(VideoProfile requestProfile); /**te - * Provides a response to a request to change the current call session video + * Provides a response to a request to change the current connection session video * properties. * This is in response to a request the InCall UI has received via the InCall UI. * - * @param responseProfile The response call video properties. + * @param responseProfile The response connection video properties. */ public abstract void onSendSessionModifyResponse(VideoProfile responseProfile); @@ -332,10 +506,10 @@ public abstract class Connection { /** * Issues a request to the video telephony framework to retrieve the cumulative data usage - * for the current call. Data usage is reported back to the caller via the + * for the current connection. Data usage is reported back to the caller via the * InCall UI. */ - public abstract void onRequestCallDataUsage(); + public abstract void onRequestConnectionDataUsage(); /** * Provides the video telephony framework with the URI of an image to be displayed to remote @@ -348,7 +522,7 @@ public abstract class Connection { /** * Invokes callback method defined in In-Call UI. * - * @param videoProfile The requested video call profile. + * @param videoProfile The requested video connection profile. */ public void receiveSessionModifyRequest(VideoProfile videoProfile) { if (mVideoCallback != null) { @@ -446,7 +620,16 @@ public abstract class Connection { private final Listener mConnectionDeathListener = new Listener() { @Override public void onDestroyed(Connection c) { - if (mConferenceableConnections.remove(c)) { + if (mConferenceables.remove(c)) { + fireOnConferenceableConnectionsChanged(); + } + } + }; + + private final Conference.Listener mConferenceDeathListener = new Conference.Listener() { + @Override + public void onDestroyed(Conference c) { + if (mConferenceables.remove(c)) { fireOnConferenceableConnectionsChanged(); } } @@ -459,9 +642,9 @@ public abstract class Connection { */ private final Set<Listener> mListeners = Collections.newSetFromMap( new ConcurrentHashMap<Listener, Boolean>(8, 0.9f, 1)); - private final List<Connection> mConferenceableConnections = new ArrayList<>(); - private final List<Connection> mUnmodifiableConferenceableConnections = - Collections.unmodifiableList(mConferenceableConnections); + private final List<IConferenceable> mConferenceables = new ArrayList<>(); + private final List<IConferenceable> mUnmodifiableConferenceables = + Collections.unmodifiableList(mConferenceables); private int mState = STATE_NEW; private AudioState mAudioState; @@ -470,7 +653,7 @@ public abstract class Connection { private String mCallerDisplayName; private int mCallerDisplayNamePresentation; private boolean mRingbackRequested = false; - private int mCallCapabilities; + private int mConnectionCapabilities; private VideoProvider mVideoProvider; private boolean mAudioModeIsVoip; private StatusHints mStatusHints; @@ -522,13 +705,13 @@ public abstract class Connection { } /** - * Returns the video state of the call. + * Returns the video state of the connection. * Valid values: {@link VideoProfile.VideoState#AUDIO_ONLY}, * {@link VideoProfile.VideoState#BIDIRECTIONAL}, * {@link VideoProfile.VideoState#TX_ENABLED}, * {@link VideoProfile.VideoState#RX_ENABLED}. * - * @return The video state of the call. + * @return The video state of the connection. * @hide */ public final int getVideoState() { @@ -536,7 +719,7 @@ public abstract class Connection { } /** - * @return The audio state of the call, describing how its audio is currently + * @return The audio state of the connection, describing how its audio is currently * being routed by the system. This is {@code null} if this Connection * does not directly know about its audio state. */ @@ -616,6 +799,7 @@ public abstract class Connection { * @hide */ final void setAudioState(AudioState state) { + checkImmutable(); Log.d(this, "setAudioState %s", state); mAudioState = state; onAudioStateChanged(state); @@ -648,10 +832,10 @@ public abstract class Connection { } /** - * Returns the connection's {@link PhoneCapabilities} + * Returns the connection's capabilities, as a bit mask of the {@code CAPABILITY_*} constants. */ - public final int getCallCapabilities() { - return mCallCapabilities; + public final int getConnectionCapabilities() { + return mConnectionCapabilities; } /** @@ -662,6 +846,7 @@ public abstract class Connection { * See {@link TelecomManager} for valid values. */ public final void setAddress(Uri address, int presentation) { + checkImmutable(); Log.d(this, "setAddress %s", address); mAddress = address; mAddressPresentation = presentation; @@ -678,6 +863,7 @@ public abstract class Connection { * See {@link TelecomManager} for valid values. */ public final void setCallerDisplayName(String callerDisplayName, int presentation) { + checkImmutable(); Log.d(this, "setCallerDisplayName %s", callerDisplayName); mCallerDisplayName = callerDisplayName; mCallerDisplayNamePresentation = presentation; @@ -697,6 +883,7 @@ public abstract class Connection { * @hide */ public final void setVideoState(int videoState) { + checkImmutable(); Log.d(this, "setVideoState %d", videoState); mVideoState = videoState; for (Listener l : mListeners) { @@ -705,18 +892,20 @@ public abstract class Connection { } /** - * Sets state to active (e.g., an ongoing call where two or more parties can actively + * Sets state to active (e.g., an ongoing connection where two or more parties can actively * communicate). */ public final void setActive() { + checkImmutable(); setRingbackRequested(false); setState(STATE_ACTIVE); } /** - * Sets state to ringing (e.g., an inbound ringing call). + * Sets state to ringing (e.g., an inbound ringing connection). */ public final void setRinging() { + checkImmutable(); setState(STATE_RINGING); } @@ -724,6 +913,7 @@ public abstract class Connection { * Sets state to initializing (this Connection is not yet ready to be used). */ public final void setInitializing() { + checkImmutable(); setState(STATE_INITIALIZING); } @@ -731,13 +921,15 @@ public abstract class Connection { * Sets state to initialized (the Connection has been set up and is now ready to be used). */ public final void setInitialized() { + checkImmutable(); setState(STATE_NEW); } /** - * Sets state to dialing (e.g., dialing an outbound call). + * Sets state to dialing (e.g., dialing an outbound connection). */ public final void setDialing() { + checkImmutable(); setState(STATE_DIALING); } @@ -745,15 +937,17 @@ public abstract class Connection { * Sets state to be on hold. */ public final void setOnHold() { + checkImmutable(); setState(STATE_HOLDING); } /** - * Sets the video call provider. + * Sets the video connection provider. * @param videoProvider The video provider. * @hide */ public final void setVideoProvider(VideoProvider videoProvider) { + checkImmutable(); mVideoProvider = videoProvider; for (Listener l : mListeners) { l.onVideoProviderChanged(this, videoProvider); @@ -772,6 +966,7 @@ public abstract class Connection { * {@link DisconnectCause}. */ public final void setDisconnected(DisconnectCause disconnectCause) { + checkImmutable(); mDisconnectCause = disconnectCause; setState(STATE_DISCONNECTED); Log.d(this, "Disconnected with cause %s", disconnectCause); @@ -781,9 +976,17 @@ public abstract class Connection { } /** - * TODO: Needs documentation. + * Informs listeners that this {@code Connection} is in a post-dial wait state. This is done + * when (a) the {@code Connection} is issuing a DTMF sequence; (b) it has encountered a "wait" + * character; and (c) it wishes to inform the In-Call app that it is waiting for the end-user + * to send an {@link #onPostDialContinue(boolean)} signal. + * + * @param remaining The DTMF character sequence remaining to be emitted once the + * {@link #onPostDialContinue(boolean)} is received, including any "wait" characters + * that remaining sequence may contain. */ public final void setPostDialWait(String remaining) { + checkImmutable(); for (Listener l : mListeners) { l.onPostDialWait(this, remaining); } @@ -791,11 +994,12 @@ public abstract class Connection { /** * Requests that the framework play a ringback tone. This is to be invoked by implementations - * that do not play a ringback tone themselves in the call's audio stream. + * that do not play a ringback tone themselves in the connection's audio stream. * * @param ringback Whether the ringback tone is to be played. */ public final void setRingbackRequested(boolean ringback) { + checkImmutable(); if (mRingbackRequested != ringback) { mRingbackRequested = ringback; for (Listener l : mListeners) { @@ -804,16 +1008,22 @@ public abstract class Connection { } } + /** @hide */ + @SystemApi @Deprecated public final void setCallCapabilities(int connectionCapabilities) { + setConnectionCapabilities(connectionCapabilities); + } + /** - * Sets the connection's {@link PhoneCapabilities}. + * Sets the connection's capabilities as a bit mask of the {@code CAPABILITY_*} constants. * - * @param callCapabilities The new call capabilities. + * @param connectionCapabilities The new connection capabilities. */ - public final void setCallCapabilities(int callCapabilities) { - if (mCallCapabilities != callCapabilities) { - mCallCapabilities = callCapabilities; + public final void setConnectionCapabilities(int connectionCapabilities) { + checkImmutable(); + if (mConnectionCapabilities != connectionCapabilities) { + mConnectionCapabilities = connectionCapabilities; for (Listener l : mListeners) { - l.onCallCapabilitiesChanged(this, mCallCapabilities); + l.onConnectionCapabilitiesChanged(this, mConnectionCapabilities); } } } @@ -833,6 +1043,7 @@ public abstract class Connection { * @param isVoip True if the audio mode is VOIP. */ public final void setAudioModeIsVoip(boolean isVoip) { + checkImmutable(); mAudioModeIsVoip = isVoip; for (Listener l : mListeners) { l.onAudioModeIsVoipChanged(this, isVoip); @@ -845,6 +1056,7 @@ public abstract class Connection { * @param statusHints The status label and icon to set. */ public final void setStatusHints(StatusHints statusHints) { + checkImmutable(); mStatusHints = statusHints; for (Listener l : mListeners) { l.onStatusHintsChanged(this, statusHints); @@ -857,29 +1069,56 @@ public abstract class Connection { * @param conferenceableConnections The set of connections this connection can conference with. */ public final void setConferenceableConnections(List<Connection> conferenceableConnections) { + checkImmutable(); clearConferenceableList(); for (Connection c : conferenceableConnections) { // If statement checks for duplicates in input. It makes it N^2 but we're dealing with a // small amount of items here. - if (!mConferenceableConnections.contains(c)) { + if (!mConferenceables.contains(c)) { c.addConnectionListener(mConnectionDeathListener); - mConferenceableConnections.add(c); + mConferenceables.add(c); } } fireOnConferenceableConnectionsChanged(); } /** - * Returns the connections with which this connection can be conferenced. + * Similar to {@link #setConferenceableConnections(java.util.List)}, sets a list of connections + * or conferences with which this connection can be conferenced. + * + * @param conferenceables The conferenceables. */ - public final List<Connection> getConferenceableConnections() { - return mUnmodifiableConferenceableConnections; + public final void setConferenceables(List<IConferenceable> conferenceables) { + clearConferenceableList(); + for (IConferenceable c : conferenceables) { + // If statement checks for duplicates in input. It makes it N^2 but we're dealing with a + // small amount of items here. + if (!mConferenceables.contains(c)) { + if (c instanceof Connection) { + Connection connection = (Connection) c; + connection.addConnectionListener(mConnectionDeathListener); + } else if (c instanceof Conference) { + Conference conference = (Conference) c; + conference.addListener(mConferenceDeathListener); + } + mConferenceables.add(c); + } + } + fireOnConferenceableConnectionsChanged(); } /** + * Returns the connections or conferences with which this connection can be conferenced. + */ + public final List<IConferenceable> getConferenceables() { + return mUnmodifiableConferenceables; + } + + /* * @hide */ public final void setConnectionService(ConnectionService connectionService) { + checkImmutable(); if (mConnectionService != null) { Log.e(this, new Exception(), "Trying to set ConnectionService on a connection " + "which is already associated with another ConnectionService."); @@ -909,13 +1148,14 @@ public abstract class Connection { /** * Sets the conference that this connection is a part of. This will fail if the connection is - * already part of a conference call. {@link #resetConference} to un-set the conference first. + * already part of a conference. {@link #resetConference} to un-set the conference first. * * @param conference The conference. * @return {@code true} if the conference was successfully set. * @hide */ public final boolean setConference(Conference conference) { + checkImmutable(); // We check to see if it is already part of another conference. if (mConference == null) { mConference = conference; @@ -942,7 +1182,7 @@ public abstract class Connection { /** * Notifies this Connection that the {@link #getAudioState()} property has a new value. * - * @param state The new call audio state. + * @param state The new connection audio state. */ public void onAudioStateChanged(AudioState state) {} @@ -972,6 +1212,15 @@ public abstract class Connection { public void onDisconnect() {} /** + * Notifies this Connection of a request to disconnect a participant of the conference managed + * by the connection. + * + * @param endpoint the {@link Uri} of the participant to disconnect. + * @hide + */ + public void onDisconnectConferenceParticipant(Uri endpoint) {} + + /** * Notifies this Connection of a request to separate from its parent conference. */ public void onSeparate() {} @@ -995,7 +1244,7 @@ public abstract class Connection { * Notifies this Connection, which is in {@link #STATE_RINGING}, of * a request to accept. * - * @param videoState The video state in which to answer the call. + * @param videoState The video state in which to answer the connection. * @hide */ public void onAnswer(int videoState) {} @@ -1019,16 +1268,6 @@ public abstract class Connection { */ public void onPostDialContinue(boolean proceed) {} - /** - * Merge this connection and the specified connection into a conference call. Once the - * connections are merged, the calls should be added to the an existing or new - * {@code Conference} instance. For new {@code Conference} instances, use - * {@code ConnectionService#addConference}. - * - * @param otherConnection The connection with which this connection should be conferenced. - */ - public void onConferenceWith(Connection otherConnection) {} - static String toLogSafePhoneNumber(String number) { // For unknown number, log empty string. if (number == null) { @@ -1055,6 +1294,7 @@ public abstract class Connection { } private void setState(int state) { + checkImmutable(); if (mState == STATE_DISCONNECTED && mState != state) { Log.d(this, "Connection already DISCONNECTED; cannot transition out of this state."); return; @@ -1070,8 +1310,16 @@ public abstract class Connection { } private static class FailureSignalingConnection extends Connection { + private boolean mImmutable = false; public FailureSignalingConnection(DisconnectCause disconnectCause) { setDisconnected(disconnectCause); + mImmutable = true; + } + + public void checkImmutable() { + if (mImmutable) { + throw new UnsupportedOperationException("Connection is immutable"); + } } } @@ -1091,23 +1339,32 @@ public abstract class Connection { } /** + * Override to throw an {@link UnsupportedOperationException} if this {@code Connection} is + * not intended to be mutated, e.g., if it is a marker for failure. Only for framework use; + * this should never be un-@hide-den. + * + * @hide + */ + public void checkImmutable() {} + + /** * Return a {@code Connection} which represents a canceled connection attempt. The returned * {@code Connection} will have state {@link #STATE_DISCONNECTED}, and cannot be moved out of * that state. This connection should not be used for anything, and no other * {@code Connection}s should be attempted. * <p> - * The returned {@code Connection} can be assumed to {@link #destroy()} itself when appropriate, * so users of this method need not maintain a reference to its return value to destroy it. * - * @return A {@code Connection} which indicates that the underlying call should be canceled. + * @return A {@code Connection} which indicates that the underlying connection should + * be canceled. */ public static Connection createCanceledConnection() { return new FailureSignalingConnection(new DisconnectCause(DisconnectCause.CANCELED)); } - private final void fireOnConferenceableConnectionsChanged() { + private final void fireOnConferenceableConnectionsChanged() { for (Listener l : mListeners) { - l.onConferenceableConnectionsChanged(this, getConferenceableConnections()); + l.onConferenceablesChanged(this, getConferenceables()); } } @@ -1118,9 +1375,28 @@ public abstract class Connection { } private final void clearConferenceableList() { - for (Connection c : mConferenceableConnections) { - c.removeConnectionListener(mConnectionDeathListener); + for (IConferenceable c : mConferenceables) { + if (c instanceof Connection) { + Connection connection = (Connection) c; + connection.removeConnectionListener(mConnectionDeathListener); + } else if (c instanceof Conference) { + Conference conference = (Conference) c; + conference.removeListener(mConferenceDeathListener); + } + } + mConferenceables.clear(); + } + + /** + * Notifies listeners of a change to conference participant(s). + * + * @param conferenceParticipants The participants. + * @hide + */ + protected final void updateConferenceParticipants( + List<ConferenceParticipant> conferenceParticipants) { + for (Listener l : mListeners) { + l.onConferenceParticipantsChanged(this, conferenceParticipants); } - mConferenceableConnections.clear(); } } diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java index 6eee99d..d0a8aee 100644 --- a/telecomm/java/android/telecom/ConnectionService.java +++ b/telecomm/java/android/telecom/ConnectionService.java @@ -16,8 +16,8 @@ package android.telecom; -import android.annotation.SystemApi; import android.annotation.SdkConstant; +import android.annotation.SystemApi; import android.app.Service; import android.content.ComponentName; import android.content.Intent; @@ -41,8 +41,37 @@ import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; /** - * A {@link android.app.Service} that provides telephone connections to processes running on an - * Android device. + * {@code ConnectionService} is an abstract service that should be implemented by any app which can + * make phone calls and want those calls to be integrated into the built-in phone app. + * Once implemented, the {@code ConnectionService} needs two additional steps before it will be + * integrated into the phone app: + * <p> + * 1. <i>Registration in AndroidManifest.xml</i> + * <br/> + * <pre> + * <service android:name="com.example.package.MyConnectionService" + * android:label="@string/some_label_for_my_connection_service" + * android:permission="android.permission.BIND_CONNECTION_SERVICE"> + * <intent-filter> + * <action android:name="android.telecom.ConnectionService" /> + * </intent-filter> + * </service> + * </pre> + * <p> + * 2. <i> Registration of {@link PhoneAccount} with {@link TelecomManager}.</i> + * <br/> + * See {@link PhoneAccount} and {@link TelecomManager#registerPhoneAccount} for more information. + * <p> + * Once registered and enabled by the user in the dialer settings, telecom will bind to a + * {@code ConnectionService} implementation when it wants that {@code ConnectionService} to place + * a call or the service has indicated that is has an incoming call through + * {@link TelecomManager#addNewIncomingCall}. The {@code ConnectionService} can then expect a call + * to {@link #onCreateIncomingConnection} or {@link #onCreateOutgoingConnection} wherein it + * should provide a new instance of a {@link Connection} object. It is through this + * {@link Connection} object that telecom receives state updates and the {@code ConnectionService} + * receives call-commands such as answer, reject, hold and disconnect. + * <p> + * When there are no more live calls, telecom will unbind from the {@code ConnectionService}. * @hide */ @SystemApi @@ -378,11 +407,13 @@ public abstract class ConnectionService extends Service { } @Override - public void onCapabilitiesChanged(Conference conference, int capabilities) { + public void onConnectionCapabilitiesChanged( + Conference conference, + int connectionCapabilities) { String id = mIdByConference.get(conference); Log.d(this, "call capabilities: conference: %s", - PhoneCapabilities.toString(capabilities)); - mAdapter.setCallCapabilities(id, capabilities); + Connection.capabilitiesToString(connectionCapabilities)); + mAdapter.setConnectionCapabilities(id, connectionCapabilities); } }; @@ -460,11 +491,11 @@ public abstract class ConnectionService extends Service { } @Override - public void onCallCapabilitiesChanged(Connection c, int capabilities) { + public void onConnectionCapabilitiesChanged(Connection c, int capabilities) { String id = mIdByConnection.get(c); Log.d(this, "capabilities: parcelableconnection: %s", - PhoneCapabilities.toString(capabilities)); - mAdapter.setCallCapabilities(id, capabilities); + Connection.capabilitiesToString(capabilities)); + mAdapter.setConnectionCapabilities(id, capabilities); } @Override @@ -486,11 +517,11 @@ public abstract class ConnectionService extends Service { } @Override - public void onConferenceableConnectionsChanged( - Connection connection, List<Connection> conferenceableConnections) { + public void onConferenceablesChanged( + Connection connection, List<IConferenceable> conferenceables) { mAdapter.setConferenceableConnections( mIdByConnection.get(connection), - createConnectionIdList(conferenceableConnections)); + createIdList(conferenceables)); } @Override @@ -552,7 +583,7 @@ public abstract class ConnectionService extends Service { Log.v(this, "createConnection, number: %s, state: %s, capabilities: %s", Connection.toLogSafePhoneNumber(number), Connection.stateToString(connection.getState()), - PhoneCapabilities.toString(connection.getCallCapabilities())); + Connection.capabilitiesToString(connection.getConnectionCapabilities())); Log.d(this, "createConnection, calling handleCreateConnectionSuccessful %s", callId); mAdapter.handleCreateConnectionComplete( @@ -561,7 +592,7 @@ public abstract class ConnectionService extends Service { new ParcelableConnection( request.getAccountHandle(), connection.getState(), - connection.getCallCapabilities(), + connection.getConnectionCapabilities(), connection.getAddress(), connection.getAddressPresentation(), connection.getCallerDisplayName(), @@ -573,7 +604,7 @@ public abstract class ConnectionService extends Service { connection.getAudioModeIsVoip(), connection.getStatusHints(), connection.getDisconnectCause(), - createConnectionIdList(connection.getConferenceableConnections()))); + createIdList(connection.getConferenceables()))); } private void abort(String callId) { @@ -653,12 +684,19 @@ public abstract class ConnectionService extends Service { private void conference(String callId1, String callId2) { Log.d(this, "conference %s, %s", callId1, callId2); + // Attempt to get second connection or conference. Connection connection2 = findConnectionForAction(callId2, "conference"); + Conference conference2 = getNullConference(); if (connection2 == getNullConnection()) { - Log.w(this, "Connection2 missing in conference request %s.", callId2); - return; + conference2 = findConferenceForAction(callId2, "conference"); + if (conference2 == getNullConference()) { + Log.w(this, "Connection2 or Conference2 missing in conference request %s.", + callId2); + return; + } } + // Attempt to get first connection or conference and perform merge. Connection connection1 = findConnectionForAction(callId1, "conference"); if (connection1 == getNullConnection()) { Conference conference1 = findConferenceForAction(callId1, "addConnection"); @@ -667,10 +705,26 @@ public abstract class ConnectionService extends Service { "Connection1 or Conference1 missing in conference request %s.", callId1); } else { - conference1.onMerge(connection2); + // Call 1 is a conference. + if (connection2 != getNullConnection()) { + // Call 2 is a connection so merge via call 1 (conference). + conference1.onMerge(connection2); + } else { + // Call 2 is ALSO a conference; this should never happen. + Log.wtf(this, "There can only be one conference and an attempt was made to " + + "merge two conferences."); + return; + } } } else { - onConference(connection1, connection2); + // Call 1 is a connection. + if (conference2 != getNullConference()) { + // Call 2 is a conference, so merge via call 2. + conference2.onMerge(connection1); + } else { + // Call 2 is a connection, so merge together. + onConference(connection1, connection2); + } } } @@ -749,7 +803,9 @@ public abstract class ConnectionService extends Service { /** * Ask some other {@code ConnectionService} to create a {@code RemoteConnection} given an - * incoming request. This is used to attach to existing incoming calls. + * incoming request. This is used by {@code ConnectionService}s that are registered with + * {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER} and want to be able to manage + * SIM-based incoming calls. * * @param connectionManagerPhoneAccount See description at * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}. @@ -766,7 +822,9 @@ public abstract class ConnectionService extends Service { /** * Ask some other {@code ConnectionService} to create a {@code RemoteConnection} given an - * outgoing request. This is used to initiate new outgoing calls. + * outgoing request. This is used by {@code ConnectionService}s that are registered with + * {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER} and want to be able to use the + * SIM-based {@code ConnectionService} to place its outgoing calls. * * @param connectionManagerPhoneAccount See description at * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}. @@ -782,12 +840,19 @@ public abstract class ConnectionService extends Service { } /** - * Adds two {@code RemoteConnection}s to some {@code RemoteConference}. + * Indicates to the relevant {@code RemoteConnectionService} that the specified + * {@link RemoteConnection}s should be merged into a conference call. + * <p> + * If the conference request is successful, the method {@link #onRemoteConferenceAdded} will + * be invoked. + * + * @param remoteConnection1 The first of the remote connections to conference. + * @param remoteConnection2 The second of the remote connections to conference. */ public final void conferenceRemoteConnections( - RemoteConnection a, - RemoteConnection b) { - mRemoteConnectionManager.conferenceRemoteConnections(a, b); + RemoteConnection remoteConnection1, + RemoteConnection remoteConnection2) { + mRemoteConnectionManager.conferenceRemoteConnections(remoteConnection1, remoteConnection2); } /** @@ -810,7 +875,7 @@ public abstract class ConnectionService extends Service { ParcelableConference parcelableConference = new ParcelableConference( conference.getPhoneAccountHandle(), conference.getState(), - conference.getCapabilities(), + conference.getConnectionCapabilities(), connectionIds); mAdapter.addConferenceCall(id, parcelableConference); @@ -825,6 +890,40 @@ public abstract class ConnectionService extends Service { } /** + * Adds a connection created by the {@link ConnectionService} and informs telecom of the new + * connection. + * + * @param phoneAccountHandle The phone account handle for the connection. + * @param connection The connection to add. + */ + public final void addExistingConnection(PhoneAccountHandle phoneAccountHandle, + Connection connection) { + + String id = addExistingConnectionInternal(connection); + if (id != null) { + List<String> emptyList = new ArrayList<>(0); + + ParcelableConnection parcelableConnection = new ParcelableConnection( + phoneAccountHandle, + connection.getState(), + connection.getConnectionCapabilities(), + connection.getAddress(), + connection.getAddressPresentation(), + connection.getCallerDisplayName(), + connection.getCallerDisplayNamePresentation(), + connection.getVideoProvider() == null ? + null : connection.getVideoProvider().getInterface(), + connection.getVideoState(), + connection.isRingbackRequested(), + connection.getAudioModeIsVoip(), + connection.getStatusHints(), + connection.getDisconnectCause(), + emptyList); + mAdapter.addExistingConnection(id, parcelableConnection); + } + } + + /** * Returns all the active {@code Connection}s for which this {@code ConnectionService} * has taken responsibility. * @@ -906,9 +1005,25 @@ public abstract class ConnectionService extends Service { */ public void onConference(Connection connection1, Connection connection2) {} + /** + * Indicates that a remote conference has been created for existing {@link RemoteConnection}s. + * When this method is invoked, this {@link ConnectionService} should create its own + * representation of the conference call and send it to telecom using {@link #addConference}. + * <p> + * This is only relevant to {@link ConnectionService}s which are registered with + * {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER}. + * + * @param conference The remote conference call. + */ public void onRemoteConferenceAdded(RemoteConference conference) {} /** + * Called when an existing connection is added remotely. + * @param connection The existing connection which was added. + */ + public void onRemoteExistingConnectionAdded(RemoteConnection connection) {} + + /** * @hide */ public boolean containsConference(Conference conference) { @@ -920,6 +1035,11 @@ public abstract class ConnectionService extends Service { onRemoteConferenceAdded(remoteConference); } + /** {@hide} */ + void addRemoteExistingConnection(RemoteConnection remoteConnection) { + onRemoteExistingConnectionAdded(remoteConnection); + } + private void onAccountsInitialized() { mAreAccountsInitialized = true; for (Runnable r : mPreInitializationConnectionRequests) { @@ -928,6 +1048,18 @@ public abstract class ConnectionService extends Service { mPreInitializationConnectionRequests.clear(); } + /** + * Adds an existing connection to the list of connections, identified by a new UUID. + * + * @param connection The connection. + * @return The UUID of the connection (e.g. the call-id). + */ + private String addExistingConnectionInternal(Connection connection) { + String id = UUID.randomUUID().toString(); + addConnection(id, connection); + return id; + } + private void addConnection(String callId, Connection connection) { mConnectionById.put(callId, connection); mIdByConnection.put(connection, callId); @@ -935,7 +1067,8 @@ public abstract class ConnectionService extends Service { connection.setConnectionService(this); } - private void removeConnection(Connection connection) { + /** {@hide} */ + protected void removeConnection(Connection connection) { String id = mIdByConnection.get(connection); connection.unsetConnectionService(this); connection.removeConnectionListener(mConnectionListener); @@ -1003,6 +1136,33 @@ public abstract class ConnectionService extends Service { return ids; } + /** + * Builds a list of {@link Connection} and {@link Conference} IDs based on the list of + * {@link IConferenceable}s passed in. + * + * @param conferenceables The {@link IConferenceable} connections and conferences. + * @return List of string conference and call Ids. + */ + private List<String> createIdList(List<IConferenceable> conferenceables) { + List<String> ids = new ArrayList<>(); + for (IConferenceable c : conferenceables) { + // Only allow Connection and Conference conferenceables. + if (c instanceof Connection) { + Connection connection = (Connection) c; + if (mIdByConnection.containsKey(connection)) { + ids.add(mIdByConnection.get(connection)); + } + } else if (c instanceof Conference) { + Conference conference = (Conference) c; + if (mIdByConference.containsKey(conference)) { + ids.add(mIdByConference.get(conference)); + } + } + } + Collections.sort(ids); + return ids; + } + private Conference getNullConference() { if (sNullConference == null) { sNullConference = new Conference(null) {}; diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapter.java b/telecomm/java/android/telecom/ConnectionServiceAdapter.java index c676172..aee9675 100644 --- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java +++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java @@ -175,10 +175,10 @@ final class ConnectionServiceAdapter implements DeathRecipient { } } - void setCallCapabilities(String callId, int capabilities) { + void setConnectionCapabilities(String callId, int capabilities) { for (IConnectionServiceAdapter adapter : mAdapters) { try { - adapter.setCallCapabilities(callId, capabilities); + adapter.setConnectionCapabilities(callId, capabilities); } catch (RemoteException ignored) { } } @@ -344,4 +344,20 @@ final class ConnectionServiceAdapter implements DeathRecipient { } } } + + /** + * Informs telecom of an existing connection which was added by the {@link ConnectionService}. + * + * @param callId The unique ID of the call being added. + * @param connection The connection. + */ + void addExistingConnection(String callId, ParcelableConnection connection) { + Log.v(this, "addExistingConnection: %s", callId); + for (IConnectionServiceAdapter adapter : mAdapters) { + try { + adapter.addExistingConnection(callId, connection); + } catch (RemoteException ignored) { + } + } + } } diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java index 217dbc3..7619da5 100644 --- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java +++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java @@ -44,7 +44,7 @@ final class ConnectionServiceAdapterServant { private static final int MSG_SET_DISCONNECTED = 5; private static final int MSG_SET_ON_HOLD = 6; private static final int MSG_SET_RINGBACK_REQUESTED = 7; - private static final int MSG_SET_CALL_CAPABILITIES = 8; + private static final int MSG_SET_CONNECTION_CAPABILITIES = 8; private static final int MSG_SET_IS_CONFERENCED = 9; private static final int MSG_ADD_CONFERENCE_CALL = 10; private static final int MSG_REMOVE_CALL = 11; @@ -57,6 +57,7 @@ final class ConnectionServiceAdapterServant { private static final int MSG_SET_ADDRESS = 18; private static final int MSG_SET_CALLER_DISPLAY_NAME = 19; private static final int MSG_SET_CONFERENCEABLE_CONNECTIONS = 20; + private static final int MSG_ADD_EXISTING_CONNECTION = 21; private final IConnectionServiceAdapter mDelegate; @@ -108,8 +109,8 @@ final class ConnectionServiceAdapterServant { case MSG_SET_RINGBACK_REQUESTED: mDelegate.setRingbackRequested((String) msg.obj, msg.arg1 == 1); break; - case MSG_SET_CALL_CAPABILITIES: - mDelegate.setCallCapabilities((String) msg.obj, msg.arg1); + case MSG_SET_CONNECTION_CAPABILITIES: + mDelegate.setConnectionCapabilities((String) msg.obj, msg.arg1); break; case MSG_SET_IS_CONFERENCED: { SomeArgs args = (SomeArgs) msg.obj; @@ -199,6 +200,16 @@ final class ConnectionServiceAdapterServant { } break; } + case MSG_ADD_EXISTING_CONNECTION: { + SomeArgs args = (SomeArgs) msg.obj; + try { + mDelegate.addExistingConnection( + (String) args.arg1, (ParcelableConnection) args.arg2); + } finally { + args.recycle(); + } + break; + } } } }; @@ -252,8 +263,9 @@ final class ConnectionServiceAdapterServant { } @Override - public void setCallCapabilities(String connectionId, int callCapabilities) { - mHandler.obtainMessage(MSG_SET_CALL_CAPABILITIES, callCapabilities, 0, connectionId) + public void setConnectionCapabilities(String connectionId, int connectionCapabilities) { + mHandler.obtainMessage( + MSG_SET_CONNECTION_CAPABILITIES, connectionCapabilities, 0, connectionId) .sendToTarget(); } @@ -345,6 +357,15 @@ final class ConnectionServiceAdapterServant { args.arg2 = conferenceableConnectionIds; mHandler.obtainMessage(MSG_SET_CONFERENCEABLE_CONNECTIONS, args).sendToTarget(); } + + @Override + public final void addExistingConnection( + String connectionId, ParcelableConnection connection) { + SomeArgs args = SomeArgs.obtain(); + args.arg1 = connectionId; + args.arg2 = connection; + mHandler.obtainMessage(MSG_ADD_EXISTING_CONNECTION, args).sendToTarget(); + } }; public ConnectionServiceAdapterServant(IConnectionServiceAdapter delegate) { diff --git a/telecomm/java/android/telecom/DisconnectCause.java b/telecomm/java/android/telecom/DisconnectCause.java index 52c1284..130d676 100644 --- a/telecomm/java/android/telecom/DisconnectCause.java +++ b/telecomm/java/android/telecom/DisconnectCause.java @@ -26,9 +26,10 @@ import java.util.Objects; /** * Describes the cause of a disconnected call. This always includes a code describing the generic - * cause of the disconnect. Optionally, it may include a localized label and/or localized description - * to display to the user which is provided by the {@link ConnectionService}. It also may contain a - * reason for the the disconnect, which is intended for logging and not for display to the user. + * cause of the disconnect. Optionally, it may include a label and/or description to display to the + * user. It is the responsibility of the {@link ConnectionService} to provide localized versions of + * the label and description. It also may contain a reason for the disconnect, which is intended for + * logging and not for display to the user. * @hide */ @SystemApi @@ -60,6 +61,11 @@ public final class DisconnectCause implements Parcelable { public static final int RESTRICTED = 8; /** Disconnected for reason not described by other disconnect codes. */ public static final int OTHER = 9; + /** + * Disconnected because the connection manager did not support the call. The call will be tried + * again without a connection manager. See {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER}. + */ + public static final int CONNECTION_MANAGER_NOT_SUPPORTED = 10; private int mDisconnectCode; private CharSequence mDisconnectLabel; @@ -88,6 +94,7 @@ public final class DisconnectCause implements Parcelable { /** * Creates a new DisconnectCause. + * * @param label The localized label to show to the user to explain the disconnect. * @param code The code for the disconnect cause. * @param description The localized description to show to the user to explain the disconnect. @@ -221,7 +228,10 @@ public final class DisconnectCause implements Parcelable { @Override public String toString() { String code = ""; - switch (getCode()) { + switch (mDisconnectCode) { + case UNKNOWN: + code = "UNKNOWN"; + break; case ERROR: code = "ERROR"; break; @@ -231,6 +241,9 @@ public final class DisconnectCause implements Parcelable { case REMOTE: code = "REMOTE"; break; + case CANCELED: + code = "CANCELED"; + break; case MISSED: code = "MISSED"; break; @@ -246,9 +259,12 @@ public final class DisconnectCause implements Parcelable { case OTHER: code = "OTHER"; break; - case UNKNOWN: + case CONNECTION_MANAGER_NOT_SUPPORTED: + code = "CONNECTION_MANAGER_NOT_SUPPORTED"; + break; default: - code = "UNKNOWN"; + code = "invalid code: " + mDisconnectCode; + break; } String label = mDisconnectLabel == null ? "" : mDisconnectLabel.toString(); String description = mDisconnectDescription == null diff --git a/telecomm/java/android/telecom/GatewayInfo.java b/telecomm/java/android/telecom/GatewayInfo.java index 3efab0f..5b8e4ab 100644 --- a/telecomm/java/android/telecom/GatewayInfo.java +++ b/telecomm/java/android/telecom/GatewayInfo.java @@ -23,12 +23,16 @@ import android.os.Parcelable; import android.text.TextUtils; /** - * When calls are made, they may contain gateway information for services which route phone calls - * through their own service/numbers. The data consists of a number to call and the package name of - * the service. This data is used in two ways: + * Encapsulated gateway address information for outgoing call. When calls are made, the system + * provides a facility to specify two addresses for the call: one to display as the address being + * dialed and a separate (gateway) address to actually dial. Telecom provides this information to + * {@link ConnectionService}s when placing the call as an instance of {@code GatewayInfo}. + * <p> + * The data consists of an address to call, an address to display and the package name of the + * service. This data is used in two ways: * <ol> - * <li> Call the appropriate routing number - * <li> Display information about how the call is being routed to the user + * <li> Call the appropriate gateway address. + * <li> Display information about how the call is being routed to the user. * </ol> * @hide */ @@ -48,31 +52,39 @@ public class GatewayInfo implements Parcelable { } /** - * Package name of the gateway provider service. used to place the call with. + * Package name of the gateway provider service that provided the gateway information. + * This can be used to identify the gateway address source and to load an appropriate icon when + * displaying gateway information in the in-call UI. */ public String getGatewayProviderPackageName() { return mGatewayProviderPackageName; } /** - * Gateway provider address to use when actually placing the call. + * Returns the gateway address to dial when placing the call. */ public Uri getGatewayAddress() { return mGatewayAddress; } /** - * The actual call address that the user is trying to connect to via the gateway. + * Returns the address that the user is trying to connect to via the gateway. */ public Uri getOriginalAddress() { return mOriginalAddress; } + /** + * Indicates whether this {@code GatewayInfo} instance contains any data. A returned value of + * false indicates that no gateway number is being used for the call. + */ public boolean isEmpty() { return TextUtils.isEmpty(mGatewayProviderPackageName) || mGatewayAddress == null; } - /** Implement the Parcelable interface */ + /** + * The Parcelable interface. + * */ public static final Parcelable.Creator<GatewayInfo> CREATOR = new Parcelable.Creator<GatewayInfo> () { diff --git a/telecomm/java/android/telecom/IConferenceable.java b/telecomm/java/android/telecom/IConferenceable.java new file mode 100644 index 0000000..095d7cb --- /dev/null +++ b/telecomm/java/android/telecom/IConferenceable.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package android.telecom; + +import android.annotation.SystemApi; + +/** + * Interface used to identify entities with which another entity can participate in a conference + * call with. The {@link ConnectionService} implementation will only recognize + * {@link IConferenceable}s which are {@link Connection}s or {@link Conference}s. + * + * @hide + */ +@SystemApi +public interface IConferenceable { + +} diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java index 11da0f2..a85e84d 100644 --- a/telecomm/java/android/telecom/InCallService.java +++ b/telecomm/java/android/telecom/InCallService.java @@ -54,6 +54,7 @@ public abstract class InCallService extends Service { private static final int MSG_SET_POST_DIAL_WAIT = 4; private static final int MSG_ON_AUDIO_STATE_CHANGED = 5; private static final int MSG_BRING_TO_FOREGROUND = 6; + private static final int MSG_ON_CAN_ADD_CALL_CHANGED = 7; /** Default Handler used to consolidate binder method calls onto a single thread. */ private final Handler mHandler = new Handler(Looper.getMainLooper()) { @@ -91,6 +92,9 @@ public abstract class InCallService extends Service { case MSG_BRING_TO_FOREGROUND: mPhone.internalBringToForeground(msg.arg1 == 1); break; + case MSG_ON_CAN_ADD_CALL_CHANGED: + mPhone.internalSetCanAddCall(msg.arg1 == 1); + break; default: break; } @@ -136,6 +140,12 @@ public abstract class InCallService extends Service { public void bringToForeground(boolean showDialpad) { mHandler.obtainMessage(MSG_BRING_TO_FOREGROUND, showDialpad ? 1 : 0, 0).sendToTarget(); } + + @Override + public void onCanAddCallChanged(boolean canAddCall) { + mHandler.obtainMessage(MSG_ON_CAN_ADD_CALL_CHANGED, canAddCall ? 1 : 0, 0) + .sendToTarget(); + } } private Phone mPhone; diff --git a/telecomm/java/android/telecom/ParcelableConference.java b/telecomm/java/android/telecom/ParcelableConference.java index 97c709c..c4e11d6 100644 --- a/telecomm/java/android/telecom/ParcelableConference.java +++ b/telecomm/java/android/telecom/ParcelableConference.java @@ -30,17 +30,17 @@ public final class ParcelableConference implements Parcelable { private PhoneAccountHandle mPhoneAccount; private int mState; - private int mCapabilities; + private int mConnectionCapabilities; private List<String> mConnectionIds; public ParcelableConference( PhoneAccountHandle phoneAccount, int state, - int capabilities, + int connectionCapabilities, List<String> connectionIds) { mPhoneAccount = phoneAccount; mState = state; - mCapabilities = capabilities; + mConnectionCapabilities = connectionCapabilities; mConnectionIds = connectionIds; } @@ -52,7 +52,7 @@ public final class ParcelableConference implements Parcelable { .append(", state: ") .append(Connection.stateToString(mState)) .append(", capabilities: ") - .append(PhoneCapabilities.toString(mCapabilities)) + .append(Connection.capabilitiesToString(mConnectionCapabilities)) .append(", children: ") .append(mConnectionIds) .toString(); @@ -66,8 +66,8 @@ public final class ParcelableConference implements Parcelable { return mState; } - public int getCapabilities() { - return mCapabilities; + public int getConnectionCapabilities() { + return mConnectionCapabilities; } public List<String> getConnectionIds() { @@ -105,7 +105,7 @@ public final class ParcelableConference implements Parcelable { public void writeToParcel(Parcel destination, int flags) { destination.writeParcelable(mPhoneAccount, 0); destination.writeInt(mState); - destination.writeInt(mCapabilities); + destination.writeInt(mConnectionCapabilities); destination.writeList(mConnectionIds); } } diff --git a/telecomm/java/android/telecom/ParcelableConnection.java b/telecomm/java/android/telecom/ParcelableConnection.java index 9004448..552e250 100644 --- a/telecomm/java/android/telecom/ParcelableConnection.java +++ b/telecomm/java/android/telecom/ParcelableConnection.java @@ -34,7 +34,7 @@ import java.util.List; public final class ParcelableConnection implements Parcelable { private final PhoneAccountHandle mPhoneAccount; private final int mState; - private final int mCapabilities; + private final int mConnectionCapabilities; private final Uri mAddress; private final int mAddressPresentation; private final String mCallerDisplayName; @@ -65,7 +65,7 @@ public final class ParcelableConnection implements Parcelable { List<String> conferenceableConnectionIds) { mPhoneAccount = phoneAccount; mState = state; - mCapabilities = capabilities; + mConnectionCapabilities = capabilities; mAddress = address; mAddressPresentation = addressPresentation; mCallerDisplayName = callerDisplayName; @@ -88,8 +88,8 @@ public final class ParcelableConnection implements Parcelable { } // Bit mask of actions a call supports, values are defined in {@link CallCapabilities}. - public int getCapabilities() { - return mCapabilities; + public int getConnectionCapabilities() { + return mConnectionCapabilities; } public Uri getHandle() { @@ -144,7 +144,7 @@ public final class ParcelableConnection implements Parcelable { .append(", state:") .append(mState) .append(", capabilities:") - .append(PhoneCapabilities.toString(mCapabilities)) + .append(Connection.capabilitiesToString(mConnectionCapabilities)) .toString(); } @@ -205,7 +205,7 @@ public final class ParcelableConnection implements Parcelable { public void writeToParcel(Parcel destination, int flags) { destination.writeParcelable(mPhoneAccount, 0); destination.writeInt(mState); - destination.writeInt(mCapabilities); + destination.writeInt(mConnectionCapabilities); destination.writeParcelable(mAddress, 0); destination.writeInt(mAddressPresentation); destination.writeString(mCallerDisplayName); diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java index 5131790..6344181 100644 --- a/telecomm/java/android/telecom/Phone.java +++ b/telecomm/java/android/telecom/Phone.java @@ -74,6 +74,16 @@ public final class Phone { * @param call A newly removed {@code Call}. */ public void onCallRemoved(Phone phone, Call call) { } + + /** + * Called when the {@code Phone} ability to add more calls changes. If the phone cannot + * support more calls then {@code canAddCall} is set to {@code false}. If it can, then it + * is set to {@code true}. + * + * @param phone The {@code Phone} calling this method. + * @param canAddCall Indicates whether an additional call can be added. + */ + public void onCanAddCallChanged(Phone phone, boolean canAddCall) { } } // A Map allows us to track each Call by its Telecom-specified call ID @@ -92,6 +102,8 @@ public final class Phone { private final List<Listener> mListeners = new CopyOnWriteArrayList<>(); + private boolean mCanAddCall = true; + /** {@hide} */ Phone(InCallAdapter adapter) { mInCallAdapter = adapter; @@ -149,6 +161,14 @@ public final class Phone { fireBringToForeground(showDialpad); } + /** {@hide} */ + final void internalSetCanAddCall(boolean canAddCall) { + if (mCanAddCall != canAddCall) { + mCanAddCall = canAddCall; + fireCanAddCallChanged(canAddCall); + } + } + /** * Called to destroy the phone and cleanup any lingering calls. * @hide @@ -191,6 +211,15 @@ public final class Phone { } /** + * Returns if the {@code Phone} can support additional calls. + * + * @return Whether the phone supports adding more calls. + */ + public final boolean canAddCall() { + return mCanAddCall; + } + + /** * Sets the microphone mute state. When this request is honored, there will be change to * the {@link #getAudioState()}. * @@ -266,6 +295,12 @@ public final class Phone { } } + private void fireCanAddCallChanged(boolean canAddCall) { + for (Listener listener : mListeners) { + listener.onCanAddCallChanged(this, canAddCall); + } + } + private void checkCallTree(ParcelableCall parcelableCall) { if (parcelableCall.getParentCallId() != null && !mCallByTelecomCallId.containsKey(parcelableCall.getParentCallId())) { diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java index 67b6328..6bd6a2f 100644 --- a/telecomm/java/android/telecom/PhoneAccount.java +++ b/telecomm/java/android/telecom/PhoneAccount.java @@ -17,9 +17,14 @@ package android.telecom; import android.annotation.SystemApi; +import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Resources.NotFoundException; +import android.graphics.Bitmap; +import android.graphics.Color; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Parcel; @@ -33,8 +38,14 @@ import java.util.List; import java.util.MissingResourceException; /** - * Describes a distinct account, line of service or call placement method that the system - * can use to place phone calls. + * Represents a distinct method to place or receive a phone call. Apps which can place calls and + * want those calls to be integrated into the dialer and in-call UI should build an instance of + * this class and register it with the system using {@link TelecomManager#registerPhoneAccount}. + * <p> + * {@link TelecomManager} uses registered {@link PhoneAccount}s to present the user with + * alternative options when placing a phone call. When building a {@link PhoneAccount}, the app + * should supply a valid {@link PhoneAccountHandle} that references the {@link ConnectionService} + * implementation Telecom will use to interact with the app. * @hide */ @SystemApi @@ -59,7 +70,7 @@ public class PhoneAccount implements Parcelable { * traditional SIM-based telephony calls. This account will be treated as a distinct method * for placing calls alongside the traditional SIM-based telephony stack. This flag is * distinct from {@link #CAPABILITY_CONNECTION_MANAGER} in that it is not allowed to manage - * calls from or use the built-in telephony stack to place its calls. + * or place calls from the built-in telephony stack. * <p> * See {@link #getCapabilities} * <p> @@ -109,31 +120,53 @@ public class PhoneAccount implements Parcelable { public static final String SCHEME_SIP = "sip"; /** - * Indicating no color is set. + * Indicating no icon tint is set. */ - public static final int NO_COLOR = -1; + public static final int NO_ICON_TINT = 0; + + /** + * Indicating no hightlight color is set. + */ + public static final int NO_HIGHLIGHT_COLOR = 0; + + /** + * Indicating no resource ID is set. + */ + public static final int NO_RESOURCE_ID = -1; private final PhoneAccountHandle mAccountHandle; private final Uri mAddress; private final Uri mSubscriptionAddress; private final int mCapabilities; private final int mIconResId; - private final int mColor; + private final String mIconPackageName; + private final Bitmap mIconBitmap; + private final int mIconTint; + private final int mHighlightColor; private final CharSequence mLabel; private final CharSequence mShortDescription; private final List<String> mSupportedUriSchemes; + /** + * Helper class for creating a {@link PhoneAccount}. + */ public static class Builder { private PhoneAccountHandle mAccountHandle; private Uri mAddress; private Uri mSubscriptionAddress; private int mCapabilities; private int mIconResId; - private int mColor = NO_COLOR; + private String mIconPackageName; + private Bitmap mIconBitmap; + private int mIconTint = NO_ICON_TINT; + private int mHighlightColor = NO_HIGHLIGHT_COLOR; private CharSequence mLabel; private CharSequence mShortDescription; private List<String> mSupportedUriSchemes = new ArrayList<String>(); + /** + * Creates a builder with the specified {@link PhoneAccountHandle} and label. + */ public Builder(PhoneAccountHandle accountHandle, CharSequence label) { this.mAccountHandle = accountHandle; this.mLabel = label; @@ -151,37 +184,128 @@ public class PhoneAccount implements Parcelable { mSubscriptionAddress = phoneAccount.getSubscriptionAddress(); mCapabilities = phoneAccount.getCapabilities(); mIconResId = phoneAccount.getIconResId(); - mColor = phoneAccount.getColor(); + mIconPackageName = phoneAccount.getIconPackageName(); + mIconBitmap = phoneAccount.getIconBitmap(); + mIconTint = phoneAccount.getIconTint(); + mHighlightColor = phoneAccount.getHighlightColor(); mLabel = phoneAccount.getLabel(); mShortDescription = phoneAccount.getShortDescription(); mSupportedUriSchemes.addAll(phoneAccount.getSupportedUriSchemes()); } + /** + * Sets the address. See {@link PhoneAccount#getAddress}. + * + * @param value The address of the phone account. + * @return The builder. + */ public Builder setAddress(Uri value) { this.mAddress = value; return this; } + /** + * Sets the subscription address. See {@link PhoneAccount#getSubscriptionAddress}. + * + * @param value The subscription address. + * @return The builder. + */ public Builder setSubscriptionAddress(Uri value) { this.mSubscriptionAddress = value; return this; } + /** + * Sets the capabilities. See {@link PhoneAccount#getCapabilities}. + * + * @param value The capabilities to set. + * @return The builder. + */ public Builder setCapabilities(int value) { this.mCapabilities = value; return this; } - public Builder setIconResId(int value) { - this.mIconResId = value; + /** + * Sets the icon. See {@link PhoneAccount#createIconDrawable}. + * + * @param packageContext The package from which to load an icon. + * @param iconResId The resource in {@code iconPackageName} representing the icon. + * @return The builder. + */ + public Builder setIcon(Context packageContext, int iconResId) { + return setIcon(packageContext.getPackageName(), iconResId); + } + + /** + * Sets the icon. See {@link PhoneAccount#createIconDrawable}. + * + * @param iconPackageName The package from which to load an icon. + * @param iconResId The resource in {@code iconPackageName} representing the icon. + * @return The builder. + */ + public Builder setIcon(String iconPackageName, int iconResId) { + return setIcon(iconPackageName, iconResId, NO_ICON_TINT); + } + + /** + * Sets the icon. See {@link PhoneAccount#createIconDrawable}. + * + * @param packageContext The package from which to load an icon. + * @param iconResId The resource in {@code iconPackageName} representing the icon. + * @param iconTint A color with which to tint this icon. + * @return The builder. + */ + public Builder setIcon(Context packageContext, int iconResId, int iconTint) { + return setIcon(packageContext.getPackageName(), iconResId, iconTint); + } + + /** + * Sets the icon. See {@link PhoneAccount#createIconDrawable}. + * + * @param iconPackageName The package from which to load an icon. + * @param iconResId The resource in {@code iconPackageName} representing the icon. + * @param iconTint A color with which to tint this icon. + * @return The builder. + */ + public Builder setIcon(String iconPackageName, int iconResId, int iconTint) { + this.mIconPackageName = iconPackageName; + this.mIconResId = iconResId; + this.mIconTint = iconTint; return this; } - public Builder setColor(int value) { - this.mColor = value; + /** + * Sets the icon. See {@link PhoneAccount#createIconDrawable}. + * + * @param iconBitmap The icon bitmap. + * @return The builder. + */ + public Builder setIcon(Bitmap iconBitmap) { + this.mIconBitmap = iconBitmap; + this.mIconPackageName = null; + this.mIconResId = NO_RESOURCE_ID; + this.mIconTint = NO_ICON_TINT; return this; } + /** + * Sets the highlight color. See {@link PhoneAccount#getHighlightColor}. + * + * @param value The highlight color. + * @return The builder. + */ + public Builder setHighlightColor(int value) { + this.mHighlightColor = value; + return this; + } + + /** + * Sets the short description. See {@link PhoneAccount#getShortDescription}. + * + * @param value The short description. + * @return The builder. + */ public Builder setShortDescription(CharSequence value) { this.mShortDescription = value; return this; @@ -191,7 +315,7 @@ public class PhoneAccount implements Parcelable { * Specifies an additional URI scheme supported by the {@link PhoneAccount}. * * @param uriScheme The URI scheme. - * @return The Builder. + * @return The builder. * @hide */ public Builder addSupportedUriScheme(String uriScheme) { @@ -205,7 +329,7 @@ public class PhoneAccount implements Parcelable { * Specifies the URI schemes supported by the {@link PhoneAccount}. * * @param uriSchemes The URI schemes. - * @return The Builder. + * @return The builder. */ public Builder setSupportedUriSchemes(List<String> uriSchemes) { mSupportedUriSchemes.clear(); @@ -235,7 +359,10 @@ public class PhoneAccount implements Parcelable { mSubscriptionAddress, mCapabilities, mIconResId, - mColor, + mIconPackageName, + mIconBitmap, + mIconTint, + mHighlightColor, mLabel, mShortDescription, mSupportedUriSchemes); @@ -248,7 +375,10 @@ public class PhoneAccount implements Parcelable { Uri subscriptionAddress, int capabilities, int iconResId, - int color, + String iconPackageName, + Bitmap iconBitmap, + int iconTint, + int highlightColor, CharSequence label, CharSequence shortDescription, List<String> supportedUriSchemes) { @@ -257,7 +387,10 @@ public class PhoneAccount implements Parcelable { mSubscriptionAddress = subscriptionAddress; mCapabilities = capabilities; mIconResId = iconResId; - mColor = color; + mIconPackageName = iconPackageName; + mIconBitmap = iconBitmap; + mIconTint = iconTint; + mHighlightColor = highlightColor; mLabel = label; mShortDescription = shortDescription; mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes); @@ -302,6 +435,9 @@ public class PhoneAccount implements Parcelable { * The raw callback number used for this {@code PhoneAccount}, as distinct from * {@link #getAddress()}. For the majority of {@code PhoneAccount}s this should be registered * as {@code null}. It is used by the system for SIM-based {@code PhoneAccount} registration + * where {@link android.telephony.TelephonyManager#setLine1NumberForDisplay(String, String)} + * has been used to alter the callback number. + * <p> * * @return The subscription number, suitable for display to the user. */ @@ -379,6 +515,12 @@ public class PhoneAccount implements Parcelable { /** * The icon resource ID for the icon of this {@code PhoneAccount}. + * <p> + * Creators of a {@code PhoneAccount} who possess the icon in static resources should prefer + * this method of indicating the icon rather than using {@link #getIconBitmap()}, since it + * leads to less resource usage. + * <p> + * Clients wishing to display a {@code PhoneAccount} should use {@link #createIconDrawable(Context)}. * * @return A resource ID. */ @@ -387,39 +529,85 @@ public class PhoneAccount implements Parcelable { } /** - * A highlight color to use in displaying information about this {@code PhoneAccount}. + * The package name from which to load the icon of this {@code PhoneAccount}. + * <p> + * If this property is {@code null}, the resource {@link #getIconResId()} will be loaded from + * the package in the {@link ComponentName} of the {@link #getAccountHandle()}. + * <p> + * Clients wishing to display a {@code PhoneAccount} should use {@link #createIconDrawable(Context)}. + * + * @return A package name. + */ + public String getIconPackageName() { + return mIconPackageName; + } + + /** + * A tint to apply to the icon of this {@code PhoneAccount}. * * @return A hexadecimal color value. */ - public int getColor() { - return mColor; + public int getIconTint() { + return mIconTint; } /** - * An icon to represent this {@code PhoneAccount} in a user interface. + * A literal icon bitmap to represent this {@code PhoneAccount} in a user interface. + * <p> + * If this property is specified, it is to be considered the preferred icon. Otherwise, the + * resource specified by {@link #getIconResId()} should be used. + * <p> + * Clients wishing to display a {@code PhoneAccount} should use + * {@link #createIconDrawable(Context)}. * - * @return An icon for this {@code PhoneAccount}. + * @return A bitmap. + */ + public Bitmap getIconBitmap() { + return mIconBitmap; + } + + /** + * A highlight color to use in displaying information about this {@code PhoneAccount}. + * + * @return A hexadecimal color value. */ - public Drawable getIcon(Context context) { - return getIcon(context, mIconResId); + public int getHighlightColor() { + return mHighlightColor; } - private Drawable getIcon(Context context, int resId) { - Context packageContext; - try { - packageContext = context.createPackageContext( - mAccountHandle.getComponentName().getPackageName(), 0); - } catch (PackageManager.NameNotFoundException e) { - Log.w(this, "Cannot find package %s", mAccountHandle.getComponentName().getPackageName()); - return null; + /** + * Builds and returns an icon {@code Drawable} to represent this {@code PhoneAccount} in a user + * interface. Uses the properties {@link #getIconResId()}, {@link #getIconPackageName()}, and + * {@link #getIconBitmap()} as necessary. + * + * @param context A {@code Context} to use for loading {@code Drawable}s. + * + * @return An icon for this {@code PhoneAccount}. + */ + public Drawable createIconDrawable(Context context) { + if (mIconBitmap != null) { + return new BitmapDrawable(context.getResources(), mIconBitmap); } - try { - return packageContext.getDrawable(resId); - } catch (NotFoundException|MissingResourceException e) { - Log.e(this, e, "Cannot find icon %d in package %s", - resId, mAccountHandle.getComponentName().getPackageName()); - return null; + + if (mIconResId != 0) { + try { + Context packageContext = context.createPackageContext(mIconPackageName, 0); + try { + Drawable iconDrawable = packageContext.getDrawable(mIconResId); + if (mIconTint != NO_ICON_TINT) { + iconDrawable.setTint(mIconTint); + } + return iconDrawable; + } catch (NotFoundException | MissingResourceException e) { + Log.e(this, e, "Cannot find icon %d in package %s", + mIconResId, mIconPackageName); + } + } catch (PackageManager.NameNotFoundException e) { + Log.w(this, "Cannot find package %s", mIconPackageName); + } } + + return new ColorDrawable(Color.TRANSPARENT); } // @@ -433,15 +621,38 @@ public class PhoneAccount implements Parcelable { @Override public void writeToParcel(Parcel out, int flags) { - out.writeParcelable(mAccountHandle, 0); - out.writeParcelable(mAddress, 0); - out.writeParcelable(mSubscriptionAddress, 0); + if (mAccountHandle == null) { + out.writeInt(0); + } else { + out.writeInt(1); + mAccountHandle.writeToParcel(out, flags); + } + if (mAddress == null) { + out.writeInt(0); + } else { + out.writeInt(1); + mAddress.writeToParcel(out, flags); + } + if (mSubscriptionAddress == null) { + out.writeInt(0); + } else { + out.writeInt(1); + mSubscriptionAddress.writeToParcel(out, flags); + } out.writeInt(mCapabilities); out.writeInt(mIconResId); - out.writeInt(mColor); + out.writeString(mIconPackageName); + if (mIconBitmap == null) { + out.writeInt(0); + } else { + out.writeInt(1); + mIconBitmap.writeToParcel(out, flags); + } + out.writeInt(mIconTint); + out.writeInt(mHighlightColor); out.writeCharSequence(mLabel); out.writeCharSequence(mShortDescription); - out.writeList(mSupportedUriSchemes); + out.writeStringList(mSupportedUriSchemes); } public static final Creator<PhoneAccount> CREATOR @@ -458,19 +669,48 @@ public class PhoneAccount implements Parcelable { }; private PhoneAccount(Parcel in) { - ClassLoader classLoader = PhoneAccount.class.getClassLoader(); - - mAccountHandle = in.readParcelable(getClass().getClassLoader()); - mAddress = in.readParcelable(getClass().getClassLoader()); - mSubscriptionAddress = in.readParcelable(getClass().getClassLoader()); + if (in.readInt() > 0) { + mAccountHandle = PhoneAccountHandle.CREATOR.createFromParcel(in); + } else { + mAccountHandle = null; + } + if (in.readInt() > 0) { + mAddress = Uri.CREATOR.createFromParcel(in); + } else { + mAddress = null; + } + if (in.readInt() > 0) { + mSubscriptionAddress = Uri.CREATOR.createFromParcel(in); + } else { + mSubscriptionAddress = null; + } mCapabilities = in.readInt(); mIconResId = in.readInt(); - mColor = in.readInt(); + mIconPackageName = in.readString(); + if (in.readInt() > 0) { + mIconBitmap = Bitmap.CREATOR.createFromParcel(in); + } else { + mIconBitmap = null; + } + mIconTint = in.readInt(); + mHighlightColor = in.readInt(); mLabel = in.readCharSequence(); mShortDescription = in.readCharSequence(); + mSupportedUriSchemes = Collections.unmodifiableList(in.createStringArrayList()); + } - List<String> supportedUriSchemes = new ArrayList<>(); - in.readList(supportedUriSchemes, classLoader); - mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes); + @Override + public String toString() { + StringBuilder sb = new StringBuilder().append("[PhoneAccount: ") + .append(mAccountHandle) + .append(" Capabilities: ") + .append(mCapabilities) + .append(" Schemes: "); + for (String scheme : mSupportedUriSchemes) { + sb.append(scheme) + .append(" "); + } + sb.append("]"); + return sb.toString(); } } diff --git a/telecomm/java/android/telecom/PhoneAccountHandle.java b/telecomm/java/android/telecom/PhoneAccountHandle.java index 652befe5..7bcf147 100644 --- a/telecomm/java/android/telecom/PhoneAccountHandle.java +++ b/telecomm/java/android/telecom/PhoneAccountHandle.java @@ -24,7 +24,16 @@ import android.os.Parcelable; import java.util.Objects; /** - * The unique identifier for a {@link PhoneAccount}. + * The unique identifier for a {@link PhoneAccount}. A {@code PhoneAccountHandle} is made of two + * parts: + * <ul> + * <li>The component name of the associated {@link ConnectionService}.</li> + * <li>A string identifier that is unique across {@code PhoneAccountHandle}s with the same + * component name.</li> + * </ul> + * + * See {@link PhoneAccount}, + * {@link TelecomManager#registerPhoneAccount TelecomManager.registerPhoneAccount}. * @hide */ @SystemApi @@ -74,9 +83,11 @@ public class PhoneAccountHandle implements Parcelable { @Override public String toString() { + // Note: Log.pii called for mId as it can contain personally identifying phone account + // information such as SIP account IDs. return new StringBuilder().append(mComponentName) .append(", ") - .append(mId) + .append(Log.pii(mId)) .toString(); } diff --git a/telecomm/java/android/telecom/PhoneCapabilities.java b/telecomm/java/android/telecom/PhoneCapabilities.java deleted file mode 100644 index de2abcb..0000000 --- a/telecomm/java/android/telecom/PhoneCapabilities.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2014, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.telecom; - -import android.annotation.SystemApi; - -/** - * Defines capabilities a phone call can support, such as conference calling and video telephony. - * Also defines properties of a phone call, such as whether it is using VoLTE technology. - * @hide - */ -@SystemApi -public final class PhoneCapabilities { - /** Call can currently be put on hold or unheld. */ - public static final int HOLD = 0x00000001; - - /** Call supports the hold feature. */ - public static final int SUPPORT_HOLD = 0x00000002; - - /** - * Calls within a conference can be merged. Some connection services create a conference call - * only after two calls have been merged. However, a conference call can also be added the - * moment there are more than one call. CDMA calls are implemented in this way because the call - * actions are more limited when more than one call exists. This flag allows merge to be exposed - * as a capability on the conference call instead of individual calls. - */ - public static final int MERGE_CONFERENCE = 0x00000004; - - /** Calls withing a conference can be swapped between foreground and background. */ - public static final int SWAP_CONFERENCE = 0x00000008; - - /** Call currently supports adding another call to this one. */ - public static final int ADD_CALL = 0x00000010; - - /** Call supports responding via text option. */ - public static final int RESPOND_VIA_TEXT = 0x00000020; - - /** Call can be muted. */ - public static final int MUTE = 0x00000040; - - /** - * Call supports conference call management. This capability only applies to conference calls - * which can have other calls as children. - */ - public static final int MANAGE_CONFERENCE = 0x00000080; - - /** - * Local device supports video telephony. - * @hide - */ - public static final int SUPPORTS_VT_LOCAL = 0x00000100; - - /** - * Remote device supports video telephony. - * @hide - */ - public static final int SUPPORTS_VT_REMOTE = 0x00000200; - - /** - * Call is using voice over LTE. - * @hide - */ - public static final int VoLTE = 0x00000400; - - /** - * Call is using voice over WIFI. - * @hide - */ - public static final int VoWIFI = 0x00000800; - - /** - * Call is able to be separated from its parent {@code Conference}, if any. - */ - public static final int SEPARATE_FROM_CONFERENCE = 0x00001000; - - /** - * Call is able to be individually disconnected when in a {@code Conference}. - */ - public static final int DISCONNECT_FROM_CONFERENCE = 0x00002000; - - public static final int ALL = HOLD | SUPPORT_HOLD | MERGE_CONFERENCE | SWAP_CONFERENCE - | ADD_CALL | RESPOND_VIA_TEXT | MUTE | MANAGE_CONFERENCE | SEPARATE_FROM_CONFERENCE - | DISCONNECT_FROM_CONFERENCE; - - public static String toString(int capabilities) { - StringBuilder builder = new StringBuilder(); - builder.append("[Capabilities:"); - if ((capabilities & HOLD) != 0) { - builder.append(" HOLD"); - } - if ((capabilities & SUPPORT_HOLD) != 0) { - builder.append(" SUPPORT_HOLD"); - } - if ((capabilities & MERGE_CONFERENCE) != 0) { - builder.append(" MERGE_CONFERENCE"); - } - if ((capabilities & SWAP_CONFERENCE) != 0) { - builder.append(" SWAP_CONFERENCE"); - } - if ((capabilities & ADD_CALL) != 0) { - builder.append(" ADD_CALL"); - } - if ((capabilities & RESPOND_VIA_TEXT) != 0) { - builder.append(" RESPOND_VIA_TEXT"); - } - if ((capabilities & MUTE) != 0) { - builder.append(" MUTE"); - } - if ((capabilities & MANAGE_CONFERENCE) != 0) { - builder.append(" MANAGE_CONFERENCE"); - } - if ((capabilities & SUPPORTS_VT_LOCAL) != 0) { - builder.append(" SUPPORTS_VT_LOCAL"); - } - if ((capabilities & SUPPORTS_VT_REMOTE) != 0) { - builder.append(" SUPPORTS_VT_REMOTE"); - } - if ((capabilities & VoLTE) != 0) { - builder.append(" VoLTE"); - } - if ((capabilities & VoWIFI) != 0) { - builder.append(" VoWIFI"); - } - builder.append("]"); - return builder.toString(); - } - - private PhoneCapabilities() {} -} diff --git a/telecomm/java/android/telecom/RemoteConference.java b/telecomm/java/android/telecom/RemoteConference.java index b548274..a8879ae 100644 --- a/telecomm/java/android/telecom/RemoteConference.java +++ b/telecomm/java/android/telecom/RemoteConference.java @@ -40,7 +40,9 @@ public final class RemoteConference { public void onDisconnected(RemoteConference conference, DisconnectCause disconnectCause) {} public void onConnectionAdded(RemoteConference conference, RemoteConnection connection) {} public void onConnectionRemoved(RemoteConference conference, RemoteConnection connection) {} - public void onCapabilitiesChanged(RemoteConference conference, int capabilities) {} + public void onConnectionCapabilitiesChanged( + RemoteConference conference, + int connectionCapabilities) {} public void onConferenceableConnectionsChanged( RemoteConference conference, List<RemoteConnection> conferenceableConnections) {} @@ -60,7 +62,7 @@ public final class RemoteConference { private int mState = Connection.STATE_NEW; private DisconnectCause mDisconnectCause; - private int mCallCapabilities; + private int mConnectionCapabilities; /** {@hide} */ RemoteConference(String id, IConnectionService connectionService) { @@ -125,11 +127,11 @@ public final class RemoteConference { } /** {@hide} */ - void setCallCapabilities(int capabilities) { - if (mCallCapabilities != capabilities) { - mCallCapabilities = capabilities; + void setConnectionCapabilities(int connectionCapabilities) { + if (mConnectionCapabilities != connectionCapabilities) { + mConnectionCapabilities = connectionCapabilities; for (Callback c : mCallbacks) { - c.onCapabilitiesChanged(this, mCallCapabilities); + c.onConnectionCapabilitiesChanged(this, mConnectionCapabilities); } } } @@ -162,8 +164,13 @@ public final class RemoteConference { return mState; } - public final int getCallCapabilities() { - return mCallCapabilities; + /** @hide */ + @Deprecated public final int getCallCapabilities() { + return getConnectionCapabilities(); + } + + public final int getConnectionCapabilities() { + return mConnectionCapabilities; } public void disconnect() { diff --git a/telecomm/java/android/telecom/RemoteConnection.java b/telecomm/java/android/telecom/RemoteConnection.java index 4a89692..95cc387 100644 --- a/telecomm/java/android/telecom/RemoteConnection.java +++ b/telecomm/java/android/telecom/RemoteConnection.java @@ -73,14 +73,21 @@ public final class RemoteConnection { */ public void onRingbackRequested(RemoteConnection connection, boolean ringback) {} + /** @hide */ + @Deprecated public void onCallCapabilitiesChanged( + RemoteConnection connection, + int callCapabilities) {} + /** * Indicates that the call capabilities of this {@code RemoteConnection} have changed. - * See {@link #getCallCapabilities()}. + * See {@link #getConnectionCapabilities()}. * * @param connection The {@code RemoteConnection} invoking this method. - * @param callCapabilities The new call capabilities of the {@code RemoteConnection}. + * @param connectionCapabilities The new capabilities of the {@code RemoteConnection}. */ - public void onCallCapabilitiesChanged(RemoteConnection connection, int callCapabilities) {} + public void onConnectionCapabilitiesChanged( + RemoteConnection connection, + int connectionCapabilities) {} /** * Invoked when the post-dial sequence in the outgoing {@code Connection} has reached a @@ -385,7 +392,7 @@ public final class RemoteConnection { private DisconnectCause mDisconnectCause; private boolean mRingbackRequested; private boolean mConnected; - private int mCallCapabilities; + private int mConnectionCapabilities; private int mVideoState; private VideoProvider mVideoProvider; private boolean mIsVoipAudioMode; @@ -410,6 +417,29 @@ public final class RemoteConnection { } /** + * @hide + */ + RemoteConnection(String callId, IConnectionService connectionService, + ParcelableConnection connection) { + mConnectionId = callId; + mConnectionService = connectionService; + mConnected = true; + mState = connection.getState(); + mDisconnectCause = connection.getDisconnectCause(); + mRingbackRequested = connection.isRingbackRequested(); + mConnectionCapabilities = connection.getConnectionCapabilities(); + mVideoState = connection.getVideoState(); + mVideoProvider = new RemoteConnection.VideoProvider(connection.getVideoProvider()); + mIsVoipAudioMode = connection.getIsVoipAudioMode(); + mStatusHints = connection.getStatusHints(); + mAddress = connection.getHandle(); + mAddressPresentation = connection.getHandlePresentation(); + mCallerDisplayName = connection.getCallerDisplayName(); + mCallerDisplayNamePresentation = connection.getCallerDisplayNamePresentation(); + mConference = null; + } + + /** * Create a RemoteConnection which is used for failed connections. Note that using it for any * "real" purpose will almost certainly fail. Callers should note the failure and act * accordingly (moving on to another RemoteConnection, for example) @@ -418,7 +448,7 @@ public final class RemoteConnection { * @hide */ RemoteConnection(DisconnectCause disconnectCause) { - this("NULL", null, null); + mConnectionId = "NULL"; mConnected = false; mState = Connection.STATE_DISCONNECTED; mDisconnectCause = disconnectCause; @@ -454,23 +484,29 @@ public final class RemoteConnection { } /** + * Obtains the reason why this {@code RemoteConnection} may have been disconnected. + * * @return For a {@link Connection#STATE_DISCONNECTED} {@code RemoteConnection}, the - * disconnect cause expressed as a code chosen from among those declared in - * {@link DisconnectCause}. + * disconnect cause expressed as a code chosen from among those declared in + * {@link DisconnectCause}. */ public DisconnectCause getDisconnectCause() { return mDisconnectCause; } /** + * Obtains the capabilities of this {@code RemoteConnection}. + * * @return A bitmask of the capabilities of the {@code RemoteConnection}, as defined in - * {@link PhoneCapabilities}. + * the {@code CAPABILITY_*} constants in class {@link Connection}. */ - public int getCallCapabilities() { - return mCallCapabilities; + public int getConnectionCapabilities() { + return mConnectionCapabilities; } /** + * Determines if the audio mode of this {@code RemoteConnection} is VOIP. + * * @return {@code true} if the {@code RemoteConnection}'s current audio mode is VOIP. */ public boolean isVoipAudioMode() { @@ -478,30 +514,38 @@ public final class RemoteConnection { } /** + * Obtains status hints pertaining to this {@code RemoteConnection}. + * * @return The current {@link StatusHints} of this {@code RemoteConnection}, - * or {@code null} if none have been set. + * or {@code null} if none have been set. */ public StatusHints getStatusHints() { return mStatusHints; } /** - * @return The address (e.g., phone number) to which the {@code RemoteConnection} is currently - * connected. + * Obtains the address of this {@code RemoteConnection}. + * + * @return The address (e.g., phone number) to which the {@code RemoteConnection} + * is currently connected. */ public Uri getAddress() { return mAddress; } /** - * @return The presentation requirements for the address. See {@link TelecomManager} for valid - * values. + * Obtains the presentation requirements for the address of this {@code RemoteConnection}. + * + * @return The presentation requirements for the address. See + * {@link TelecomManager} for valid values. */ public int getAddressPresentation() { return mAddressPresentation; } /** + * Obtains the display name for this {@code RemoteConnection}'s caller. + * * @return The display name for the caller. */ public CharSequence getCallerDisplayName() { @@ -509,16 +553,20 @@ public final class RemoteConnection { } /** + * Obtains the presentation requirements for this {@code RemoteConnection}'s + * caller's display name. + * * @return The presentation requirements for the caller display name. See - * {@link TelecomManager} for valid values. + * {@link TelecomManager} for valid values. */ public int getCallerDisplayNamePresentation() { return mCallerDisplayNamePresentation; } /** - * @return The video state of the {@code RemoteConnection}. See - * {@link VideoProfile.VideoState}. + * Obtains the video state of this {@code RemoteConnection}. + * + * @return The video state of the {@code RemoteConnection}. See {@link VideoProfile.VideoState}. * @hide */ public int getVideoState() { @@ -526,6 +574,8 @@ public final class RemoteConnection { } /** + * Obtains the video provider of this {@code RemoteConnection}. + * * @return The video provider associated with this {@code RemoteConnection}. * @hide */ @@ -534,8 +584,10 @@ public final class RemoteConnection { } /** + * Determines whether this {@code RemoteConnection} is requesting ringback. + * * @return Whether the {@code RemoteConnection} is requesting that the framework play a - * ringback tone on its behalf. + * ringback tone on its behalf. */ public boolean isRingbackRequested() { return false; @@ -777,10 +829,11 @@ public final class RemoteConnection { /** * @hide */ - void setCallCapabilities(int callCapabilities) { - mCallCapabilities = callCapabilities; + void setConnectionCapabilities(int connectionCapabilities) { + mConnectionCapabilities = connectionCapabilities; for (Callback c : mCallbacks) { - c.onCallCapabilitiesChanged(this, callCapabilities); + c.onConnectionCapabilitiesChanged(this, connectionCapabilities); + c.onCallCapabilitiesChanged(this, connectionCapabilities); } } diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java index af4ee22..906ecaa 100644 --- a/telecomm/java/android/telecom/RemoteConnectionService.java +++ b/telecomm/java/android/telecom/RemoteConnectionService.java @@ -41,8 +41,9 @@ import java.util.UUID; */ final class RemoteConnectionService { + // Note: Casting null to avoid ambiguous constructor reference. private static final RemoteConnection NULL_CONNECTION = - new RemoteConnection("NULL", null, null); + new RemoteConnection("NULL", null, (ConnectionRequest) null); private static final RemoteConference NULL_CONFERENCE = new RemoteConference("NULL", null); @@ -58,7 +59,7 @@ final class RemoteConnectionService { if (connection != NULL_CONNECTION && mPendingConnections.contains(connection)) { mPendingConnections.remove(connection); // Unconditionally initialize the connection ... - connection.setCallCapabilities(parcel.getCapabilities()); + connection.setConnectionCapabilities(parcel.getConnectionCapabilities()); connection.setAddress( parcel.getHandle(), parcel.getHandlePresentation()); connection.setCallerDisplayName( @@ -138,13 +139,13 @@ final class RemoteConnectionService { } @Override - public void setCallCapabilities(String callId, int callCapabilities) { + public void setConnectionCapabilities(String callId, int connectionCapabilities) { if (mConnectionById.containsKey(callId)) { - findConnectionForAction(callId, "setCallCapabilities") - .setCallCapabilities(callCapabilities); + findConnectionForAction(callId, "setConnectionCapabilities") + .setConnectionCapabilities(connectionCapabilities); } else { - findConferenceForAction(callId, "setCallCapabilities") - .setCallCapabilities(callCapabilities); + findConferenceForAction(callId, "setConnectionCapabilities") + .setConnectionCapabilities(connectionCapabilities); } } @@ -191,7 +192,7 @@ final class RemoteConnectionService { } conference.setState(parcel.getState()); - conference.setCallCapabilities(parcel.getCapabilities()); + conference.setConnectionCapabilities(parcel.getConnectionCapabilities()); mConferenceById.put(callId, conference); conference.registerCallback(new RemoteConference.Callback() { @Override @@ -286,6 +287,15 @@ final class RemoteConnectionService { .setConferenceableConnections(conferenceable); } } + + @Override + public void addExistingConnection(String callId, ParcelableConnection connection) { + // TODO: add contents of this method + RemoteConnection remoteConnction = new RemoteConnection(callId, + mOutgoingConnectionServiceRpc, connection); + + mOurConnectionServiceImpl.addRemoteExistingConnection(remoteConnction); + } }; private final ConnectionServiceAdapterServant mServant = diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java index e87615e..2a3d7ab 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -17,10 +17,12 @@ package android.telecom; import android.annotation.SystemApi; import android.content.ComponentName; import android.content.Context; +import android.net.Uri; import android.os.Bundle; import android.os.RemoteException; import android.os.ServiceManager; import android.telephony.TelephonyManager; +import android.text.TextUtils; import android.util.Log; import com.android.internal.telecom.ITelecomService; @@ -30,8 +32,16 @@ import java.util.Collections; import java.util.List; /** - * Provides access to Telecom-related functionality. - * TODO: Move this all into PhoneManager. + * Provides access to information about active calls and registration/call-management functionality. + * Apps can use methods in this class to determine the current call state. + * <p> + * Apps do not instantiate this class directly; instead, they retrieve a reference to an instance + * through {@link Context#getSystemService Context.getSystemService(Context.TELECOM_SERVICE)}. + * <p> + * Note that access to some telecom information is permission-protected. Your app cannot access the + * protected information or gain access to protected functionality unless it has the appropriate + * permissions declared in its manifest file. Where permissions apply, they are noted in the method + * descriptions. */ public class TelecomManager { @@ -62,6 +72,7 @@ public class TelecomManager { * {@link android.telecom.ConnectionService}. * @hide */ + @SystemApi public static final String ACTION_CONNECTION_SERVICE_CONFIGURE = "android.telecom.action.CONNECTION_SERVICE_CONFIGURE"; @@ -76,6 +87,7 @@ public class TelecomManager { * {@link PhoneAccount} preferences. * @hide */ + @SystemApi public static final String ACTION_CHANGE_PHONE_ACCOUNTS = "android.telecom.action.CHANGE_PHONE_ACCOUNTS"; @@ -107,6 +119,7 @@ public class TelecomManager { * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}. * @hide */ + @SystemApi public static final String EXTRA_PHONE_ACCOUNT_HANDLE = "android.telecom.extra.PHONE_ACCOUNT_HANDLE"; @@ -117,6 +130,7 @@ public class TelecomManager { * * @hide */ + @SystemApi public static final String EXTRA_INCOMING_CALL_EXTRAS = "android.telecom.extra.INCOMING_CALL_EXTRAS"; @@ -128,6 +142,7 @@ public class TelecomManager { * * @hide */ + @SystemApi public static final String EXTRA_OUTGOING_CALL_EXTRAS = "android.telecom.extra.OUTGOING_CALL_EXTRAS"; @@ -156,6 +171,7 @@ public class TelecomManager { * containing the component name of the associated connection service. * @hide */ + @SystemApi public static final String EXTRA_CONNECTION_SERVICE = "android.telecom.extra.CONNECTION_SERVICE"; @@ -192,6 +208,7 @@ public class TelecomManager { * user's expected caller ID. * @hide */ + @SystemApi public static final String EXTRA_CALL_BACK_NUMBER = "android.telecom.extra.CALL_BACK_NUMBER"; /** @@ -332,9 +349,9 @@ public class TelecomManager { * @param uriScheme The URI scheme. * @return The {@link PhoneAccountHandle} corresponding to the user-chosen default for outgoing * phone calls for a specified URI scheme. - * * @hide */ + @SystemApi public PhoneAccountHandle getDefaultOutgoingPhoneAccount(String uriScheme) { try { if (isServiceConnected()) { @@ -439,11 +456,22 @@ public class TelecomManager { * @return The phone account handle of the current connection manager. * @hide */ + @SystemApi public PhoneAccountHandle getConnectionManager() { return getSimCallManager(); } /** + * Returns the list of registered SIM call managers. + * @return List of registered SIM call managers. + * @hide + */ + @SystemApi + public List<PhoneAccountHandle> getRegisteredConnectionManagers() { + return getSimCallManagers(); + } + + /** * Returns a list of the {@link PhoneAccountHandle}s which can be used to make and receive phone * calls which support the specified URI scheme. * <P> @@ -454,9 +482,9 @@ public class TelecomManager { * * @param uriScheme The URI scheme. * @return A list of {@code PhoneAccountHandle} objects supporting the URI scheme. - * * @hide */ + @SystemApi public List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(String uriScheme) { try { if (isServiceConnected()) { @@ -497,6 +525,7 @@ public class TelecomManager { * otherwise. * @hide */ + @SystemApi public boolean hasMultipleCallCapableAccounts() { return getCallCapablePhoneAccounts().size() > 1; } @@ -507,6 +536,7 @@ public class TelecomManager { * @return A list of {@code PhoneAccountHandle} objects. * @hide */ + @SystemApi public List<PhoneAccountHandle> getPhoneAccountsForPackage() { try { if (isServiceConnected()) { @@ -526,6 +556,7 @@ public class TelecomManager { * @return The {@link PhoneAccount} object. * @hide */ + @SystemApi public PhoneAccount getPhoneAccount(PhoneAccountHandle account) { try { if (isServiceConnected()) { @@ -592,9 +623,19 @@ public class TelecomManager { } /** - * Register a {@link PhoneAccount} for use by the system. + * Register a {@link PhoneAccount} for use by the system. When registering + * {@link PhoneAccount}s, existing registrations will be overwritten if the + * {@link PhoneAccountHandle} matches that of a {@link PhoneAccount} which is already + * registered. Once registered, the {@link PhoneAccount} is listed to the user as an option + * when placing calls. The user may still need to enable the {@link PhoneAccount} within + * the phone app settings before the account is usable. + * <p> + * A {@link SecurityException} will be thrown if an app tries to register a + * {@link PhoneAccountHandle} where the package name specified within + * {@link PhoneAccountHandle#getComponentName()} does not match the package name of the app. * * @param account The complete {@link PhoneAccount}. + * * @hide */ @SystemApi @@ -641,6 +682,20 @@ public class TelecomManager { } /** + * Remove all Accounts that belong to the specified package from the system. + * @hide + */ + public void clearAccountsForPackage(String packageName) { + try { + if (isServiceConnected() && !TextUtils.isEmpty(packageName)) { + getTelecomService().clearAccounts(packageName); + } + } catch (RemoteException e) { + Log.e(TAG, "Error calling ITelecomService#clearAccountsForPackage()", e); + } + } + + /** * @hide */ @SystemApi @@ -683,7 +738,6 @@ public class TelecomManager { * Requires permission: {@link android.Manifest.permission#READ_PHONE_STATE} * </p> */ - @SystemApi public boolean isInCall() { try { if (isServiceConnected()) { @@ -701,6 +755,11 @@ public class TelecomManager { * {@link TelephonyManager#CALL_STATE_RINGING} * {@link TelephonyManager#CALL_STATE_OFFHOOK} * {@link TelephonyManager#CALL_STATE_IDLE} + * + * Note that this API does not require the + * {@link android.Manifest.permission#READ_PHONE_STATE} permission. This is intentional, to + * preserve the behavior of {@link TelephonyManager#getCallState()}, which also did not require + * the permission. * @hide */ @SystemApi @@ -875,6 +934,7 @@ public class TelecomManager { * Processes the specified dial string as an MMI code. * MMI codes are any sequence of characters entered into the dialpad that contain a "*" or "#". * Some of these sequences launch special behavior through handled by Telephony. + * This method uses the default subscription. * <p> * Requires that the method-caller be set as the system dialer app. * </p> @@ -895,6 +955,52 @@ public class TelecomManager { } /** + * Processes the specified dial string as an MMI code. + * MMI codes are any sequence of characters entered into the dialpad that contain a "*" or "#". + * Some of these sequences launch special behavior through handled by Telephony. + * <p> + * Requires that the method-caller be set as the system dialer app. + * </p> + * + * @param accountHandle The handle for the account the MMI code should apply to. + * @param dialString The digits to dial. + * @return True if the digits were processed as an MMI code, false otherwise. + * @hide + */ + @SystemApi + public boolean handleMmi(PhoneAccountHandle accountHandle, String dialString) { + ITelecomService service = getTelecomService(); + if (service != null) { + try { + return service.handlePinMmiForPhoneAccount(accountHandle, dialString); + } catch (RemoteException e) { + Log.e(TAG, "Error calling ITelecomService#handlePinMmi", e); + } + } + return false; + } + + /** + * @param accountHandle The handle for the account to derive an adn query URI for or + * {@code null} to return a URI which will use the default account. + * @return The URI (with the content:// scheme) specific to the specified {@link PhoneAccount} + * for the the content retrieve. + * @hide + */ + @SystemApi + public Uri getAdnUriForPhoneAccount(PhoneAccountHandle accountHandle) { + ITelecomService service = getTelecomService(); + if (service != null && accountHandle != null) { + try { + return service.getAdnUriForPhoneAccount(accountHandle); + } catch (RemoteException e) { + Log.e(TAG, "Error calling ITelecomService#getAdnUriForPhoneAccount", e); + } + } + return Uri.parse("content://icc/adn"); + } + + /** * Removes the missed-call notification if one is present. * <p> * Requires that the method-caller be set as the system dialer app. diff --git a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl index 5daa568..4517a96 100644 --- a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl +++ b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl @@ -52,7 +52,7 @@ oneway interface IConnectionServiceAdapter { void setRingbackRequested(String callId, boolean ringing); - void setCallCapabilities(String callId, int callCapabilities); + void setConnectionCapabilities(String callId, int connectionCapabilities); void setIsConferenced(String callId, String conferenceCallId); @@ -77,4 +77,6 @@ oneway interface IConnectionServiceAdapter { void setCallerDisplayName(String callId, String callerDisplayName, int presentation); void setConferenceableConnections(String callId, in List<String> conferenceableCallIds); + + void addExistingConnection(String callId, in ParcelableConnection connection); } diff --git a/telecomm/java/com/android/internal/telecom/IInCallService.aidl b/telecomm/java/com/android/internal/telecom/IInCallService.aidl index 35f6f65..d26f6cb 100644 --- a/telecomm/java/com/android/internal/telecom/IInCallService.aidl +++ b/telecomm/java/com/android/internal/telecom/IInCallService.aidl @@ -43,4 +43,6 @@ oneway interface IInCallService { void onAudioStateChanged(in AudioState audioState); void bringToForeground(boolean showDialpad); + + void onCanAddCallChanged(boolean canAddCall); } diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl index 91f44b9..cbd9d69 100644 --- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl +++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl @@ -18,6 +18,7 @@ package com.android.internal.telecom; import android.content.ComponentName; import android.telecom.PhoneAccountHandle; +import android.net.Uri; import android.os.Bundle; import android.telecom.PhoneAccount; @@ -169,6 +170,16 @@ interface ITelecomService { boolean handlePinMmi(String dialString); /** + * @see TelecomServiceImpl#handleMmi + */ + boolean handlePinMmiForPhoneAccount(in PhoneAccountHandle accountHandle, String dialString); + + /** + * @see TelecomServiceImpl#getAdnUriForPhoneAccount + */ + Uri getAdnUriForPhoneAccount(in PhoneAccountHandle accountHandle); + + /** * @see TelecomServiceImpl#isTtySupported */ boolean isTtySupported(); |
