Ims: Add support for Adhoc Conference calls
Add support for Adhoc Conference calls Test: Manual Bug: 62151032 Change-Id: Id50d235595d2133f867848ffdebdfe11e2f1c896
This commit is contained in:
@@ -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}.
|
||||
|
||||
Reference in New Issue
Block a user