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

Commit 2e1f2831 authored by William Escande's avatar William Escande
Browse files

Adapter: use callback wrapper for audio profiles

Bug: 311772251
Flag: Exempt refactor
Test: atest CtsBluetoothTestTests
Change-Id: I183950ae56eadd2919387473f079f246d6a72b59
parent 9b890042
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -280,6 +280,8 @@ interface IBluetooth
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})")
    Bundle getPreferredAudioProfiles(in BluetoothDevice device, in AttributionSource source);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})")
    int isDualModeAudioEnabled(in AttributionSource attributionSource);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})")
    int registerPreferredAudioProfilesChangedCallback(in IBluetoothPreferredAudioProfilesCallback callback, in AttributionSource attributionSource);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})")
    int unregisterPreferredAudioProfilesChangedCallback(in IBluetoothPreferredAudioProfilesCallback callback, in AttributionSource attributionSource);
+19 −1
Original line number Diff line number Diff line
@@ -4027,6 +4027,24 @@ public class AdapterService extends Service {
            return service.notifyActiveDeviceChangeApplied(device);
        }

        @Override
        public int isDualModeAudioEnabled(AttributionSource source) {
            AdapterService service = getService();
            if (service == null) {
                return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
            }
            if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
                return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
            }
            service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);

            if (!Utils.isDualModeAudioEnabled()) {
                return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED;
            }

            return BluetoothStatusCodes.SUCCESS;
        }

        @Override
        public int registerPreferredAudioProfilesChangedCallback(
                IBluetoothPreferredAudioProfilesCallback callback, AttributionSource source) {
@@ -4045,7 +4063,7 @@ public class AdapterService extends Service {
            service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);

            // If LE only mode is enabled, the dual mode audio feature is disabled
            if (!isDualModeAudioEnabled()) {
            if (!Utils.isDualModeAudioEnabled()) {
                return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED;
            }

+44 −76
Original line number Diff line number Diff line
@@ -889,8 +889,6 @@ public final class BluetoothAdapter {
            mMetadataListeners = new HashMap<>();
    private final Map<BluetoothConnectionCallback, Executor>
            mBluetoothConnectionCallbackExecutorMap = new HashMap<>();
    private final Map<PreferredAudioProfilesChangedCallback, Executor>
            mAudioProfilesChangedCallbackExecutorMap = new HashMap<>();

    private static final class ProfileConnection {
        int mProfile;
@@ -1128,6 +1126,28 @@ public final class BluetoothAdapter {
                new CallbackWrapper(
                        registerQualityReportCallbackConsumer,
                        unregisterQualityReportCallbackConsumer);
        Consumer<IBluetooth> registerAudioProfilesCallbackConsumer =
                (IBluetooth service) -> {
                    try {
                        service.registerPreferredAudioProfilesChangedCallback(
                                mPreferredAudioProfilesChangedCallback, mAttributionSource);
                    } catch (RemoteException e) {
                        Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
                    }
                };
        Consumer<IBluetooth> unregisterAudioProfilesCallbackConsumer =
                (IBluetooth service) -> {
                    try {
                        service.unregisterPreferredAudioProfilesChangedCallback(
                                mPreferredAudioProfilesChangedCallback, mAttributionSource);
                    } catch (RemoteException e) {
                        Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
                    }
                };
        mAudioProfilesCallbackWrapper =
                new CallbackWrapper(
                        registerAudioProfilesCallbackConsumer,
                        unregisterAudioProfilesCallbackConsumer);
    }

    /**
@@ -3762,21 +3782,7 @@ public final class BluetoothAdapter {
                                        }
                                    });
                        }
                        synchronized (mAudioProfilesChangedCallbackExecutorMap) {
                            if (!mAudioProfilesChangedCallbackExecutorMap.isEmpty()) {
                                try {
                                    mService.registerPreferredAudioProfilesChangedCallback(
                                            mPreferredAudioProfilesChangedCallback,
                                            mAttributionSource);
                                } catch (RemoteException e) {
                                    Log.e(
                                            TAG,
                                            "onBluetoothServiceUp: Failed to register bluetooth"
                                                    + "connection callback",
                                            e);
                                }
                            }
                        }
                        mAudioProfilesCallbackWrapper.registerToNewService(mService);
                        mQualityCallbackWrapper.registerToNewService(mService);
                    } finally {
                        mServiceLock.readLock().unlock();
@@ -5068,24 +5074,19 @@ public final class BluetoothAdapter {
        return BluetoothStatusCodes.ERROR_UNKNOWN;
    }

    @SuppressLint("AndroidFrameworkBluetoothPermission")
    private final CallbackWrapper<PreferredAudioProfilesChangedCallback, IBluetooth>
            mAudioProfilesCallbackWrapper;

    private final IBluetoothPreferredAudioProfilesCallback mPreferredAudioProfilesChangedCallback =
            new IBluetoothPreferredAudioProfilesCallback.Stub() {
                @Override
                public void onPreferredAudioProfilesChanged(
                        BluetoothDevice device, Bundle preferredAudioProfiles, int status) {
                    for (Map.Entry<PreferredAudioProfilesChangedCallback, Executor>
                            callbackExecutorEntry :
                                    mAudioProfilesChangedCallbackExecutorMap.entrySet()) {
                        PreferredAudioProfilesChangedCallback callback =
                                callbackExecutorEntry.getKey();
                        Executor executor = callbackExecutorEntry.getValue();
                        executor.execute(
                                () ->
                                        callback.onPreferredAudioProfilesChanged(
                    mAudioProfilesCallbackWrapper.forEach(
                            (cb) ->
                                    cb.onPreferredAudioProfilesChanged(
                                            device, preferredAudioProfiles, status));
                }
                }
            };

    /** @hide */
@@ -5126,37 +5127,21 @@ public final class BluetoothAdapter {
            @NonNull @CallbackExecutor Executor executor,
            @NonNull PreferredAudioProfilesChangedCallback callback) {
        if (DBG) Log.d(TAG, "registerPreferredAudioProfilesChangedCallback()");
        requireNonNull(executor, "executor cannot be null");
        requireNonNull(callback, "callback cannot be null");
        requireNonNull(callback);
        requireNonNull(executor);

        synchronized (mAudioProfilesChangedCallbackExecutorMap) {
            // If the callback map is empty, we register the service-to-app callback
            if (mAudioProfilesChangedCallbackExecutorMap.isEmpty()) {
                int serviceCallStatus = BluetoothStatusCodes.ERROR_UNKNOWN;
        mServiceLock.readLock().lock();
        try {
                    if (mService != null) {
                        serviceCallStatus =
                                mService.registerPreferredAudioProfilesChangedCallback(
                                        mPreferredAudioProfilesChangedCallback, mAttributionSource);
            int status = mService.isDualModeAudioEnabled(mAttributionSource);
            if (status != BluetoothStatusCodes.SUCCESS) {
                return status;
            }
            mAudioProfilesCallbackWrapper.registerCallback(mService, callback, executor);
        } catch (RemoteException e) {
            Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
        } finally {
            mServiceLock.readLock().unlock();
        }
                if (serviceCallStatus != BluetoothStatusCodes.SUCCESS) {
                    return serviceCallStatus;
                }
            }

            // Adds the passed in callback to our local mapping
            if (mAudioProfilesChangedCallbackExecutorMap.containsKey(callback)) {
                throw new IllegalArgumentException("This callback has already been registered");
            } else {
                mAudioProfilesChangedCallbackExecutorMap.put(callback, executor);
            }
        }

        return BluetoothStatusCodes.SUCCESS;
    }
@@ -5196,32 +5181,15 @@ public final class BluetoothAdapter {
    public int unregisterPreferredAudioProfilesChangedCallback(
            @NonNull PreferredAudioProfilesChangedCallback callback) {
        if (DBG) Log.d(TAG, "unregisterPreferredAudioProfilesChangedCallback()");
        requireNonNull(callback, "callback cannot be null");

        synchronized (mAudioProfilesChangedCallbackExecutorMap) {
            if (mAudioProfilesChangedCallbackExecutorMap.remove(callback) == null) {
                throw new IllegalArgumentException("This callback has not been registered");
            }
        }

        if (!mAudioProfilesChangedCallbackExecutorMap.isEmpty()) {
            return BluetoothStatusCodes.SUCCESS;
        }

        // If the callback map is empty, we unregister the service-to-app callback
        mServiceLock.readLock().lock();
        try {
            if (mService != null) {
                return mService.unregisterPreferredAudioProfilesChangedCallback(
                        mPreferredAudioProfilesChangedCallback, mAttributionSource);
            }
        } catch (RemoteException e) {
            Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
            mAudioProfilesCallbackWrapper.unregisterCallback(mService, callback);
        } finally {
            mServiceLock.readLock().unlock();
        }

        return BluetoothStatusCodes.ERROR_UNKNOWN;
        return BluetoothStatusCodes.SUCCESS;
    }

    /**