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

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

Support load preemption in SoundTriggerMiddleware

This change add support for HAL-based model preemption in
SoundTriggerMiddleware and gets rid of the notion of service
availability.

Test: atest SoundTriggerMiddlewareImplTest SoundHw2CompatTest
      Manual verification of basic soundtrigger flows.
Bug: 178722883
Change-Id: I8bc5949844bb8754335a98b09935ade651cb7903
parent f950e4f6
Loading
Loading
Loading
Loading
+12 −4
Original line number Original line Diff line number Diff line
@@ -364,11 +364,19 @@ public class SoundTriggerModule {
        }
        }


        @Override
        @Override
        public synchronized void onRecognitionAvailabilityChange(boolean available)
        public void onModelUnloaded(int modelHandle) throws RemoteException {
                throws RemoteException {
            // TODO: Implement
            throw new RuntimeException("Implement me");
        }

        @Override
        public synchronized void onResourceConditionChange() throws RemoteException {
            // TODO: Temporary hack.
            Message m = mHandler.obtainMessage(EVENT_SERVICE_STATE_CHANGE,
            Message m = mHandler.obtainMessage(EVENT_SERVICE_STATE_CHANGE,
                    available ? SoundTrigger.SERVICE_STATE_ENABLED
                    SoundTrigger.SERVICE_STATE_DISABLED);
                            : SoundTrigger.SERVICE_STATE_DISABLED);
            mHandler.sendMessage(m);
            m = mHandler.obtainMessage(EVENT_SERVICE_STATE_CHANGE,
                    SoundTrigger.SERVICE_STATE_ENABLED);
            mHandler.sendMessage(m);
            mHandler.sendMessage(m);
        }
        }


