Merge "Filter various callbacks in BluetoothPhoneService" into lmp-dev automerge: baf107f
automerge: 831a975
* commit '831a9752933a01b3c7576a466ee77d0e7d765d62':
Filter various callbacks in BluetoothPhoneService
diff --git a/src/com/android/server/telecom/BluetoothPhoneService.java b/src/com/android/server/telecom/BluetoothPhoneService.java
index 51dbbdf..8bf50ae 100644
--- a/src/com/android/server/telecom/BluetoothPhoneService.java
+++ b/src/com/android/server/telecom/BluetoothPhoneService.java
@@ -329,16 +329,63 @@
@Override
public void onCallStateChanged(Call call, int oldState, int newState) {
+ // If a call is being put on hold because of a new connecting call, ignore the
+ // CONNECTING since the BT state update needs to send out the numHeld = 1 + dialing
+ // state atomically.
+ // When the call later transitions to DIALING/DISCONNECTED we will then send out the
+ // aggregated update.
+ if (oldState == CallState.ACTIVE && newState == CallState.ON_HOLD) {
+ for (Call otherCall : CallsManager.getInstance().getCalls()) {
+ if (otherCall.getState() == CallState.CONNECTING) {
+ return;
+ }
+ }
+ }
+
+ // To have an active call and another dialing at the same time is an invalid BT
+ // state. We can assume that the active call will be automatically held which will
+ // send another update at which point we will be in the right state.
+ if (CallsManager.getInstance().getActiveCall() != null
+ && oldState == CallState.CONNECTING && newState == CallState.DIALING) {
+ return;
+ }
updateHeadsetWithCallState(false /* force */);
}
@Override
public void onForegroundCallChanged(Call oldForegroundCall, Call newForegroundCall) {
- updateHeadsetWithCallState(false /* force */);
+ // The BluetoothPhoneService does not need to respond to changes in foreground calls,
+ // which are always accompanied by call state changes anyway.
}
@Override
public void onIsConferencedChanged(Call call) {
+ /*
+ * Filter certain onIsConferencedChanged callbacks. Unfortunately this needs to be done
+ * because conference change events are not atomic and multiple callbacks get fired
+ * when two calls are conferenced together. This confuses updateHeadsetWithCallState
+ * if it runs in the middle of two calls being conferenced and can cause spurious and
+ * incorrect headset state updates. One of the scenarios is described below for CDMA
+ * conference calls.
+ *
+ * 1) Call 1 and Call 2 are being merged into conference Call 3.
+ * 2) Call 1 has its parent set to Call 3, but Call 2 does not have a parent yet.
+ * 3) updateHeadsetWithCallState now thinks that there are two active calls (Call 2 and
+ * Call 3) when there is actually only one active call (Call 3).
+ */
+ if (call.getParentCall() != null) {
+ // If this call is newly conferenced, ignore the callback. We only care about the
+ // one sent for the parent conference call.
+ Log.d(this, "Ignoring onIsConferenceChanged from child call with new parent");
+ return;
+ }
+ if (call.getChildCalls().size() == 1) {
+ // If this is a parent call with only one child, ignore the callback as well since
+ // the minimum number of child calls to start a conference call is 2. We expect
+ // this to be called again when the parent call has another child call added.
+ Log.d(this, "Ignoring onIsConferenceChanged from parent with only one child call");
+ return;
+ }
updateHeadsetWithCallState(false /* force */);
}
};
@@ -649,6 +696,7 @@
// For conference calls which support swapping the active call within the conference
// (namely CDMA calls) we need to expose that as a held call in order for the BT device
// to show "swap" and "merge" functionality.
+ boolean ignoreHeldCallChange = false;
if (activeCall != null && activeCall.isConference()) {
if (activeCall.can(PhoneCapabilities.SWAP_CONFERENCE)) {
// Indicate that BT device should show SWAP command by indicating that there is a
@@ -657,6 +705,16 @@
} else if (activeCall.can(PhoneCapabilities.MERGE_CONFERENCE)) {
numHeldCalls = 1; // Merge is available, so expose via numHeldCalls.
}
+
+ for (Call childCall : activeCall.getChildCalls()) {
+ // Held call has changed due to it being combined into a CDMA conference. Keep
+ // track of this and ignore any future update since it doesn't really count as
+ // a call change.
+ if (mOldHeldCall == childCall) {
+ ignoreHeldCallChange = true;
+ break;
+ }
+ }
}
if (mBluetoothHeadset != null &&
@@ -665,7 +723,7 @@
bluetoothCallState != mBluetoothCallState ||
!TextUtils.equals(ringingAddress, mRingingAddress) ||
ringingAddressType != mRingingAddressType ||
- heldCall != mOldHeldCall ||
+ (heldCall != mOldHeldCall && !ignoreHeldCallChange) ||
force)) {
// If the call is transitioning into the alerting state, send DIALING first.
@@ -682,7 +740,18 @@
mRingingAddressType = ringingAddressType;
if (sendDialingFirst) {
- Log.i(TAG, "Sending dialing state");
+ // Log in full to make logs easier to debug.
+ Log.i(TAG, "updateHeadsetWithCallState " +
+ "numActive %s, " +
+ "numHeld %s, " +
+ "callState %s, " +
+ "ringing number %s, " +
+ "ringing type %s",
+ mNumActiveCalls,
+ mNumHeldCalls,
+ CALL_STATE_DIALING,
+ Log.pii(mRingingAddress),
+ mRingingAddressType);
mBluetoothHeadset.phoneStateChanged(
mNumActiveCalls,
mNumHeldCalls,