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

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

move profiles connection away from main thread

By using the main handler to perform binder task, we may load the app
main thread un-necessarily.
Instead use a lock to prevent race condition and block whatever is the
thread that call into getProfileProxy (delegating the responsibilities
of a slow call to the caller thread management)

Test: atest pts-bot (any test that requires the profiles)
Flag: Exempt refactor
Bug: 367914132
Bug: 370815283
Change-Id: Ib7ad3119375b95938751eeec20081f2455ec01b5
parent e0d80767
Loading
Loading
Loading
Loading
+69 −39
Original line number Diff line number Diff line
@@ -893,6 +893,7 @@ public final class BluetoothAdapter {
            mListener = listener;
        }

        @GuardedBy("BluetoothAdapter.sProfileLock")
        void connect(BluetoothProfile proxy, IBinder binder) {
            Log.d(TAG, BluetoothProfile.getProfileName(mProfile) + " connected");
            mConnected = true;
@@ -900,6 +901,7 @@ public final class BluetoothAdapter {
            mListener.onServiceConnected(mProfile, proxy);
        }

        @GuardedBy("BluetoothAdapter.sProfileLock")
        void disconnect(BluetoothProfile proxy) {
            Log.d(TAG, BluetoothProfile.getProfileName(mProfile) + " disconnected");
            mConnected = false;
@@ -908,6 +910,9 @@ public final class BluetoothAdapter {
        }
    }

    private static final Object sProfileLock = new Object();

    @GuardedBy("sProfileLock")
    private final Map<BluetoothProfile, ProfileConnection> mProfileConnections =
            new ConcurrentHashMap<>();

@@ -3651,16 +3656,25 @@ public final class BluetoothAdapter {
        BluetoothProfile profileProxy = constructor.apply(context, this);
        ProfileConnection connection = new ProfileConnection(profile, listener);

        mMainHandler.post(
        Runnable connectAction =
                () -> {
                    synchronized (sProfileLock) {
                        // Synchronize with the binder callback to prevent performing the
                        // connection.connect
                        // concurrently
                        mProfileConnections.put(profileProxy, connection);

                        IBinder binder = getProfile(profile);
                        if (binder != null) {
                            connection.connect(profileProxy, binder);
                        }
                });

                    }
                };
        if (Flags.getProfileUseLock()) {
            connectAction.run();
            return true;
        }
        mMainHandler.post(connectAction);
        return true;
    }

@@ -3697,6 +3711,7 @@ public final class BluetoothAdapter {
            return;
        }

        synchronized (sProfileLock) {
            ProfileConnection connection = mProfileConnections.remove(proxy);
            if (connection != null) {
                if (proxy instanceof BluetoothLeCallControl callControl) {
@@ -3706,6 +3721,7 @@ public final class BluetoothAdapter {
                connection.disconnect(proxy);
            }
        }
    }

    /**
     * Close the connection of the profile proxy to the Service.
@@ -3876,8 +3892,9 @@ public final class BluetoothAdapter {

                @RequiresNoPermission
                public void onBluetoothOn() {
                    mMainHandler.post(
                    Runnable btOnAction =
                            () -> {
                                synchronized (sProfileLock) {
                                    mProfileConnections.forEach(
                                            (proxy, connection) -> {
                                                if (connection.mConnected) return;
@@ -3889,24 +3906,36 @@ public final class BluetoothAdapter {
                                                    Log.e(
                                                            TAG,
                                                            "onBluetoothOn: Binder null for "
                                                                + BluetoothProfile.getProfileName(
                                                                        connection.mProfile));
                                                                    + BluetoothProfile.getProfileName(connection.mProfile));
                                                }
                                            });
                            });
                                }
                            };
                    if (Flags.getProfileUseLock()) {
                        btOnAction.run();
                        return;
                    }
                    mMainHandler.post(btOnAction);
                }

                @RequiresNoPermission
                public void onBluetoothOff() {
                    mMainHandler.post(
                    Runnable btOffAction =
                            () -> {
                                synchronized (sProfileLock) {
                                    mProfileConnections.forEach(
                                            (proxy, connection) -> {
                                                if (connection.mConnected) {
                                                    connection.disconnect(proxy);
                                                }
                                            });
                            });
                                }
                            };
                    if (Flags.getProfileUseLock()) {
                        btOffAction.run();
                        return;
                    }
                    mMainHandler.post(btOffAction);
                }
            };

@@ -4203,6 +4232,7 @@ public final class BluetoothAdapter {
    }

    /** Return a binder to a Profile service */
    @GuardedBy("sProfileLock")
    private @Nullable IBinder getProfile(int profile) {
        mServiceLock.readLock().lock();
        try {