summaryrefslogtreecommitdiffstats
path: root/telecomm
diff options
context:
space:
mode:
authorRoshan Pius <rpius@google.com>2015-07-07 17:34:51 -0700
committerRoshan Pius <rpius@google.com>2015-07-08 14:47:36 -0700
commit1ca6207a1ec5bf9c12027c4f09a4fe18bd3f825c (patch)
tree8479fba2d82ad20bf8826fead004e93233a95fa0 /telecomm
parent1a257545b2d1e8bd95393ee6637e70be7d230bc6 (diff)
downloadframeworks_base-1ca6207a1ec5bf9c12027c4f09a4fe18bd3f825c.zip
frameworks_base-1ca6207a1ec5bf9c12027c4f09a4fe18bd3f825c.tar.gz
frameworks_base-1ca6207a1ec5bf9c12027c4f09a4fe18bd3f825c.tar.bz2
Change sequence of call removal from Phone's db.
Since the Call API's callbacks are now fired from handlers, they end up changing the order in which the callbacks from the Phone and Call API's are fired. To preserve the below ordering, we move the call removal from Phone's db to after all the onCallDestoryedcallbacks have executed. 1. Call->onStateChanged 2. Call->onDetailsChanged 3. Call->onCallDestroyed 4. Phone->onCallRemoved BUG: 22127504 Change-Id: Ice17f727decb516baabbe69adae598ebdf370094
Diffstat (limited to 'telecomm')
-rw-r--r--telecomm/java/android/telecom/Call.java43
1 files changed, 36 insertions, 7 deletions
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index e756a57..4569549 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -921,7 +921,8 @@ public final class Call {
*/
public void registerCallback(Callback callback, Handler handler) {
unregisterCallback(callback);
- if (callback != null && handler != null) {
+ // Don't allow new callback registration if the call is already being destroyed.
+ if (callback != null && handler != null && mState != STATE_DISCONNECTED) {
mCallbackRecords.add(new CallbackRecord<Callback>(callback, handler));
}
}
@@ -932,7 +933,8 @@ public final class Call {
* @param callback A {@code Callback}.
*/
public void unregisterCallback(Callback callback) {
- if (callback != null) {
+ // Don't allow callback deregistration if the call is already being destroyed.
+ if (callback != null && mState != STATE_DISCONNECTED) {
for (CallbackRecord<Callback> record : mCallbackRecords) {
if (record.getCallback() == callback) {
mCallbackRecords.remove(record);
@@ -1080,7 +1082,6 @@ public final class Call {
// DISCONNECTED Call while still relying on the existence of that Call in the Phone's list.
if (mState == STATE_DISCONNECTED) {
fireCallDestroyed();
- mPhone.internalRemoveCall(this);
}
}
@@ -1096,7 +1097,6 @@ public final class Call {
mState = Call.STATE_DISCONNECTED;
fireStateChanged(mState);
fireCallDestroyed();
- mPhone.internalRemoveCall(this);
}
}
@@ -1192,13 +1192,42 @@ public final class Call {
}
private void fireCallDestroyed() {
- for (CallbackRecord<Callback> record: mCallbackRecords) {
- final Call call = this;
+ /**
+ * To preserve the ordering of the Call's onCallDestroyed callback and Phone's
+ * onCallRemoved callback, we remove this call from the Phone's record
+ * only once all of the registered onCallDestroyed callbacks are executed.
+ * All the callbacks get removed from our records as a part of this operation
+ * since onCallDestroyed is the final callback.
+ */
+ final Call call = this;
+ if (mCallbackRecords.isEmpty()) {
+ // No callbacks registered, remove the call from Phone's record.
+ mPhone.internalRemoveCall(call);
+ }
+ for (final CallbackRecord<Callback> record : mCallbackRecords) {
final Callback callback = record.getCallback();
record.getHandler().post(new Runnable() {
@Override
public void run() {
- callback.onCallDestroyed(call);
+ boolean isFinalRemoval = false;
+ RuntimeException toThrow = null;
+ try {
+ callback.onCallDestroyed(call);
+ } catch (RuntimeException e) {
+ toThrow = e;
+ }
+ synchronized(Call.this) {
+ mCallbackRecords.remove(record);
+ if (mCallbackRecords.isEmpty()) {
+ isFinalRemoval = true;
+ }
+ }
+ if (isFinalRemoval) {
+ mPhone.internalRemoveCall(call);
+ }
+ if (toThrow != null) {
+ throw toThrow;
+ }
}
});
}