Merge "Ims: Add support for Adhoc Conference calls" am: 0ab00030a2 am: cac198c770 am: a6d033fa37
Change-Id: I866deb01383fdc648822ef60304f4ca54c36b699
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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}.
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -1809,6 +1809,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
|
||||
@@ -2014,6 +2053,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.
|
||||
*
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -245,11 +245,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
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user