Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7f2b7353 authored by Harshita Ojha's avatar Harshita Ojha
Browse files

Added synchronized(LOCK) keyword to protect member variables of onCallRemoved and onCallAdded

For conference call, while calls are in transition to merge state, AT+CLCC command is being received from the peer.
The objects in 'mBluetoothCallHashMap' are accessed/modified concurrently from BluetoothInCallService & BluetoothLeCallControl Classes.
This seems to be resulted in 'ConcurrentModificationException' and causes crash.

Bug: 367777221
Test: m packages/modules/Bluetooth with Manual testing.
Flag: EXEMPT
Change-Id: I7723e3f2234c58c472210e00f2a1b5e1f0c47401
parent bb29aaf4
Loading
Loading
Loading
Loading
+72 −66
Original line number Diff line number Diff line
@@ -624,6 +624,7 @@ public class BluetoothInCallService extends InCallService {

    @RequiresPermission(allOf = {BLUETOOTH_CONNECT, MODIFY_PHONE_STATE})
    public void onCallAdded(BluetoothCall call) {
        synchronized (LOCK) {
            if (call.isExternalCall()) {
                Log.d(TAG, "onCallAdded: external call");
                return;
@@ -636,7 +637,8 @@ public class BluetoothInCallService extends InCallService {

                mBluetoothCallHashMap.put(call.getId(), call);
                if (!call.isConference()) {
                mMaxNumberOfCalls = Integer.max(mMaxNumberOfCalls, mBluetoothCallHashMap.size());
                    mMaxNumberOfCalls =
                            Integer.max(mMaxNumberOfCalls, mBluetoothCallHashMap.size());
                }
                updateHeadsetWithCallState(false /* force */);

@@ -648,6 +650,7 @@ public class BluetoothInCallService extends InCallService {
                Log.i(TAG, "onCallAdded: call already exists");
            }
        }
    }

    public void sendBluetoothCallQualityReport(
            long timestamp,
@@ -694,6 +697,7 @@ public class BluetoothInCallService extends InCallService {
     */
    @RequiresPermission(allOf = {BLUETOOTH_CONNECT, MODIFY_PHONE_STATE})
    public void onCallRemoved(BluetoothCall call, boolean forceRemoveCallback) {
        synchronized (LOCK) {
            Log.i(TAG, "onCallRemoved, forceRemoveCallback=" + forceRemoveCallback);
            CallStateCallback callback = getCallback(call);
            if (callback != null && (forceRemoveCallback || !call.isExternalCall())) {
@@ -739,7 +743,8 @@ public class BluetoothInCallService extends InCallService {

            updateHeadsetWithCallState(false /* force */);

        if (Flags.maintainCallIndexAfterConference() && mConferenceCallClccIndexMap.size() > 0) {
            if (Flags.maintainCallIndexAfterConference()
                    && mConferenceCallClccIndexMap.size() > 0) {
                int anyActiveCalls = mCallInfo.isNullCall(mCallInfo.getActiveCall()) ? 0 : 1;
                int numHeldCalls = mCallInfo.getNumHeldCalls();
                // If no call is active or held clear the hashmap.
@@ -753,6 +758,7 @@ public class BluetoothInCallService extends InCallService {
                        call.getTbsCallId(), getTbsTerminationReason(call));
            }
        }
    }

    @Override
    @RequiresPermission(allOf = {BLUETOOTH_CONNECT, MODIFY_PHONE_STATE})