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

Commit 77c195d5 authored by Ytai Ben-Tsvi's avatar Ytai Ben-Tsvi
Browse files

Avoid deadlock on soundtrigger HAL death

Bug: 155540720
Test: Hard to reproduce this condition. Did a manual verification that
      there is no regression in existing functionality.
Change-Id: I89a2edb8b6e47e01c7cac52aeb0c7fc2e9e487b7
parent 2e0fd15e
Loading
Loading
Loading
Loading
+10 −8
Original line number Diff line number Diff line
@@ -783,15 +783,17 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
        @Override
        public void onModuleDied() {
            synchronized (SoundTriggerMiddlewareValidation.this) {
                try {
                mState = ModuleStatus.DEAD;
            }
            // Trigger the callback outside of the lock to avoid deadlocks.
            try {
                mCallback.onModuleDied();
            } catch (RemoteException e) {
                // Dead client will be handled by binderDied() - no need to handle here.
                // In any case, client callbacks are considered best effort.
                Log.e(TAG, "Client callback exception.", e);
            }
            }

        }

        @Override
+23 −12
Original line number Diff line number Diff line
@@ -35,8 +35,10 @@ import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.util.Log;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

@@ -166,13 +168,24 @@ class SoundTriggerModule implements IHwBinder.DeathRecipient {
    }

    @Override
    public synchronized void serviceDied(long cookie) {
    public void serviceDied(long cookie) {
        Log.w(TAG, String.format("Underlying HAL driver died."));
        List<ISoundTriggerCallback> callbacks = new ArrayList<>(mActiveSessions.size());
        synchronized (this) {
            for (Session session : mActiveSessions) {
            session.moduleDied();
                callbacks.add(session.moduleDied());
            }
            reset();
        }
        // Trigger the callbacks outside of the lock to avoid deadlocks.
        for (ISoundTriggerCallback callback : callbacks) {
            try {
                callback.onModuleDied();
            } catch (RemoteException e) {
                throw e.rethrowAsRuntimeException();
            }
        }
    }

    /**
     * Resets the transient state of this object.
@@ -379,15 +392,13 @@ class SoundTriggerModule implements IHwBinder.DeathRecipient {

        /**
         * The underlying module HAL is dead.
         * @return The client callback that needs to be invoked to notify the client.
         */
        private void moduleDied() {
            try {
                mCallback.onModuleDied();
        private ISoundTriggerCallback moduleDied() {
            ISoundTriggerCallback callback = mCallback;
            removeSession(this);
            mCallback = null;
            } catch (RemoteException e) {
                e.rethrowAsRuntimeException();
            }
            return callback;
        }

        private void checkValid() {