Merge "Ims: Add support for Adhoc Conference calls"

This commit is contained in:
Treehugger Robot
2020-01-22 21:16:19 +00:00
committed by Gerrit Code Review
17 changed files with 817 additions and 19 deletions

View File

@@ -43608,6 +43608,7 @@ package android.telecom {
field public static final int PROPERTY_GENERIC_CONFERENCE = 2; // 0x2
field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 128; // 0x80
field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10
field public static final int PROPERTY_IS_ADHOC_CONFERENCE = 8192; // 0x2000
field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40
field public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 2048; // 0x800
field public static final int PROPERTY_RTT = 1024; // 0x400
@@ -43685,6 +43686,7 @@ package android.telecom {
public abstract class Conference extends android.telecom.Conferenceable {
ctor public Conference(android.telecom.PhoneAccountHandle);
method public final boolean addConnection(android.telecom.Connection);
method @NonNull public static android.telecom.Conference createFailedConference(@NonNull android.telecom.DisconnectCause, @NonNull android.telecom.PhoneAccountHandle);
method public final void destroy();
method public final android.telecom.CallAudioState getCallAudioState();
method public final java.util.List<android.telecom.Connection> getConferenceableConnections();
@@ -43699,6 +43701,8 @@ package android.telecom {
method public final android.telecom.StatusHints getStatusHints();
method public android.telecom.Connection.VideoProvider getVideoProvider();
method public int getVideoState();
method public final boolean isRingbackRequested();
method public void onAnswer(int);
method public void onCallAudioStateChanged(android.telecom.CallAudioState);
method public void onConnectionAdded(android.telecom.Connection);
method public void onDisconnect();
@@ -43707,6 +43711,7 @@ package android.telecom {
method public void onMerge(android.telecom.Connection);
method public void onMerge();
method public void onPlayDtmfTone(char);
method public void onReject();
method public void onSeparate(android.telecom.Connection);
method public void onStopDtmfTone();
method public void onSwap();
@@ -43726,6 +43731,8 @@ package android.telecom {
method public final void setDisconnected(android.telecom.DisconnectCause);
method public final void setExtras(@Nullable android.os.Bundle);
method public final void setOnHold();
method public final void setRingbackRequested(boolean);
method public final void setRinging();
method public final void setStatusHints(android.telecom.StatusHints);
method public final void setVideoProvider(android.telecom.Connection, android.telecom.Connection.VideoProvider);
method public final void setVideoState(android.telecom.Connection, int);
@@ -43883,6 +43890,7 @@ package android.telecom {
field public static final int PROPERTY_ASSISTED_DIALING_USED = 512; // 0x200
field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 32; // 0x20
field public static final int PROPERTY_HIGH_DEF_AUDIO = 4; // 0x4
field public static final int PROPERTY_IS_ADHOC_CONFERENCE = 4096; // 0x1000
field public static final int PROPERTY_IS_EXTERNAL_CALL = 16; // 0x10
field public static final int PROPERTY_IS_RTT = 256; // 0x100
field public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 1024; // 0x400
@@ -43955,8 +43963,10 @@ package android.telecom {
method public android.telecom.PhoneAccountHandle getAccountHandle();
method public android.net.Uri getAddress();
method public android.os.Bundle getExtras();
method @Nullable public java.util.List<android.net.Uri> getParticipants();
method public android.telecom.Connection.RttTextStream getRttTextStream();
method public int getVideoState();
method public boolean isAdhocConferenceCall();
method public boolean isRequestingRtt();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telecom.ConnectionRequest> CREATOR;
@@ -43976,9 +43986,13 @@ package android.telecom {
method public void onConference(android.telecom.Connection, android.telecom.Connection);
method public void onConnectionServiceFocusGained();
method public void onConnectionServiceFocusLost();
method @Nullable public android.telecom.Conference onCreateIncomingConference(@Nullable android.telecom.PhoneAccountHandle, @Nullable android.telecom.ConnectionRequest);
method public void onCreateIncomingConferenceFailed(@Nullable android.telecom.PhoneAccountHandle, @Nullable android.telecom.ConnectionRequest);
method public android.telecom.Connection onCreateIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public void onCreateIncomingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public android.telecom.Connection onCreateIncomingHandoverConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method @Nullable public android.telecom.Conference onCreateOutgoingConference(@Nullable android.telecom.PhoneAccountHandle, @Nullable android.telecom.ConnectionRequest);
method public void onCreateOutgoingConferenceFailed(@Nullable android.telecom.PhoneAccountHandle, @Nullable android.telecom.ConnectionRequest);
method public android.telecom.Connection onCreateOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public void onCreateOutgoingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public android.telecom.Connection onCreateOutgoingHandoverConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
@@ -44093,6 +44107,7 @@ package android.telecom {
method public boolean supportsUriScheme(String);
method public android.telecom.PhoneAccount.Builder toBuilder();
method public void writeToParcel(android.os.Parcel, int);
field public static final int CAPABILITY_ADHOC_CONFERENCE_CALLING = 16384; // 0x4000
field public static final int CAPABILITY_CALL_PROVIDER = 2; // 0x2
field public static final int CAPABILITY_CALL_SUBJECT = 64; // 0x40
field public static final int CAPABILITY_CONNECTION_MANAGER = 1; // 0x1
@@ -44288,6 +44303,7 @@ package android.telecom {
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ANSWER_PHONE_CALLS, android.Manifest.permission.MODIFY_PHONE_STATE}) public void acceptRingingCall();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ANSWER_PHONE_CALLS, android.Manifest.permission.MODIFY_PHONE_STATE}) public void acceptRingingCall(int);
method public void addNewIncomingCall(android.telecom.PhoneAccountHandle, android.os.Bundle);
method public void addNewIncomingConference(@NonNull android.telecom.PhoneAccountHandle, @NonNull android.os.Bundle);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void cancelMissedCallsNotification();
method public android.content.Intent createManageBlockedNumbersIntent();
method @Deprecated @RequiresPermission(android.Manifest.permission.ANSWER_PHONE_CALLS) public boolean endCall();
@@ -44315,6 +44331,7 @@ package android.telecom {
method public void registerPhoneAccount(android.telecom.PhoneAccount);
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void showInCallScreen(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void silenceRinger();
method @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void startConference(@NonNull java.util.List<android.net.Uri>, @NonNull android.os.Bundle);
method public void unregisterPhoneAccount(android.telecom.PhoneAccountHandle);
field public static final String ACTION_CHANGE_DEFAULT_DIALER = "android.telecom.action.CHANGE_DEFAULT_DIALER";
field public static final String ACTION_CHANGE_PHONE_ACCOUNTS = "android.telecom.action.CHANGE_PHONE_ACCOUNTS";
@@ -44793,6 +44810,7 @@ package android.telephony {
field public static final String KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool";
field public static final String KEY_SMS_REQUIRES_DESTINATION_NUMBER_CONVERSION_BOOL = "sms_requires_destination_number_conversion_bool";
field public static final String KEY_SUPPORT_3GPP_CALL_FORWARDING_WHILE_ROAMING_BOOL = "support_3gpp_call_forwarding_while_roaming_bool";
field public static final String KEY_SUPPORT_ADHOC_CONFERENCE_CALLS_BOOL = "support_adhoc_conference_calls_bool";
field public static final String KEY_SUPPORT_CLIR_NETWORK_DEFAULT_BOOL = "support_clir_network_default_bool";
field public static final String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool";
field public static final String KEY_SUPPORT_EMERGENCY_SMS_OVER_IMS_BOOL = "support_emergency_sms_over_ims_bool";

View File

@@ -2884,6 +2884,8 @@ package android.telecom {
method @NonNull public android.telecom.ConnectionRequest.Builder setAccountHandle(@NonNull android.telecom.PhoneAccountHandle);
method @NonNull public android.telecom.ConnectionRequest.Builder setAddress(@NonNull android.net.Uri);
method @NonNull public android.telecom.ConnectionRequest.Builder setExtras(@NonNull android.os.Bundle);
method @NonNull public android.telecom.ConnectionRequest.Builder setIsAdhocConferenceCall(boolean);
method @NonNull public android.telecom.ConnectionRequest.Builder setParticipants(@Nullable java.util.List<android.net.Uri>);
method @NonNull public android.telecom.ConnectionRequest.Builder setRttPipeFromInCall(@NonNull android.os.ParcelFileDescriptor);
method @NonNull public android.telecom.ConnectionRequest.Builder setRttPipeToInCall(@NonNull android.os.ParcelFileDescriptor);
method @NonNull public android.telecom.ConnectionRequest.Builder setShouldShowIncomingCallUi(boolean);

View File

@@ -547,8 +547,14 @@ public final class Call {
*/
public static final int PROPERTY_VOIP_AUDIO_MODE = 0x00001000;
/**
* Indicates that the call is an adhoc conference call. This property can be set for both
* incoming and outgoing calls.
*/
public static final int PROPERTY_IS_ADHOC_CONFERENCE = 0x00002000;
//******************************************************************************************
// Next PROPERTY value: 0x00002000
// Next PROPERTY value: 0x00004000
//******************************************************************************************
private final String mTelecomCallId;
@@ -726,6 +732,9 @@ public final class Call {
if (hasProperty(properties, PROPERTY_VOIP_AUDIO_MODE)) {
builder.append(" PROPERTY_VOIP_AUDIO_MODE");
}
if (hasProperty(properties, PROPERTY_IS_ADHOC_CONFERENCE)) {
builder.append(" PROPERTY_IS_ADHOC_CONFERENCE");
}
builder.append("]");
return builder.toString();
}

View File

@@ -69,6 +69,7 @@ public abstract class Conference extends Conferenceable {
public void onConnectionEvent(Conference c, String event, Bundle extras) {}
public void onCallerDisplayNameChanged(
Conference c, String callerDisplayName, int presentation) {}
public void onRingbackRequested(Conference c, boolean ringback) {}
}
private final Set<Listener> mListeners = new CopyOnWriteArraySet<>();
@@ -97,6 +98,7 @@ public abstract class Conference extends Conferenceable {
private int mAddressPresentation;
private String mCallerDisplayName;
private int mCallerDisplayNamePresentation;
private boolean mRingbackRequested = false;
private final Connection.Listener mConnectionDeathListener = new Connection.Listener() {
@Override
@@ -169,6 +171,14 @@ public abstract class Conference extends Conferenceable {
return mState;
}
/**
* Returns whether this conference is requesting that the system play a ringback tone
* on its behalf.
*/
public final boolean isRingbackRequested() {
return mRingbackRequested;
}
/**
* Returns the capabilities of the conference. See {@code CAPABILITY_*} constants in class
* {@link Connection} for valid values.
@@ -307,6 +317,35 @@ public abstract class Conference extends Conferenceable {
*/
public void onConnectionAdded(Connection connection) {}
/**
* Notifies this Conference, which is in {@code STATE_RINGING}, of
* a request to accept.
* For managed {@link ConnectionService}s, this will be called when the user answers a call via
* the default dialer's {@link InCallService}.
*
* @param videoState The video state in which to answer the connection.
*/
public void onAnswer(int videoState) {}
/**
* Notifies this Conference, which is in {@code STATE_RINGING}, of
* a request to accept.
* For managed {@link ConnectionService}s, this will be called when the user answers a call via
* the default dialer's {@link InCallService}.
* @hide
*/
public final void onAnswer() {
onAnswer(VideoProfile.STATE_AUDIO_ONLY);
}
/**
* Notifies this Conference, which is in {@code STATE_RINGING}, of
* a request to reject.
* For managed {@link ConnectionService}s, this will be called when the user rejects a call via
* the default dialer's {@link InCallService}.
*/
public void onReject() {}
/**
* Sets state to be on hold.
*/
@@ -321,10 +360,18 @@ public abstract class Conference extends Conferenceable {
setState(Connection.STATE_DIALING);
}
/**
* Sets state to be ringing.
*/
public final void setRinging() {
setState(Connection.STATE_RINGING);
}
/**
* Sets state to be active.
*/
public final void setActive() {
setRingbackRequested(false);
setState(Connection.STATE_ACTIVE);
}
@@ -435,6 +482,21 @@ public abstract class Conference extends Conferenceable {
fireOnConferenceableConnectionsChanged();
}
/**
* 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 conference's audio stream.
*
* @param ringback Whether the ringback tone is to be played.
*/
public final void setRingbackRequested(boolean ringback) {
if (mRingbackRequested != ringback) {
mRingbackRequested = ringback;
for (Listener l : mListeners) {
l.onRingbackRequested(this, ringback);
}
}
}
/**
* Set the video state for the conference.
* Valid values: {@link VideoProfile#STATE_AUDIO_ONLY},
@@ -640,14 +702,6 @@ public abstract class Conference extends Conferenceable {
}
private void setState(int newState) {
if (newState != Connection.STATE_ACTIVE &&
newState != Connection.STATE_HOLDING &&
newState != Connection.STATE_DISCONNECTED) {
Log.w(this, "Unsupported state transition for Conference call.",
Connection.stateToString(newState));
return;
}
if (mState != newState) {
int oldState = mState;
mState = newState;
@@ -657,6 +711,37 @@ public abstract class Conference extends Conferenceable {
}
}
private static class FailureSignalingConference extends Conference {
private boolean mImmutable = false;
public FailureSignalingConference(DisconnectCause disconnectCause,
PhoneAccountHandle phoneAccount) {
super(phoneAccount);
setDisconnected(disconnectCause);
mImmutable = true;
}
public void checkImmutable() {
if (mImmutable) {
throw new UnsupportedOperationException("Conference is immutable");
}
}
}
/**
* Return a {@code Conference} which represents a failed conference attempt. The returned
* {@code Conference} will have a {@link android.telecom.DisconnectCause} and as specified,
* and a {@link #getState()} of {@code STATE_DISCONNECTED}.
* <p>
* The returned {@code Conference} 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.
*
* @param disconnectCause The disconnect cause, ({@see android.telecomm.DisconnectCause}).
* @return A {@code Conference} which indicates failure.
*/
public @NonNull static Conference createFailedConference(
@NonNull DisconnectCause disconnectCause, @NonNull PhoneAccountHandle phoneAccount) {
return new FailureSignalingConference(disconnectCause, phoneAccount);
}
private final void clearConferenceableList() {
for (Connection c : mConferenceableConnections) {
c.removeConnectionListener(mConnectionDeathListener);
@@ -667,11 +752,13 @@ public abstract class Conference extends Conferenceable {
@Override
public String toString() {
return String.format(Locale.US,
"[State: %s,Capabilites: %s, VideoState: %s, VideoProvider: %s, ThisObject %s]",
"[State: %s,Capabilites: %s, VideoState: %s, VideoProvider: %s,"
+ "isRingbackRequested: %s, ThisObject %s]",
Connection.stateToString(mState),
Call.Details.capabilitiesToString(mConnectionCapabilities),
getVideoState(),
getVideoProvider(),
isRingbackRequested() ? "Y" : "N",
super.toString());
}

View File

@@ -497,8 +497,17 @@ public abstract class Connection extends Conferenceable {
@TestApi
public static final int PROPERTY_REMOTELY_HOSTED = 1 << 11;
/**
* Set by the framework to indicate that it is an adhoc conference call.
* <p>
* This is used for Outgoing and incoming conference calls.
*
*/
public static final int PROPERTY_IS_ADHOC_CONFERENCE = 1 << 12;
//**********************************************************************************************
// Next PROPERTY value: 1<<12
// Next PROPERTY value: 1<<13
//**********************************************************************************************
/**
@@ -1018,6 +1027,10 @@ public abstract class Connection extends Conferenceable {
builder.append(isLong ? " PROPERTY_REMOTELY_HOSTED" : " remote_hst");
}
if ((properties & PROPERTY_IS_ADHOC_CONFERENCE) == PROPERTY_IS_ADHOC_CONFERENCE) {
builder.append(isLong ? " PROPERTY_IS_ADHOC_CONFERENCE" : " adhoc_conf");
}
builder.append("]");
return builder.toString();
}

View File

@@ -26,6 +26,9 @@ import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
import java.util.ArrayList;
import java.util.List;
/**
* Simple data container encapsulating a request to some entity to
* create a new {@link Connection}.
@@ -46,6 +49,8 @@ public final class ConnectionRequest implements Parcelable {
private boolean mShouldShowIncomingCallUi = false;
private ParcelFileDescriptor mRttPipeToInCall;
private ParcelFileDescriptor mRttPipeFromInCall;
private List<Uri> mParticipants;
private boolean mIsAdhocConference = false;
public Builder() { }
@@ -58,6 +63,15 @@ public final class ConnectionRequest implements Parcelable {
return this;
}
/**
* Sets the participants for the resulting {@link ConnectionRequest}
* @param participants The participants to which the {@link Connection} is to connect.
*/
public @NonNull Builder setParticipants(@Nullable List<Uri> participants) {
this.mParticipants = participants;
return this;
}
/**
* Sets the address for the resulting {@link ConnectionRequest}
* @param address The address(e.g., phone number) to which the {@link Connection} is to
@@ -107,6 +121,16 @@ public final class ConnectionRequest implements Parcelable {
return this;
}
/**
* Sets isAdhocConference for the resulting {@link ConnectionRequest}
* @param isAdhocConference {@code true} if it is a adhoc conference call
* {@code false}, if not a adhoc conference call
*/
public @NonNull Builder setIsAdhocConferenceCall(boolean isAdhocConference) {
this.mIsAdhocConference = isAdhocConference;
return this;
}
/**
* Sets the RTT pipe for transferring text into the {@link ConnectionService} for the
* resulting {@link ConnectionRequest}
@@ -141,7 +165,9 @@ public final class ConnectionRequest implements Parcelable {
mTelecomCallId,
mShouldShowIncomingCallUi,
mRttPipeFromInCall,
mRttPipeToInCall);
mRttPipeToInCall,
mParticipants,
mIsAdhocConference);
}
}
@@ -155,6 +181,8 @@ public final class ConnectionRequest implements Parcelable {
private final ParcelFileDescriptor mRttPipeFromInCall;
// Cached return value of getRttTextStream -- we don't want to wrap it more than once.
private Connection.RttTextStream mRttTextStream;
private List<Uri> mParticipants;
private final boolean mIsAdhocConference;
/**
* @param accountHandle The accountHandle which should be used to place the call.
@@ -214,6 +242,21 @@ public final class ConnectionRequest implements Parcelable {
boolean shouldShowIncomingCallUi,
ParcelFileDescriptor rttPipeFromInCall,
ParcelFileDescriptor rttPipeToInCall) {
this(accountHandle, handle, extras, videoState, telecomCallId,
shouldShowIncomingCallUi, rttPipeFromInCall, rttPipeToInCall, null, false);
}
private ConnectionRequest(
PhoneAccountHandle accountHandle,
Uri handle,
Bundle extras,
int videoState,
String telecomCallId,
boolean shouldShowIncomingCallUi,
ParcelFileDescriptor rttPipeFromInCall,
ParcelFileDescriptor rttPipeToInCall,
List<Uri> participants,
boolean isAdhocConference) {
mAccountHandle = accountHandle;
mAddress = handle;
mExtras = extras;
@@ -222,6 +265,8 @@ public final class ConnectionRequest implements Parcelable {
mShouldShowIncomingCallUi = shouldShowIncomingCallUi;
mRttPipeFromInCall = rttPipeFromInCall;
mRttPipeToInCall = rttPipeToInCall;
mParticipants = participants;
mIsAdhocConference = isAdhocConference;
}
private ConnectionRequest(Parcel in) {
@@ -233,6 +278,11 @@ public final class ConnectionRequest implements Parcelable {
mShouldShowIncomingCallUi = in.readInt() == 1;
mRttPipeFromInCall = in.readParcelable(getClass().getClassLoader());
mRttPipeToInCall = in.readParcelable(getClass().getClassLoader());
mParticipants = new ArrayList<Uri>();
in.readList(mParticipants, getClass().getClassLoader());
mIsAdhocConference = in.readInt() == 1;
}
/**
@@ -245,6 +295,11 @@ public final class ConnectionRequest implements Parcelable {
*/
public Uri getAddress() { return mAddress; }
/**
* The participants to which the {@link Connection} is to connect.
*/
public @Nullable List<Uri> getParticipants() { return mParticipants; }
/**
* Application-specific extra data. Used for passing back information from an incoming
* call {@code Intent}, and for any proprietary extensions arranged between a client
@@ -289,6 +344,13 @@ public final class ConnectionRequest implements Parcelable {
return mShouldShowIncomingCallUi;
}
/**
* @return {@code true} if the call is a adhoc conference call else @return {@code false}
*/
public boolean isAdhocConferenceCall() {
return mIsAdhocConference;
}
/**
* Gets the {@link ParcelFileDescriptor} that is used to send RTT text from the connection
* service to the in-call UI. In order to obtain an
@@ -345,11 +407,12 @@ public final class ConnectionRequest implements Parcelable {
@Override
public String toString() {
return String.format("ConnectionRequest %s %s",
return String.format("ConnectionRequest %s %s isAdhocConf: %s",
mAddress == null
? Uri.EMPTY
: Connection.toLogSafePhoneNumber(mAddress.toString()),
bundleToString(mExtras));
bundleToString(mExtras),
isAdhocConferenceCall() ? "Y" : "N");
}
private static String bundleToString(Bundle extras){
@@ -406,5 +469,7 @@ public final class ConnectionRequest implements Parcelable {
destination.writeInt(mShouldShowIncomingCallUi ? 1 : 0);
destination.writeParcelable(mRttPipeFromInCall, 0);
destination.writeParcelable(mRttPipeToInCall, 0);
destination.writeList(mParticipants);
destination.writeInt(mIsAdhocConference ? 1 : 0);
}
}

View File

@@ -154,6 +154,9 @@ public abstract class ConnectionService extends Service {
private static final String SESSION_CONNECTION_SERVICE_FOCUS_LOST = "CS.cSFL";
private static final String SESSION_CONNECTION_SERVICE_FOCUS_GAINED = "CS.cSFG";
private static final String SESSION_HANDOVER_FAILED = "CS.haF";
private static final String SESSION_CREATE_CONF = "CS.crConf";
private static final String SESSION_CREATE_CONF_COMPLETE = "CS.crConfC";
private static final String SESSION_CREATE_CONF_FAILED = "CS.crConfF";
private static final int MSG_ADD_CONNECTION_SERVICE_ADAPTER = 1;
private static final int MSG_CREATE_CONNECTION = 2;
@@ -188,6 +191,9 @@ public abstract class ConnectionService extends Service {
private static final int MSG_HANDOVER_FAILED = 32;
private static final int MSG_HANDOVER_COMPLETE = 33;
private static final int MSG_DEFLECT = 34;
private static final int MSG_CREATE_CONFERENCE = 35;
private static final int MSG_CREATE_CONFERENCE_COMPLETE = 36;
private static final int MSG_CREATE_CONFERENCE_FAILED = 37;
private static Connection sNullConnection;
@@ -290,6 +296,63 @@ public abstract class ConnectionService extends Service {
}
}
@Override
public void createConference(
PhoneAccountHandle connectionManagerPhoneAccount,
String id,
ConnectionRequest request,
boolean isIncoming,
boolean isUnknown,
Session.Info sessionInfo) {
Log.startSession(sessionInfo, SESSION_CREATE_CONF);
try {
SomeArgs args = SomeArgs.obtain();
args.arg1 = connectionManagerPhoneAccount;
args.arg2 = id;
args.arg3 = request;
args.arg4 = Log.createSubsession();
args.argi1 = isIncoming ? 1 : 0;
args.argi2 = isUnknown ? 1 : 0;
mHandler.obtainMessage(MSG_CREATE_CONFERENCE, args).sendToTarget();
} finally {
Log.endSession();
}
}
@Override
public void createConferenceComplete(String id, Session.Info sessionInfo) {
Log.startSession(sessionInfo, SESSION_CREATE_CONF_COMPLETE);
try {
SomeArgs args = SomeArgs.obtain();
args.arg1 = id;
args.arg2 = Log.createSubsession();
mHandler.obtainMessage(MSG_CREATE_CONFERENCE_COMPLETE, args).sendToTarget();
} finally {
Log.endSession();
}
}
@Override
public void createConferenceFailed(
PhoneAccountHandle connectionManagerPhoneAccount,
String callId,
ConnectionRequest request,
boolean isIncoming,
Session.Info sessionInfo) {
Log.startSession(sessionInfo, SESSION_CREATE_CONF_FAILED);
try {
SomeArgs args = SomeArgs.obtain();
args.arg1 = callId;
args.arg2 = request;
args.arg3 = Log.createSubsession();
args.arg4 = connectionManagerPhoneAccount;
args.argi1 = isIncoming ? 1 : 0;
mHandler.obtainMessage(MSG_CREATE_CONFERENCE_FAILED, args).sendToTarget();
} finally {
Log.endSession();
}
}
@Override
public void handoverFailed(String callId, ConnectionRequest request, int reason,
Session.Info sessionInfo) {
@@ -802,6 +865,106 @@ public abstract class ConnectionService extends Service {
}
break;
}
case MSG_CREATE_CONFERENCE: {
SomeArgs args = (SomeArgs) msg.obj;
Log.continueSession((Session) args.arg4, SESSION_HANDLER + SESSION_CREATE_CONN);
try {
final PhoneAccountHandle connectionManagerPhoneAccount =
(PhoneAccountHandle) args.arg1;
final String id = (String) args.arg2;
final ConnectionRequest request = (ConnectionRequest) args.arg3;
final boolean isIncoming = args.argi1 == 1;
final boolean isUnknown = args.argi2 == 1;
if (!mAreAccountsInitialized) {
Log.d(this, "Enqueueing pre-initconference request %s", id);
mPreInitializationConnectionRequests.add(
new android.telecom.Logging.Runnable(
SESSION_HANDLER + SESSION_CREATE_CONF + ".pIConfR",
null /*lock*/) {
@Override
public void loggedRun() {
createConference(connectionManagerPhoneAccount,
id,
request,
isIncoming,
isUnknown);
}
}.prepare());
} else {
createConference(connectionManagerPhoneAccount,
id,
request,
isIncoming,
isUnknown);
}
} finally {
args.recycle();
Log.endSession();
}
break;
}
case MSG_CREATE_CONFERENCE_COMPLETE: {
SomeArgs args = (SomeArgs) msg.obj;
Log.continueSession((Session) args.arg2,
SESSION_HANDLER + SESSION_CREATE_CONN_COMPLETE);
try {
final String id = (String) args.arg1;
if (!mAreAccountsInitialized) {
Log.d(this, "Enqueueing pre-init conference request %s", id);
mPreInitializationConnectionRequests.add(
new android.telecom.Logging.Runnable(
SESSION_HANDLER + SESSION_CREATE_CONF_COMPLETE
+ ".pIConfR",
null /*lock*/) {
@Override
public void loggedRun() {
notifyCreateConferenceComplete(id);
}
}.prepare());
} else {
notifyCreateConferenceComplete(id);
}
} finally {
args.recycle();
Log.endSession();
}
break;
}
case MSG_CREATE_CONFERENCE_FAILED: {
SomeArgs args = (SomeArgs) msg.obj;
Log.continueSession((Session) args.arg3, SESSION_HANDLER +
SESSION_CREATE_CONN_FAILED);
try {
final String id = (String) args.arg1;
final ConnectionRequest request = (ConnectionRequest) args.arg2;
final boolean isIncoming = args.argi1 == 1;
final PhoneAccountHandle connectionMgrPhoneAccount =
(PhoneAccountHandle) args.arg4;
if (!mAreAccountsInitialized) {
Log.d(this, "Enqueueing pre-init conference request %s", id);
mPreInitializationConnectionRequests.add(
new android.telecom.Logging.Runnable(
SESSION_HANDLER + SESSION_CREATE_CONF_FAILED
+ ".pIConfR",
null /*lock*/) {
@Override
public void loggedRun() {
createConferenceFailed(connectionMgrPhoneAccount, id,
request, isIncoming);
}
}.prepare());
} else {
Log.i(this, "createConferenceFailed %s", id);
createConferenceFailed(connectionMgrPhoneAccount, id, request,
isIncoming);
}
} finally {
args.recycle();
Log.endSession();
}
break;
}
case MSG_HANDOVER_FAILED: {
SomeArgs args = (SomeArgs) msg.obj;
Log.continueSession((Session) args.arg3, SESSION_HANDLER +
@@ -1162,6 +1325,12 @@ public abstract class ConnectionService extends Service {
public void onStateChanged(Conference conference, int oldState, int newState) {
String id = mIdByConference.get(conference);
switch (newState) {
case Connection.STATE_RINGING:
mAdapter.setRinging(id);
break;
case Connection.STATE_DIALING:
mAdapter.setDialing(id);
break;
case Connection.STATE_ACTIVE:
mAdapter.setActive(id);
break;
@@ -1292,6 +1461,13 @@ public abstract class ConnectionService extends Service {
mAdapter.onConnectionEvent(id, event, extras);
}
}
@Override
public void onRingbackRequested(Conference c, boolean ringback) {
String id = mIdByConference.get(c);
Log.d(this, "Adapter conference onRingback %b", ringback);
mAdapter.setRingbackRequested(id, ringback);
}
};
private final Connection.Listener mConnectionListener = new Connection.Listener() {
@@ -1534,6 +1710,70 @@ public abstract class ConnectionService extends Service {
return super.onUnbind(intent);
}
/**
* This can be used by telecom to either create a new outgoing conference call or attach
* to an existing incoming conference call. In either case, telecom will cycle through a
* set of services and call createConference until a connection service cancels the process
* or completes it successfully.
*/
private void createConference(
final PhoneAccountHandle callManagerAccount,
final String callId,
final ConnectionRequest request,
boolean isIncoming,
boolean isUnknown) {
Conference conference = null;
conference = isIncoming ? onCreateIncomingConference(callManagerAccount, request)
: onCreateOutgoingConference(callManagerAccount, request);
Log.d(this, "createConference, conference: %s", conference);
if (conference == null) {
Log.i(this, "createConference, implementation returned null conference.");
conference = Conference.createFailedConference(
new DisconnectCause(DisconnectCause.ERROR, "IMPL_RETURNED_NULL_CONFERENCE"),
request.getAccountHandle());
}
if (conference.getExtras() != null) {
conference.getExtras().putString(Connection.EXTRA_ORIGINAL_CONNECTION_ID, callId);
}
mConferenceById.put(callId, conference);
mIdByConference.put(conference, callId);
conference.addListener(mConferenceListener);
ParcelableConference parcelableConference = new ParcelableConference(
request.getAccountHandle(),
conference.getState(),
conference.getConnectionCapabilities(),
conference.getConnectionProperties(),
Collections.<String>emptyList(), //connectionIds
conference.getVideoProvider() == null ?
null : conference.getVideoProvider().getInterface(),
conference.getVideoState(),
conference.getConnectTimeMillis(),
conference.getConnectionStartElapsedRealTime(),
conference.getStatusHints(),
conference.getExtras(),
conference.getAddress(),
conference.getAddressPresentation(),
conference.getCallerDisplayName(),
conference.getCallerDisplayNamePresentation(),
conference.getDisconnectCause(),
conference.isRingbackRequested());
if (conference.getState() != Connection.STATE_DISCONNECTED) {
conference.setTelecomCallId(callId);
mAdapter.setVideoProvider(callId, conference.getVideoProvider());
mAdapter.setVideoState(callId, conference.getVideoState());
onConferenceAdded(conference);
}
Log.d(this, "createConference, calling handleCreateConferenceSuccessful %s", callId);
mAdapter.handleCreateConferenceComplete(
callId,
request,
parcelableConference);
}
/**
* This can be used by telecom to either create a new outgoing call or attach to an existing
* incoming call. In either case, telecom will cycle through a set of services and call
@@ -1645,6 +1885,18 @@ public abstract class ConnectionService extends Service {
}
}
private void createConferenceFailed(final PhoneAccountHandle callManagerAccount,
final String callId, final ConnectionRequest request,
boolean isIncoming) {
Log.i(this, "createConferenceFailed %s", callId);
if (isIncoming) {
onCreateIncomingConferenceFailed(callManagerAccount, request);
} else {
onCreateOutgoingConferenceFailed(callManagerAccount, request);
}
}
private void handoverFailed(final String callId, final ConnectionRequest request,
int reason) {
@@ -1669,6 +1921,24 @@ public abstract class ConnectionService extends Service {
"notifyCreateConnectionComplete"));
}
/**
* Called by Telecom when the creation of a new Conference has completed and it is now added
* to Telecom.
* @param callId The ID of the connection.
*/
private void notifyCreateConferenceComplete(final String callId) {
Log.i(this, "notifyCreateConferenceComplete %s", callId);
if (callId == null) {
// This could happen if the conference fails quickly and is removed from the
// ConnectionService before Telecom sends the create conference complete callback.
Log.w(this, "notifyCreateConferenceComplete: callId is null.");
return;
}
onCreateConferenceComplete(findConferenceForAction(callId,
"notifyCreateConferenceComplete"));
}
private void abort(String callId) {
Log.d(this, "abort %s", callId);
findConnectionForAction(callId, "abort").onAbort();
@@ -1676,12 +1946,20 @@ public abstract class ConnectionService extends Service {
private void answerVideo(String callId, int videoState) {
Log.d(this, "answerVideo %s", callId);
findConnectionForAction(callId, "answer").onAnswer(videoState);
if (mConnectionById.containsKey(callId)) {
findConnectionForAction(callId, "answer").onAnswer(videoState);
} else {
findConferenceForAction(callId, "answer").onAnswer(videoState);
}
}
private void answer(String callId) {
Log.d(this, "answer %s", callId);
findConnectionForAction(callId, "answer").onAnswer();
if (mConnectionById.containsKey(callId)) {
findConnectionForAction(callId, "answer").onAnswer();
} else {
findConferenceForAction(callId, "answer").onAnswer();
}
}
private void deflect(String callId, Uri address) {
@@ -1691,7 +1969,11 @@ public abstract class ConnectionService extends Service {
private void reject(String callId) {
Log.d(this, "reject %s", callId);
findConnectionForAction(callId, "reject").onReject();
if (mConnectionById.containsKey(callId)) {
findConnectionForAction(callId, "reject").onReject();
} else {
findConferenceForAction(callId, "reject").onReject();
}
}
private void reject(String callId, String rejectWithMessage) {
@@ -2198,6 +2480,21 @@ public abstract class ConnectionService extends Service {
ConnectionRequest request) {
return null;
}
/**
* Create a {@code Connection} given an incoming request. This is used to attach to existing
* incoming conference call.
*
* @param connectionManagerPhoneAccount See description at
* {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
* @param request Details about the incoming call.
* @return The {@code Connection} object to satisfy this call, or {@code null} to
* not handle the call.
*/
public @Nullable Conference onCreateIncomingConference(
@Nullable PhoneAccountHandle connectionManagerPhoneAccount,
@Nullable ConnectionRequest request) {
return null;
}
/**
* Called after the {@link Connection} returned by
@@ -2211,6 +2508,19 @@ public abstract class ConnectionService extends Service {
public void onCreateConnectionComplete(Connection connection) {
}
/**
* Called after the {@link Conference} returned by
* {@link #onCreateIncomingConference(PhoneAccountHandle, ConnectionRequest)}
* or {@link #onCreateOutgoingConference(PhoneAccountHandle, ConnectionRequest)} has been
* added to the {@link ConnectionService} and sent to Telecom.
*
* @param conference the {@link Conference}.
* @hide
*/
public void onCreateConferenceComplete(Conference conference) {
}
/**
* Called by Telecom to inform the {@link ConnectionService} that its request to create a new
* incoming {@link Connection} was denied.
@@ -2249,6 +2559,47 @@ public abstract class ConnectionService extends Service {
ConnectionRequest request) {
}
/**
* Called by Telecom to inform the {@link ConnectionService} that its request to create a new
* incoming {@link Conference} was denied.
* <p>
* Used when a self-managed {@link ConnectionService} attempts to create a new incoming
* {@link Conference}, but Telecom has determined that the call cannot be allowed at this time.
* The {@link ConnectionService} is responsible for silently rejecting the new incoming
* {@link Conference}.
* <p>
* See {@link TelecomManager#isIncomingCallPermitted(PhoneAccountHandle)} for more information.
*
* @param connectionManagerPhoneAccount See description at
* {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
* @param request The incoming connection request.
*/
public void onCreateIncomingConferenceFailed(
@Nullable PhoneAccountHandle connectionManagerPhoneAccount,
@Nullable ConnectionRequest request) {
}
/**
* Called by Telecom to inform the {@link ConnectionService} that its request to create a new
* outgoing {@link Conference} was denied.
* <p>
* Used when a self-managed {@link ConnectionService} attempts to create a new outgoing
* {@link Conference}, but Telecom has determined that the call cannot be placed at this time.
* The {@link ConnectionService} is responisible for informing the user that the
* {@link Conference} cannot be made at this time.
* <p>
* See {@link TelecomManager#isOutgoingCallPermitted(PhoneAccountHandle)} for more information.
*
* @param connectionManagerPhoneAccount See description at
* {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
* @param request The outgoing connection request.
*/
public void onCreateOutgoingConferenceFailed(
@Nullable PhoneAccountHandle connectionManagerPhoneAccount,
@Nullable ConnectionRequest request) {
}
/**
* Trigger recalculate functinality for conference calls. This is used when a Telephony
* Connection is part of a conference controller but is not yet added to Connection
@@ -2288,6 +2639,36 @@ public abstract class ConnectionService extends Service {
return null;
}
/**
* Create a {@code Conference} given an outgoing request. This is used to initiate new
* outgoing conference call.
*
* @param connectionManagerPhoneAccount The connection manager account to use for managing
* this call.
* <p>
* If this parameter is not {@code null}, it means that this {@code ConnectionService}
* has registered one or more {@code PhoneAccount}s having
* {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER}. This parameter will contain
* one of these {@code PhoneAccount}s, while the {@code request} will contain another
* (usually but not always distinct) {@code PhoneAccount} to be used for actually
* making the connection.
* <p>
* If this parameter is {@code null}, it means that this {@code ConnectionService} is
* being asked to make a direct connection. The
* {@link ConnectionRequest#getAccountHandle()} of parameter {@code request} will be
* a {@code PhoneAccount} registered by this {@code ConnectionService} to use for
* making the connection.
* @param request Details about the outgoing call.
* @return The {@code Conference} object to satisfy this call, or the result of an invocation
* of {@link Connection#createFailedConnection(DisconnectCause)} to not handle the call.
*/
public @Nullable Conference onCreateOutgoingConference(
@Nullable PhoneAccountHandle connectionManagerPhoneAccount,
@Nullable ConnectionRequest request) {
return null;
}
/**
* Called by Telecom to request that a {@link ConnectionService} creates an instance of an
* outgoing handover {@link Connection}.

View File

@@ -100,6 +100,19 @@ final class ConnectionServiceAdapter implements DeathRecipient {
}
}
void handleCreateConferenceComplete(
String id,
ConnectionRequest request,
ParcelableConference conference) {
for (IConnectionServiceAdapter adapter : mAdapters) {
try {
adapter.handleCreateConferenceComplete(id, request, conference,
Log.getExternalSession());
} catch (RemoteException e) {
}
}
}
/**
* Sets a call's state to active (e.g., an ongoing call where two parties can actively
* communicate).

View File

@@ -75,6 +75,7 @@ final class ConnectionServiceAdapterServant {
private static final int MSG_SET_PHONE_ACCOUNT_CHANGED = 34;
private static final int MSG_CONNECTION_SERVICE_FOCUS_RELEASED = 35;
private static final int MSG_SET_CONFERENCE_STATE = 36;
private static final int MSG_HANDLE_CREATE_CONFERENCE_COMPLETE = 37;
private final IConnectionServiceAdapter mDelegate;
@@ -103,6 +104,19 @@ final class ConnectionServiceAdapterServant {
}
break;
}
case MSG_HANDLE_CREATE_CONFERENCE_COMPLETE: {
SomeArgs args = (SomeArgs) msg.obj;
try {
mDelegate.handleCreateConferenceComplete(
(String) args.arg1,
(ConnectionRequest) args.arg2,
(ParcelableConference) args.arg3,
null /*Session.Info*/);
} finally {
args.recycle();
}
break;
}
case MSG_SET_ACTIVE:
mDelegate.setActive((String) msg.obj, null /*Session.Info*/);
break;
@@ -365,6 +379,20 @@ final class ConnectionServiceAdapterServant {
mHandler.obtainMessage(MSG_HANDLE_CREATE_CONNECTION_COMPLETE, args).sendToTarget();
}
@Override
public void handleCreateConferenceComplete(
String id,
ConnectionRequest request,
ParcelableConference conference,
Session.Info sessionInfo) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = id;
args.arg2 = request;
args.arg3 = conference;
mHandler.obtainMessage(MSG_HANDLE_CREATE_CONFERENCE_COMPLETE, args).sendToTarget();
}
@Override
public void setActive(String connectionId, Session.Info sessionInfo) {
mHandler.obtainMessage(MSG_SET_ACTIVE, connectionId).sendToTarget();

View File

@@ -47,6 +47,34 @@ public final class ParcelableConference implements Parcelable {
private final int mAddressPresentation;
private final String mCallerDisplayName;
private final int mCallerDisplayNamePresentation;
private DisconnectCause mDisconnectCause;
private boolean mRingbackRequested;
public ParcelableConference(
PhoneAccountHandle phoneAccount,
int state,
int connectionCapabilities,
int connectionProperties,
List<String> connectionIds,
IVideoProvider videoProvider,
int videoState,
long connectTimeMillis,
long connectElapsedTimeMillis,
StatusHints statusHints,
Bundle extras,
Uri address,
int addressPresentation,
String callerDisplayName,
int callerDisplayNamePresentation,
DisconnectCause disconnectCause,
boolean ringbackRequested) {
this(phoneAccount, state, connectionCapabilities, connectionProperties, connectionIds,
videoProvider, videoState, connectTimeMillis, connectElapsedTimeMillis,
statusHints, extras, address, addressPresentation, callerDisplayName,
callerDisplayNamePresentation);
mDisconnectCause = disconnectCause;
mRingbackRequested = ringbackRequested;
}
public ParcelableConference(
PhoneAccountHandle phoneAccount,
@@ -79,6 +107,8 @@ public final class ParcelableConference implements Parcelable {
mAddressPresentation = addressPresentation;
mCallerDisplayName = callerDisplayName;
mCallerDisplayNamePresentation = callerDisplayNamePresentation;
mDisconnectCause = null;
mRingbackRequested = false;
}
@Override
@@ -100,6 +130,10 @@ public final class ParcelableConference implements Parcelable {
.append(mVideoState)
.append(", VideoProvider: ")
.append(mVideoProvider)
.append(", isRingbackRequested: ")
.append(mRingbackRequested)
.append(", disconnectCause: ")
.append(mDisconnectCause)
.toString();
}
@@ -151,6 +185,13 @@ public final class ParcelableConference implements Parcelable {
return mAddress;
}
public final DisconnectCause getDisconnectCause() {
return mDisconnectCause;
}
public boolean isRingbackRequested() {
return mRingbackRequested;
}
public int getHandlePresentation() {
return mAddressPresentation;
}
@@ -177,11 +218,14 @@ public final class ParcelableConference implements Parcelable {
int addressPresentation = source.readInt();
String callerDisplayName = source.readString();
int callerDisplayNamePresentation = source.readInt();
DisconnectCause disconnectCause = source.readParcelable(classLoader);
boolean isRingbackRequested = source.readInt() == 1;
return new ParcelableConference(phoneAccount, state, capabilities, properties,
connectionIds, videoCallProvider, videoState, connectTimeMillis,
connectElapsedTimeMillis, statusHints, extras, address, addressPresentation,
callerDisplayName, callerDisplayNamePresentation);
callerDisplayName, callerDisplayNamePresentation, disconnectCause,
isRingbackRequested);
}
@Override
@@ -215,5 +259,7 @@ public final class ParcelableConference implements Parcelable {
destination.writeInt(mAddressPresentation);
destination.writeString(mCallerDisplayName);
destination.writeInt(mCallerDisplayNamePresentation);
destination.writeParcelable(mDisconnectCause, 0);
destination.writeInt(mRingbackRequested ? 1 : 0);
}
}

View File

@@ -331,7 +331,17 @@ public final class PhoneAccount implements Parcelable {
*/
public static final int CAPABILITY_EMERGENCY_PREFERRED = 0x2000;
/* NEXT CAPABILITY: 0x4000 */
/**
* An adhoc conference call is established by providing a list of addresses to
* {@code TelecomManager#startConference(List<Uri>, int videoState)} where the
* {@link ConnectionService} is responsible for connecting all indicated participants
* to a conference simultaneously.
* This is in contrast to conferences formed by merging calls together (e.g. using
* {@link android.telecom.Call#mergeConference()}).
*/
public static final int CAPABILITY_ADHOC_CONFERENCE_CALLING = 0x4000;
/* NEXT CAPABILITY: 0x8000 */
/**
* URI scheme for telephone number URIs.
@@ -1054,6 +1064,9 @@ public final class PhoneAccount implements Parcelable {
if (hasCapabilities(CAPABILITY_RTT)) {
sb.append("Rtt");
}
if (hasCapabilities(CAPABILITY_ADHOC_CONFERENCE_CALLING)) {
sb.append("AdhocConf");
}
return sb.toString();
}

View File

@@ -100,6 +100,14 @@ final class RemoteConnectionService {
}
}
@Override
public void handleCreateConferenceComplete(
String id,
ConnectionRequest request,
ParcelableConference parcel,
Session.Info info) {
}
@Override
public void setActive(String callId, Session.Info sessionInfo) {
if (mConnectionById.containsKey(callId)) {

View File

@@ -1802,6 +1802,45 @@ public class TelecomManager {
}
}
/**
* Registers a new incoming conference. A {@link ConnectionService} should invoke this method
* when it has an incoming conference. For managed {@link ConnectionService}s, the specified
* {@link PhoneAccountHandle} must have been registered with {@link #registerPhoneAccount} and
* the user must have enabled the corresponding {@link PhoneAccount}. This can be checked using
* {@link #getPhoneAccount}. Self-managed {@link ConnectionService}s must have
* {@link android.Manifest.permission#MANAGE_OWN_CALLS} to add a new incoming call.
* <p>
* The incoming conference you are adding is assumed to have a video state of
* {@link VideoProfile#STATE_AUDIO_ONLY}, unless the extra value
* {@link #EXTRA_INCOMING_VIDEO_STATE} is specified.
* <p>
* Once invoked, this method will cause the system to bind to the {@link ConnectionService}
* associated with the {@link PhoneAccountHandle} and request additional information about the
* call (See {@link ConnectionService#onCreateIncomingConference}) before starting the incoming
* call UI.
* <p>
* For a managed {@link ConnectionService}, a {@link SecurityException} will be thrown if either
* the {@link PhoneAccountHandle} does not correspond to a registered {@link PhoneAccount} or
* the associated {@link PhoneAccount} is not currently enabled by the user.
*
* @param phoneAccount A {@link PhoneAccountHandle} registered with
* {@link #registerPhoneAccount}.
* @param extras A bundle that will be passed through to
* {@link ConnectionService#onCreateIncomingConference}.
*/
public void addNewIncomingConference(@NonNull PhoneAccountHandle phoneAccount,
@NonNull Bundle extras) {
try {
if (isServiceConnected()) {
getTelecomService().addNewIncomingConference(
phoneAccount, extras == null ? new Bundle() : extras);
}
} catch (RemoteException e) {
Log.e(TAG, "RemoteException adding a new incoming conference: " + phoneAccount, e);
}
}
/**
* Registers a new unknown call with Telecom. This can only be called by the system Telephony
* service. This is invoked when Telephony detects a new unknown connection that was neither
@@ -2006,6 +2045,42 @@ public class TelecomManager {
}
}
/**
* Place a new conference call with the provided participants using the system telecom service
* This method doesn't support placing of emergency calls.
*
* An adhoc conference call is established by providing a list of addresses to
* {@code TelecomManager#startConference(List<Uri>, int videoState)} where the
* {@link ConnectionService} is responsible for connecting all indicated participants
* to a conference simultaneously.
* This is in contrast to conferences formed by merging calls together (e.g. using
* {@link android.telecom.Call#mergeConference()}).
*
* The following keys are supported in the supplied extras.
* <ul>
* <li>{@link #EXTRA_PHONE_ACCOUNT_HANDLE}</li>
* <li>{@link #EXTRA_START_CALL_WITH_SPEAKERPHONE}</li>
* <li>{@link #EXTRA_START_CALL_WITH_VIDEO_STATE}</li>
* </ul>
*
* @param participants List of participants to start conference with
* @param extras Bundle of extras to use with the call
*/
@RequiresPermission(android.Manifest.permission.CALL_PHONE)
public void startConference(@NonNull List<Uri> participants,
@NonNull Bundle extras) {
ITelecomService service = getTelecomService();
if (service != null) {
try {
service.startConference(participants, extras,
mContext.getOpPackageName());
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelecomService#placeCall", e);
}
}
}
/**
* Enables and disables specified phone account.
*

View File

@@ -53,6 +53,20 @@ oneway interface IConnectionService {
void createConnectionFailed(in PhoneAccountHandle connectionManagerPhoneAccount, String callId,
in ConnectionRequest request, boolean isIncoming, in Session.Info sessionInfo);
void createConference(
in PhoneAccountHandle connectionManagerPhoneAccount,
String callId,
in ConnectionRequest request,
boolean isIncoming,
boolean isUnknown,
in Session.Info sessionInfo);
void createConferenceComplete(String callId, in Session.Info sessionInfo);
void createConferenceFailed(in PhoneAccountHandle connectionManagerPhoneAccount, String callId,
in ConnectionRequest request, boolean isIncoming, in Session.Info sessionInfo);
void abort(String callId, in Session.Info sessionInfo);
void answerVideo(String callId, int videoState, in Session.Info sessionInfo);

View File

@@ -44,6 +44,12 @@ oneway interface IConnectionServiceAdapter {
in ParcelableConnection connection,
in Session.Info sessionInfo);
void handleCreateConferenceComplete(
String callId,
in ConnectionRequest request,
in ParcelableConference connection,
in Session.Info sessionInfo);
void setActive(String callId, in Session.Info sessionInfo);
void setRinging(String callId, in Session.Info sessionInfo);

View File

@@ -241,11 +241,22 @@ interface ITelecomService {
*/
void addNewIncomingCall(in PhoneAccountHandle phoneAccount, in Bundle extras);
/**
* @see TelecomServiceImpl#addNewIncomingConference
*/
void addNewIncomingConference(in PhoneAccountHandle phoneAccount, in Bundle extras);
/**
* @see TelecomServiceImpl#addNewUnknownCall
*/
void addNewUnknownCall(in PhoneAccountHandle phoneAccount, in Bundle extras);
/**
* @see TelecomServiceImpl#startConference
*/
void startConference(in List<Uri> participants, in Bundle extras,
String callingPackage);
/**
* @see TelecomServiceImpl#placeCall
*/

View File

@@ -1079,6 +1079,14 @@ public class CarrierConfigManager {
public static final String KEY_IGNORE_RTT_MODE_SETTING_BOOL =
"ignore_rtt_mode_setting_bool";
/**
* Determines whether adhoc conference calls are supported by a carrier. When {@code true},
* adhoc conference calling is supported, {@code false otherwise}.
*/
public static final String KEY_SUPPORT_ADHOC_CONFERENCE_CALLS_BOOL =
"support_adhoc_conference_calls_bool";
/**
* Determines whether conference calls are supported by a carrier. When {@code true},
* conference calling is supported, {@code false otherwise}.
@@ -3522,6 +3530,7 @@ public class CarrierConfigManager {
sDefaults.putBoolean(KEY_CALL_FORWARDING_MAP_NON_NUMBER_TO_VOICEMAIL_BOOL, false);
sDefaults.putBoolean(KEY_IGNORE_RTT_MODE_SETTING_BOOL, false);
sDefaults.putInt(KEY_CDMA_3WAYCALL_FLASH_DELAY_INT , 0);
sDefaults.putBoolean(KEY_SUPPORT_ADHOC_CONFERENCE_CALLS_BOOL, false);
sDefaults.putBoolean(KEY_SUPPORT_CONFERENCE_CALL_BOOL, true);
sDefaults.putBoolean(KEY_SUPPORT_IMS_CONFERENCE_CALL_BOOL, true);
sDefaults.putBoolean(KEY_SUPPORT_MANAGE_IMS_CONFERENCE_CALL_BOOL, true);