Fix potential out of order callbacks.
Combined all queues into a single queue to guarantee ordering.
Change-Id: Ib0f20ac56eaa4e1ece26821cb668611fc4579abc
diff --git a/src/com/android/phone/CallHandlerServiceProxy.java b/src/com/android/phone/CallHandlerServiceProxy.java
index 8a8e99d..d13aa75 100644
--- a/src/com/android/phone/CallHandlerServiceProxy.java
+++ b/src/com/android/phone/CallHandlerServiceProxy.java
@@ -53,10 +53,11 @@
private CallCommandService mCallCommandService;
private CallModeler mCallModeler;
private Context mContext;
+
private ICallHandlerService mCallHandlerServiceGuarded; // Guarded by mServiceAndQueueLock
- private List<Call> mIncomingCallQueueGuarded; // Guarded by mServiceAndQueueLock
- private List<List<Call>> mUpdateCallQueueGuarded; // Guarded by mServiceAndQueueLock
- private List<Call> mDisconnectCallQueueGuarded; // Guarded by mServiceAndQueueLock
+ // Single queue to guarantee ordering
+ private List<QueueParams> mQueue; // Guarded by mServiceAndQueueLock
+
private final Object mServiceAndQueueLock = new Object();
private int mBindRetryCount = 0;
@@ -283,16 +284,14 @@
* Called when the in-call UI service is connected. Send command interface to in-call.
*/
private void onCallHandlerServiceConnected(ICallHandlerService callHandlerService) {
+
synchronized (mServiceAndQueueLock) {
mCallHandlerServiceGuarded = callHandlerService;
// Before we send any updates, we need to set up the initial service calls.
makeInitialServiceCalls();
- // TODO(klp): combine queues into a single ordered queue.
- processIncomingCallQueue();
- processUpdateCallQueue();
- processDisconnectQueue();
+ processQueue();
}
}
@@ -311,59 +310,65 @@
}
}
+ private List<QueueParams> getQueue() {
+ if (mQueue == null) {
+ mQueue = Lists.newArrayList();
+ }
+ return mQueue;
+ }
private void enqueueDisconnect(Call call) {
- if (mDisconnectCallQueueGuarded == null) {
- mDisconnectCallQueueGuarded = Lists.newArrayList();
- }
- mDisconnectCallQueueGuarded.add(new Call(call));
+ getQueue().add(new QueueParams(QueueParams.METHOD_DISCONNECT, new Call(call)));
}
private void enqueueIncoming(Call call) {
- if (mIncomingCallQueueGuarded == null) {
- mIncomingCallQueueGuarded = Lists.newArrayList();
- }
- mIncomingCallQueueGuarded.add(new Call(call));
+ getQueue().add(new QueueParams(QueueParams.METHOD_INCOMING, new Call(call)));
}
private void enqueueUpdate(List<Call> calls) {
- if (mUpdateCallQueueGuarded == null) {
- mUpdateCallQueueGuarded = Lists.newArrayList();
- }
final List<Call> copy = Lists.newArrayList();
for (Call call : calls) {
copy.add(new Call(call));
}
- mUpdateCallQueueGuarded.add(copy);
+ getQueue().add(new QueueParams(QueueParams.METHOD_INCOMING, copy));
}
- private void processDisconnectQueue() {
- if (mDisconnectCallQueueGuarded != null) {
- for (Call call : mDisconnectCallQueueGuarded) {
- onDisconnect(call);
+ private void processQueue() {
+ List<QueueParams> queue = getQueue();
+ for (QueueParams params : queue) {
+ switch (params.mMethod) {
+ case QueueParams.METHOD_INCOMING:
+ onIncoming((Call) params.mArg);
+ break;
+ case QueueParams.METHOD_UPDATE:
+ onUpdate((List<Call>) params.mArg);
+ break;
+ case QueueParams.METHOD_DISCONNECT:
+ onDisconnect((Call) params.mArg);
+ break;
+ default:
+ throw new IllegalArgumentException("Method type " + params.mMethod +
+ " not recognized.");
}
- mDisconnectCallQueueGuarded.clear();
- mDisconnectCallQueueGuarded = null;
}
+ mQueue.clear();
+ mQueue = null;
}
- private void processIncomingCallQueue() {
- if (mIncomingCallQueueGuarded != null) {
- for (Call call : mIncomingCallQueueGuarded) {
- onIncoming(call);
- }
- mIncomingCallQueueGuarded.clear();
- mIncomingCallQueueGuarded = null;
- }
- }
+ /**
+ * Holds method parameters.
+ */
+ private static class QueueParams {
+ private static final int METHOD_INCOMING = 1;
+ private static final int METHOD_UPDATE = 2;
+ private static final int METHOD_DISCONNECT = 3;
- private void processUpdateCallQueue() {
- if (mUpdateCallQueueGuarded != null) {
- for (List<Call> calls : mUpdateCallQueueGuarded) {
- onUpdate(calls);
- }
- mUpdateCallQueueGuarded.clear();
- mUpdateCallQueueGuarded = null;
+ private final int mMethod;
+ private final Object mArg;
+
+ private QueueParams(int method, Object arg) {
+ mMethod = method;
+ this.mArg = arg;
}
}
}