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

Commit 6327e3f7 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 11520864 from 03cfb518 to 24Q2-release

Change-Id: I1a9d7f3cf9afec929a40d0983d43e6b4b88ac2a6
parents 22f506bd 03cfb518
Loading
Loading
Loading
Loading
+22 −30
Original line number Diff line number Diff line
@@ -41,7 +41,6 @@ import android.bluetooth.BufferConstraints;
import android.bluetooth.IBluetoothA2dp;
import android.companion.CompanionDeviceManager;
import android.content.AttributionSource;
import android.content.Context;
import android.content.Intent;
import android.media.AudioDeviceCallback;
import android.media.AudioDeviceInfo;
@@ -90,18 +89,18 @@ public class A2dpService extends ProfileService {

    private static A2dpService sA2dpService;

    private AdapterService mAdapterService;
    private DatabaseManager mDatabaseManager;
    private final A2dpNativeInterface mNativeInterface;
    private final AdapterService mAdapterService;
    private final AudioManager mAudioManager;
    private final DatabaseManager mDatabaseManager;
    private final CompanionDeviceManager mCompanionDeviceManager;

    private HandlerThread mStateMachinesThread;
    private Handler mHandler = null;

    private final A2dpNativeInterface mNativeInterface;
    @VisibleForTesting
    ServiceFactory mFactory = new ServiceFactory();
    @VisibleForTesting
    AudioManager mAudioManager;
    private A2dpCodecConfig mA2dpCodecConfig;
    private CompanionDeviceManager mCompanionDeviceManager;

    @GuardedBy("mStateMachines")
    private BluetoothDevice mActiveDevice;
@@ -126,15 +125,20 @@ public class A2dpService extends ProfileService {
    private final AudioManagerAudioDeviceCallback mAudioManagerAudioDeviceCallback =
            new AudioManagerAudioDeviceCallback();

    public A2dpService(Context ctx) {
        super(ctx);
        mNativeInterface = requireNonNull(A2dpNativeInterface.getInstance());
    public A2dpService(AdapterService adapterService) {
        this(adapterService, A2dpNativeInterface.getInstance());
    }

    @VisibleForTesting
    A2dpService(Context ctx, A2dpNativeInterface nativeInterface) {
        super(ctx);
    A2dpService(AdapterService adapterService, A2dpNativeInterface nativeInterface) {
        super(requireNonNull(adapterService));
        mAdapterService = adapterService;
        mNativeInterface = requireNonNull(nativeInterface);
        mDatabaseManager = requireNonNull(mAdapterService.getDatabase());
        mAudioManager = requireNonNull(getSystemService(AudioManager.class));

        // Some platform may not have the FEATURE_COMPANION_DEVICE_SETUP
        mCompanionDeviceManager = getSystemService(CompanionDeviceManager.class);
    }

    public static boolean isEnabled() {
@@ -157,20 +161,6 @@ public class A2dpService extends ProfileService {
            throw new IllegalStateException("start() called twice");
        }

        // Step 1: Get AdapterService, DatabaseManager, AudioManager.
        // None of them can be null.
        mAdapterService =
                requireNonNull(
                        AdapterService.getAdapterService(),
                        "AdapterService cannot be null when A2dpService starts");
        mDatabaseManager =
                requireNonNull(
                        mAdapterService.getDatabase(),
                        "DatabaseManager cannot be null when A2dpService starts");
        mAudioManager = getSystemService(AudioManager.class);
        mCompanionDeviceManager = getSystemService(CompanionDeviceManager.class);
        requireNonNull(mAudioManager, "AudioManager cannot be null when A2dpService starts");

        // Step 2: Get maximum number of connected audio devices
        mMaxConnectedAudioDevices = mAdapterService.getMaxConnectedAudioDevices();
        Log.i(TAG, "Max connected audio devices set to " + mMaxConnectedAudioDevices);
@@ -255,10 +245,6 @@ public class A2dpService extends ProfileService {

        // Step 2: Reset maximum number of connected audio devices
        mMaxConnectedAudioDevices = 1;

        // Step 1: Clear AdapterService, AudioManager
        mAudioManager = null;
        mAdapterService = null;
    }

    @Override
@@ -1608,6 +1594,12 @@ public class A2dpService extends ProfileService {
                return;
            }
            if (!hasBluetoothPrivilegedPermission(service)) {
                if (service.mCompanionDeviceManager == null) {
                    throw new SecurityException(
                            "Caller should have BLUETOOTH_PRIVILEGED in order to call"
                                    + " setCodecConfigPreference without a CompanionDeviceManager"
                                    + " service");
                }
                enforceCdmAssociation(service.mCompanionDeviceManager, service,
                        source.getPackageName(), Binder.getCallingUid(), device);
            }
+29 −0
Original line number Diff line number Diff line
@@ -978,6 +978,20 @@ public class BassClientService extends ProfileService {
        }
    }

    private void informConnectedDeviceAboutScanOffloadStop() {
        for (BluetoothDevice device : getConnectedDevices()) {
            synchronized (mStateMachines) {
                BassClientStateMachine stateMachine = getOrCreateStateMachine(device);
                if (stateMachine == null) {
                    Log.w(TAG, "informConnectedDeviceAboutScanOffloadStop: Can't get state "
                            + "machine for device: " + device);
                    continue;
                }
                stateMachine.sendMessage(BassClientStateMachine.STOP_SCAN_OFFLOAD);
            }
        }
    }

    void handleConnectionStateChanged(BluetoothDevice device, int fromState, int toState) {
        mHandler.post(() -> connectionStateChanged(device, fromState, toState));
    }
@@ -1339,6 +1353,7 @@ public class BassClientService extends ProfileService {

                public void onScanFailed(int errorCode) {
                    Log.e(TAG, "Scan Failure:" + errorCode);
                    informConnectedDeviceAboutScanOffloadStop();
                }
            };
            // when starting scan, clear the previously cached broadcast scan results
@@ -1364,6 +1379,19 @@ public class BassClientService extends ProfileService {
                        .setServiceData(BassConstants.BAAS_UUID,
                                serviceData, serviceDataMask).build());
            }

            for (BluetoothDevice device : getConnectedDevices()) {
                synchronized (mStateMachines) {
                    BassClientStateMachine stateMachine = getOrCreateStateMachine(device);
                    if (stateMachine == null) {
                        Log.w(TAG, "startSearchingForSources: Can't get state machine for "
                                + "device: " + device);
                        continue;
                    }
                    stateMachine.sendMessage(BassClientStateMachine.START_SCAN_OFFLOAD);
                }
            }

            scanner.startScan(filters, settings, mSearchScanCallback);
            sEventLogger.logd(TAG, "startSearchingForSources");
            mCallbacks.notifySearchStarted(BluetoothStatusCodes.REASON_LOCAL_APP_REQUEST);
@@ -1391,6 +1419,7 @@ public class BassClientService extends ProfileService {
                mCallbacks.notifySearchStopFailed(BluetoothStatusCodes.ERROR_UNKNOWN);
                return;
            }
            informConnectedDeviceAboutScanOffloadStop();
            scanner.stopScan(mSearchScanCallback);
            mSearchScanCallback = null;
            sEventLogger.logd(TAG, "stopSearchingForSources");
+0 −15
Original line number Diff line number Diff line
@@ -470,8 +470,6 @@ public class BassClientStateMachine extends StateMachine {
                                null);
            } catch (IllegalArgumentException ex) {
                Log.w(TAG, "registerSync:IllegalArgumentException");
                Message message = obtainMessage(STOP_SCAN_OFFLOAD);
                sendMessage(message);
                mPeriodicAdvCallbacksMap.remove(tempHandle);
                return false;
            }
@@ -521,9 +519,6 @@ public class BassClientStateMachine extends StateMachine {
                // all sources are removed, clean up
                removeMessages(PSYNC_ACTIVE_TIMEOUT);
                mService.clearNotifiedFlags();
                // trigger scan stop here
                Message message = obtainMessage(STOP_SCAN_OFFLOAD);
                sendMessage(message);
            }
        }
    }
