Finalize implementation of Remote Connection Service (1/4)
Change-Id: I3788c9ab03a979f22ab628637adf6d520038cb6e
This commit is contained in:
@@ -74,7 +74,7 @@ public final class Call {
|
||||
private final String mCallerDisplayName;
|
||||
private final int mCallerDisplayNamePresentation;
|
||||
private final PhoneAccountHandle mAccountHandle;
|
||||
private final int mCapabilities;
|
||||
private final int mCallCapabilities;
|
||||
private final int mDisconnectCauseCode;
|
||||
private final String mDisconnectCauseMsg;
|
||||
private final long mConnectTimeMillis;
|
||||
@@ -125,8 +125,8 @@ public final class Call {
|
||||
* @return A bitmask of the capabilities of the {@code Call}, as defined in
|
||||
* {@link CallCapabilities}.
|
||||
*/
|
||||
public int getCapabilities() {
|
||||
return mCapabilities;
|
||||
public int getCallCapabilities() {
|
||||
return mCallCapabilities;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -162,14 +162,15 @@ public final class Call {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the video state of the {@code Call}.
|
||||
* @return The video state of the {@code Call}.
|
||||
*/
|
||||
public int getVideoState() {
|
||||
return mVideoState;
|
||||
}
|
||||
|
||||
/*
|
||||
* @return The current {@link android.telecomm.StatusHints}, or null if none has been set.
|
||||
/**
|
||||
* @return The current {@link android.telecomm.StatusHints}, or {@code null} if none
|
||||
* have been set.
|
||||
*/
|
||||
public StatusHints getStatusHints() {
|
||||
return mStatusHints;
|
||||
@@ -186,7 +187,7 @@ public final class Call {
|
||||
Objects.equals(mCallerDisplayNamePresentation,
|
||||
d.mCallerDisplayNamePresentation) &&
|
||||
Objects.equals(mAccountHandle, d.mAccountHandle) &&
|
||||
Objects.equals(mCapabilities, d.mCapabilities) &&
|
||||
Objects.equals(mCallCapabilities, d.mCallCapabilities) &&
|
||||
Objects.equals(mDisconnectCauseCode, d.mDisconnectCauseCode) &&
|
||||
Objects.equals(mDisconnectCauseMsg, d.mDisconnectCauseMsg) &&
|
||||
Objects.equals(mConnectTimeMillis, d.mConnectTimeMillis) &&
|
||||
@@ -205,7 +206,7 @@ public final class Call {
|
||||
Objects.hashCode(mCallerDisplayName) +
|
||||
Objects.hashCode(mCallerDisplayNamePresentation) +
|
||||
Objects.hashCode(mAccountHandle) +
|
||||
Objects.hashCode(mCapabilities) +
|
||||
Objects.hashCode(mCallCapabilities) +
|
||||
Objects.hashCode(mDisconnectCauseCode) +
|
||||
Objects.hashCode(mDisconnectCauseMsg) +
|
||||
Objects.hashCode(mConnectTimeMillis) +
|
||||
@@ -233,7 +234,7 @@ public final class Call {
|
||||
mCallerDisplayName = callerDisplayName;
|
||||
mCallerDisplayNamePresentation = callerDisplayNamePresentation;
|
||||
mAccountHandle = accountHandle;
|
||||
mCapabilities = capabilities;
|
||||
mCallCapabilities = capabilities;
|
||||
mDisconnectCauseCode = disconnectCauseCode;
|
||||
mDisconnectCauseMsg = disconnectCauseMsg;
|
||||
mConnectTimeMillis = connectTimeMillis;
|
||||
@@ -288,15 +289,6 @@ public final class Call {
|
||||
*/
|
||||
public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {}
|
||||
|
||||
/**
|
||||
* Invoked when the outgoing {@code Call} has finished dialing but is sending DTMF signals
|
||||
* that were embedded into the outgoing number.
|
||||
*
|
||||
* @param call The {@code Call} invoking this method.
|
||||
* @param remainingPostDialSequence The post-dial characters that remain to be sent.
|
||||
*/
|
||||
public void onPostDial(Call call, String remainingPostDialSequence) {}
|
||||
|
||||
/**
|
||||
* Invoked when the post-dial sequence in the outgoing {@code Call} has reached a pause
|
||||
* character. This causes the post-dial signals to stop pending user confirmation. An
|
||||
@@ -314,7 +306,6 @@ public final class Call {
|
||||
* @param call The {@code Call} invoking this method.
|
||||
* @param videoCall The {@code Call.VideoCall} associated with the {@code Call}.
|
||||
*/
|
||||
|
||||
public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {}
|
||||
|
||||
/**
|
||||
@@ -427,8 +418,6 @@ public final class Call {
|
||||
*
|
||||
* A post-dial DTMF string is a string of digits entered after a phone number, when dialed,
|
||||
* that are immediately sent as DTMF tones to the recipient as soon as the connection is made.
|
||||
* While these tones are playing, this {@code Call} will notify listeners via
|
||||
* {@link Listener#onPostDial(Call, String)}.
|
||||
*
|
||||
* If the DTMF string contains a {@link TelecommManager#DTMF_CHARACTER_PAUSE} symbol, this
|
||||
* {@code Call} will temporarily pause playing the tones for a pre-defined period of time.
|
||||
@@ -656,12 +645,6 @@ public final class Call {
|
||||
}
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
final void internalSetPostDial(String remaining) {
|
||||
mRemainingPostDialSequence = remaining;
|
||||
firePostDial(mRemainingPostDialSequence);
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
final void internalSetPostDialWait(String remaining) {
|
||||
mRemainingPostDialSequence = remaining;
|
||||
@@ -715,13 +698,6 @@ public final class Call {
|
||||
}
|
||||
}
|
||||
|
||||
private void firePostDial(String remainingPostDialSequence) {
|
||||
Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
|
||||
for (int i = 0; i < listeners.length; i++) {
|
||||
listeners[i].onPostDial(this, remainingPostDialSequence);
|
||||
}
|
||||
}
|
||||
|
||||
private void firePostDialWait(String remainingPostDialSequence) {
|
||||
Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
|
||||
for (int i = 0; i < listeners.length; i++) {
|
||||
|
||||
@@ -39,6 +39,7 @@ import com.android.internal.telecomm.IVideoCallCallback;
|
||||
import com.android.internal.telecomm.IVideoCallProvider;
|
||||
import com.android.internal.telecomm.RemoteServiceCallback;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -81,6 +82,7 @@ public abstract class ConnectionService extends Service {
|
||||
private final RemoteConnectionManager mRemoteConnectionManager = new RemoteConnectionManager();
|
||||
|
||||
private boolean mAreAccountsInitialized = false;
|
||||
private final List<Runnable> mPreInitializationConnectionRequests = new ArrayList<>();
|
||||
private final ConnectionServiceAdapter mAdapter = new ConnectionServiceAdapter();
|
||||
|
||||
/**
|
||||
@@ -226,11 +228,23 @@ public abstract class ConnectionService extends Service {
|
||||
case MSG_CREATE_CONNECTION: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
try {
|
||||
PhoneAccountHandle connectionManagerPhoneAccount =
|
||||
final PhoneAccountHandle connectionManagerPhoneAccount =
|
||||
(PhoneAccountHandle) args.arg1;
|
||||
ConnectionRequest request = (ConnectionRequest) args.arg2;
|
||||
boolean isIncoming = args.argi1 == 1;
|
||||
createConnection(connectionManagerPhoneAccount, request, isIncoming);
|
||||
final ConnectionRequest request = (ConnectionRequest) args.arg2;
|
||||
final boolean isIncoming = args.argi1 == 1;
|
||||
if (!mAreAccountsInitialized) {
|
||||
mPreInitializationConnectionRequests.add(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
createConnection(
|
||||
connectionManagerPhoneAccount,
|
||||
request,
|
||||
isIncoming);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
createConnection(connectionManagerPhoneAccount, request, isIncoming);
|
||||
}
|
||||
} finally {
|
||||
args.recycle();
|
||||
}
|
||||
@@ -643,7 +657,7 @@ public abstract class ConnectionService extends Service {
|
||||
componentNames.get(i),
|
||||
IConnectionService.Stub.asInterface(services.get(i)));
|
||||
}
|
||||
mAreAccountsInitialized = true;
|
||||
onAccountsInitialized();
|
||||
Log.d(this, "remote connection services found: " + services);
|
||||
}
|
||||
});
|
||||
@@ -803,6 +817,14 @@ public abstract class ConnectionService extends Service {
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private void onAccountsInitialized() {
|
||||
mAreAccountsInitialized = true;
|
||||
for (Runnable r : mPreInitializationConnectionRequests) {
|
||||
r.run();
|
||||
}
|
||||
mPreInitializationConnectionRequests.clear();
|
||||
}
|
||||
|
||||
private void addConnection(String callId, Connection connection) {
|
||||
mConnectionById.put(callId, connection);
|
||||
mIdByConnection.put(connection, callId);
|
||||
|
||||
@@ -0,0 +1,377 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
R* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.telecomm;
|
||||
|
||||
import com.android.internal.os.SomeArgs;
|
||||
import com.android.internal.telecomm.IConnectionServiceAdapter;
|
||||
import com.android.internal.telecomm.IVideoCallProvider;
|
||||
import com.android.internal.telecomm.RemoteServiceCallback;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
|
||||
/**
|
||||
* A component that provides an RPC servant implementation of {@link IConnectionServiceAdapter},
|
||||
* posting incoming messages on the main thread on a client-supplied delegate object.
|
||||
*
|
||||
* TODO: Generate this and similar classes using a compiler starting from AIDL interfaces.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
final class ConnectionServiceAdapterServant {
|
||||
private static final int MSG_HANDLE_CREATE_CONNECTION_SUCCESSFUL = 1;
|
||||
private static final int MSG_HANDLE_CREATE_CONNECTION_FAILED = 2;
|
||||
private static final int MSG_HANDLE_CREATE_CONNECTION_CANCELLED = 3;
|
||||
private static final int MSG_SET_ACTIVE = 4;
|
||||
private static final int MSG_SET_RINGING = 5;
|
||||
private static final int MSG_SET_DIALING = 6;
|
||||
private static final int MSG_SET_DISCONNECTED = 7;
|
||||
private static final int MSG_SET_ON_HOLD = 8;
|
||||
private static final int MSG_SET_REQUESTING_RINGBACK = 9;
|
||||
private static final int MSG_SET_CALL_CAPABILITIES = 10;
|
||||
private static final int MSG_SET_IS_CONFERENCED = 11;
|
||||
private static final int MSG_ADD_CONFERENCE_CALL = 12;
|
||||
private static final int MSG_REMOVE_CALL = 13;
|
||||
private static final int MSG_ON_POST_DIAL_WAIT = 14;
|
||||
private static final int MSG_QUERY_REMOTE_CALL_SERVICES = 15;
|
||||
private static final int MSG_SET_VIDEO_STATE = 16;
|
||||
private static final int MSG_SET_VIDEO_CALL_PROVIDER = 17;
|
||||
private static final int MSG_SET_AUDIO_MODE_IS_VOIP = 18;
|
||||
private static final int MSG_SET_STATUS_HINTS = 19;
|
||||
private static final int MSG_SET_HANDLE = 20;
|
||||
private static final int MSG_SET_CALLER_DISPLAY_NAME = 21;
|
||||
private static final int MSG_START_ACTIVITY_FROM_IN_CALL = 22;
|
||||
|
||||
private final IConnectionServiceAdapter mDelegate;
|
||||
|
||||
private final Handler mHandler = new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
try {
|
||||
internalHandleMessage(msg);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
|
||||
// Internal method defined to centralize handling of RemoteException
|
||||
private void internalHandleMessage(Message msg) throws RemoteException {
|
||||
switch (msg.what) {
|
||||
case MSG_HANDLE_CREATE_CONNECTION_SUCCESSFUL: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
try {
|
||||
mDelegate.handleCreateConnectionSuccessful(
|
||||
(ConnectionRequest) args.arg1,
|
||||
(ParcelableConnection) args.arg2);
|
||||
} finally {
|
||||
args.recycle();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_HANDLE_CREATE_CONNECTION_FAILED: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
try {
|
||||
mDelegate.handleCreateConnectionFailed(
|
||||
(ConnectionRequest) args.arg1,
|
||||
args.argi1,
|
||||
(String) args.arg2);
|
||||
} finally {
|
||||
args.recycle();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_HANDLE_CREATE_CONNECTION_CANCELLED: {
|
||||
mDelegate.handleCreateConnectionCancelled((ConnectionRequest) msg.obj);
|
||||
break;
|
||||
}
|
||||
case MSG_SET_ACTIVE:
|
||||
mDelegate.setActive((String) msg.obj);
|
||||
break;
|
||||
case MSG_SET_RINGING:
|
||||
mDelegate.setRinging((String) msg.obj);
|
||||
break;
|
||||
case MSG_SET_DIALING:
|
||||
mDelegate.setDialing((String) msg.obj);
|
||||
break;
|
||||
case MSG_SET_DISCONNECTED: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
try {
|
||||
mDelegate.setDisconnected(
|
||||
(String) args.arg1, args.argi1, (String) args.arg2);
|
||||
} finally {
|
||||
args.recycle();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_SET_ON_HOLD:
|
||||
mDelegate.setOnHold((String) msg.obj);
|
||||
break;
|
||||
case MSG_SET_REQUESTING_RINGBACK:
|
||||
mDelegate.setRequestingRingback((String) msg.obj, msg.arg1 == 1);
|
||||
break;
|
||||
case MSG_SET_CALL_CAPABILITIES:
|
||||
mDelegate.setCallCapabilities((String) msg.obj, msg.arg1);
|
||||
break;
|
||||
case MSG_SET_IS_CONFERENCED: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
try {
|
||||
mDelegate.setIsConferenced((String) args.arg1, (String) args.arg2);
|
||||
} finally {
|
||||
args.recycle();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_ADD_CONFERENCE_CALL:
|
||||
mDelegate.addConferenceCall((String) msg.obj);
|
||||
break;
|
||||
case MSG_REMOVE_CALL:
|
||||
mDelegate.removeCall((String) msg.obj);
|
||||
break;
|
||||
case MSG_ON_POST_DIAL_WAIT: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
try {
|
||||
mDelegate.onPostDialWait((String) args.arg1, (String) args.arg2);
|
||||
} finally {
|
||||
args.recycle();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_QUERY_REMOTE_CALL_SERVICES:
|
||||
mDelegate.queryRemoteConnectionServices((RemoteServiceCallback) msg.obj);
|
||||
break;
|
||||
case MSG_SET_VIDEO_STATE:
|
||||
mDelegate.setVideoState((String) msg.obj, msg.arg1);
|
||||
break;
|
||||
case MSG_SET_VIDEO_CALL_PROVIDER: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
try {
|
||||
mDelegate.setVideoCallProvider((String) args.arg1,
|
||||
(IVideoCallProvider) args.arg2);
|
||||
} finally {
|
||||
args.recycle();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_SET_AUDIO_MODE_IS_VOIP:
|
||||
mDelegate.setAudioModeIsVoip((String) msg.obj, msg.arg1 == 1);
|
||||
break;
|
||||
case MSG_SET_STATUS_HINTS: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
try {
|
||||
mDelegate.setStatusHints((String) args.arg1, (StatusHints) args.arg2);
|
||||
} finally {
|
||||
args.recycle();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_SET_HANDLE: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
try {
|
||||
mDelegate.setHandle((String) args.arg1, (Uri) args.arg2, args.argi1);
|
||||
} finally {
|
||||
args.recycle();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_SET_CALLER_DISPLAY_NAME: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
try {
|
||||
mDelegate.setCallerDisplayName(
|
||||
(String) args.arg1, (String) args.arg2, args.argi1);
|
||||
} finally {
|
||||
args.recycle();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_START_ACTIVITY_FROM_IN_CALL: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
try {
|
||||
mDelegate.startActivityFromInCall(
|
||||
(String) args.arg1, (PendingIntent) args.arg2);
|
||||
} finally {
|
||||
args.recycle();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final IConnectionServiceAdapter mStub = new IConnectionServiceAdapter.Stub() {
|
||||
@Override
|
||||
public void handleCreateConnectionSuccessful(
|
||||
ConnectionRequest request, ParcelableConnection connection) {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = request;
|
||||
args.arg2 = connection;
|
||||
mHandler.obtainMessage(MSG_HANDLE_CREATE_CONNECTION_SUCCESSFUL, args).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCreateConnectionFailed(
|
||||
ConnectionRequest request, int errorCode, String errorMessage) {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = request;
|
||||
args.argi1 = errorCode;
|
||||
args.arg2 = errorMessage;
|
||||
mHandler.obtainMessage(MSG_HANDLE_CREATE_CONNECTION_FAILED, args).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCreateConnectionCancelled(ConnectionRequest request) {
|
||||
mHandler.obtainMessage(MSG_HANDLE_CREATE_CONNECTION_CANCELLED, request).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActive(String connectionId) {
|
||||
mHandler.obtainMessage(MSG_SET_ACTIVE, connectionId).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRinging(String connectionId) {
|
||||
mHandler.obtainMessage(MSG_SET_RINGING, connectionId).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDialing(String connectionId) {
|
||||
mHandler.obtainMessage(MSG_SET_DIALING, connectionId).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDisconnected(
|
||||
String connectionId, int disconnectCause, String disconnectMessage) {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = connectionId;
|
||||
args.arg2 = disconnectMessage;
|
||||
args.argi1 = disconnectCause;
|
||||
mHandler.obtainMessage(MSG_SET_DISCONNECTED, args).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnHold(String connectionId) {
|
||||
mHandler.obtainMessage(MSG_SET_ON_HOLD, connectionId).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRequestingRingback(String connectionId, boolean ringback) {
|
||||
mHandler.obtainMessage(MSG_SET_REQUESTING_RINGBACK, ringback ? 1 : 0, 0, connectionId)
|
||||
.sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCallCapabilities(String connectionId, int callCapabilities) {
|
||||
mHandler.obtainMessage(MSG_SET_CALL_CAPABILITIES, callCapabilities, 0, connectionId)
|
||||
.sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIsConferenced(String callId, String conferenceCallId) {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = callId;
|
||||
args.arg2 = conferenceCallId;
|
||||
mHandler.obtainMessage(MSG_SET_IS_CONFERENCED, args).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addConferenceCall(String callId) {
|
||||
mHandler.obtainMessage(MSG_ADD_CONFERENCE_CALL, callId).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCall(String connectionId) {
|
||||
mHandler.obtainMessage(MSG_REMOVE_CALL, connectionId).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPostDialWait(String connectionId, String remainingDigits) {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = connectionId;
|
||||
args.arg2 = remainingDigits;
|
||||
mHandler.obtainMessage(MSG_ON_POST_DIAL_WAIT, args).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queryRemoteConnectionServices(RemoteServiceCallback callback) {
|
||||
mHandler.obtainMessage(MSG_QUERY_REMOTE_CALL_SERVICES, callback).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVideoState(String connectionId, int videoState) {
|
||||
mHandler.obtainMessage(MSG_SET_VIDEO_STATE, videoState, 0, connectionId).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVideoCallProvider(
|
||||
String connectionId, IVideoCallProvider videoCallProvider) {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = connectionId;
|
||||
args.arg2 = videoCallProvider;
|
||||
mHandler.obtainMessage(MSG_SET_VIDEO_CALL_PROVIDER, args).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setAudioModeIsVoip(String connectionId, boolean isVoip) {
|
||||
mHandler.obtainMessage(MSG_SET_AUDIO_MODE_IS_VOIP, isVoip ? 1 : 0, 0,
|
||||
connectionId).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setStatusHints(String connectionId, StatusHints statusHints) {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = connectionId;
|
||||
args.arg2 = statusHints;
|
||||
mHandler.obtainMessage(MSG_SET_STATUS_HINTS, args).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setHandle(String connectionId, Uri handle, int presentation) {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = connectionId;
|
||||
args.arg2 = handle;
|
||||
args.argi1 = presentation;
|
||||
mHandler.obtainMessage(MSG_SET_HANDLE, args).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setCallerDisplayName(
|
||||
String connectionId, String callerDisplayName, int presentation) {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = connectionId;
|
||||
args.arg2 = callerDisplayName;
|
||||
args.argi1 = presentation;
|
||||
mHandler.obtainMessage(MSG_SET_CALLER_DISPLAY_NAME, args).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void startActivityFromInCall(String connectionId, PendingIntent intent) {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = connectionId;
|
||||
args.arg2 = intent;
|
||||
mHandler.obtainMessage(MSG_START_ACTIVITY_FROM_IN_CALL, args).sendToTarget();
|
||||
}
|
||||
};
|
||||
|
||||
public ConnectionServiceAdapterServant(IConnectionServiceAdapter delegate) {
|
||||
mDelegate = delegate;
|
||||
}
|
||||
|
||||
public IConnectionServiceAdapter getStub() {
|
||||
return mStub;
|
||||
}
|
||||
}
|
||||
@@ -41,11 +41,10 @@ public abstract class InCallService extends Service {
|
||||
private static final int MSG_SET_IN_CALL_ADAPTER = 1;
|
||||
private static final int MSG_ADD_CALL = 2;
|
||||
private static final int MSG_UPDATE_CALL = 3;
|
||||
private static final int MSG_SET_POST_DIAL = 4;
|
||||
private static final int MSG_SET_POST_DIAL_WAIT = 5;
|
||||
private static final int MSG_ON_AUDIO_STATE_CHANGED = 6;
|
||||
private static final int MSG_BRING_TO_FOREGROUND = 7;
|
||||
private static final int MSG_START_ACTIVITY = 8;
|
||||
private static final int MSG_SET_POST_DIAL_WAIT = 4;
|
||||
private static final int MSG_ON_AUDIO_STATE_CHANGED = 5;
|
||||
private static final int MSG_BRING_TO_FOREGROUND = 6;
|
||||
private static final int MSG_START_ACTIVITY = 7;
|
||||
|
||||
/** Default Handler used to consolidate binder method calls onto a single thread. */
|
||||
private final Handler mHandler = new Handler(Looper.getMainLooper()) {
|
||||
@@ -62,17 +61,6 @@ public abstract class InCallService extends Service {
|
||||
case MSG_UPDATE_CALL:
|
||||
mPhone.internalUpdateCall((ParcelableCall) msg.obj);
|
||||
break;
|
||||
case MSG_SET_POST_DIAL: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
try {
|
||||
String callId = (String) args.arg1;
|
||||
String remaining = (String) args.arg2;
|
||||
mPhone.internalSetPostDial(callId, remaining);
|
||||
} finally {
|
||||
args.recycle();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_SET_POST_DIAL_WAIT: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
try {
|
||||
@@ -124,10 +112,7 @@ public abstract class InCallService extends Service {
|
||||
|
||||
@Override
|
||||
public void setPostDial(String callId, String remaining) {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = callId;
|
||||
args.arg2 = remaining;
|
||||
mHandler.obtainMessage(MSG_SET_POST_DIAL, args).sendToTarget();
|
||||
// TODO: Unused
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -120,14 +120,6 @@ public final class Phone {
|
||||
}
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
final void internalSetPostDial(String telecommId, String remaining) {
|
||||
Call call = mCallByTelecommCallId.get(telecommId);
|
||||
if (call != null) {
|
||||
call.internalSetPostDial(remaining);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
final void internalSetPostDialWait(String telecommId, String remaining) {
|
||||
Call call = mCallByTelecommCallId.get(telecommId);
|
||||
|
||||
@@ -24,25 +24,152 @@ import android.telephony.DisconnectCause;
|
||||
import com.android.internal.telecomm.IConnectionService;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* RemoteConnection object used by RemoteConnectionService.
|
||||
*/
|
||||
public final class RemoteConnection {
|
||||
|
||||
public static abstract class Listener {
|
||||
/**
|
||||
* Invoked when the state of this {@code RemoteConnection} has changed. See
|
||||
* {@link #getState()}.
|
||||
*
|
||||
* @param connection The {@code RemoteConnection} invoking this method.
|
||||
* @param state The new state of the {@code RemoteConnection}.
|
||||
*/
|
||||
public void onStateChanged(RemoteConnection connection, int state) {}
|
||||
public void onDisconnected(RemoteConnection connection, int cause, String message) {}
|
||||
|
||||
/**
|
||||
* Invoked when the parent of this {@code RemoteConnection} has changed. See
|
||||
* {@link #getParent()}.
|
||||
*
|
||||
* @param connection The {@code RemoteConnection} invoking this method.
|
||||
* @param parent The new parent of the {@code RemoteConnection}.
|
||||
*/
|
||||
public void onParentChanged(RemoteConnection connection, RemoteConnection parent) {}
|
||||
|
||||
/**
|
||||
* Invoked when the children of this {@code RemoteConnection} have changed. See
|
||||
* {@link #getChildren()}.
|
||||
*
|
||||
* @param connection The {@code RemoteConnection} invoking this method.
|
||||
* @param children The new children of the {@code RemoteConnection}.
|
||||
*/
|
||||
public void onChildrenChanged(
|
||||
RemoteConnection connection, List<RemoteConnection> children) {}
|
||||
|
||||
/**
|
||||
* Invoked when this {@code RemoteConnection} is disconnected.
|
||||
*
|
||||
* @param connection The {@code RemoteConnection} invoking this method.
|
||||
* @param disconnectCauseCode The failure code ({@see DisconnectCause}) associated with this
|
||||
* failed connection.
|
||||
* @param disconnectCauseMessage The reason for the connection failure. This will not be
|
||||
* displayed to the user.
|
||||
*/
|
||||
public void onDisconnected(
|
||||
RemoteConnection connection,
|
||||
int disconnectCauseCode,
|
||||
String disconnectCauseMessage) {}
|
||||
|
||||
/**
|
||||
* Invoked when this {@code RemoteConnection} is requesting ringback. See
|
||||
* {@link #isRequestingRingback()}.
|
||||
*
|
||||
* @param connection The {@code RemoteConnection} invoking this method.
|
||||
* @param ringback Whether the {@code RemoteConnection} is requesting ringback.
|
||||
*/
|
||||
public void onRequestingRingback(RemoteConnection connection, boolean ringback) {}
|
||||
|
||||
/**
|
||||
* Indicates that the call capabilities of this {@code RemoteConnection} have changed.
|
||||
* See {@link #getCallCapabilities()}.
|
||||
*
|
||||
* @param connection The {@code RemoteConnection} invoking this method.
|
||||
* @param callCapabilities The new call capabilities of the {@code RemoteConnection}.
|
||||
*/
|
||||
public void onCallCapabilitiesChanged(RemoteConnection connection, int callCapabilities) {}
|
||||
public void onPostDialWait(RemoteConnection connection, String remainingDigits) {}
|
||||
|
||||
/**
|
||||
* Invoked when the post-dial sequence in the outgoing {@code Connection} has reached a
|
||||
* pause character. This causes the post-dial signals to stop pending user confirmation. An
|
||||
* implementation should present this choice to the user and invoke
|
||||
* {@link #postDialContinue(boolean)} when the user makes the choice.
|
||||
*
|
||||
* @param connection The {@code RemoteConnection} invoking this method.
|
||||
* @param remainingPostDialSequence The post-dial characters that remain to be sent.
|
||||
*/
|
||||
public void onPostDialWait(RemoteConnection connection, String remainingPostDialSequence) {}
|
||||
|
||||
/**
|
||||
* Indicates that the VOIP audio status of this {@code RemoteConnection} has changed.
|
||||
* See {@link #getAudioModeIsVoip()}.
|
||||
*
|
||||
* @param connection The {@code RemoteConnection} invoking this method.
|
||||
* @param isVoip Whether the new audio state of the {@code RemoteConnection} is VOIP.
|
||||
*/
|
||||
public void onAudioModeIsVoipChanged(RemoteConnection connection, boolean isVoip) {}
|
||||
|
||||
/**
|
||||
* Indicates that the status hints of this {@code RemoteConnection} have changed. See
|
||||
* {@link #getStatusHints()} ()}.
|
||||
*
|
||||
* @param connection The {@code RemoteConnection} invoking this method.
|
||||
* @param statusHints The new status hints of the {@code RemoteConnection}.
|
||||
*/
|
||||
public void onStatusHintsChanged(RemoteConnection connection, StatusHints statusHints) {}
|
||||
|
||||
/**
|
||||
* Indicates that the handle (e.g., phone number) of this {@code RemoteConnection} has
|
||||
* changed. See {@link #getHandle()} and {@link #getHandlePresentation()}.
|
||||
*
|
||||
* @param connection The {@code RemoteConnection} invoking this method.
|
||||
* @param handle The new handle of the {@code RemoteConnection}.
|
||||
* @param presentation The {@link CallPropertyPresentation} which controls how the
|
||||
* handle is shown.
|
||||
*/
|
||||
public void onHandleChanged(RemoteConnection connection, Uri handle, int presentation) {}
|
||||
|
||||
/**
|
||||
* Indicates that the caller display name of this {@code RemoteConnection} has changed.
|
||||
* See {@link #getCallerDisplayName()} and {@link #getCallerDisplayNamePresentation()}.
|
||||
*
|
||||
* @param connection The {@code RemoteConnection} invoking this method.
|
||||
* @param callerDisplayName The new caller display name of the {@code RemoteConnection}.
|
||||
* @param presentation The {@link CallPropertyPresentation} which controls how the
|
||||
* caller display name is shown.
|
||||
*/
|
||||
public void onCallerDisplayNameChanged(
|
||||
RemoteConnection connection, String callerDisplayName, int presentation) {}
|
||||
|
||||
/**
|
||||
* Indicates that the video state of this {@code RemoteConnection} has changed.
|
||||
* See {@link #getVideoState()}.
|
||||
*
|
||||
* @param connection The {@code RemoteConnection} invoking this method.
|
||||
* @param videoState The new video state of the {@code RemoteConnection}.
|
||||
*/
|
||||
public void onVideoStateChanged(RemoteConnection connection, int videoState) {}
|
||||
|
||||
/**
|
||||
* Indicates that this {@code RemoteConnection} is requesting that the in-call UI
|
||||
* launch the specified activity.
|
||||
*
|
||||
* @param connection The {@code RemoteConnection} invoking this method.
|
||||
* @param intent A {@link PendingIntent} that the {@code RemoteConnection} wishes to
|
||||
* have launched on its behalf.
|
||||
*/
|
||||
public void onStartActivityFromInCall(RemoteConnection connection, PendingIntent intent) {}
|
||||
|
||||
/**
|
||||
* Indicates that this {@code RemoteConnection} has been destroyed. No further requests
|
||||
* should be made to the {@code RemoteConnection}, and references to it should be cleared.
|
||||
*
|
||||
* @param connection The {@code RemoteConnection} invoking this method.
|
||||
*/
|
||||
public void onDestroyed(RemoteConnection connection) {}
|
||||
}
|
||||
|
||||
@@ -51,8 +178,8 @@ public final class RemoteConnection {
|
||||
private final Set<Listener> mListeners = new HashSet<>();
|
||||
|
||||
private int mState = Connection.State.NEW;
|
||||
private int mDisconnectCause = DisconnectCause.NOT_VALID;
|
||||
private String mDisconnectMessage;
|
||||
private int mDisconnectCauseCode = DisconnectCause.NOT_VALID;
|
||||
private String mDisconnectCauseMessage;
|
||||
private boolean mRequestingRingback;
|
||||
private boolean mConnected;
|
||||
private int mCallCapabilities;
|
||||
@@ -69,10 +196,9 @@ public final class RemoteConnection {
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
RemoteConnection(IConnectionService connectionService, ConnectionRequest request,
|
||||
boolean isIncoming) {
|
||||
RemoteConnection(IConnectionService connectionService, ConnectionRequest request) {
|
||||
mConnectionService = connectionService;
|
||||
mConnectionId = request.getCallId();
|
||||
mConnectionId = request == null ? "NULL" : request.getCallId();
|
||||
|
||||
mConnected = true;
|
||||
mState = Connection.State.INITIALIZING;
|
||||
@@ -87,73 +213,161 @@ public final class RemoteConnection {
|
||||
* @param failureMessage
|
||||
*/
|
||||
private RemoteConnection(int failureCode, String failureMessage) {
|
||||
this(null, null, true);
|
||||
this(null, null);
|
||||
mConnected = false;
|
||||
mState = Connection.State.FAILED;
|
||||
mFailureCode = failureCode;
|
||||
mFailureMessage = failureMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener to this {@code RemoteConnection}.
|
||||
*
|
||||
* @param listener A {@code Listener}.
|
||||
*/
|
||||
public void addListener(Listener listener) {
|
||||
mListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a listener from this {@code RemoteConnection}.
|
||||
*
|
||||
* @param listener A {@code Listener}.
|
||||
*/
|
||||
public void removeListener(Listener listener) {
|
||||
mListeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the parent of this {@code RemoteConnection} in a conference, if any.
|
||||
*
|
||||
* @return The parent {@code RemoteConnection}, or {@code null} if this {@code RemoteConnection}
|
||||
* is not a child of any conference {@code RemoteConnection}s.
|
||||
*/
|
||||
public RemoteConnection getParent() { return null; }
|
||||
|
||||
/**
|
||||
* Obtains the children of this conference {@code RemoteConnection}, if any.
|
||||
*
|
||||
* @return The children of this {@code RemoteConnection} if this {@code RemoteConnection} is
|
||||
* a conference, or an empty {@code List} otherwise.
|
||||
*/
|
||||
public List<RemoteConnection> getChildren() { return null; }
|
||||
|
||||
/**
|
||||
* Obtains the state of this {@code RemoteConnection}.
|
||||
*
|
||||
* @return A state value, chosen from the {@code STATE_*} constants.
|
||||
*/
|
||||
public int getState() {
|
||||
return mState;
|
||||
}
|
||||
|
||||
public int getDisconnectCause() {
|
||||
return mDisconnectCause;
|
||||
/**
|
||||
* @return For a {@link Connection.State#DISCONNECTED} {@code RemoteConnection}, the
|
||||
* disconnect cause expressed as a code chosen from among those declared in
|
||||
* {@link DisconnectCause}.
|
||||
*/
|
||||
public int getDisconnectCauseCode() {
|
||||
return mDisconnectCauseCode;
|
||||
}
|
||||
|
||||
public String getDisconnectMessage() {
|
||||
return mDisconnectMessage;
|
||||
/**
|
||||
* @return For a {@link Connection.State#DISCONNECTED} {@code RemoteConnection}, an optional
|
||||
* reason for disconnection expressed as a free text message.
|
||||
*/
|
||||
public String getDisconnectCauseMessage() {
|
||||
return mDisconnectCauseMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A bitmask of the capabilities of the {@code RemoteConnection}, as defined in
|
||||
* {@link CallCapabilities}.
|
||||
*/
|
||||
public int getCallCapabilities() {
|
||||
return mCallCapabilities;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if the {@code RemoteConnection}'s current audio mode is VOIP.
|
||||
*/
|
||||
public boolean getAudioModeIsVoip() {
|
||||
return mAudioModeIsVoip;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The current {@link android.telecomm.StatusHints} of this {@code RemoteConnection},
|
||||
* or {@code null} if none have been set.
|
||||
*/
|
||||
public StatusHints getStatusHints() {
|
||||
return mStatusHints;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The handle (e.g., phone number) to which the {@code RemoteConnection} is currently
|
||||
* connected.
|
||||
*/
|
||||
public Uri getHandle() {
|
||||
return mHandle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The presentation requirements for the handle. See
|
||||
* {@link android.telecomm.CallPropertyPresentation} for valid values.
|
||||
*/
|
||||
public int getHandlePresentation() {
|
||||
return mHandlePresentation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The display name for the caller.
|
||||
*/
|
||||
public String getCallerDisplayName() {
|
||||
return mCallerDisplayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The presentation requirements for the caller display name. See
|
||||
* {@link android.telecomm.CallPropertyPresentation} for valid values.
|
||||
*/
|
||||
public int getCallerDisplayNamePresentation() {
|
||||
return mCallerDisplayNamePresentation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The video state of the {@code RemoteConnection}. See
|
||||
* {@link VideoCallProfile.VideoState}.
|
||||
*/
|
||||
public int getVideoState() {
|
||||
return mVideoState;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The failure code ({@see DisconnectCause}) associated with this failed
|
||||
* {@code RemoteConnection}.
|
||||
*/
|
||||
public int getFailureCode() {
|
||||
return mFailureCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The reason for the connection failure. This will not be displayed to the user.
|
||||
*/
|
||||
public String getFailureMessage() {
|
||||
return mFailureMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether the {@code RemoteConnection} is requesting that the framework play a
|
||||
* ringback tone on its behalf.
|
||||
*/
|
||||
public boolean isRequestingRingback() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs this {@code RemoteConnection} to abort.
|
||||
*/
|
||||
public void abort() {
|
||||
try {
|
||||
if (mConnected) {
|
||||
@@ -163,6 +377,10 @@ public final class RemoteConnection {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs this {@link Connection.State#RINGING} {@code RemoteConnection} to answer.
|
||||
* @param videoState The video state in which to answer the call.
|
||||
*/
|
||||
public void answer(int videoState) {
|
||||
try {
|
||||
if (mConnected) {
|
||||
@@ -172,6 +390,9 @@ public final class RemoteConnection {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs this {@link Connection.State#RINGING} {@code RemoteConnection} to reject.
|
||||
*/
|
||||
public void reject() {
|
||||
try {
|
||||
if (mConnected) {
|
||||
@@ -181,6 +402,9 @@ public final class RemoteConnection {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs this {@code RemoteConnection} to go on hold.
|
||||
*/
|
||||
public void hold() {
|
||||
try {
|
||||
if (mConnected) {
|
||||
@@ -190,6 +414,9 @@ public final class RemoteConnection {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs this {@link Connection.State#HOLDING} call to release from hold.
|
||||
*/
|
||||
public void unhold() {
|
||||
try {
|
||||
if (mConnected) {
|
||||
@@ -199,6 +426,9 @@ public final class RemoteConnection {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs this {@code RemoteConnection} to disconnect.
|
||||
*/
|
||||
public void disconnect() {
|
||||
try {
|
||||
if (mConnected) {
|
||||
@@ -208,7 +438,16 @@ public final class RemoteConnection {
|
||||
}
|
||||
}
|
||||
|
||||
public void playDtmf(char digit) {
|
||||
/**
|
||||
* Instructs this {@code RemoteConnection} to play a dual-tone multi-frequency signaling
|
||||
* (DTMF) tone.
|
||||
*
|
||||
* Any other currently playing DTMF tone in the specified call is immediately stopped.
|
||||
*
|
||||
* @param digit A character representing the DTMF digit for which to play the tone. This
|
||||
* value must be one of {@code '0'} through {@code '9'}, {@code '*'} or {@code '#'}.
|
||||
*/
|
||||
public void playDtmfTone(char digit) {
|
||||
try {
|
||||
if (mConnected) {
|
||||
mConnectionService.playDtmfTone(mConnectionId, digit);
|
||||
@@ -217,7 +456,14 @@ public final class RemoteConnection {
|
||||
}
|
||||
}
|
||||
|
||||
public void stopDtmf() {
|
||||
/**
|
||||
* Instructs this {@code RemoteConnection} to stop any dual-tone multi-frequency signaling
|
||||
* (DTMF) tone currently playing.
|
||||
*
|
||||
* DTMF tones are played by calling {@link #playDtmfTone(char)}. If no DTMF tone is
|
||||
* currently playing, this method will do nothing.
|
||||
*/
|
||||
public void stopDtmfTone() {
|
||||
try {
|
||||
if (mConnected) {
|
||||
mConnectionService.stopDtmfTone(mConnectionId);
|
||||
@@ -226,6 +472,27 @@ public final class RemoteConnection {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs this {@code RemoteConnection} to continue playing a post-dial DTMF string.
|
||||
*
|
||||
* A post-dial DTMF string is a string of digits following the first instance of either
|
||||
* {@link TelecommManager#DTMF_CHARACTER_WAIT} or {@link TelecommManager#DTMF_CHARACTER_PAUSE}.
|
||||
* These digits are immediately sent as DTMF tones to the recipient as soon as the
|
||||
* connection is made.
|
||||
*
|
||||
* If the DTMF string contains a {@link TelecommManager#DTMF_CHARACTER_PAUSE} symbol, this
|
||||
* {@code RemoteConnection} will temporarily pause playing the tones for a pre-defined period
|
||||
* of time.
|
||||
*
|
||||
* If the DTMF string contains a {@link TelecommManager#DTMF_CHARACTER_WAIT} symbol, this
|
||||
* {@code RemoteConnection} will pause playing the tones and notify listeners via
|
||||
* {@link Listener#onPostDialWait(RemoteConnection, String)}. At this point, the in-call app
|
||||
* should display to the user an indication of this state and an affordance to continue
|
||||
* the postdial sequence. When the user decides to continue the postdial sequence, the in-call
|
||||
* app should invoke the {@link #postDialContinue(boolean)} method.
|
||||
*
|
||||
* @param proceed Whether or not to continue with the post-dial sequence.
|
||||
*/
|
||||
public void postDialContinue(boolean proceed) {
|
||||
try {
|
||||
if (mConnected) {
|
||||
@@ -235,6 +502,10 @@ public final class RemoteConnection {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs this {@code RemoteConnection} to swap itself with an existing background call,
|
||||
* if one such call exists.
|
||||
*/
|
||||
public void swapWithBackgroundCall() {
|
||||
try {
|
||||
if (mConnected) {
|
||||
@@ -244,6 +515,11 @@ public final class RemoteConnection {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the audio state of this {@code RemoteConnection}.
|
||||
*
|
||||
* @param state The audio state of this {@code RemoteConnection}.
|
||||
*/
|
||||
public void setAudioState(CallAudioState state) {
|
||||
try {
|
||||
if (mConnected) {
|
||||
@@ -271,8 +547,8 @@ public final class RemoteConnection {
|
||||
void setDisconnected(int cause, String message) {
|
||||
if (mState != Connection.State.DISCONNECTED) {
|
||||
mState = Connection.State.DISCONNECTED;
|
||||
mDisconnectCause = cause;
|
||||
mDisconnectMessage = message;
|
||||
mDisconnectCauseCode = cause;
|
||||
mDisconnectCauseMessage = message;
|
||||
|
||||
for (Listener l : mListeners) {
|
||||
l.onDisconnected(this, cause, message);
|
||||
@@ -382,13 +658,6 @@ public final class RemoteConnection {
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
void setConnectionService(IConnectionService connectionService) {
|
||||
mConnectionService = connectionService;
|
||||
mConnectionService = null;
|
||||
setState(Connection.State.NEW);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a RemoteConnection which is in the {@link Connection.State#FAILED} state. Attempting
|
||||
* to use it for anything will almost certainly result in bad things happening. Do not do this.
|
||||
@@ -396,7 +665,6 @@ public final class RemoteConnection {
|
||||
* @return a failed {@link RemoteConnection}
|
||||
*
|
||||
* @hide
|
||||
*
|
||||
*/
|
||||
public static RemoteConnection failure(int failureCode, String failureMessage) {
|
||||
return new RemoteConnection(failureCode, failureMessage);
|
||||
|
||||
@@ -17,14 +17,11 @@
|
||||
package android.telecomm;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.net.Uri;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import com.android.internal.telecomm.IConnectionService;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -37,18 +34,13 @@ public class RemoteConnectionManager {
|
||||
if (!mRemoteConnectionServices.containsKey(componentName)) {
|
||||
try {
|
||||
RemoteConnectionService remoteConnectionService =
|
||||
new RemoteConnectionService(componentName, connectionService);
|
||||
new RemoteConnectionService(connectionService);
|
||||
mRemoteConnectionServices.put(componentName, remoteConnectionService);
|
||||
} catch (RemoteException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<PhoneAccountHandle> getAccounts(Uri handle) {
|
||||
List<PhoneAccountHandle> accountHandles = new LinkedList<>();
|
||||
return accountHandles;
|
||||
}
|
||||
|
||||
public RemoteConnection createRemoteConnection(
|
||||
PhoneAccountHandle connectionManagerPhoneAccount,
|
||||
ConnectionRequest request,
|
||||
|
||||
@@ -17,21 +17,21 @@
|
||||
package android.telecomm;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.ComponentName;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.IBinder.DeathRecipient;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.telephony.DisconnectCause;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.internal.os.SomeArgs;
|
||||
import com.android.internal.telecomm.IConnectionService;
|
||||
import com.android.internal.telecomm.IConnectionServiceAdapter;
|
||||
import com.android.internal.telecomm.IVideoCallProvider;
|
||||
import com.android.internal.telecomm.RemoteServiceCallback;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
@@ -39,369 +39,187 @@ import java.util.UUID;
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
final class RemoteConnectionService implements DeathRecipient {
|
||||
private static final int MSG_HANDLE_CREATE_CONNECTION_SUCCESSFUL = 1;
|
||||
private static final int MSG_HANDLE_CREATE_CONNECTION_FAILED = 2;
|
||||
private static final int MSG_HANDLE_CREATE_CONNECTION_CANCELLED = 3;
|
||||
private static final int MSG_SET_ACTIVE = 4;
|
||||
private static final int MSG_SET_RINGING = 5;
|
||||
private static final int MSG_SET_DIALING = 6;
|
||||
private static final int MSG_SET_DISCONNECTED = 7;
|
||||
private static final int MSG_SET_ON_HOLD = 8;
|
||||
private static final int MSG_SET_REQUESTING_RINGBACK = 9;
|
||||
private static final int MSG_SET_CALL_CAPABILITIES = 10;
|
||||
private static final int MSG_SET_IS_CONFERENCED = 11;
|
||||
private static final int MSG_ADD_CONFERENCE_CALL = 12;
|
||||
private static final int MSG_REMOVE_CALL = 13;
|
||||
private static final int MSG_ON_POST_DIAL_WAIT = 14;
|
||||
private static final int MSG_QUERY_REMOTE_CALL_SERVICES = 15;
|
||||
private static final int MSG_SET_VIDEO_STATE = 16;
|
||||
private static final int MSG_SET_CALL_VIDEO_PROVIDER = 17;
|
||||
private static final int MSG_SET_AUDIO_MODE_IS_VOIP = 18;
|
||||
private static final int MSG_SET_STATUS_HINTS = 19;
|
||||
private static final int MSG_SET_HANDLE = 20;
|
||||
private static final int MSG_SET_CALLER_DISPLAY_NAME = 21;
|
||||
private static final int MSG_START_ACTIVITY_FROM_IN_CALL = 22;
|
||||
final class RemoteConnectionService {
|
||||
|
||||
private final IConnectionService mConnectionService;
|
||||
private final ComponentName mComponentName;
|
||||
private static final RemoteConnection NULL_CONNECTION = new RemoteConnection(null, null);
|
||||
|
||||
private String mConnectionId;
|
||||
// Remote connection services only support a single connection.
|
||||
private RemoteConnection mConnection;
|
||||
|
||||
private final Handler mHandler = new Handler() {
|
||||
private final IConnectionServiceAdapter mServantDelegate = new IConnectionServiceAdapter() {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MSG_HANDLE_CREATE_CONNECTION_SUCCESSFUL: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
try {
|
||||
ConnectionRequest request = (ConnectionRequest) args.arg1;
|
||||
if (isPendingConnection(request.getCallId())) {
|
||||
ParcelableConnection parcel = (ParcelableConnection) args.arg2;
|
||||
mConnection.setState(parcel.getState());
|
||||
mConnection.setCallCapabilities(parcel.getCapabilities());
|
||||
mConnection.setHandle(
|
||||
parcel.getHandle(), parcel.getHandlePresentation());
|
||||
mConnection.setCallerDisplayName(
|
||||
parcel.getCallerDisplayName(),
|
||||
parcel.getCallerDisplayNamePresentation());
|
||||
// TODO: Do we need to support video providers for remote connections?
|
||||
}
|
||||
} finally {
|
||||
args.recycle();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_HANDLE_CREATE_CONNECTION_FAILED: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
try {
|
||||
ConnectionRequest request = (ConnectionRequest) args.arg1;
|
||||
if (isPendingConnection(request.getCallId())) {
|
||||
// TODO: How do we propogate the failure codes?
|
||||
destroyConnection();
|
||||
}
|
||||
} finally {
|
||||
args.recycle();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_HANDLE_CREATE_CONNECTION_CANCELLED: {
|
||||
ConnectionRequest request = (ConnectionRequest) msg.obj;
|
||||
if (isPendingConnection(request.getCallId())) {
|
||||
destroyConnection();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_SET_ACTIVE:
|
||||
if (isCurrentConnection(msg.obj)) {
|
||||
mConnection.setState(Connection.State.ACTIVE);
|
||||
}
|
||||
break;
|
||||
case MSG_SET_RINGING:
|
||||
if (isCurrentConnection(msg.obj)) {
|
||||
mConnection.setState(Connection.State.RINGING);
|
||||
}
|
||||
break;
|
||||
case MSG_SET_DIALING:
|
||||
if (isCurrentConnection(msg.obj)) {
|
||||
mConnection.setState(Connection.State.DIALING);
|
||||
}
|
||||
break;
|
||||
case MSG_SET_DISCONNECTED: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
try {
|
||||
if (isCurrentConnection(args.arg1)) {
|
||||
mConnection.setDisconnected(args.argi1, (String) args.arg2);
|
||||
}
|
||||
} finally {
|
||||
args.recycle();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_SET_ON_HOLD:
|
||||
if (isCurrentConnection(msg.obj)) {
|
||||
mConnection.setState(Connection.State.HOLDING);
|
||||
}
|
||||
break;
|
||||
case MSG_SET_REQUESTING_RINGBACK:
|
||||
if (isCurrentConnection(msg.obj)) {
|
||||
mConnection.setRequestingRingback(msg.arg1 == 1);
|
||||
}
|
||||
break;
|
||||
case MSG_SET_CALL_CAPABILITIES:
|
||||
if (isCurrentConnection(msg.obj)) {
|
||||
mConnection.setCallCapabilities(msg.arg1);
|
||||
}
|
||||
break;
|
||||
case MSG_SET_IS_CONFERENCED:
|
||||
// not supported for remote connections.
|
||||
break;
|
||||
case MSG_ADD_CONFERENCE_CALL:
|
||||
// not supported for remote connections.
|
||||
break;
|
||||
case MSG_REMOVE_CALL:
|
||||
if (isCurrentConnection(msg.obj)) {
|
||||
destroyConnection();
|
||||
}
|
||||
break;
|
||||
case MSG_ON_POST_DIAL_WAIT: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
try {
|
||||
if (isCurrentConnection(args.arg1)) {
|
||||
mConnection.setPostDialWait((String) args.arg2);
|
||||
}
|
||||
} finally {
|
||||
args.recycle();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_QUERY_REMOTE_CALL_SERVICES:
|
||||
// Not supported from remote connection service.
|
||||
break;
|
||||
case MSG_SET_VIDEO_STATE:
|
||||
if (isCurrentConnection(msg.obj)) {
|
||||
mConnection.setVideoState(msg.arg1);
|
||||
}
|
||||
break;
|
||||
case MSG_SET_CALL_VIDEO_PROVIDER:
|
||||
// not supported for remote connections.
|
||||
break;
|
||||
case MSG_SET_AUDIO_MODE_IS_VOIP:
|
||||
if (isCurrentConnection(msg.obj)) {
|
||||
mConnection.setAudioModeIsVoip(msg.arg1 == 1);
|
||||
}
|
||||
break;
|
||||
case MSG_SET_STATUS_HINTS: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
try {
|
||||
if (isCurrentConnection(args.arg1)) {
|
||||
mConnection.setStatusHints((StatusHints) args.arg2);
|
||||
}
|
||||
} finally {
|
||||
args.recycle();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_SET_HANDLE: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
try {
|
||||
if (isCurrentConnection(args.arg1)) {
|
||||
mConnection.setHandle((Uri) args.arg2, args.argi1);
|
||||
}
|
||||
} finally {
|
||||
args.recycle();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_SET_CALLER_DISPLAY_NAME: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
try {
|
||||
if (isCurrentConnection(msg.arg1)) {
|
||||
mConnection.setCallerDisplayName((String) args.arg2, args.argi1);
|
||||
}
|
||||
} finally {
|
||||
args.recycle();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_START_ACTIVITY_FROM_IN_CALL: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
try {
|
||||
if (isCurrentConnection(msg.arg1)) {
|
||||
mConnection.startActivityFromInCall((PendingIntent) args.arg2);
|
||||
}
|
||||
} finally {
|
||||
args.recycle();
|
||||
}
|
||||
break;
|
||||
}
|
||||
public void handleCreateConnectionSuccessful(ConnectionRequest request,
|
||||
ParcelableConnection parcel) {
|
||||
RemoteConnection connection = findConnectionForAction(
|
||||
request.getCallId(), "handleCreateConnectionSuccessful");
|
||||
if (connection != NULL_CONNECTION && mPendingConnections.contains(connection)) {
|
||||
mPendingConnections.remove(connection);
|
||||
connection.setState(parcel.getState());
|
||||
connection.setCallCapabilities(parcel.getCapabilities());
|
||||
connection.setHandle(
|
||||
parcel.getHandle(), parcel.getHandlePresentation());
|
||||
connection.setCallerDisplayName(
|
||||
parcel.getCallerDisplayName(),
|
||||
parcel.getCallerDisplayNamePresentation());
|
||||
// TODO: Do we need to support video providers for remote connections?
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
private final IConnectionServiceAdapter mAdapter = new IConnectionServiceAdapter.Stub() {
|
||||
@Override
|
||||
public void handleCreateConnectionSuccessful(
|
||||
ConnectionRequest request, ParcelableConnection connection) {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = request;
|
||||
args.arg2 = connection;
|
||||
mHandler.obtainMessage(MSG_HANDLE_CREATE_CONNECTION_SUCCESSFUL, args).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCreateConnectionFailed(
|
||||
ConnectionRequest request, int errorCode, String errorMessage) {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = request;
|
||||
args.argi1 = errorCode;
|
||||
args.arg2 = errorMessage;
|
||||
mHandler.obtainMessage(MSG_HANDLE_CREATE_CONNECTION_FAILED, args).sendToTarget();
|
||||
public void handleCreateConnectionFailed(ConnectionRequest request, int errorCode,
|
||||
String errorMessage) {
|
||||
// TODO: How do we propagate the failure codes?
|
||||
findConnectionForAction(
|
||||
request.getCallId(), "handleCreateConnectionFailed")
|
||||
.setDestroyed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCreateConnectionCancelled(ConnectionRequest request) {
|
||||
mHandler.obtainMessage(MSG_HANDLE_CREATE_CONNECTION_CANCELLED, request).sendToTarget();
|
||||
findConnectionForAction(
|
||||
request.getCallId(), "handleCreateConnectionCancelled")
|
||||
.setDestroyed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActive(String connectionId) {
|
||||
mHandler.obtainMessage(MSG_SET_ACTIVE, connectionId).sendToTarget();
|
||||
public void setActive(String callId) {
|
||||
findConnectionForAction(callId, "setActive")
|
||||
.setState(Connection.State.ACTIVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRinging(String connectionId) {
|
||||
mHandler.obtainMessage(MSG_SET_RINGING, connectionId).sendToTarget();
|
||||
public void setRinging(String callId) {
|
||||
findConnectionForAction(callId, "setRinging")
|
||||
.setState(Connection.State.RINGING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDialing(String connectionId) {
|
||||
mHandler.obtainMessage(MSG_SET_DIALING, connectionId).sendToTarget();
|
||||
public void setDialing(String callId) {
|
||||
findConnectionForAction(callId, "setDialing")
|
||||
.setState(Connection.State.DIALING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDisconnected(
|
||||
String connectionId, int disconnectCause, String disconnectMessage) {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = connectionId;
|
||||
args.arg2 = disconnectMessage;
|
||||
args.argi1 = disconnectCause;
|
||||
mHandler.obtainMessage(MSG_SET_DISCONNECTED, args).sendToTarget();
|
||||
public void setDisconnected(String callId, int disconnectCause,
|
||||
String disconnectMessage) {
|
||||
findConnectionForAction(callId, "setDisconnected")
|
||||
.setDisconnected(disconnectCause, disconnectMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnHold(String connectionId) {
|
||||
mHandler.obtainMessage(MSG_SET_ON_HOLD, connectionId).sendToTarget();
|
||||
public void setOnHold(String callId) {
|
||||
findConnectionForAction(callId, "setOnHold")
|
||||
.setState(Connection.State.HOLDING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRequestingRingback(String connectionId, boolean ringback) {
|
||||
mHandler.obtainMessage(MSG_SET_REQUESTING_RINGBACK, ringback ? 1 : 0, 0, connectionId)
|
||||
.sendToTarget();
|
||||
public void setRequestingRingback(String callId, boolean ringing) {
|
||||
findConnectionForAction(callId, "setRequestingRingback")
|
||||
.setRequestingRingback(ringing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCallCapabilities(String connectionId, int callCapabilities) {
|
||||
mHandler.obtainMessage(MSG_SET_CALL_CAPABILITIES, callCapabilities, 0, connectionId)
|
||||
.sendToTarget();
|
||||
public void setCallCapabilities(String callId, int callCapabilities) {
|
||||
findConnectionForAction("callId", "setCallCapabilities")
|
||||
.setCallCapabilities(callCapabilities);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIsConferenced(String connectionId, String conferenceConnectionId) {
|
||||
public void setIsConferenced(String callId, String conferenceCallId) {
|
||||
// not supported for remote connections.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addConferenceCall(String connectionId) {
|
||||
public void addConferenceCall(String callId) {
|
||||
// not supported for remote connections.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCall(String connectionId) {
|
||||
mHandler.obtainMessage(MSG_REMOVE_CALL, connectionId).sendToTarget();
|
||||
public void removeCall(String callId) {
|
||||
findConnectionForAction(callId, "removeCall")
|
||||
.setDestroyed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPostDialWait(String connectionId, String remainingDigits) {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = connectionId;
|
||||
args.arg2 = remainingDigits;
|
||||
mHandler.obtainMessage(MSG_ON_POST_DIAL_WAIT, args).sendToTarget();
|
||||
public void onPostDialWait(String callId, String remaining) {
|
||||
findConnectionForAction(callId, "onPostDialWait")
|
||||
.setPostDialWait(remaining);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queryRemoteConnectionServices(RemoteServiceCallback callback) {
|
||||
try {
|
||||
// Not supported from remote connection service.
|
||||
callback.onError();
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
// Not supported from remote connection service.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVideoState(String connectionId, int videoState) {
|
||||
mHandler.obtainMessage(MSG_SET_VIDEO_STATE, videoState, 0, connectionId).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVideoCallProvider(
|
||||
String connectionId, IVideoCallProvider videoCallProvider) {
|
||||
public void setVideoCallProvider(String callId,
|
||||
IVideoCallProvider videoCallProvider) {
|
||||
// not supported for remote connections.
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setAudioModeIsVoip(String connectionId, boolean isVoip) {
|
||||
mHandler.obtainMessage(MSG_SET_AUDIO_MODE_IS_VOIP, isVoip ? 1 : 0, 0,
|
||||
connectionId).sendToTarget();
|
||||
public void setVideoState(String callId, int videoState) {
|
||||
findConnectionForAction(callId, "setVideoState")
|
||||
.setVideoState(videoState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setStatusHints(String connectionId, StatusHints statusHints) {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = connectionId;
|
||||
args.arg2 = statusHints;
|
||||
mHandler.obtainMessage(MSG_SET_STATUS_HINTS, args).sendToTarget();
|
||||
public void setAudioModeIsVoip(String callId, boolean isVoip) {
|
||||
findConnectionForAction(callId, "setAudioModeIsVoip")
|
||||
.setAudioModeIsVoip(isVoip);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setHandle(String connectionId, Uri handle, int presentation) {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = connectionId;
|
||||
args.arg2 = handle;
|
||||
args.argi1 = presentation;
|
||||
mHandler.obtainMessage(MSG_SET_HANDLE, args).sendToTarget();
|
||||
public void setStatusHints(String callId, StatusHints statusHints) {
|
||||
findConnectionForAction(callId, "setStatusHints")
|
||||
.setStatusHints(statusHints);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setCallerDisplayName(
|
||||
String connectionId, String callerDisplayName, int presentation) {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = connectionId;
|
||||
args.arg2 = callerDisplayName;
|
||||
args.argi1 = presentation;
|
||||
mHandler.obtainMessage(MSG_SET_CALLER_DISPLAY_NAME, args).sendToTarget();
|
||||
public void setHandle(String callId, Uri handle, int presentation) {
|
||||
findConnectionForAction(callId, "setHandle")
|
||||
.setHandle(handle, presentation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void startActivityFromInCall(String connectionId, PendingIntent intent) {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = connectionId;
|
||||
args.arg2 = intent;
|
||||
mHandler.obtainMessage(MSG_START_ACTIVITY_FROM_IN_CALL, args).sendToTarget();
|
||||
public void setCallerDisplayName(String callId, String callerDisplayName,
|
||||
int presentation) {
|
||||
findConnectionForAction(callId, "setCallerDisplayName")
|
||||
.setCallerDisplayName(callerDisplayName, presentation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startActivityFromInCall(String callId, PendingIntent intent) {
|
||||
findConnectionForAction(callId, "startActivityFromInCall")
|
||||
.startActivityFromInCall(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder asBinder() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
|
||||
RemoteConnectionService(ComponentName componentName, IConnectionService connectionService)
|
||||
throws RemoteException {
|
||||
mComponentName = componentName;
|
||||
mConnectionService = connectionService;
|
||||
private final ConnectionServiceAdapterServant mServant =
|
||||
new ConnectionServiceAdapterServant(mServantDelegate);
|
||||
|
||||
mConnectionService.addConnectionServiceAdapter(mAdapter);
|
||||
mConnectionService.asBinder().linkToDeath(this, 0);
|
||||
private final DeathRecipient mDeathRecipient = new DeathRecipient() {
|
||||
@Override
|
||||
public void binderDied() {
|
||||
for (RemoteConnection c : mConnectionById.values()) {
|
||||
c.setDestroyed();
|
||||
}
|
||||
mConnectionById.clear();
|
||||
mPendingConnections.clear();
|
||||
mConnectionService.asBinder().unlinkToDeath(mDeathRecipient, 0);
|
||||
}
|
||||
};
|
||||
|
||||
private final IConnectionService mConnectionService;
|
||||
private final Map<String, RemoteConnection> mConnectionById = new HashMap<>();
|
||||
private final Set<RemoteConnection> mPendingConnections = new HashSet<>();
|
||||
|
||||
RemoteConnectionService(IConnectionService connectionService) throws RemoteException {
|
||||
mConnectionService = connectionService;
|
||||
mConnectionService.addConnectionServiceAdapter(mServant.getStub());
|
||||
mConnectionService.asBinder().linkToDeath(mDeathRecipient, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -409,66 +227,37 @@ final class RemoteConnectionService implements DeathRecipient {
|
||||
return "[RemoteCS - " + mConnectionService.asBinder().toString() + "]";
|
||||
}
|
||||
|
||||
/** ${inheritDoc} */
|
||||
@Override
|
||||
public final void binderDied() {
|
||||
if (mConnection != null) {
|
||||
destroyConnection();
|
||||
}
|
||||
|
||||
release();
|
||||
}
|
||||
|
||||
final RemoteConnection createRemoteConnection(
|
||||
PhoneAccountHandle connectionManagerPhoneAccount,
|
||||
ConnectionRequest request,
|
||||
boolean isIncoming) {
|
||||
if (mConnectionId == null) {
|
||||
String id = UUID.randomUUID().toString();
|
||||
ConnectionRequest newRequest = new ConnectionRequest(
|
||||
request.getAccountHandle(),
|
||||
id,
|
||||
request.getHandle(),
|
||||
request.getHandlePresentation(),
|
||||
request.getExtras(),
|
||||
request.getVideoState());
|
||||
mConnection = new RemoteConnection(mConnectionService, request, isIncoming);
|
||||
try {
|
||||
mConnectionService.createConnection(
|
||||
connectionManagerPhoneAccount,
|
||||
newRequest,
|
||||
isIncoming);
|
||||
mConnectionId = id;
|
||||
} catch (RemoteException e) {
|
||||
mConnection = RemoteConnection.failure(DisconnectCause.ERROR_UNSPECIFIED,
|
||||
e.toString());
|
||||
}
|
||||
return mConnection;
|
||||
} else {
|
||||
return RemoteConnection.failure(DisconnectCause.ERROR_UNSPECIFIED, null);
|
||||
ConnectionRequest newRequest = new ConnectionRequest(
|
||||
request.getAccountHandle(),
|
||||
UUID.randomUUID().toString(),
|
||||
request.getHandle(),
|
||||
request.getHandlePresentation(),
|
||||
request.getExtras(),
|
||||
request.getVideoState());
|
||||
try {
|
||||
mConnectionService.createConnection(
|
||||
connectionManagerPhoneAccount,
|
||||
newRequest,
|
||||
isIncoming);
|
||||
RemoteConnection connection =
|
||||
new RemoteConnection(mConnectionService, request);
|
||||
mPendingConnections.add(connection);
|
||||
mConnectionById.put(newRequest.getCallId(), connection);
|
||||
return connection;
|
||||
} catch (RemoteException e) {
|
||||
return RemoteConnection.failure(DisconnectCause.ERROR_UNSPECIFIED, e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases the resources associated with this Remote connection service. Should be called when
|
||||
* the remote service is no longer being used.
|
||||
*/
|
||||
void release() {
|
||||
mConnectionService.asBinder().unlinkToDeath(this, 0);
|
||||
}
|
||||
|
||||
private boolean isPendingConnection(String id) {
|
||||
return TextUtils.equals(mConnectionId, id);
|
||||
}
|
||||
|
||||
private boolean isCurrentConnection(Object obj) {
|
||||
return obj instanceof String && mConnection != null &&
|
||||
TextUtils.equals(mConnectionId, (String) obj);
|
||||
}
|
||||
|
||||
private void destroyConnection() {
|
||||
mConnection.setDestroyed();
|
||||
mConnection = null;
|
||||
mConnectionId = null;
|
||||
private RemoteConnection findConnectionForAction(String callId, String action) {
|
||||
if (mConnectionById.containsKey(callId)) {
|
||||
return mConnectionById.get(callId);
|
||||
}
|
||||
Log.w(this, "%s - Cannot find Connection %s", action, callId);
|
||||
return NULL_CONNECTION;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user