summaryrefslogtreecommitdiffstats
path: root/telecomm/java
diff options
context:
space:
mode:
Diffstat (limited to 'telecomm/java')
-rw-r--r--telecomm/java/android/telecomm/Connection.java406
1 files changed, 92 insertions, 314 deletions
diff --git a/telecomm/java/android/telecomm/Connection.java b/telecomm/java/android/telecomm/Connection.java
index b55f62a..8845821 100644
--- a/telecomm/java/android/telecomm/Connection.java
+++ b/telecomm/java/android/telecomm/Connection.java
@@ -19,9 +19,6 @@ package android.telecomm;
import android.app.PendingIntent;
import android.net.Uri;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import com.android.internal.os.SomeArgs;
import java.util.ArrayList;
import java.util.HashSet;
@@ -33,32 +30,6 @@ import java.util.Set;
*/
public abstract class Connection {
- private static final int MSG_ADD_CONNECTION_LISTENER = 1;
- private static final int MSG_REMOVE_CONNECTION_LISTENER = 2;
- private static final int MSG_SET_AUDIO_STATE = 3;
- private static final int MSG_SET_PARENT_CONNECTION = 4;
- private static final int MSG_SET_HANDLE = 5;
- private static final int MSG_SET_CALLER_DISPLAY_NAME = 6;
- private static final int MSG_SET_CANCELED = 7;
- private static final int MSG_SET_FAILED = 8;
- private static final int MSG_SET_VIDEO_STATE = 9;
- private static final int MSG_SET_ACTIVE = 10;
- private static final int MSG_SET_RINGING = 11;
- private static final int MSG_SET_INITIALIZING = 12;
- private static final int MSG_SET_INITIALIZED = 13;
- private static final int MSG_SET_DIALING = 14;
- private static final int MSG_SET_ON_HOLD = 15;
- private static final int MSG_SET_VIDEO_CALL_PROVIDER = 16;
- private static final int MSG_SET_DISCONNECTED = 17;
- private static final int MSG_SET_POST_DIAL_WAIT = 18;
- private static final int MSG_SET_REQUESTING_RINGBACK = 19;
- private static final int MSG_SET_CALL_CAPABILITIES = 20;
- private static final int MSG_DESTROY = 21;
- private static final int MSG_SET_SIGNAL = 22;
- private static final int MSG_SET_AUDIO_MODE_IS_VOIP = 23;
- private static final int MSG_SET_STATUS_HINTS = 24;
- private static final int MSG_START_ACTIVITY_FROM_IN_CALL = 25;
-
/** @hide */
public abstract static class Listener {
public void onStateChanged(Connection c, int state) {}
@@ -78,6 +49,7 @@ public abstract class Connection {
public void onAudioModeIsVoipChanged(Connection c, boolean isVoip) {}
public void onStatusHintsChanged(Connection c, StatusHints statusHints) {}
public void onStartActivityFromInCall(Connection c, PendingIntent intent) {}
+ public void onFailed(Connection c, int code, String msg) {}
}
public final class State {
@@ -115,220 +87,6 @@ public abstract class Connection {
private String mFailureMessage;
private boolean mIsCanceled;
- private final Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_ADD_CONNECTION_LISTENER: {
- Listener listener = (Listener) msg.obj;
- mListeners.add(listener);
- }
- break;
- case MSG_REMOVE_CONNECTION_LISTENER: {
- Listener listener = (Listener) msg.obj;
- mListeners.remove(listener);
- }
- break;
- case MSG_SET_AUDIO_STATE: {
- CallAudioState state = (CallAudioState) msg.obj;
- mCallAudioState = state;
- onSetAudioState(state);
- }
- break;
- case MSG_SET_PARENT_CONNECTION: {
- Connection parentConnection = (Connection) msg.obj;
- if (mParentConnection != parentConnection) {
- if (mParentConnection != null) {
- mParentConnection.removeChild(Connection.this);
- }
- mParentConnection = parentConnection;
- if (mParentConnection != null) {
- mParentConnection.addChild(Connection.this);
- // do something if the child connections goes down to ZERO.
- }
- for (Listener l : mListeners) {
- l.onParentConnectionChanged(Connection.this, mParentConnection);
- }
- }
- }
- break;
- case MSG_SET_HANDLE: {
- SomeArgs args = (SomeArgs) msg.obj;
- try {
- Uri handle = (Uri) args.arg1;
- int presentation = args.argi1;
- mHandle = handle;
- mHandlePresentation = presentation;
- for (Listener l : mListeners) {
- l.onHandleChanged(Connection.this, handle, presentation);
- }
- } finally {
- args.recycle();
- }
- }
- break;
- case MSG_SET_CALLER_DISPLAY_NAME: {
- SomeArgs args = (SomeArgs) msg.obj;
- try {
- String callerDisplayName = (String) args.arg1;
- int presentation = args.argi1;
- mCallerDisplayName = callerDisplayName;
- mCallerDisplayNamePresentation = presentation;
- for (Listener l : mListeners) {
- l.onCallerDisplayNameChanged(Connection.this, callerDisplayName,
- presentation);
- }
- } finally {
- args.recycle();
- }
- }
- break;
- case MSG_SET_CANCELED: {
- setState(State.CANCELED);
- }
- break;
- case MSG_SET_FAILED: {
- SomeArgs args = (SomeArgs) msg.obj;
- try {
- int code = args.argi1;
- String message = (String) args.arg1;
- mFailureCode = code;
- mFailureMessage = message;
- setState(State.FAILED);
- } finally {
- args.recycle();
- }
- }
- break;
- case MSG_SET_VIDEO_STATE: {
- int videoState = ((Integer) msg.obj).intValue();
- mVideoState = videoState;
- for (Listener l : mListeners) {
- l.onVideoStateChanged(Connection.this, mVideoState);
- }
- }
- break;
- case MSG_SET_ACTIVE: {
- setRequestingRingback(false);
- setState(State.ACTIVE);
- }
- break;
- case MSG_SET_RINGING: {
- setState(State.RINGING);
- }
- break;
- case MSG_SET_INITIALIZING: {
- setState(State.INITIALIZING);
- }
- break;
- case MSG_SET_INITIALIZED: {
- setState(State.NEW);
- }
- break;
- case MSG_SET_DIALING: {
- setState(State.DIALING);
- }
- break;
- case MSG_SET_ON_HOLD: {
- setState(State.HOLDING);
- }
- break;
- case MSG_SET_VIDEO_CALL_PROVIDER: {
- ConnectionService.VideoCallProvider videoCallProvider =
- (ConnectionService.VideoCallProvider) msg.obj;
- mVideoCallProvider = videoCallProvider;
- for (Listener l : mListeners) {
- l.onVideoCallProviderChanged(Connection.this, videoCallProvider);
- }
- }
- break;
- case MSG_SET_DISCONNECTED: {
- SomeArgs args = (SomeArgs) msg.obj;
- try {
- int cause = args.argi1;
- String message = (String) args.arg1;
- setState(State.DISCONNECTED);
- Log.d(this, "Disconnected with cause %d message %s", cause, message);
- for (Listener l : mListeners) {
- l.onDisconnected(Connection.this, cause, message);
- }
- } finally {
- args.recycle();
- }
- }
- break;
- case MSG_SET_POST_DIAL_WAIT: {
- String remaining = (String) msg.obj;
- for (Listener l : mListeners) {
- l.onPostDialWait(Connection.this, remaining);
- }
- }
- break;
- case MSG_SET_REQUESTING_RINGBACK: {
- boolean ringback = ((Boolean) msg.obj).booleanValue();
- if (mRequestingRingback != ringback) {
- mRequestingRingback = ringback;
- for (Listener l : mListeners) {
- l.onRequestingRingback(Connection.this, ringback);
- }
- }
- } break;
- case MSG_SET_CALL_CAPABILITIES: {
- int callCapabilities = ((Integer) msg.obj).intValue();
- if (mCallCapabilities != callCapabilities) {
- mCallCapabilities = callCapabilities;
- for (Listener l : mListeners) {
- l.onCallCapabilitiesChanged(Connection.this, mCallCapabilities);
- }
- }
- }
- break;
- case MSG_DESTROY: {
- // TODO: Is this still relevant because everything is on the main thread now.
- // It is possible that onDestroy() will trigger the listener to remove itself
- // which will result in a concurrent modification exception. To counteract
- // this we make a copy of the listeners and iterate on that.
- for (Listener l : new ArrayList<>(mListeners)) {
- if (mListeners.contains(l)) {
- l.onDestroyed(Connection.this);
- }
- }
- }
- break;
- case MSG_SET_SIGNAL: {
- Bundle details = (Bundle) msg.obj;
- for (Listener l : mListeners) {
- l.onSignalChanged(Connection.this, details);
- }
- }
- break;
- case MSG_SET_AUDIO_MODE_IS_VOIP: {
- boolean isVoip = ((Boolean) msg.obj).booleanValue();
- mAudioModeIsVoip = isVoip;
- for (Listener l : mListeners) {
- l.onAudioModeIsVoipChanged(Connection.this, isVoip);
- }
- }
- break;
- case MSG_SET_STATUS_HINTS: {
- StatusHints statusHints = (StatusHints) msg.obj;
- mStatusHints = statusHints;
- for (Listener l : mListeners) {
- l.onStatusHintsChanged(Connection.this, statusHints);
- }
- }
- break;
- case MSG_START_ACTIVITY_FROM_IN_CALL: {
- PendingIntent intent = (PendingIntent) msg.obj;
- for (Listener l : mListeners) {
- l.onStartActivityFromInCall(Connection.this, intent);
- }
- }
- break;
- }
- }
- };
-
/**
* Create a new Connection.
*/
@@ -430,7 +188,7 @@ public abstract class Connection {
* @hide
*/
public final Connection addConnectionListener(Listener l) {
- mHandler.obtainMessage(MSG_ADD_CONNECTION_LISTENER, l).sendToTarget();
+ mListeners.add(l);
return this;
}
@@ -443,7 +201,7 @@ public abstract class Connection {
* @hide
*/
public final Connection removeConnectionListener(Listener l) {
- mHandler.obtainMessage(MSG_REMOVE_CONNECTION_LISTENER, l).sendToTarget();
+ mListeners.remove(l);
return this;
}
@@ -469,7 +227,8 @@ public abstract class Connection {
*/
final void setAudioState(CallAudioState state) {
Log.d(this, "setAudioState %s", state);
- mHandler.obtainMessage(MSG_SET_AUDIO_STATE, state).sendToTarget();
+ mCallAudioState = state;
+ onSetAudioState(state);
}
/**
@@ -507,7 +266,19 @@ public abstract class Connection {
*/
public final void setParentConnection(Connection parentConnection) {
Log.d(this, "parenting %s to %s", this, parentConnection);
- mHandler.obtainMessage(MSG_SET_PARENT_CONNECTION, parentConnection).sendToTarget();
+ if (mParentConnection != parentConnection) {
+ if (mParentConnection != null) {
+ mParentConnection.removeChild(this);
+ }
+ mParentConnection = parentConnection;
+ if (mParentConnection != null) {
+ mParentConnection.addChild(this);
+ // do something if the child connections goes down to ZERO.
+ }
+ for (Listener l : mListeners) {
+ l.onParentConnectionChanged(this, mParentConnection);
+ }
+ }
}
public final Connection getParentConnection() {
@@ -534,10 +305,11 @@ public abstract class Connection {
*/
public final void setHandle(Uri handle, int presentation) {
Log.d(this, "setHandle %s", handle);
- SomeArgs args = SomeArgs.obtain();
- args.arg1 = handle;
- args.argi1 = presentation;
- mHandler.obtainMessage(MSG_SET_HANDLE, args).sendToTarget();
+ mHandle = handle;
+ mHandlePresentation = presentation;
+ for (Listener l : mListeners) {
+ l.onHandleChanged(this, handle, presentation);
+ }
}
/**
@@ -549,10 +321,11 @@ public abstract class Connection {
*/
public final void setCallerDisplayName(String callerDisplayName, int presentation) {
Log.d(this, "setCallerDisplayName %s", callerDisplayName);
- SomeArgs args = SomeArgs.obtain();
- args.arg1 = callerDisplayName;
- args.argi1 = presentation;
- mHandler.obtainMessage(MSG_SET_CALLER_DISPLAY_NAME, args).sendToTarget();
+ mCallerDisplayName = callerDisplayName;
+ mCallerDisplayNamePresentation = presentation;
+ for (Listener l : mListeners) {
+ l.onCallerDisplayNameChanged(this, callerDisplayName, presentation);
+ }
}
/**
@@ -561,7 +334,7 @@ public abstract class Connection {
*/
public final void setCanceled() {
Log.d(this, "setCanceled");
- mHandler.obtainMessage(MSG_SET_CANCELED).sendToTarget();
+ setState(State.CANCELED);
}
/**
@@ -577,10 +350,9 @@ public abstract class Connection {
*/
public final void setFailed(int code, String message) {
Log.d(this, "setFailed (%d: %s)", code, message);
- SomeArgs args = SomeArgs.obtain();
- args.argi1 = code;
- args.arg1 = message;
- mHandler.obtainMessage(MSG_SET_FAILED, args).sendToTarget();
+ mFailureCode = code;
+ mFailureMessage = message;
+ setState(State.FAILED);
}
/**
@@ -594,7 +366,10 @@ public abstract class Connection {
*/
public final void setVideoState(int videoState) {
Log.d(this, "setVideoState %d", videoState);
- mHandler.obtainMessage(MSG_SET_VIDEO_STATE, Integer.valueOf(videoState)).sendToTarget();
+ mVideoState = videoState;
+ for (Listener l : mListeners) {
+ l.onVideoStateChanged(this, mVideoState);
+ }
}
/**
@@ -602,28 +377,28 @@ public abstract class Connection {
* communicate).
*/
public final void setActive() {
- mHandler.obtainMessage(MSG_SET_ACTIVE).sendToTarget();
+ setRequestingRingback(false);
+ setState(State.ACTIVE);
}
/**
* Sets state to ringing (e.g., an inbound ringing call).
*/
public final void setRinging() {
- mHandler.obtainMessage(MSG_SET_RINGING).sendToTarget();
+ setState(State.RINGING);
}
/**
* Sets state to initializing (this Connection is not yet ready to be used).
*/
public final void setInitializing() {
- mHandler.obtainMessage(MSG_SET_INITIALIZING).sendToTarget();
+ setState(State.INITIALIZING);
}
/**
* Sets state to initialized (the Connection has been set up and is now ready to be used).
*/
public final void setInitialized() {
- mHandler.obtainMessage(MSG_SET_INITIALIZED).sendToTarget();
setState(State.NEW);
}
@@ -631,14 +406,14 @@ public abstract class Connection {
* Sets state to dialing (e.g., dialing an outbound call).
*/
public final void setDialing() {
- mHandler.obtainMessage(MSG_SET_DIALING).sendToTarget();
+ setState(State.DIALING);
}
/**
* Sets state to be on hold.
*/
public final void setOnHold() {
- mHandler.obtainMessage(MSG_SET_ON_HOLD).sendToTarget();
+ setState(State.HOLDING);
}
/**
@@ -646,7 +421,10 @@ public abstract class Connection {
* @param videoCallProvider The video call provider.
*/
public final void setVideoCallProvider(ConnectionService.VideoCallProvider videoCallProvider) {
- mHandler.obtainMessage(MSG_SET_VIDEO_CALL_PROVIDER, videoCallProvider).sendToTarget();
+ mVideoCallProvider = videoCallProvider;
+ for (Listener l : mListeners) {
+ l.onVideoCallProviderChanged(this, videoCallProvider);
+ }
}
public final ConnectionService.VideoCallProvider getVideoCallProvider() {
@@ -661,17 +439,20 @@ public abstract class Connection {
* @param message Optional call-service-provided message about the disconnect.
*/
public final void setDisconnected(int cause, String message) {
- SomeArgs args = SomeArgs.obtain();
- args.argi1 = cause;
- args.arg1 = message;
- mHandler.obtainMessage(MSG_SET_DISCONNECTED, args).sendToTarget();
+ setState(State.DISCONNECTED);
+ Log.d(this, "Disconnected with cause %d message %s", cause, message);
+ for (Listener l : mListeners) {
+ l.onDisconnected(this, cause, message);
+ }
}
/**
* TODO(santoscordon): Needs documentation.
*/
public final void setPostDialWait(String remaining) {
- mHandler.obtainMessage(MSG_SET_POST_DIAL_WAIT, remaining).sendToTarget();
+ for (Listener l : mListeners) {
+ l.onPostDialWait(this, remaining);
+ }
}
/**
@@ -681,8 +462,12 @@ public abstract class Connection {
* @param ringback Whether the ringback tone is to be played.
*/
public final void setRequestingRingback(boolean ringback) {
- mHandler.obtainMessage(MSG_SET_REQUESTING_RINGBACK, Boolean.valueOf(ringback))
- .sendToTarget();
+ if (mRequestingRingback != ringback) {
+ mRequestingRingback = ringback;
+ for (Listener l : mListeners) {
+ l.onRequestingRingback(this, ringback);
+ }
+ }
}
/**
@@ -691,15 +476,26 @@ public abstract class Connection {
* @param callCapabilities The new call capabilities.
*/
public final void setCallCapabilities(int callCapabilities) {
- mHandler.obtainMessage(MSG_SET_CALL_CAPABILITIES, Integer.valueOf(callCapabilities))
- .sendToTarget();
+ if (mCallCapabilities != callCapabilities) {
+ mCallCapabilities = callCapabilities;
+ for (Listener l : mListeners) {
+ l.onCallCapabilitiesChanged(this, mCallCapabilities);
+ }
+ }
}
/**
* TODO(santoscordon): Needs documentation.
*/
public final void destroy() {
- mHandler.obtainMessage(MSG_DESTROY).sendToTarget();
+ // It is possible that onDestroy() will trigger the listener to remove itself which will
+ // result in a concurrent modification exception. To counteract this we make a copy of the
+ // listeners and iterate on that.
+ for (Listener l : new ArrayList<>(mListeners)) {
+ if (mListeners.contains(l)) {
+ l.onDestroyed(this);
+ }
+ }
}
/**
@@ -708,7 +504,9 @@ public abstract class Connection {
* @param details A {@link android.os.Bundle} containing details of the current level.
*/
public final void setSignal(Bundle details) {
- mHandler.obtainMessage(MSG_SET_SIGNAL, details).sendToTarget();
+ for (Listener l : mListeners) {
+ l.onSignalChanged(this, details);
+ }
}
/**
@@ -717,7 +515,10 @@ public abstract class Connection {
* @param isVoip True if the audio mode is VOIP.
*/
public final void setAudioModeIsVoip(boolean isVoip) {
- mHandler.obtainMessage(MSG_SET_AUDIO_MODE_IS_VOIP, Boolean.valueOf(isVoip)).sendToTarget();
+ mAudioModeIsVoip = isVoip;
+ for (Listener l : mListeners) {
+ l.onAudioModeIsVoipChanged(this, isVoip);
+ }
}
/**
@@ -726,7 +527,10 @@ public abstract class Connection {
* @param statusHints The status label and icon to set.
*/
public final void setStatusHints(StatusHints statusHints) {
- mHandler.obtainMessage(MSG_SET_STATUS_HINTS, statusHints).sendToTarget();
+ mStatusHints = statusHints;
+ for (Listener l : mListeners) {
+ l.onStatusHintsChanged(this, statusHints);
+ }
}
/**
@@ -738,13 +542,13 @@ public abstract class Connection {
if (!intent.isActivity()) {
throw new IllegalArgumentException("Activity intent required.");
}
- mHandler.obtainMessage(MSG_START_ACTIVITY_FROM_IN_CALL, intent).sendToTarget();
+ for (Listener l : mListeners) {
+ l.onStartActivityFromInCall(this, intent);
+ }
}
/**
* Notifies this Connection that the {@link #getCallAudioState()} property has a new value.
- * <p>
- * This callback will happen on the main thread.
*
* @param state The new call audio state.
*/
@@ -753,8 +557,6 @@ public abstract class Connection {
/**
* Notifies this Connection of an internal state change. This method is called after the
* state is changed.
- * <p>
- * This callback will happen on the main thread.
*
* @param state The new state, a {@link Connection.State} member.
*/
@@ -762,8 +564,6 @@ public abstract class Connection {
/**
* Notifies this Connection of a request to play a DTMF tone.
- * <p>
- * This callback will happen on the main thread.
*
* @param c A DTMF character.
*/
@@ -771,81 +571,61 @@ public abstract class Connection {
/**
* Notifies this Connection of a request to stop any currently playing DTMF tones.
- * <p>
- * This callback will happen on the main thread.
*/
public void onStopDtmfTone() {}
/**
* Notifies this Connection of a request to disconnect.
- * <p>
- * This callback will happen on the main thread.
*/
public void onDisconnect() {}
/**
* Notifies this Connection of a request to disconnect.
- * <p>
- * This callback will happen on the main thread.
*/
public void onSeparate() {}
/**
* Notifies this Connection of a request to abort.
- * <p>
- * This callback will happen on the main thread.
*/
public void onAbort() {}
/**
* Notifies this Connection of a request to hold.
- * <p>
- * This callback will happen on the main thread.
*/
public void onHold() {}
/**
* Notifies this Connection of a request to exit a hold state.
- * <p>
- * This callback will happen on the main thread.
*/
public void onUnhold() {}
/**
- * Notifies this Connection, which is in {@link State#RINGING}, of a request to accept.
- * <p>
- * This callback will happen on the main thread.
+ * Notifies this Connection, which is in {@link State#RINGING}, of
+ * a request to accept.
*
* @param videoState The video state in which to answer the call.
*/
public void onAnswer(int videoState) {}
/**
- * Notifies this Connection, which is in {@link State#RINGING}, of a request to reject.
- * <p>
- * This callback will happen on the main thread.
+ * Notifies this Connection, which is in {@link State#RINGING}, of
+ * a request to reject.
*/
public void onReject() {}
/**
* Notifies this Connection whether the user wishes to proceed with the post-dial DTMF codes.
- * <p>
- * This callback will happen on the main thread.
*/
public void onPostDialContinue(boolean proceed) {}
/**
* Swap this call with a background call. This is used for calls that don't support hold,
* e.g. CDMA.
- * <p>
- * This callback will happen on the main thread.
*/
public void onSwapWithBackgroundCall() {}
/**
* TODO(santoscordon): Needs documentation.
- * <p>
- * This callback will happen on the main thread.
*/
public void onChildrenChanged(List<Connection> children) {}
@@ -854,14 +634,12 @@ public abstract class Connection {
*/
public void onPhoneAccountClicked() {}
- /** This must be called from the main thread. */
private void addChild(Connection connection) {
Log.d(this, "adding child %s", connection);
mChildConnections.add(connection);
onChildrenChanged(mChildConnections);
}
- /** This must be called from the main thread. */
private void removeChild(Connection connection) {
Log.d(this, "removing child %s", connection);
mChildConnections.remove(connection);