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

Commit fc2ac5bf authored by Łukasz Rymanowski's avatar Łukasz Rymanowski
Browse files

Bluetooth: Fix common issue in registerCallback APIs

This fixes race if callback is registered before BT is On.

Bug: 150670922
Test: compile/manual
Sponsor: @jpawlowski
Change-Id: If7e9adba30ce0bba57acb503feb0f47c730da5d3
parent 38f103e2
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -473,15 +473,19 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable
            @NonNull Callback callback) {
        Objects.requireNonNull(executor, "executor cannot be null");
        Objects.requireNonNull(callback, "callback cannot be null");
        if (!isEnabled()) {
            throw new IllegalStateException("service not enabled");
        }

        if (DBG) log("registerCallback");

        synchronized (mCallbackExecutorMap) {
            // If the callback map is empty, we register the service-to-app callback
            if (mCallbackExecutorMap.isEmpty()) {
                if (!isEnabled()) {
                    /* If Bluetooth is off, just store callback and it will be registered
                     * when Bluetooth is on
                     */
                    mCallbackExecutorMap.put(callback, executor);
                    return;
                }
                try {
                    final IBluetoothHapClient service = getService();
                    if (service != null) {
@@ -490,7 +494,7 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable
                        service.registerCallback(mCallback, mAttributionSource, recv);
                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
                    }
                } catch (IllegalStateException | TimeoutException e) {
                } catch (TimeoutException e) {
                    Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
+8 −4
Original line number Diff line number Diff line
@@ -425,15 +425,19 @@ public final class BluetoothLeBroadcast implements AutoCloseable, BluetoothProfi
            @NonNull Callback callback) {
        Objects.requireNonNull(executor, "executor cannot be null");
        Objects.requireNonNull(callback, "callback cannot be null");
        if (!isEnabled()) {
            throw new IllegalStateException("service not enabled");
        }

        if (DBG) log("registerCallback");

        synchronized (mCallbackExecutorMap) {
            // If the callback map is empty, we register the service-to-app callback
            if (mCallbackExecutorMap.isEmpty()) {
                if (!mAdapter.isEnabled()) {
                    /* If Bluetooth is off, just store callback and it will be registered
                     * when Bluetooth is on
                     */
                    mCallbackExecutorMap.put(callback, executor);
                    return;
                }
                try {
                    final IBluetoothLeAudio service = getService();
                    if (service != null) {
@@ -442,7 +446,7 @@ public final class BluetoothLeBroadcast implements AutoCloseable, BluetoothProfi
                        service.registerLeBroadcastCallback(mCallback, mAttributionSource, recv);
                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
                    }
                } catch (TimeoutException | IllegalStateException e) {
                } catch (TimeoutException e) {
                    Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
+8 −1
Original line number Diff line number Diff line
@@ -344,6 +344,13 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose
        synchronized (mCallbackExecutorMap) {
            // If the callback map is empty, we register the service-to-app callback
            if (mCallbackExecutorMap.isEmpty()) {
                if (!mAdapter.isEnabled()) {
                    /* If Bluetooth is off, just store callback and it will be registered
                     * when Bluetooth is on
                     */
                    mCallbackExecutorMap.put(callback, executor);
                    return;
                }
                try {
                    final IBluetoothVolumeControl service = getService();
                    if (service != null) {
@@ -355,7 +362,7 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose
                } catch (RemoteException e) {
                    Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
                    throw e.rethrowFromSystemServer();
                } catch (IllegalStateException | TimeoutException e) {
                } catch (TimeoutException e) {
                    Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
                }
            }