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

Commit 324dbdb6 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "[soundtrigger] Fix releaseAudioSession deadlock" into main

parents 1219e36c 6f2d0e6c
Loading
Loading
Loading
Loading
+25 −23
Original line number Diff line number Diff line
@@ -257,58 +257,60 @@ class SoundTriggerModule implements IBinder.DeathRecipient, ISoundTriggerHal.Glo

        @Override
        public int loadModel(@NonNull SoundModel model) {
            synchronized (SoundTriggerModule.this) {
                SoundTriggerMiddlewareImpl.AudioSessionProvider.AudioSession audioSession =
                        mAudioSessionProvider.acquireSession();
            SoundTriggerMiddlewareImpl.AudioSessionProvider.AudioSession audioSession = null;
            try {
                synchronized (SoundTriggerModule.this) {
                    audioSession = mAudioSessionProvider.acquireSession();
                    checkValid();
                    Model loadedModel = new Model();
                    return loadedModel.load(model, audioSession);
                }
            } catch (Exception e) {
                    // We must do this outside the lock, to avoid possible deadlocks with the remote
                    // process that provides the audio sessions, which may also be calling into us.
                try {
                    if (audioSession != null) {
                        mAudioSessionProvider.releaseSession(audioSession.mSessionHandle);
                    }
                } catch (Exception ee) {
                    Slog.e(TAG, "Failed to release session.", ee);
                }
                throw e;
            }
        }
        }

        @Override
        public int loadPhraseModel(@NonNull PhraseSoundModel model) {
            synchronized (SoundTriggerModule.this) {
                SoundTriggerMiddlewareImpl.AudioSessionProvider.AudioSession audioSession =
                        mAudioSessionProvider.acquireSession();
            SoundTriggerMiddlewareImpl.AudioSessionProvider.AudioSession audioSession = null;
            try {
                synchronized (SoundTriggerModule.this) {
                    audioSession = mAudioSessionProvider.acquireSession();
                    checkValid();
                    Model loadedModel = new Model();
                    int result = loadedModel.load(model, audioSession);
                    Slog.d(TAG, String.format("loadPhraseModel()->%d", result));
                    return result;
                }
            } catch (Exception e) {
                    // We must do this outside the lock, to avoid possible deadlocks with the remote
                    // process that provides the audio sessions, which may also be calling into us.
                try {
                    if (audioSession != null) {
                        mAudioSessionProvider.releaseSession(audioSession.mSessionHandle);
                    }
                } catch (Exception ee) {
                    Slog.e(TAG, "Failed to release session.", ee);
                }
                throw e;
            }
        }
        }

        @Override
        public void unloadModel(int modelHandle) {
            int sessionHandle;
            synchronized (SoundTriggerModule.this) {
                checkValid();
                final var session = mLoadedModels.get(modelHandle).getSession();
                sessionHandle = session.mSessionHandle;
                mLoadedModels.remove(modelHandle);
                mAudioSessionProvider.releaseSession(session.mSessionHandle);
            }
            mAudioSessionProvider.releaseSession(sessionHandle);
            // We don't need to post-synchronize on anything once the HAL has finished the unload
            // and dispatched any appropriate callbacks -- since we don't do any state checking
            // onModelUnloaded regardless.