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

Commit 881d91fe authored by Kyunglyul Hyun's avatar Kyunglyul Hyun
Browse files

Prevent CME by using CopyOnWriteArraySet

A thread enumerating trackers could be
different form a therad adding/removing a tracker.
By using CopyOnWriteArraySet, we can prevent
ConcurrentModificationException.

Bug: 312945444
Flag: EXTEMPT, no logical changes
Test: atest DistanceMeasurementManagerTest --iterations 200
Change-Id: I67c07a13aee08e7a0ac35c9c250c7700dfcb56cd
parent 115e5865
Loading
Loading
Loading
Loading
+16 −23
Original line number Diff line number Diff line
@@ -31,12 +31,12 @@ import android.util.Log;
import com.android.bluetooth.btservice.AdapterService;
import com.android.internal.annotations.VisibleForTesting;

import java.util.HashSet;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * Manages distnace measurement operations and interacts with Gabeldorsche stack.
 * Manages distance measurement operations and interacts with Gabeldorsche stack.
 *
 * @hide
 */
@@ -52,12 +52,10 @@ public class DistanceMeasurementManager {
    private final AdapterService mAdapterService;
    private HandlerThread mHandlerThread;
    DistanceMeasurementNativeInterface mDistanceMeasurementNativeInterface;
    private ConcurrentHashMap<String, HashSet<DistanceMeasurementTracker>> mRssiTrackers =
            new ConcurrentHashMap<>();
    private final ConcurrentHashMap<String, CopyOnWriteArraySet<DistanceMeasurementTracker>>
            mRssiTrackers = new ConcurrentHashMap<>();

    /**
     * Constructor of {@link DistanceMeasurementManager}.
     */
    /** Constructor of {@link DistanceMeasurementManager}. */
    DistanceMeasurementManager(AdapterService adapterService) {
        mAdapterService = adapterService;

@@ -111,14 +109,13 @@ public class DistanceMeasurementManager {
    }

    private synchronized void startRssiTracker(DistanceMeasurementTracker tracker) {
        mRssiTrackers.putIfAbsent(tracker.mIdentityAddress,
                new HashSet<DistanceMeasurementTracker>());
        HashSet<DistanceMeasurementTracker> set = mRssiTrackers.get(tracker.mIdentityAddress);
        if (set.contains(tracker)) {
        mRssiTrackers.putIfAbsent(tracker.mIdentityAddress, new CopyOnWriteArraySet<>());
        CopyOnWriteArraySet<DistanceMeasurementTracker> set =
                mRssiTrackers.get(tracker.mIdentityAddress);
        if (!set.add(tracker)) {
            Log.w(TAG, "Already registered");
            return;
        }
        set.add(tracker);
        mDistanceMeasurementNativeInterface.startDistanceMeasurement(tracker.mIdentityAddress,
                tracker.mFrequency, DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_RSSI);
    }
@@ -151,7 +148,7 @@ public class DistanceMeasurementManager {

    private synchronized int stopRssiTracker(UUID uuid, String identityAddress,
            boolean timeout) {
        HashSet<DistanceMeasurementTracker> set = mRssiTrackers.get(identityAddress);
        CopyOnWriteArraySet<DistanceMeasurementTracker> set = mRssiTrackers.get(identityAddress);
        if (set == null) {
            Log.w(TAG, "Can't find rssi tracker");
            return BluetoothStatusCodes.ERROR_DISTANCE_MEASUREMENT_INTERNAL;
@@ -231,7 +228,7 @@ public class DistanceMeasurementManager {
    }

    void handleRssiStarted(String address) {
        HashSet<DistanceMeasurementTracker> set = mRssiTrackers.get(address);
        CopyOnWriteArraySet<DistanceMeasurementTracker> set = mRssiTrackers.get(address);
        if (set == null) {
            Log.w(TAG, "Can't find rssi tracker");
            return;
@@ -262,7 +259,7 @@ public class DistanceMeasurementManager {
    }

    void handleRssiStartFail(String address, int reason) {
        HashSet<DistanceMeasurementTracker> set = mRssiTrackers.get(address);
        CopyOnWriteArraySet<DistanceMeasurementTracker> set = mRssiTrackers.get(address);
        if (set == null) {
            Log.w(TAG, "Can't find rssi tracker");
            return;
@@ -272,10 +269,8 @@ public class DistanceMeasurementManager {
                invokeStartFail(tracker.mCallback, tracker.mDevice, reason);
            }
        }
        synchronized (set) {
        set.removeIf(tracker -> !tracker.mStarted);
    }
    }

    void onDistanceMeasurementStopped(String address, int reason, int method) {
        logd("onDistanceMeasurementStopped address:" + BluetoothUtils.toAnonymizedAddress(address)
@@ -290,7 +285,7 @@ public class DistanceMeasurementManager {
    }

    void handleRssiStopped(String address, int reason) {
        HashSet<DistanceMeasurementTracker> set = mRssiTrackers.get(address);
        CopyOnWriteArraySet<DistanceMeasurementTracker> set = mRssiTrackers.get(address);
        if (set == null) {
            Log.w(TAG, "Can't find rssi tracker");
            return;
@@ -301,10 +296,8 @@ public class DistanceMeasurementManager {
                invokeOnStopped(tracker.mCallback, tracker.mDevice, reason);
            }
        }
        synchronized (set) {
        set.removeIf(tracker -> tracker.mStarted);
    }
    }

    void onDistanceMeasurementResult(String address, int centimeter, int errorCentimeter,
            int azimuthAngle, int errorAzimuthAngle, int altitudeAngle, int errorAltitudeAngle,
@@ -323,7 +316,7 @@ public class DistanceMeasurementManager {
    }

    void handleRssiResult(String address, DistanceMeasurementResult result) {
        HashSet<DistanceMeasurementTracker> set = mRssiTrackers.get(address);
        CopyOnWriteArraySet<DistanceMeasurementTracker> set = mRssiTrackers.get(address);
        if (set == null) {
            Log.w(TAG, "Can't find rssi tracker");
            return;