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

Commit a1eb2797 authored by Felix Oghina's avatar Felix Oghina
Browse files

[hotword] init audioflinger outside of lock

The lock used in HotwordDetectionConnection is shared with VoiceInteractionManagerServiceStub, meaning UI thread can end up waiting for audio flinger service to initialize, causing a freeze.

Not that this is not a perfect fix, since the first call (in HotwordDetectionConnection constructor) is still locked. However, the deadlock seems to occur when the service dies and we try to re-initialize, which this change should fix.

Bug: 215887032

Test: atest CtsVoiceInteractionTestCases

Change-Id: I35c682910ac6605041175ab523a71f2b83b499dc
parent ab8218db
Loading
Loading
Loading
Loading
+22 −11
Original line number Diff line number Diff line
@@ -153,7 +153,8 @@ final class HotwordDetectionConnection {
    private int mRestartCount = 0;
    @NonNull private ServiceConnection mRemoteHotwordDetectionService;
    @NonNull private ServiceConnection mRemoteVisualQueryDetectionService;
    private IBinder mAudioFlinger;
    @GuardedBy("mLock")
    @Nullable private IBinder mAudioFlinger;
    @GuardedBy("mLock")
    private boolean mDebugHotwordLogging = false;

@@ -193,7 +194,7 @@ final class HotwordDetectionConnection {
                new Intent(VisualQueryDetectionService.SERVICE_INTERFACE);
        visualQueryDetectionServiceIntent.setComponent(mVisualQueryDetectionComponentName);

        initAudioFlingerLocked();
        initAudioFlinger();

        mHotwordDetectionServiceConnectionFactory =
                new ServiceConnectionFactory(hotwordDetectionServiceIntent,
@@ -226,31 +227,41 @@ final class HotwordDetectionConnection {
        }
    }

    private void initAudioFlingerLocked() {
    private void initAudioFlinger() {
        if (DEBUG) {
            Slog.d(TAG, "initAudioFlingerLocked");
            Slog.d(TAG, "initAudioFlinger");
        }
        mAudioFlinger = ServiceManager.waitForService("media.audio_flinger");
        if (mAudioFlinger == null) {
        final IBinder audioFlinger = ServiceManager.waitForService("media.audio_flinger");
        if (audioFlinger == null) {
            setAudioFlinger(null);
            throw new IllegalStateException("Service media.audio_flinger wasn't found.");
        }
        if (DEBUG) {
            Slog.d(TAG, "Obtained audio_flinger binder.");
        }
        try {
            mAudioFlinger.linkToDeath(mAudioServerDeathRecipient, /* flags= */ 0);
            audioFlinger.linkToDeath(mAudioServerDeathRecipient, /* flags= */ 0);
        } catch (RemoteException e) {
            Slog.w(TAG, "Audio server died before we registered a DeathRecipient; "
                    + "retrying init.", e);
            initAudioFlingerLocked();
            initAudioFlinger();
            return;
        }

        setAudioFlinger(audioFlinger);
    }

    private void setAudioFlinger(@Nullable IBinder audioFlinger) {
        synchronized (mLock) {
            mAudioFlinger = audioFlinger;
        }
    }

    private void audioServerDied() {
        Slog.w(TAG, "Audio server died; restarting the HotwordDetectionService.");
        synchronized (mLock) {
        // TODO: Check if this needs to be scheduled on a different thread.
            initAudioFlingerLocked();
        initAudioFlinger();
        synchronized (mLock) {
            // We restart the process instead of simply sending over the new binder, to avoid race
            // conditions with audio reading in the service.
            restartProcessLocked();