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

Commit f1d39c38 authored by William Escande's avatar William Escande
Browse files

Wait for state callback before ending constructor

Bug: 361671423
Bug: 357645528
Flag: com.android.bluetooth.flags.broadcast_adapter_state_with_callback
Test: atest CtsBluetoothTestCases:BluetoothDeviceTest
Change-Id: I1179ff7a95cd22eb6ef9fd25c4d2a2066e1ab7e0
parent 57e1f1e5
Loading
Loading
Loading
Loading
+33 −0
Original line number Diff line number Diff line
@@ -96,8 +96,12 @@ import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.WeakHashMap;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.BiFunction;
import java.util.function.Consumer;
@@ -873,6 +877,7 @@ public final class BluetoothAdapter {
    @GuardedBy("mServiceLock")
    private IBluetooth mService;

    private static CompletableFuture<Void> sAdapterStateFuture = null;
    private static int sAdapterState = BluetoothAdapter.STATE_OFF;

    private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock();
@@ -1173,6 +1178,20 @@ public final class BluetoothAdapter {
                new CallbackWrapper(
                        registerBluetoothConnectionCallbackConsumer,
                        unregisterBluetoothConnectionCallbackConsumer);

        if (!Flags.broadcastAdapterStateWithCallback()) {
            return;
        }
        // Make sure that we are waiting on the state callback prior to returning from constructor
        CompletableFuture<Void> futureState = sAdapterStateFuture;
        if (futureState != null) {
            try {
                futureState.get(1_000, TimeUnit.MILLISECONDS);
            } catch (InterruptedException | ExecutionException | TimeoutException e) {
                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
            }
        }
        Log.i(TAG, "Adapter created with state: " + nameForState(sAdapterState));
    }

    /**
@@ -3784,6 +3803,12 @@ public final class BluetoothAdapter {

                @RequiresNoPermission
                public void onBluetoothAdapterStateChange(int newState) {
                    Log.v(TAG, "onBluetoothAdapterStateChange(" + nameForState(newState) + ")");
                    CompletableFuture<Void> future = sAdapterStateFuture;
                    sAdapterStateFuture = null;
                    if (future != null) {
                        future.complete(null);
                    }
                    sAdapterState = newState;
                }
            };
@@ -4218,6 +4243,11 @@ public final class BluetoothAdapter {
            return;
        }
        if (wantRegistered) {
            if (Flags.broadcastAdapterStateWithCallback()
                    && sAdapterState == BluetoothAdapter.STATE_OFF
                    && sAdapterStateFuture == null) {
                sAdapterStateFuture = new CompletableFuture<>();
            }
            try {
                sService =
                        IBluetooth.Stub.asInterface(
@@ -4232,6 +4262,9 @@ public final class BluetoothAdapter {
            } catch (RemoteException e) {
                throw e.rethrowAsRuntimeException();
            }
            if (Flags.broadcastAdapterStateWithCallback()) {
                sAdapterState = BluetoothAdapter.STATE_OFF;
            }
        }
        sServiceRegistered = wantRegistered;
    }