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

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

Add support for start/load "busy" error code

This change allows the soundtrigger HAL to return -EBUSY on start and
load and adds proper handling in the middleware.

Test: atest SoundTriggerMiddlewareImplTest SoundHw2CompatTest
Bug: 178722883
Change-Id: I7d34d5ec076486527b5540da4cd7f18ca362260b
parent f7353078
Loading
Loading
Loading
Loading
+11 −3
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
import android.media.soundtrigger_middleware.Status;
import android.os.IHwBinder;
import android.os.RemoteException;
import android.system.OsConstants;

import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
@@ -125,6 +126,13 @@ final class SoundTriggerHw2Compat implements ISoundTriggerHw2 {
        }
    }

    private static void handleHalStatusAllowBusy(int status, String methodName) {
        if (status == -OsConstants.EBUSY) {
            throw new RecoverableException(Status.RESOURCE_CONTENTION);
        }
        handleHalStatus(status, methodName);
    }

    @Override
    public android.hardware.soundtrigger.V2_3.Properties getProperties() {
        try {
@@ -177,7 +185,7 @@ final class SoundTriggerHw2Compat implements ISoundTriggerHw2 {
                            retval.set(r);
                            handle.set(h);
                        });
                handleHalStatus(retval.get(), "loadSoundModel_2_4");
                handleHalStatusAllowBusy(retval.get(), "loadSoundModel_2_4");
            } catch (NotSupported e) {
                // Fall-back to the 2.1 version:
                try {
@@ -213,7 +221,7 @@ final class SoundTriggerHw2Compat implements ISoundTriggerHw2 {
                            retval.set(r);
                            handle.set(h);
                        });
                handleHalStatus(retval.get(), "loadPhraseSoundModel_2_4");
                handleHalStatusAllowBusy(retval.get(), "loadPhraseSoundModel_2_4");
            } catch (NotSupported e) {
                // Fall-back to the 2.1 version:
                try {
@@ -265,7 +273,7 @@ final class SoundTriggerHw2Compat implements ISoundTriggerHw2 {
        try {
            try {
                int retval = as2_4().startRecognition_2_4(modelHandle, config);
                handleHalStatus(retval, "startRecognition_2_4");
                handleHalStatusAllowBusy(retval, "startRecognition_2_4");
            } catch (NotSupported e) {
                // Fall-back to the 2.3 version:
                try {
+88 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import android.os.HwParcel;
import android.os.IHwBinder;
import android.os.IHwInterface;
import android.os.RemoteException;
import android.system.OsConstants;

import org.junit.Before;
import org.junit.Test;
@@ -269,6 +270,37 @@ public class SoundHw2CompatTest {
        }
    }

    private void testLoadGenericModelBusy_2_4() throws Exception {
        final android.hardware.soundtrigger.V2_4.ISoundTriggerHw driver_2_4 =
                (android.hardware.soundtrigger.V2_4.ISoundTriggerHw) mHalDriver;

        doAnswer(invocation -> {
            android.hardware.soundtrigger.V2_4.ISoundTriggerHw.loadSoundModel_2_4Callback
                    resultCallback = invocation.getArgument(2);

            // This is the return of this method.
            resultCallback.onValues(-OsConstants.EBUSY, 0);
            return null;
        }).when(driver_2_4).loadSoundModel_2_4(any(), any(), any());

        ISoundTriggerHw2.ModelCallback canonicalCallback = mock(
                ISoundTriggerHw2.ModelCallback.class);
        try {
            mCanonical.loadSoundModel(TestUtil.createGenericSoundModel_2_1(),
                    canonicalCallback);
            fail("Expected an exception");
        } catch (RecoverableException e) {
            assertEquals(Status.RESOURCE_CONTENTION, e.errorCode);
        }
    }

    @Test
    public void testLoadGenericModelBusy() throws Exception {
        if (mHalDriver instanceof android.hardware.soundtrigger.V2_4.ISoundTriggerHw) {
            testLoadGenericModelBusy_2_4();
        }
    }

    private void testLoadPhraseModel_2_0() throws Exception {
        final int handle = 29;
        ArgumentCaptor<android.hardware.soundtrigger.V2_0.ISoundTriggerHw.PhraseSoundModel>
@@ -384,6 +416,37 @@ public class SoundHw2CompatTest {
        }
    }

    private void testLoadPhraseModelBusy_2_4() throws Exception {
        final android.hardware.soundtrigger.V2_4.ISoundTriggerHw driver_2_4 =
                (android.hardware.soundtrigger.V2_4.ISoundTriggerHw) mHalDriver;

        doAnswer(invocation -> {
            android.hardware.soundtrigger.V2_4.ISoundTriggerHw.loadPhraseSoundModel_2_4Callback
                    resultCallback = invocation.getArgument(2);

            // This is the return of this method.
            resultCallback.onValues(-OsConstants.EBUSY, 0);
            return null;
        }).when(driver_2_4).loadPhraseSoundModel_2_4(any(), any(), any());

        ISoundTriggerHw2.ModelCallback canonicalCallback = mock(
                ISoundTriggerHw2.ModelCallback.class);
        try {
            mCanonical.loadPhraseSoundModel(TestUtil.createPhraseSoundModel_2_1(),
                    canonicalCallback);
            fail("Expected an exception");
        } catch (RecoverableException e) {
            assertEquals(Status.RESOURCE_CONTENTION, e.errorCode);
        }
    }

    @Test
    public void testLoadPhraseModelBusy() throws Exception {
        if (mHalDriver instanceof android.hardware.soundtrigger.V2_4.ISoundTriggerHw) {
            testLoadPhraseModelBusy_2_4();
        }
    }

    @Test
    public void testUnloadModel() throws Exception {
        mCanonical.unloadSoundModel(14);
@@ -521,6 +584,31 @@ public class SoundHw2CompatTest {
        }
    }

    private void testStartRecognitionBusy_2_4() throws Exception {
        final android.hardware.soundtrigger.V2_4.ISoundTriggerHw driver_2_4 =
                (android.hardware.soundtrigger.V2_4.ISoundTriggerHw) mHalDriver;

        final int handle = 68;
        when(driver_2_4.startRecognition_2_4(eq(handle), any())).thenReturn(-OsConstants.EBUSY);

        android.hardware.soundtrigger.V2_3.RecognitionConfig config =
                TestUtil.createRecognitionConfig_2_3(34, 35);
        try {
            mCanonical.startRecognition(handle, config);
            fail("Expected an exception");
        } catch (RecoverableException e) {
            assertEquals(Status.RESOURCE_CONTENTION, e.errorCode);
        }
        verify(driver_2_4).startRecognition_2_4(eq(handle), any());
    }

    @Test
    public void testStartRecognitionBusy() throws Exception {
        if (mHalDriver instanceof android.hardware.soundtrigger.V2_4.ISoundTriggerHw) {
            testStartRecognitionBusy_2_4();
        }
    }

    @Test
    public void testStopRecognition() throws Exception {
        mCanonical.stopRecognition(17);
+25 −0
Original line number Diff line number Diff line
@@ -251,6 +251,31 @@ public class SoundTriggerMiddlewareImplTest {
        module.detach();
    }

    @Test
    public void testStartRecognitionBusy() throws Exception {
        initService(true);
        ISoundTriggerCallback callback = createCallbackMock();
        ISoundTriggerModule module = mService.attach(0, callback);

        // Load the model.
        final int hwHandle = 7;
        int handle = loadGenericModel(module, hwHandle).first;

        // Start the model.
        doThrow(new RecoverableException(Status.RESOURCE_CONTENTION)).when(
                mHalDriver).startRecognition(eq(7), any());

        try {
            RecognitionConfig config = TestUtil.createRecognitionConfig();
            module.startRecognition(handle, config);
            fail("Expected an exception");
        } catch (RecoverableException e) {
            assertEquals(Status.RESOURCE_CONTENTION, e.errorCode);
        }

        verify(mHalDriver).startRecognition(eq(7), any());
    }

    @Test
    public void testStartStopPhraseRecognition() throws Exception {
        initService(true);