summaryrefslogtreecommitdiffstats
path: root/telecomm/java
diff options
context:
space:
mode:
Diffstat (limited to 'telecomm/java')
-rw-r--r--telecomm/java/android/telecom/AudioState.java54
-rw-r--r--telecomm/java/android/telecom/Call.java165
-rw-r--r--telecomm/java/android/telecom/Conference.java114
-rw-r--r--telecomm/java/android/telecom/ConferenceParticipant.aidl22
-rw-r--r--telecomm/java/android/telecom/ConferenceParticipant.java158
-rw-r--r--telecomm/java/android/telecom/Connection.java406
-rw-r--r--telecomm/java/android/telecom/ConnectionService.java214
-rw-r--r--telecomm/java/android/telecom/ConnectionServiceAdapter.java20
-rw-r--r--telecomm/java/android/telecom/ConnectionServiceAdapterServant.java31
-rw-r--r--telecomm/java/android/telecom/DisconnectCause.java28
-rw-r--r--telecomm/java/android/telecom/GatewayInfo.java30
-rw-r--r--telecomm/java/android/telecom/IConferenceable.java31
-rw-r--r--telecomm/java/android/telecom/InCallService.java10
-rw-r--r--telecomm/java/android/telecom/ParcelableConference.java14
-rw-r--r--telecomm/java/android/telecom/ParcelableConnection.java12
-rw-r--r--telecomm/java/android/telecom/Phone.java35
-rw-r--r--telecomm/java/android/telecom/PhoneAccount.java344
-rw-r--r--telecomm/java/android/telecom/PhoneAccountHandle.java15
-rw-r--r--telecomm/java/android/telecom/PhoneCapabilities.java143
-rw-r--r--telecomm/java/android/telecom/RemoteConference.java23
-rw-r--r--telecomm/java/android/telecom/RemoteConnection.java97
-rw-r--r--telecomm/java/android/telecom/RemoteConnectionService.java26
-rw-r--r--telecomm/java/android/telecom/TelecomManager.java118
-rw-r--r--telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl4
-rw-r--r--telecomm/java/com/android/internal/telecom/IInCallService.aidl2
-rw-r--r--telecomm/java/com/android/internal/telecom/ITelecomService.aidl11
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>
+ * &lt;service android:name="com.example.package.MyConnectionService"
+ * android:label="@string/some_label_for_my_connection_service"
+ * android:permission="android.permission.BIND_CONNECTION_SERVICE"&gt;
+ * &lt;intent-filter&gt;
+ * &lt;action android:name="android.telecom.ConnectionService" /&gt;
+ * &lt;/intent-filter&gt;
+ * &lt;/service&gt;
+ * </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();