+13 −6
Original line number Original line Diff line number Diff line
@@ -28,22 +28,29 @@ oneway interface ISoundTriggerCallback {
     * Invoked whenever a recognition event is triggered (typically, on recognition, but also in
     * Invoked whenever a recognition event is triggered (typically, on recognition, but also in
     * case of external aborting of a recognition or a forced recognition event - see the status
     * case of external aborting of a recognition or a forced recognition event - see the status
     * code in the event for determining).
     * code in the event for determining).
     * In case of abortion, the caller may retry after the next onRecognitionAvailabilityChange()
     * callback.
     */
     */
    void onRecognition(int modelHandle, in RecognitionEvent event);
    void onRecognition(int modelHandle, in RecognitionEvent event);
     /**
     /**
      * Invoked whenever a phrase recognition event is triggered (typically, on recognition, but
      * Invoked whenever a phrase recognition event is triggered (typically, on recognition, but
      * also in case of external aborting of a recognition or a forced recognition event - see the
      * also in case of external aborting of a recognition or a forced recognition event - see the
      * status code in the event for determining).
      * status code in the event for determining).
      * In case of abortion, the caller may retry after the next onRecognitionAvailabilityChange()
      * callback.
      */
      */
    void onPhraseRecognition(int modelHandle, in PhraseRecognitionEvent event);
    void onPhraseRecognition(int modelHandle, in PhraseRecognitionEvent event);
    /**
    /**
     * Notifies the client the recognition has become available after previously having been
     * Notifies the client that some start/load operations that have previously failed for resource
     * unavailable, or vice versa. This method will always be invoked once immediately after
     * reasons (threw a ServiceSpecificException(RESOURCE_CONTENTION) or have been preempted) may
     * attachment, and then every time there is a change in availability.
     * now succeed. This is not a guarantee, but a hint for the client to retry.
     * When availability changes from available to unavailable, all active recognitions are aborted,
     * and this event will be sent in addition to the abort event.
     */
     */
    void onRecognitionAvailabilityChange(boolean available);
    void onResourceConditionChange();
    /**
     * Notifies the client that a model had been preemptively unloaded by the service.
     * The caller may retry after the next onRecognitionAvailabilityChange() callback.
     */
    void onModelUnloaded(int modelHandle);
    /**
    /**
     * Notifies the client that the associated module has crashed and restarted. The module instance
     * Notifies the client that the associated module has crashed and restarted. The module instance
     * is no longer usable and will throw a ServiceSpecificException with a Status.DEAD_OBJECT code
     * is no longer usable and will throw a ServiceSpecificException with a Status.DEAD_OBJECT code
+3 −0
Original line number Original line Diff line number Diff line
@@ -75,6 +75,9 @@ interface ISoundTriggerModule {
     * Once a recognition event is passed to the client, the recognition automatically become
     * Once a recognition event is passed to the client, the recognition automatically become
     * inactive, unless the event is of the RecognitionStatus.FORCED kind. Client can also shut down
     * inactive, unless the event is of the RecognitionStatus.FORCED kind. Client can also shut down
     * the recognition explicitly, via stopRecognition.
     * the recognition explicitly, via stopRecognition.
     *
     * May throw a ServiceSpecificException with an RESOURCE_CONTENTION status to indicate that
     * resources required for starting the model are currently consumed by other clients.
     */
     */
    void startRecognition(int modelHandle, in RecognitionConfig config);
    void startRecognition(int modelHandle, in RecognitionConfig config);


+3 −5
Original line number Original line Diff line number Diff line
@@ -17,9 +17,7 @@
package com.android.server.soundtrigger_middleware;
package com.android.server.soundtrigger_middleware;


import android.annotation.NonNull;
import android.annotation.NonNull;
import android.hardware.soundtrigger.V2_0.ISoundTriggerHw;
import android.media.soundtrigger_middleware.ISoundTriggerCallback;
import android.media.soundtrigger_middleware.ISoundTriggerCallback;
import android.media.soundtrigger_middleware.ISoundTriggerMiddlewareService;
import android.media.soundtrigger_middleware.ISoundTriggerModule;
import android.media.soundtrigger_middleware.ISoundTriggerModule;
import android.media.soundtrigger_middleware.SoundTriggerModuleDescriptor;
import android.media.soundtrigger_middleware.SoundTriggerModuleDescriptor;
import android.os.IBinder;
import android.os.IBinder;
@@ -84,15 +82,15 @@ public class SoundTriggerMiddlewareImpl implements ISoundTriggerMiddlewareIntern
            @NonNull AudioSessionProvider audioSessionProvider) {
            @NonNull AudioSessionProvider audioSessionProvider) {
        List<SoundTriggerModule> modules = new ArrayList<>(halFactories.length);
        List<SoundTriggerModule> modules = new ArrayList<>(halFactories.length);


        for (int i = 0; i < halFactories.length; ++i) {
        for (HalFactory halFactory : halFactories) {
            try {
            try {
                modules.add(new SoundTriggerModule(halFactories[i], audioSessionProvider));
                modules.add(new SoundTriggerModule(halFactory, audioSessionProvider));
            } catch (Exception e) {
            } catch (Exception e) {
                Log.e(TAG, "Failed to add a SoundTriggerModule instance", e);
                Log.e(TAG, "Failed to add a SoundTriggerModule instance", e);
            }
            }
        }
        }


        mModules = modules.toArray(new SoundTriggerModule[modules.size()]);
        mModules = modules.toArray(new SoundTriggerModule[0]);
    }
    }


    /**
    /**
+19 −7
Original line number Original line Diff line number Diff line
@@ -57,9 +57,10 @@ import java.util.Objects;
 *     }
 *     }
 * }
 * }
 * </code></pre>
 * </code></pre>
 * The actual handling of these events is then done inside of {@link #logReturnWithObject(Object,
 * The actual handling of these events is then done inside of
 * String, Object, Object[])}, {@link #logVoidReturnWithObject(Object, String, Object[])} and {@link
 * {@link #logReturnWithObject(Object, Identity, String, Object, Object[])},
 * #logExceptionWithObject(Object, String, Exception, Object[])}.
 * {@link #logVoidReturnWithObject(Object, Identity, String, Object[])} and {@link
 * #logExceptionWithObject(Object, Identity, String, Exception, Object[])}.
 */
 */
public class SoundTriggerMiddlewareLogging implements ISoundTriggerMiddlewareInternal, Dumpable {
public class SoundTriggerMiddlewareLogging implements ISoundTriggerMiddlewareInternal, Dumpable {
    private static final String TAG = "SoundTriggerMiddlewareLogging";
    private static final String TAG = "SoundTriggerMiddlewareLogging";
@@ -322,12 +323,23 @@ public class SoundTriggerMiddlewareLogging implements ISoundTriggerMiddlewareInt
            }
            }


            @Override
            @Override
            public void onRecognitionAvailabilityChange(boolean available) throws RemoteException {
            public void onModelUnloaded(int modelHandle) throws RemoteException {
                try {
                try {
                    mCallbackDelegate.onRecognitionAvailabilityChange(available);
                    mCallbackDelegate.onModelUnloaded(modelHandle);
                    logVoidReturn("onRecognitionAvailabilityChange", available);
                    logVoidReturn("onModelUnloaded", modelHandle);
                } catch (Exception e) {
                } catch (Exception e) {
                    logException("onRecognitionAvailabilityChange", e, available);
                    logException("onModelUnloaded", e, modelHandle);
                    throw e;
                }
            }

            @Override
            public void onResourceConditionChange() throws RemoteException {
                try {
                    mCallbackDelegate.onResourceConditionChange();
                    logVoidReturn("onResourceConditionChange");
                } catch (Exception e) {
                    logException("onResourceConditionChange", e);
                    throw e;
                    throw e;
                }
                }
            }
            }
Loading