@@ -731,10 +726,6 @@ public class BassClientStateMachine extends StateMachine {
                    Log.e(TAG, "There is no valid sync handle for this Source");
                }
            }
        } else if (state == BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED
                || state == BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_NO_PAST) {
            Message message = obtainMessage(STOP_SCAN_OFFLOAD);
            sendMessage(message);
        }
    }

@@ -1165,10 +1156,6 @@ public class BassClientStateMachine extends StateMachine {
                }
            } else {
                log("failed to sync to PA: " + mPASyncRetryCounter);
                if (!mAutoTriggered) {
                    Message message = obtainMessage(STOP_SCAN_OFFLOAD);
                    sendMessage(message);
                }
                mAutoTriggered = false;
                // remove failed sync handle
                mPeriodicAdvCallbacksMap.remove(BassConstants.INVALID_SYNC_HANDLE);
@@ -2003,8 +1990,6 @@ public class BassClientStateMachine extends StateMachine {
            case ADD_BCAST_SOURCE:
                if (!isSuccess(status)) {
                    cancelActiveSync(null);
                    Message message = obtainMessage(STOP_SCAN_OFFLOAD);
                    sendMessage(message);
                    if (mPendingMetadata != null) {
                        mService.getCallbacks()
                                .notifySourceAddFailed(mDevice, mPendingMetadata, status);
+10 −1
Original line number Diff line number Diff line
@@ -3046,7 +3046,16 @@ public class AdapterService extends Service {
                return BluetoothDevice.CONNECTION_STATE_DISCONNECTED;
            }

            if (Flags.apiGetConnectionStateUsingIdentityAddress()) {
                final long token = Binder.clearCallingIdentity();
                try {
                    return service.getConnectionState(device);
                } finally {
                    Binder.restoreCallingIdentity(token);
                }
            } else {
                return service.getConnectionState(device);
            }
        }

        @Override
+97 −7
Original line number Diff line number Diff line
@@ -147,6 +147,9 @@ public class LeAudioService extends ProfileService {
                    .setSampleRate(BluetoothLeAudioCodecConfig.SAMPLE_RATE_48000)
                    .build();

    /* 5 seconds timeout for Broadcast streaming state transition */
    private static final int DIALING_OUT_TIMEOUT_MS = 5000;

    private AdapterService mAdapterService;
    private DatabaseManager mDatabaseManager;
    private HandlerThread mStateMachinesThread;
@@ -167,6 +170,7 @@ public class LeAudioService extends ProfileService {
    boolean mBluetoothEnabled = false;
    BluetoothDevice mHfpHandoverDevice = null;
    LeAudioBroadcasterNativeInterface mLeAudioBroadcasterNativeInterface = null;
    private DialingOutTimeoutEvent mDialingOutTimeoutEvent = null;
    @VisibleForTesting
    AudioManager mAudioManager;
    LeAudioTmapGattServer mTmapGattServer;
@@ -428,6 +432,8 @@ public class LeAudioService extends ProfileService {
        mAwaitingBroadcastCreateResponse = false;
        mIsSourceStreamMonitorModeEnabled = false;

        clearBroadcastTimeoutCallback();

        mHandler.removeCallbacks(this::init);
        removeActiveDevice(false);

@@ -1084,6 +1090,11 @@ public class LeAudioService extends ProfileService {
            return;
        }
        if (DBG) Log.d(TAG, "startBroadcast");

        /* Start timeout to recover from stucked/error start Broadcast operation */
        mDialingOutTimeoutEvent = new DialingOutTimeoutEvent();
        mHandler.postDelayed(mDialingOutTimeoutEvent, DIALING_OUT_TIMEOUT_MS);

        mLeAudioBroadcasterNativeInterface.startBroadcast(broadcastId);
    }

@@ -1750,12 +1761,19 @@ public class LeAudioService extends ProfileService {
     * @param newDevice new supported broadcast audio device
     * @param previousDevice previous no longer supported broadcast audio device
     */
    /* TODO implement unicast overlap with connected unicast device */
    private void updateBroadcastActiveDevice(
            BluetoothDevice newDevice,
            BluetoothDevice previousDevice,
            boolean suppressNoisyIntent) {
        mActiveBroadcastAudioDevice = newDevice;
        if (DBG) {
            Log.d(
                    TAG,
                    "updateBroadcastActiveDevice: newDevice: "
                            + newDevice
                            + ", previousDevice: "
                            + previousDevice);
        }
        mAudioManager.handleBluetoothActiveDeviceChanged(
                newDevice, previousDevice, getBroadcastProfile(suppressNoisyIntent));
    }
@@ -2272,6 +2290,16 @@ public class LeAudioService extends ProfileService {
                            || mBroadcastIdDeactivatedForUnicastTransition.isPresent())) {
                leaveConnectedInputDevice = true;
                newDirections |= AUDIO_DIRECTION_INPUT_BIT;

                /* Update Broadcast device before streaming state in handover case to avoid switch
                 * to non LE Audio device in Audio Manager e.g. Phone Speaker.
                 */
                BluetoothDevice device =
                        mAdapterService.getDeviceFromByte(
                                Utils.getBytesFromAddress("FF:FF:FF:FF:FF:FF"));
                if (!device.equals(mActiveBroadcastAudioDevice)) {
                    updateBroadcastActiveDevice(device, mActiveBroadcastAudioDevice, true);
                }
            }

            descriptor.mIsActive = false;
@@ -2558,8 +2586,6 @@ public class LeAudioService extends ProfileService {
            updateFallbackUnicastGroupIdForBroadcast(LE_AUDIO_GROUP_ID_INVALID);
            updateBroadcastActiveDevice(null, mActiveBroadcastAudioDevice, false);
            return;
        } else {
            updateBroadcastActiveDevice(null, mActiveBroadcastAudioDevice, true);
        }

        if (DBG) {
@@ -2573,6 +2599,21 @@ public class LeAudioService extends ProfileService {
        setActiveDevice(unicastDevice);
    }

    void clearBroadcastTimeoutCallback() {
        if (mHandler == null) {
            Log.e(TAG, "No callback handler");
            return;
        }

        /* Timeout callback already cleared */
        if (mDialingOutTimeoutEvent == null) {
            return;
        }

        mHandler.removeCallbacks(mDialingOutTimeoutEvent);
        mDialingOutTimeoutEvent = null;
    }

    // Suppressed since this is part of a local process
    @SuppressLint("AndroidFrameworkRequiresPermission")
    void messageFromNative(LeAudioStackEvent stackEvent) {
@@ -2786,6 +2827,11 @@ public class LeAudioService extends ProfileService {
            switch (groupStatus) {
                case LeAudioStackEvent.GROUP_STATUS_ACTIVE: {
                    handleGroupTransitToActive(groupId);

                    /* Clear possible exposed broadcast device after activating unicast */
                    if (mActiveBroadcastAudioDevice != null) {
                        updateBroadcastActiveDevice(null, mActiveBroadcastAudioDevice, true);
                    }
                    break;
                }
                case LeAudioStackEvent.GROUP_STATUS_INACTIVE: {
@@ -2831,6 +2877,20 @@ public class LeAudioService extends ProfileService {

            } else {
                // TODO: Improve reason reporting or extend the native stack event with reason code
                Log.e(
                        TAG,
                        "EVENT_TYPE_BROADCAST_CREATED: Failed to create broadcast: " + broadcastId);

                /* Disconnect Broadcast device which was connected to avoid non LE Audio sound
                 * leak in handover scenario.
                 */
                if ((mUnicastGroupIdDeactivatedForBroadcastTransition != LE_AUDIO_GROUP_ID_INVALID)
                        && mCreateBroadcastQueue.isEmpty()
                        && (!Objects.equals(device, mActiveBroadcastAudioDevice))) {
                    clearBroadcastTimeoutCallback();
                    updateBroadcastActiveDevice(null, mActiveBroadcastAudioDevice, false);
                }

                notifyBroadcastStartFailed(broadcastId, BluetoothStatusCodes.ERROR_UNKNOWN);
            }

@@ -2926,11 +2986,21 @@ public class LeAudioService extends ProfileService {
                        bassClientService.suspendReceiversSourceSynchronization(broadcastId);
                    }

                    // Notify audio manager
                    updateBroadcastActiveDevice(null, mActiveBroadcastAudioDevice, true);

                    /* Restore the Unicast stream from before the Broadcast was started. */
                    if (mUnicastGroupIdDeactivatedForBroadcastTransition
                            != LE_AUDIO_GROUP_ID_INVALID) {
                        transitionFromBroadcastToUnicast();
                    } else {
                        // Notify audio manager
                        if (mBroadcastDescriptors.values().stream()
                                .noneMatch(
                                        d ->
                                                d.mState.equals(
                                                        LeAudioStackEvent
                                                                .BROADCAST_STATE_STREAMING))) {
                            updateBroadcastActiveDevice(null, mActiveBroadcastAudioDevice, false);
                        }
                    }
                    break;
                case LeAudioStackEvent.BROADCAST_STATE_STOPPING:
                    if (DBG) Log.d(TAG, "Broadcast broadcastId: " + broadcastId + " stopping.");
@@ -2942,6 +3012,8 @@ public class LeAudioService extends ProfileService {
                    notifyPlaybackStarted(broadcastId,
                            BluetoothStatusCodes.REASON_LOCAL_STACK_REQUEST);

                    clearBroadcastTimeoutCallback();

                    if (previousState == LeAudioStackEvent.BROADCAST_STATE_PAUSED) {
                        if (bassClientService != null) {
                            bassClientService.resumeReceiversSourceSynchronization();
@@ -4250,6 +4322,24 @@ public class LeAudioService extends ProfileService {
        return audioFrameworkCalls;
    }

    class DialingOutTimeoutEvent implements Runnable {
        @Override
        public void run() {
            Log.w(TAG, "Failed to start Broadcast in time");

            mDialingOutTimeoutEvent = null;

            if (getLeAudioService() == null) {
                Log.e(TAG, "DialingOutTimeoutEvent: No LE Audio service");
                return;
            }

            if (mActiveBroadcastAudioDevice != null) {
                updateBroadcastActiveDevice(null, mActiveBroadcastAudioDevice, false);
            }
        }
    }

    /**
     * Binder object: must be a static class or memory leak may occur
     */
Loading