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

Commit c0e6644b authored by Santiago Seifert's avatar Santiago Seifert Committed by Android (Google) Code Review
Browse files

Merge "Run audio and bluetooth calls on handler" into main

parents efb828d8 14315e9d
Loading
Loading
Loading
Loading
+40 −17
Original line number Diff line number Diff line
@@ -204,23 +204,24 @@ import java.util.Objects;
            Slog.w(TAG, "transferTo: Ignoring transfer request to unknown route id : " + routeId);
            return;
        }
        // TODO: b/329929065 - Push audio manager and bluetooth operations to the handler, so that
        // they don't run on a binder thread, so as to prevent possible deadlocks (these operations
        // may need system_server binder threads to complete).
        if (mediaRoute2InfoHolder.mCorrespondsToInactiveBluetoothRoute) {
            // By default, the last connected device is the active route so we don't need to apply a
            // routing audio policy.
            mBluetoothRouteController.activateBluetoothDeviceWithAddress(
                    mediaRoute2InfoHolder.mMediaRoute2Info.getAddress());
            mAudioManager.removePreferredDeviceForStrategy(mStrategyForMedia);
        } else {
            AudioDeviceAttributes attr =
                    new AudioDeviceAttributes(
                            AudioDeviceAttributes.ROLE_OUTPUT,
                            mediaRoute2InfoHolder.mAudioDeviceInfoType,
                            /* address= */ ""); // This is not a BT device, hence no address needed.
            mAudioManager.setPreferredDeviceForStrategy(mStrategyForMedia, attr);
        Runnable transferAction = getTransferActionForRoute(mediaRoute2InfoHolder);
        Runnable guardedTransferAction =
                () -> {
                    try {
                        transferAction.run();
                    } catch (Throwable throwable) {
                        // We swallow the exception to avoid crashing system_server, since this
                        // doesn't run on a binder thread.
                        Slog.e(
                                TAG,
                                "Unexpected exception while transferring to route id: " + routeId,
                                throwable);
                        mHandler.post(this::rebuildAvailableRoutesAndNotify);
                    }
                };
        // We post the transfer operation to the handler to avoid making these calls on a binder
        // thread. See class javadoc for details.
        mHandler.post(guardedTransferAction);
    }

    @RequiresPermission(
@@ -236,6 +237,28 @@ import java.util.Objects;
        return true;
    }

    private Runnable getTransferActionForRoute(MediaRoute2InfoHolder mediaRoute2InfoHolder) {
        if (mediaRoute2InfoHolder.mCorrespondsToInactiveBluetoothRoute) {
            String deviceAddress = mediaRoute2InfoHolder.mMediaRoute2Info.getAddress();
            return () -> {
                // By default, the last connected device is the active route so we don't
                // need to apply a routing audio policy.
                mBluetoothRouteController.activateBluetoothDeviceWithAddress(deviceAddress);
                mAudioManager.removePreferredDeviceForStrategy(mStrategyForMedia);
            };

        } else {
            AudioDeviceAttributes deviceAttributes =
                    new AudioDeviceAttributes(
                            AudioDeviceAttributes.ROLE_OUTPUT,
                            mediaRoute2InfoHolder.mAudioDeviceInfoType,
                            /* address= */ ""); // This is not a BT device, hence no address needed.
            return () ->
                    mAudioManager.setPreferredDeviceForStrategy(
                            mStrategyForMedia, deviceAttributes);
        }
    }

    @RequiresPermission(
            anyOf = {
                Manifest.permission.MODIFY_AUDIO_ROUTING,
+9 −2
Original line number Diff line number Diff line
@@ -69,6 +69,13 @@ import java.util.Set;
public class AudioManagerRouteControllerTest {

    private static final String FAKE_ROUTE_NAME = "fake name";

    /**
     * The number of milliseconds to wait for an asynchronous operation before failing an associated
     * assertion.
     */
    private static final int ASYNC_CALL_TIMEOUTS_MS = 1000;

    private static final AudioDeviceInfo FAKE_AUDIO_DEVICE_INFO_BUILTIN_SPEAKER =
            createAudioDeviceInfo(
                    AudioSystem.DEVICE_OUT_SPEAKER, "name_builtin", /* address= */ null);
@@ -231,7 +238,7 @@ public class AudioManagerRouteControllerTest {
        MediaRoute2Info builtInSpeakerRoute =
                getAvailableRouteWithType(MediaRoute2Info.TYPE_BUILTIN_SPEAKER);
        mControllerUnderTest.transferTo(builtInSpeakerRoute.getId());
        verify(mMockAudioManager)
        verify(mMockAudioManager, Mockito.timeout(ASYNC_CALL_TIMEOUTS_MS))
                .setPreferredDeviceForStrategy(
                        mMediaAudioProductStrategy,
                        createAudioDeviceAttribute(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER));
@@ -239,7 +246,7 @@ public class AudioManagerRouteControllerTest {
        MediaRoute2Info wiredHeadsetRoute =
                getAvailableRouteWithType(MediaRoute2Info.TYPE_WIRED_HEADSET);
        mControllerUnderTest.transferTo(wiredHeadsetRoute.getId());
        verify(mMockAudioManager)
        verify(mMockAudioManager, Mockito.timeout(ASYNC_CALL_TIMEOUTS_MS))
                .setPreferredDeviceForStrategy(
                        mMediaAudioProductStrategy,
                        createAudioDeviceAttribute(AudioDeviceInfo.TYPE_WIRED_HEADSET));