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

Commit 6a8804d2 authored by Łukasz Rymanowski's avatar Łukasz Rymanowski Committed by Gerrit Code Review
Browse files

Merge "leaudio: Add audio server scanner to the LeAudioService"

parents 2f573ec4 de563c4b
Loading
Loading
Loading
Loading
+140 −0
Original line number Original line Diff line number Diff line
@@ -40,6 +40,11 @@ import android.bluetooth.IBluetoothLeAudio;
import android.bluetooth.IBluetoothLeAudioCallback;
import android.bluetooth.IBluetoothLeAudioCallback;
import android.bluetooth.IBluetoothLeBroadcastCallback;
import android.bluetooth.IBluetoothLeBroadcastCallback;
import android.bluetooth.IBluetoothVolumeControl;
import android.bluetooth.IBluetoothVolumeControl;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.AttributionSource;
import android.content.AttributionSource;
import android.content.BroadcastReceiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Context;
@@ -149,6 +154,10 @@ public class LeAudioService extends ProfileService {
    @VisibleForTesting
    @VisibleForTesting
    RemoteCallbackList<IBluetoothLeAudioCallback> mLeAudioCallbacks;
    RemoteCallbackList<IBluetoothLeAudioCallback> mLeAudioCallbacks;


    BluetoothLeScanner mAudioServersScanner;
    /* When mScanCallback is not null, it means scan is started. */
    ScanCallback mScanCallback;

    private class LeAudioGroupDescriptor {
    private class LeAudioGroupDescriptor {
        LeAudioGroupDescriptor(boolean isInbandRingtonEnabled) {
        LeAudioGroupDescriptor(boolean isInbandRingtonEnabled) {
            mIsConnected = false;
            mIsConnected = false;
@@ -347,6 +356,9 @@ public class LeAudioService extends ProfileService {
            mTmapStarted = false;
            mTmapStarted = false;
        }
        }


        stopAudioServersBackgroundScan();
        mAudioServersScanner = null;

        //Don't wait for async call with INACTIVE group status, clean active
        //Don't wait for async call with INACTIVE group status, clean active
        //device for active group.
        //device for active group.
        synchronized (mGroupLock) {
        synchronized (mGroupLock) {
@@ -1118,6 +1130,53 @@ public class LeAudioService extends ProfileService {
        sendBroadcast(intent, BLUETOOTH_CONNECT);
        sendBroadcast(intent, BLUETOOTH_CONNECT);
    }
    }


    boolean isScannerNeeded() {
        if (mDeviceDescriptors.isEmpty() || !mBluetoothEnabled) {
            if (DBG) {
                Log.d(TAG, "isScannerNeeded: false, mBluetoothEnabled: " + mBluetoothEnabled);
            }
            return false;
        }

        if (DBG) {
            Log.d(TAG, "isScannerNeeded: true");
        }
        return true;
    }

    private class AudioServerScanCallback extends ScanCallback {
        int mMaxScanRetires = 10;
        int mScanRetries = 0;

        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            /* Filter is set in the way, that there will be no results found.
             * We just need a scanner to be running for the APCF filtering defined in native
             */
        }

        @Override
        public void onBatchScanResults(List<ScanResult> results) {
            /* Filter is set in the way, that there will be no results found.
             * We just need a scanner to be running for the APCF filtering defined in native
             */
        }

        @Override
        public void onScanFailed(int errorCode) {
            Log.w(TAG, "Scan failed " + errorCode + " scan retries: " + mScanRetries);
            switch(errorCode) {
                case SCAN_FAILED_INTERNAL_ERROR: {
                    if (mScanRetries < mMaxScanRetires) {
                        mScanRetries++;
                        Log.w(TAG, "Failed to start. Let's retry");
                        mHandler.post(() -> startAudioServersBackgroundScan(/* retry = */ true));
                    }
                }
            }
        }
    }

    /* Notifications of audio device connection/disconn events. */
    /* Notifications of audio device connection/disconn events. */
    private class AudioManagerAudioDeviceCallback extends AudioDeviceCallback {
    private class AudioManagerAudioDeviceCallback extends AudioDeviceCallback {
        @Override
        @Override
@@ -1631,6 +1690,71 @@ public class LeAudioService extends ProfileService {
        }
        }
    }
    }


    void stopAudioServersBackgroundScan() {
        if (DBG) {
            Log.d(TAG, "stopAudioServersBackgroundScan");
        }

        if (mAudioServersScanner == null || mScanCallback == null) {
            if (DBG) {
                Log.d(TAG, "stopAudioServersBackgroundScan: already stopped");
                return;
            }
        }

        mAudioServersScanner.stopScan(mScanCallback);

        /* Callback is the indicator for scanning being enabled */
        mScanCallback = null;
    }

    void startAudioServersBackgroundScan(boolean retry) {
        if (DBG) {
            Log.d(TAG, "startAudioServersBackgroundScan, retry: " + retry);
        }

        if (!isScannerNeeded()) {
            return;
        }

        if (mAudioServersScanner == null) {
            mAudioServersScanner = BluetoothAdapter.getDefaultAdapter().getBluetoothLeScanner();
            if (mAudioServersScanner == null) {
                Log.e(TAG, "startAudioServersBackgroundScan: Could not get scanner");
                return;
            }
        }

        if (!retry) {
            if (mScanCallback != null) {
                if (DBG) {
                    Log.d(TAG, "startAudioServersBackgroundScan: Scanning already enabled");
                    return;
                }
            }
            mScanCallback = new AudioServerScanCallback();
        }

        /* Filter we are building here will not match to anything.
         * Eventually we should be able to start scan from native when
         * b/276350722 is done
         */
        byte[] serviceData = new byte[]{0x11};

        ArrayList filterList = new ArrayList<ScanFilter>();
        ScanFilter filter = new ScanFilter.Builder()
                .setServiceData(BluetoothUuid.LE_AUDIO, serviceData)
                .build();
        filterList.add(filter);

        ScanSettings settings = new ScanSettings.Builder()
                .setLegacy(false)
                .setScanMode(ScanSettings.SCAN_MODE_BALANCED)
                .build();

        mAudioServersScanner.startScan(filterList, settings, mScanCallback);
    }

    // Suppressed since this is part of a local process
    // Suppressed since this is part of a local process
    @SuppressLint("AndroidFrameworkRequiresPermission")
    @SuppressLint("AndroidFrameworkRequiresPermission")
    void messageFromNative(LeAudioStackEvent stackEvent) {
    void messageFromNative(LeAudioStackEvent stackEvent) {
@@ -1661,6 +1785,8 @@ public class LeAudioService extends ProfileService {
                    switch (stackEvent.valueInt1) {
                    switch (stackEvent.valueInt1) {
                        case LeAudioStackEvent.CONNECTION_STATE_DISCONNECTING:
                        case LeAudioStackEvent.CONNECTION_STATE_DISCONNECTING:
                        case LeAudioStackEvent.CONNECTION_STATE_DISCONNECTED:
                        case LeAudioStackEvent.CONNECTION_STATE_DISCONNECTED:
                            startAudioServersBackgroundScan(/* retry = */ false);

                            boolean disconnectDueToUnbond =
                            boolean disconnectDueToUnbond =
                                    (BluetoothDevice.BOND_NONE
                                    (BluetoothDevice.BOND_NONE
                                            == mAdapterService.getBondState(device));
                                            == mAdapterService.getBondState(device));
@@ -2040,6 +2166,9 @@ public class LeAudioService extends ProfileService {
            descriptor.mStateMachine = null;
            descriptor.mStateMachine = null;


            mDeviceDescriptors.remove(device);
            mDeviceDescriptors.remove(device);
            if (!isScannerNeeded()) {
                stopAudioServersBackgroundScan();
            }
        }
        }
    }
    }


@@ -2079,6 +2208,10 @@ public class LeAudioService extends ProfileService {
            Log.e(TAG, "deviceConnected: no descriptors for group: "
            Log.e(TAG, "deviceConnected: no descriptors for group: "
                    + deviceDescriptor.mGroupId);
                    + deviceDescriptor.mGroupId);
        }
        }

        if (!isScannerNeeded()) {
            stopAudioServersBackgroundScan();
        }
    }
    }


    /**
    /**
@@ -2099,6 +2232,10 @@ public class LeAudioService extends ProfileService {
            removeStateMachine(device);
            removeStateMachine(device);
        }
        }


        if (!isScannerNeeded()) {
            stopAudioServersBackgroundScan();
        }

        synchronized (mGroupLock) {
        synchronized (mGroupLock) {
            LeAudioGroupDescriptor descriptor = getGroupDescriptor(deviceDescriptor.mGroupId);
            LeAudioGroupDescriptor descriptor = getGroupDescriptor(deviceDescriptor.mGroupId);
            if (descriptor == null) {
            if (descriptor == null) {
@@ -2408,6 +2545,8 @@ public class LeAudioService extends ProfileService {
                setAuthorizationForRelatedProfiles(device, true);
                setAuthorizationForRelatedProfiles(device, true);
            }
            }
        }
        }

        startAudioServersBackgroundScan(/* retry = */ false);
    }
    }


    private LeAudioGroupDescriptor getGroupDescriptor(int groupId) {
    private LeAudioGroupDescriptor getGroupDescriptor(int groupId) {
@@ -2461,6 +2600,7 @@ public class LeAudioService extends ProfileService {


        if (mBluetoothEnabled) {
        if (mBluetoothEnabled) {
            setAuthorizationForRelatedProfiles(device, true);
            setAuthorizationForRelatedProfiles(device, true);
            startAudioServersBackgroundScan(/* retry = */ false);
        }
        }
    }
    }