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

Commit 5d0a6677 authored by William Escande's avatar William Escande
Browse files

SystemServer: Broadcast callback no longer need synchro

RemoteCallbackList implements synchronization which enables calling register / unregister as a broadcast is active.

It is still invalid to start two concurrent broadcasts, but this possibility is prevented by the fact that broadcasts are now all run on the same thread.

Bug: 288450479
Test: m Bluetooth
Flag: Exempt refactor cleanup
Change-Id: I505d61049eb5b643d3e993dd5ddd2404b3f6cf9a
parent 913996b4
Loading
Loading
Loading
Loading
+27 −62
Original line number Diff line number Diff line
@@ -741,19 +741,15 @@ class BluetoothManagerService {

    // Called from unsafe binder thread
    IBluetooth registerAdapter(IBluetoothManagerCallback callback) {
        synchronized (mCallbacks) {
        mCallbacks.register(callback);
        }
        // Copy to local variable to avoid race condition when checking for null
        AdapterBinder adapter = mAdapter;
        return adapter != null ? adapter.getAdapterBinder() : null;
    }

    void unregisterAdapter(IBluetoothManagerCallback callback) {
        synchronized (mCallbacks) {
        mCallbacks.unregister(callback);
    }
    }

    boolean isEnabled() {
        return getState() == STATE_ON;
@@ -1243,74 +1239,43 @@ class BluetoothManagerService {
        mHandler.obtainMessage(MESSAGE_USER_UNLOCKED, userHandle).sendToTarget();
    }

    private void sendBluetoothOnCallback() {
        synchronized (mCallbacks) {
            try {
                int n = mCallbacks.beginBroadcast();
                Log.d(TAG, "Broadcasting onBluetoothOn() to " + n + " receivers.");
                for (int i = 0; i < n; i++) {
                    try {
                        mCallbacks.getBroadcastItem(i).onBluetoothOn();
                    } catch (RemoteException e) {
                        Log.e(TAG, "Unable to call onBluetoothOn() on callback #" + i, e);
                    }
                }
            } finally {
                mCallbacks.finishBroadcast();
            }
        }
    @FunctionalInterface
    public interface RemoteExceptionConsumer<T> {
        void accept(T t) throws RemoteException;
    }

    private void sendBluetoothOffCallback() {
        synchronized (mCallbacks) {
            try {
                int n = mCallbacks.beginBroadcast();
                Log.d(TAG, "Broadcasting onBluetoothOff() to " + n + " receivers.");
                for (int i = 0; i < n; i++) {
    private void broadcastToAdapters(
            String logAction, RemoteExceptionConsumer<IBluetoothManagerCallback> action) {
        final int itemCount = mCallbacks.beginBroadcast();
        Log.d(TAG, "Broadcasting " + logAction + "() to " + itemCount + " receivers.");
        for (int i = 0; i < itemCount; i++) {
            try {
                        mCallbacks.getBroadcastItem(i).onBluetoothOff();
                action.accept(mCallbacks.getBroadcastItem(i));
            } catch (RemoteException e) {
                        Log.e(TAG, "Unable to call onBluetoothOff() on callback #" + i, e);
                Log.e(TAG, "RemoteException while calling " + logAction + "()#" + i, e);
            }
        }
            } finally {
        mCallbacks.finishBroadcast();
    }

    private void sendBluetoothOnCallback() {
        broadcastToAdapters("sendBluetoothOnCallback", IBluetoothManagerCallback::onBluetoothOn);
    }

    private void sendBluetoothOffCallback() {
        broadcastToAdapters("sendBluetoothOffCallback", IBluetoothManagerCallback::onBluetoothOff);
    }

    /** Inform BluetoothAdapter instances that Adapter service is up */
    private void sendBluetoothServiceUpCallback() {
        synchronized (mCallbacks) {
            int n = mCallbacks.beginBroadcast();
            Log.d(TAG, "sendBluetoothServiceUpCallback(): to " + n + " receivers");
            for (int i = 0; i < n; i++) {
                try {
                    mCallbacks
                            .getBroadcastItem(i)
                            .onBluetoothServiceUp(mAdapter.getAdapterBinder().asBinder());
                } catch (RemoteException e) {
                    Log.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e);
                }
            }
            mCallbacks.finishBroadcast();
        }
        broadcastToAdapters(
                "sendBluetoothServiceUpCallback",
                (item) -> item.onBluetoothServiceUp(mAdapter.getAdapterBinder().asBinder()));
    }

    /** Inform BluetoothAdapter instances that Adapter service is down */
    private void sendBluetoothServiceDownCallback() {
        synchronized (mCallbacks) {
            int n = mCallbacks.beginBroadcast();
            Log.d(TAG, "sendBluetoothServiceDownCallback(): to " + n + " receivers");
            for (int i = 0; i < n; i++) {
                try {
                    mCallbacks.getBroadcastItem(i).onBluetoothServiceDown();
                } catch (RemoteException e) {
                    Log.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e);
                }
            }
            mCallbacks.finishBroadcast();
        }
        broadcastToAdapters(
                "sendBluetoothServiceDownCallback",
                IBluetoothManagerCallback::onBluetoothServiceDown);
    }

    // Called from unsafe binder thread