Add AIDL interfaces for fake STHAL

- Define injection interfaces, and sub-interfaces generated by the fake
STHAL receiving particular events.
- Use injection interfaces as session objects to handle async-ness.

Test: AIDL files compile
Fixes: 271197938
Change-Id: Ic169550c82881b3ca69562bc22c2a97aabd0c4f9
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index cbbd16b..fa16e16 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -42,6 +42,7 @@
 import android.media.AudioFormat;
 import android.media.permission.Identity;
 import android.media.soundtrigger.Status;
+import android.media.soundtrigger_middleware.ISoundTriggerInjection;
 import android.media.soundtrigger_middleware.ISoundTriggerMiddlewareService;
 import android.media.soundtrigger_middleware.SoundTriggerModuleDescriptor;
 import android.os.Build;
@@ -77,9 +78,11 @@
     }
 
     /**
+     * Model architecture associated with a fake STHAL which can be injected.
+     * Used for testing purposes.
      * @hide
      */
-    public static final String FAKE_HAL_ARCH = "injection";
+    public static final String FAKE_HAL_ARCH = ISoundTriggerInjection.FAKE_HAL_ARCH;
 
     /**
      * Status code used when the operation succeeded
diff --git a/media/Android.bp b/media/Android.bp
index e8555b0..f69dd3c 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -29,10 +29,7 @@
         },
     },
     srcs: [
-        "aidl/android/media/soundtrigger_middleware/ISoundTriggerCallback.aidl",
-        "aidl/android/media/soundtrigger_middleware/ISoundTriggerMiddlewareService.aidl",
-        "aidl/android/media/soundtrigger_middleware/ISoundTriggerModule.aidl",
-        "aidl/android/media/soundtrigger_middleware/SoundTriggerModuleDescriptor.aidl",
+        "aidl/android/media/soundtrigger_middleware/*.aidl",
     ],
     imports: [
         "android.media.audio.common.types-V2",
diff --git a/media/aidl/android/media/soundtrigger_middleware/IAcknowledgeEvent.aidl b/media/aidl/android/media/soundtrigger_middleware/IAcknowledgeEvent.aidl
new file mode 100644
index 0000000..237e71a
--- /dev/null
+++ b/media/aidl/android/media/soundtrigger_middleware/IAcknowledgeEvent.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.soundtrigger_middleware;
+
+/**
+ * Opaque callback for acknowledging oneway events.
+ * Since there is no return channel for oneway events,
+ * passing this interface in a oneway method allows the service to call
+ * back to the client to indicate the event was registered.
+ * This essentially functions like a <code> Future<void> </code> without
+ * an error channel.
+ * {@hide}
+ */
+oneway interface IAcknowledgeEvent {
+    /**
+     * Acknowledge that the event has been received.
+     */
+    void eventReceived();
+
+}
diff --git a/media/aidl/android/media/soundtrigger_middleware/IInjectGlobalEvent.aidl b/media/aidl/android/media/soundtrigger_middleware/IInjectGlobalEvent.aidl
new file mode 100644
index 0000000..dcf3945
--- /dev/null
+++ b/media/aidl/android/media/soundtrigger_middleware/IInjectGlobalEvent.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.soundtrigger_middleware;
+
+import android.media.soundtrigger_middleware.IAcknowledgeEvent;
+
+/**
+ * Interface for injecting global events to the fake STHAL.
+ * {@hide}
+ */
+oneway interface IInjectGlobalEvent {
+
+    /**
+     * Request a fake STHAL restart.
+     * This invalidates the {@link IInjectGlobalEvent}.
+     */
+    void triggerRestart();
+
+    /**
+     * Triggers global resource contention into the fake STHAL. Loads/startRecognition
+     * will fail with RESOURCE_CONTENTION.
+     * @param isContended - true to enable resource contention. false to disable resource contention
+     *                      and resume normal functionality.
+     * @param callback - Call {@link IAcknowledgeEvent#eventReceived()} on this interface once
+     * the contention status is successfully set.
+     */
+    void setResourceContention(boolean isContended, IAcknowledgeEvent callback);
+
+}
diff --git a/media/aidl/android/media/soundtrigger_middleware/IInjectModelEvent.aidl b/media/aidl/android/media/soundtrigger_middleware/IInjectModelEvent.aidl
new file mode 100644
index 0000000..7752c17
--- /dev/null
+++ b/media/aidl/android/media/soundtrigger_middleware/IInjectModelEvent.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.soundtrigger_middleware;
+
+/**
+ * Interface for injecting model events into the fake ST HAL.
+ *
+ * {@hide}
+ */
+oneway interface IInjectModelEvent {
+    /**
+     * Trigger a preemptive model unload for the model session associated with
+     * this object.
+     * This invalidates the {@link IInjectModelEvent} session.
+     */
+    void triggerUnloadModel();
+
+}
diff --git a/media/aidl/android/media/soundtrigger_middleware/IInjectRecognitionEvent.aidl b/media/aidl/android/media/soundtrigger_middleware/IInjectRecognitionEvent.aidl
new file mode 100644
index 0000000..f1398c6
--- /dev/null
+++ b/media/aidl/android/media/soundtrigger_middleware/IInjectRecognitionEvent.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.soundtrigger_middleware;
+
+import android.media.soundtrigger.PhraseRecognitionExtra;
+
+/**
+ * Interface for injecting recognition events into the ST Mock HAL.
+ * {@hide}
+ */
+oneway interface IInjectRecognitionEvent {
+
+    /**
+     * Trigger a recognition event for the recognition session associated with
+     * this object.
+     * This invalidates the {@link IInjectRecognitionEvent}.
+     * @param data the recognition data that the client of this model will receive
+     * @param phraseExtras extra data only delivered for keyphrase models.
+     */
+    void triggerRecognitionEvent(in byte[] data,
+            in @nullable PhraseRecognitionExtra[] phraseExtras);
+
+    /**
+     * Trigger an abort event for the recognition session associated with this object.
+     * This invalidates the {@link IInjectRecognitionEvent}.
+     */
+    void triggerAbortRecognition();
+}
diff --git a/media/aidl/android/media/soundtrigger_middleware/ISoundTriggerInjection.aidl b/media/aidl/android/media/soundtrigger_middleware/ISoundTriggerInjection.aidl
new file mode 100644
index 0000000..732744b
--- /dev/null
+++ b/media/aidl/android/media/soundtrigger_middleware/ISoundTriggerInjection.aidl
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.soundtrigger_middleware;
+
+import android.media.soundtrigger.RecognitionConfig;
+import android.media.soundtrigger.SoundModel;
+import android.media.soundtrigger.Phrase;
+
+import android.media.soundtrigger_middleware.IInjectModelEvent;
+import android.media.soundtrigger_middleware.IInjectRecognitionEvent;
+import android.media.soundtrigger_middleware.IInjectGlobalEvent;
+import android.media.soundtrigger_middleware.ISoundTriggerInjection;
+
+/**
+ * An injection interface for {@link android.media.soundtrigger_middleware.FakeSoundTriggerHal}.
+ * To avoid deadlocks, all calls to this interface and the sub-interface it creates are oneway.
+ * Calls are identified as stale via "Session" parameters.
+ * The client implements this interface and registers it with
+ * {@link ISoundTriggerMiddlewareService#attachMockHalInjection(ISoundTriggerInjection)}.
+ * Then, the client will receive callbacks which observe mock HAL events.
+ * There are two types of calls.
+ * 1) Those that provide a new injection sub-interface (contains param .*Injection).
+ * 2) Those that are sessioned via an injection sub-interface (contains param .*Session).
+ * The new injection sub-interfaces generated by (1) can be used to trigger HAL events.
+ * Some calls within (2) will invalidate the session object which they are associated with
+ * (e.g. {@link soundModelUnloaded}), and will be noted as such.
+ * Some calls within the injection interface (e.g. {@link IInjectModelEvent#triggerUnloadModel()})
+ * will invalidate the session object they are called upon, and will be noted as such.
+ * @hide
+ */
+oneway interface ISoundTriggerInjection {
+
+    /**
+     * Value of {@link android.media.soundtrigger.Properties#supportedModelArch} that
+     * identifies the HAL as a fake HAL.
+     */
+    const String FAKE_HAL_ARCH = "injection";
+
+    /**
+     * Called following attachment via
+     * {@link ISoundTriggerMiddlewareService#attachMockHalInjection(ISoundTriggerInjection)}.
+     * Provides the client an injection interface for events which are always (globally) valid.
+     * @param globalInjection - Interface used to inject global events to the fake HAL.
+     * Used as a session object for further callbacks associated with the HAL globally.
+     */
+    void registerGlobalEventInjection(IInjectGlobalEvent globalInjection);
+
+    /**
+     * Called when the HAL has been restarted by the framework. Not called after a
+     * {@link IInjectGlobalEvent#triggerRestart()}.
+     * @param globalSession - The interface previously provided by a
+     * {@link registerGlobalEventInjection} call which this restart is associated with.
+     * Used to disambiguate stale restart events from a subsequent global session.
+     */
+    void onRestarted(IInjectGlobalEvent globalSession);
+
+    /**
+     * Called when the HAL has been detached by the framework.
+     * @param globalSession - The interface previously provided by a
+     * {@link registerGlobalEventInjection} call which this detach is associated with.
+     * Used to disambiguate stale detach events from a subsequent global session.
+     */
+    void onFrameworkDetached(IInjectGlobalEvent globalSession);
+
+    /**
+     * Called when a client is attached to the framework. This event is not actually
+     * delivered to the HAL, but is useful to understand the framework state.
+     * @param token - An opaque token representing the framework client session.
+     * Associated with a subsequent call to {@link onClientDetached(IBinder)}.
+     * @param globalSession - The global STHAL session this attach is associated with.
+     */
+    void onClientAttached(IBinder token, IInjectGlobalEvent globalSession);
+
+    /**
+     * Called when a client detaches from the framework. This event is not actually
+     * delivered to the HAL, but is useful to understand the framework state.
+     * @param token - The opaque token returned by a previous
+     * {@link onClientAttached(IBinder, IInjectGlobalEvent} call.
+     */
+    void onClientDetached(IBinder token);
+
+    /**
+     * Called when a sound model is loaded into the fake STHAL by the framework.
+     * @param model - The model data for the newly loaded model.
+     * @param phrases - The phrase data for the newly loaded model, if it is a keyphrase model.
+     *                  Null otherwise.
+     * @param modelInjection - Interface used to inject events associated with the newly loaded
+     * model into the fake STHAL.
+     * Used as a session object for further callbacks associated with this newly loaded model.
+     * @param globalSession - The session object representing the global STHAL instance this load
+     * is associated with.
+     */
+    void onSoundModelLoaded(in SoundModel model, in @nullable Phrase[] phrases,
+                        IInjectModelEvent modelInjection, IInjectGlobalEvent globalSession);
+
+    /**
+     * Called when the fake STHAL receives a set parameter call from the framework on a previously
+     * loaded model.
+     * @param modelParam - Code of the parameter being set, see
+     * {@link android.media.soundtrigger.ModelParameter}
+     * @param value - Value to set the modelParam to
+     * @param modelSession - Session object of the loaded model the set param call is associated
+     * with.
+     */
+
+    void onParamSet(int modelParam, int value, IInjectModelEvent modelSession);
+
+
+    /**
+     * Called when a previously loaded model in the fake STHAL has recognition started by the
+     * framework.
+     * @param audioSessionToken - The audio session token passed by the framework which will be
+     * contained within a received recognition event.
+     * @param config - The recognition config passed by the framework for this recognition.
+     * @param recognitionInjection - A new injection interface which allows the client to
+     * trigger events associated with this newly started recognition.
+     * @param modelSession - The session object representing the loaded model that this
+     * recognition is associated with.
+     */
+    void onRecognitionStarted(int audioSessionToken, in RecognitionConfig config,
+            IInjectRecognitionEvent recognitionInjection, IInjectModelEvent modelSession);
+
+    /**
+     * Called when a previously started recognition in the fake STHAL is stopped by the framework.
+     * Not called following any calls on {@link IInjectRecognitionEvent}.
+     * @param recognitionSession - The session object received via a previous call to
+     * {@link recognitionStarted(int, RecognitionConfig, IInjectModelEvent,
+     * IInjectRecognitionEvent} which has been unloaded.
+     * This session is invalidated subsequent to this call, and no triggers will be respected.
+     */
+    void onRecognitionStopped(IInjectRecognitionEvent recognitionSession);
+
+    /**
+     * Called when a previously loaded model in the fake STHAL is unloaded by the framework.
+     * Not called following {@link IInjectModelEvent#triggerUnloadModel()}.
+     * @param modelSession - The session object received via a previous call to
+     * {@link soundModelLoaded(SoundModel, Phrase[], IInjectModelEvent} which has been unloaded.
+     * This session is invalidated subsequent to this call, and no triggers will be respected.
+     */
+    void onSoundModelUnloaded(IInjectModelEvent modelSession);
+
+    /**
+     * Called when this injection interface has been preempted by a subsequent call to
+     * {@link ISoundTriggerMiddleware#attachFakeHal(ISoundTriggerInjection)}.
+     * No more events will be delivered, and any further injection will be ignored.
+     */
+    void onPreempted();
+
+}
diff --git a/media/aidl/android/media/soundtrigger_middleware/ISoundTriggerModule.aidl b/media/aidl/android/media/soundtrigger_middleware/ISoundTriggerModule.aidl
index 0b46fd4..18688ce 100644
--- a/media/aidl/android/media/soundtrigger_middleware/ISoundTriggerModule.aidl
+++ b/media/aidl/android/media/soundtrigger_middleware/ISoundTriggerModule.aidl
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.media.soundtrigger_middleware;
 
 import android.media.soundtrigger.ModelParameter;
@@ -148,4 +149,4 @@
      * All models must have been unloaded prior to calling this method.
      */
     void detach();
-}
\ No newline at end of file
+}