Migrate SoundTrigger implementation to new service

The API offered by SoundTrigger.java is now implemented on top of
the new soundtrigger_middleware service.
There is no longer any need for JNI - the API now talks directly
with the AIDL interface of the new service.

In the process, some annotations and input validation have been added
to improve the overall quality of this API.

Change-Id: I731ffd5a275b88f38d84dd3daa022a13f97a5ee1
Bug: 142070343
diff --git a/core/java/android/hardware/soundtrigger/ConversionUtil.java b/core/java/android/hardware/soundtrigger/ConversionUtil.java
new file mode 100644
index 0000000..8231c58
--- /dev/null
+++ b/core/java/android/hardware/soundtrigger/ConversionUtil.java
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2019 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.hardware.soundtrigger;
+
+import android.hardware.soundtrigger.ModelParams;
+import android.media.AudioFormat;
+import android.media.audio.common.AudioConfig;
+import android.media.soundtrigger_middleware.ConfidenceLevel;
+import android.media.soundtrigger_middleware.ModelParameterRange;
+import android.media.soundtrigger_middleware.Phrase;
+import android.media.soundtrigger_middleware.PhraseRecognitionEvent;
+import android.media.soundtrigger_middleware.PhraseRecognitionExtra;
+import android.media.soundtrigger_middleware.PhraseSoundModel;
+import android.media.soundtrigger_middleware.RecognitionConfig;
+import android.media.soundtrigger_middleware.RecognitionEvent;
+import android.media.soundtrigger_middleware.RecognitionMode;
+import android.media.soundtrigger_middleware.SoundModel;
+import android.media.soundtrigger_middleware.SoundTriggerModuleDescriptor;
+import android.media.soundtrigger_middleware.SoundTriggerModuleProperties;
+
+import android.annotation.Nullable;
+
+import java.util.Arrays;
+import java.util.UUID;
+
+/** @hide */
+class ConversionUtil {
+    public static SoundTrigger.ModuleProperties aidl2apiModuleDescriptor(
+            SoundTriggerModuleDescriptor aidlDesc) {
+        SoundTriggerModuleProperties properties = aidlDesc.properties;
+        return new SoundTrigger.ModuleProperties(
+                aidlDesc.handle,
+                properties.implementor,
+                properties.description,
+                properties.uuid,
+                properties.version,
+                properties.maxSoundModels,
+                properties.maxKeyPhrases,
+                properties.maxUsers,
+                aidl2apiRecognitionModes(properties.recognitionModes),
+                properties.captureTransition,
+                properties.maxBufferMs,
+                properties.concurrentCapture,
+                properties.powerConsumptionMw,
+                properties.triggerInEvent
+        );
+    }
+
+    public static int aidl2apiRecognitionModes(int aidlModes) {
+        int result = 0;
+        if ((aidlModes & RecognitionMode.VOICE_TRIGGER) != 0) {
+            result |= SoundTrigger.RECOGNITION_MODE_VOICE_TRIGGER;
+        }
+        if ((aidlModes & RecognitionMode.USER_IDENTIFICATION) != 0) {
+            result |= SoundTrigger.RECOGNITION_MODE_USER_IDENTIFICATION;
+        }
+        if ((aidlModes & RecognitionMode.USER_AUTHENTICATION) != 0) {
+            result |= SoundTrigger.RECOGNITION_MODE_USER_AUTHENTICATION;
+        }
+        if ((aidlModes & RecognitionMode.GENERIC_TRIGGER) != 0) {
+            result |= SoundTrigger.RECOGNITION_MODE_GENERIC;
+        }
+        return result;
+    }
+
+    public static int api2aidlRecognitionModes(int apiModes) {
+        int result = 0;
+        if ((apiModes & SoundTrigger.RECOGNITION_MODE_VOICE_TRIGGER) != 0) {
+            result |= RecognitionMode.VOICE_TRIGGER;
+        }
+        if ((apiModes & SoundTrigger.RECOGNITION_MODE_USER_IDENTIFICATION) != 0) {
+            result |= RecognitionMode.USER_IDENTIFICATION;
+        }
+        if ((apiModes & SoundTrigger.RECOGNITION_MODE_USER_AUTHENTICATION) != 0) {
+            result |= RecognitionMode.USER_AUTHENTICATION;
+        }
+        if ((apiModes & SoundTrigger.RECOGNITION_MODE_GENERIC) != 0) {
+            result |= RecognitionMode.GENERIC_TRIGGER;
+        }
+        return result;
+    }
+
+
+    public static SoundModel api2aidlGenericSoundModel(SoundTrigger.GenericSoundModel apiModel) {
+        return api2aidlSoundModel(apiModel);
+    }
+
+    public static SoundModel api2aidlSoundModel(SoundTrigger.SoundModel apiModel) {
+        SoundModel aidlModel = new SoundModel();
+        aidlModel.type = apiModel.type;
+        aidlModel.uuid = api2aidlUuid(apiModel.uuid);
+        aidlModel.vendorUuid = api2aidlUuid(apiModel.vendorUuid);
+        aidlModel.data = Arrays.copyOf(apiModel.data, apiModel.data.length);
+        return aidlModel;
+    }
+
+    public static String api2aidlUuid(UUID apiUuid) {
+        return apiUuid.toString();
+    }
+
+    public static PhraseSoundModel api2aidlPhraseSoundModel(
+            SoundTrigger.KeyphraseSoundModel apiModel) {
+        PhraseSoundModel aidlModel = new PhraseSoundModel();
+        aidlModel.common = api2aidlSoundModel(apiModel);
+        aidlModel.phrases = new Phrase[apiModel.keyphrases.length];
+        for (int i = 0; i < apiModel.keyphrases.length; ++i) {
+            aidlModel.phrases[i] = api2aidlPhrase(apiModel.keyphrases[i]);
+        }
+        return aidlModel;
+    }
+
+    public static Phrase api2aidlPhrase(SoundTrigger.Keyphrase apiPhrase) {
+        Phrase aidlPhrase = new Phrase();
+        aidlPhrase.id = apiPhrase.id;
+        aidlPhrase.recognitionModes = api2aidlRecognitionModes(apiPhrase.recognitionModes);
+        aidlPhrase.users = Arrays.copyOf(apiPhrase.users, apiPhrase.users.length);
+        aidlPhrase.locale = apiPhrase.locale;
+        aidlPhrase.text = apiPhrase.text;
+        return aidlPhrase;
+    }
+
+    public static RecognitionConfig api2aidlRecognitionConfig(
+            SoundTrigger.RecognitionConfig apiConfig) {
+        RecognitionConfig aidlConfig = new RecognitionConfig();
+        aidlConfig.captureRequested = apiConfig.captureRequested;
+        // apiConfig.allowMultipleTriggers is ignored by the lower layers.
+        aidlConfig.phraseRecognitionExtras =
+                new PhraseRecognitionExtra[apiConfig.keyphrases.length];
+        for (int i = 0; i < apiConfig.keyphrases.length; ++i) {
+            aidlConfig.phraseRecognitionExtras[i] = api2aidlPhraseRecognitionExtra(
+                    apiConfig.keyphrases[i]);
+        }
+        aidlConfig.data = Arrays.copyOf(apiConfig.data, apiConfig.data.length);
+        return aidlConfig;
+    }
+
+    public static PhraseRecognitionExtra api2aidlPhraseRecognitionExtra(
+            SoundTrigger.KeyphraseRecognitionExtra apiExtra) {
+        PhraseRecognitionExtra aidlExtra = new PhraseRecognitionExtra();
+        aidlExtra.id = apiExtra.id;
+        aidlExtra.recognitionModes = api2aidlRecognitionModes(apiExtra.recognitionModes);
+        aidlExtra.confidenceLevel = apiExtra.coarseConfidenceLevel;
+        aidlExtra.levels = new ConfidenceLevel[apiExtra.confidenceLevels.length];
+        for (int i = 0; i < apiExtra.confidenceLevels.length; ++i) {
+            aidlExtra.levels[i] = api2aidlConfidenceLevel(apiExtra.confidenceLevels[i]);
+        }
+        return aidlExtra;
+    }
+
+    public static SoundTrigger.KeyphraseRecognitionExtra aidl2apiPhraseRecognitionExtra(
+            PhraseRecognitionExtra aidlExtra) {
+        SoundTrigger.ConfidenceLevel[] apiLevels =
+                new SoundTrigger.ConfidenceLevel[aidlExtra.levels.length];
+        for (int i = 0; i < aidlExtra.levels.length; ++i) {
+            apiLevels[i] = aidl2apiConfidenceLevel(aidlExtra.levels[i]);
+        }
+        return new SoundTrigger.KeyphraseRecognitionExtra(aidlExtra.id,
+                aidl2apiRecognitionModes(aidlExtra.recognitionModes),
+                aidlExtra.confidenceLevel, apiLevels);
+    }
+
+    public static ConfidenceLevel api2aidlConfidenceLevel(
+            SoundTrigger.ConfidenceLevel apiLevel) {
+        ConfidenceLevel aidlLevel = new ConfidenceLevel();
+        aidlLevel.levelPercent = apiLevel.confidenceLevel;
+        aidlLevel.userId = apiLevel.userId;
+        return aidlLevel;
+    }
+
+    public static SoundTrigger.ConfidenceLevel aidl2apiConfidenceLevel(
+            ConfidenceLevel apiLevel) {
+        return new SoundTrigger.ConfidenceLevel(apiLevel.userId, apiLevel.levelPercent);
+    }
+
+    public static SoundTrigger.RecognitionEvent aidl2apiRecognitionEvent(
+            int modelHandle, RecognitionEvent aidlEvent) {
+        return new SoundTrigger.GenericRecognitionEvent(
+                aidlEvent.status,
+                modelHandle, aidlEvent.captureAvailable, aidlEvent.captureSession,
+                aidlEvent.captureDelayMs, aidlEvent.capturePreambleMs, aidlEvent.triggerInData,
+                aidl2apiAudioFormat(aidlEvent.audioConfig), aidlEvent.data);
+    }
+
+    public static SoundTrigger.RecognitionEvent aidl2apiPhraseRecognitionEvent(
+            int modelHandle,
+            PhraseRecognitionEvent aidlEvent) {
+        SoundTrigger.KeyphraseRecognitionExtra[] apiExtras =
+                new SoundTrigger.KeyphraseRecognitionExtra[aidlEvent.phraseExtras.length];
+        for (int i = 0; i < aidlEvent.phraseExtras.length; ++i) {
+            apiExtras[i] = aidl2apiPhraseRecognitionExtra(aidlEvent.phraseExtras[i]);
+        }
+        return new SoundTrigger.KeyphraseRecognitionEvent(aidlEvent.common.status, modelHandle,
+                aidlEvent.common.captureAvailable,
+                aidlEvent.common.captureSession, aidlEvent.common.captureDelayMs,
+                aidlEvent.common.capturePreambleMs, aidlEvent.common.triggerInData,
+                aidl2apiAudioFormat(aidlEvent.common.audioConfig), aidlEvent.common.data,
+                apiExtras);
+    }
+
+    public static AudioFormat aidl2apiAudioFormat(AudioConfig audioConfig) {
+        AudioFormat.Builder apiBuilder = new AudioFormat.Builder();
+        apiBuilder.setSampleRate(audioConfig.sampleRateHz);
+        apiBuilder.setChannelMask(aidl2apiChannelInMask(audioConfig.channelMask));
+        apiBuilder.setEncoding(aidl2apiEncoding(audioConfig.format));
+        return apiBuilder.build();
+    }
+
+    public static int aidl2apiEncoding(int aidlFormat) {
+        switch (aidlFormat) {
+            case android.media.audio.common.AudioFormat.PCM
+                    | android.media.audio.common.AudioFormat.PCM_SUB_16_BIT:
+                return AudioFormat.ENCODING_PCM_16BIT;
+
+            case android.media.audio.common.AudioFormat.PCM
+                    | android.media.audio.common.AudioFormat.PCM_SUB_8_BIT:
+                return AudioFormat.ENCODING_PCM_8BIT;
+
+            case android.media.audio.common.AudioFormat.PCM
+                    | android.media.audio.common.AudioFormat.PCM_SUB_FLOAT:
+            case android.media.audio.common.AudioFormat.PCM
+                    | android.media.audio.common.AudioFormat.PCM_SUB_8_24_BIT:
+            case android.media.audio.common.AudioFormat.PCM
+                    | android.media.audio.common.AudioFormat.PCM_SUB_24_BIT_PACKED:
+            case android.media.audio.common.AudioFormat.PCM
+                    | android.media.audio.common.AudioFormat.PCM_SUB_32_BIT:
+                return AudioFormat.ENCODING_PCM_FLOAT;
+
+            case android.media.audio.common.AudioFormat.AC3:
+                return AudioFormat.ENCODING_AC3;
+
+            case android.media.audio.common.AudioFormat.E_AC3:
+                return AudioFormat.ENCODING_E_AC3;
+
+            case android.media.audio.common.AudioFormat.DTS:
+                return AudioFormat.ENCODING_DTS;
+
+            case android.media.audio.common.AudioFormat.DTS_HD:
+                return AudioFormat.ENCODING_DTS_HD;
+
+            case android.media.audio.common.AudioFormat.MP3:
+                return AudioFormat.ENCODING_MP3;
+
+            case android.media.audio.common.AudioFormat.AAC
+                    | android.media.audio.common.AudioFormat.AAC_SUB_LC:
+                return AudioFormat.ENCODING_AAC_LC;
+
+            case android.media.audio.common.AudioFormat.AAC
+                    | android.media.audio.common.AudioFormat.AAC_SUB_HE_V1:
+                return AudioFormat.ENCODING_AAC_HE_V1;
+
+            case android.media.audio.common.AudioFormat.AAC
+                    | android.media.audio.common.AudioFormat.AAC_SUB_HE_V2:
+                return AudioFormat.ENCODING_AAC_HE_V2;
+
+            case android.media.audio.common.AudioFormat.IEC61937:
+                return AudioFormat.ENCODING_IEC61937;
+
+            case android.media.audio.common.AudioFormat.DOLBY_TRUEHD:
+                return AudioFormat.ENCODING_DOLBY_TRUEHD;
+
+            case android.media.audio.common.AudioFormat.AAC
+                    | android.media.audio.common.AudioFormat.AAC_SUB_ELD:
+                return AudioFormat.ENCODING_AAC_ELD;
+
+            case android.media.audio.common.AudioFormat.AAC
+                    | android.media.audio.common.AudioFormat.AAC_SUB_XHE:
+                return AudioFormat.ENCODING_AAC_XHE;
+
+            case android.media.audio.common.AudioFormat.AC4:
+                return AudioFormat.ENCODING_AC4;
+
+            case android.media.audio.common.AudioFormat.E_AC3
+                    | android.media.audio.common.AudioFormat.E_AC3_SUB_JOC:
+                return AudioFormat.ENCODING_E_AC3_JOC;
+
+            case android.media.audio.common.AudioFormat.MAT:
+            case android.media.audio.common.AudioFormat.MAT
+                    | android.media.audio.common.AudioFormat.MAT_SUB_1_0:
+            case android.media.audio.common.AudioFormat.MAT
+                    | android.media.audio.common.AudioFormat.MAT_SUB_2_0:
+            case android.media.audio.common.AudioFormat.MAT
+                    | android.media.audio.common.AudioFormat.MAT_SUB_2_1:
+                return AudioFormat.ENCODING_DOLBY_MAT;
+
+            case android.media.audio.common.AudioFormat.DEFAULT:
+                return AudioFormat.ENCODING_DEFAULT;
+
+            default:
+                return AudioFormat.ENCODING_INVALID;
+        }
+    }
+
+    public static int api2aidlModelParameter(int apiParam) {
+        switch (apiParam) {
+            case ModelParams.THRESHOLD_FACTOR:
+                return android.media.soundtrigger_middleware.ModelParameter.THRESHOLD_FACTOR;
+            default:
+                return android.media.soundtrigger_middleware.ModelParameter.INVALID;
+        }
+    }
+
+    public static int aidl2apiChannelInMask(int aidlMask) {
+        // We're assuming AudioFormat.CHANNEL_IN_* constants are kept in sync with
+        // android.media.audio.common.AudioChannelMask.
+        return aidlMask;
+    }
+
+    public static SoundTrigger.ModelParamRange aidl2apiModelParameterRange(
+            @Nullable ModelParameterRange aidlRange) {
+        if (aidlRange == null) {
+            return null;
+        }
+        return new SoundTrigger.ModelParamRange(aidlRange.minInclusive, aidlRange.maxInclusive);
+    }
+}
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index 86f3eec..5484df4 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -22,18 +22,29 @@
 import static android.system.OsConstants.EPERM;
 import static android.system.OsConstants.EPIPE;
 
+import static java.util.Objects.requireNonNull;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityThread;
+import android.content.Context;
 import android.media.AudioFormat;
+import android.media.soundtrigger_middleware.ISoundTriggerMiddlewareService;
+import android.media.soundtrigger_middleware.SoundTriggerModuleDescriptor;
 import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 import java.util.UUID;
 
 /**
@@ -44,6 +55,7 @@
  */
 @SystemApi
 public class SoundTrigger {
+    private static final String TAG = "SoundTrigger";
 
     private SoundTrigger() {
     }
@@ -119,15 +131,15 @@
          * recognition callback event */
         public final boolean returnsTriggerInEvent;
 
-        ModuleProperties(int id, String implementor, String description,
-                String uuid, int version, int maxSoundModels, int maxKeyphrases,
+        ModuleProperties(int id, @NonNull String implementor, @NonNull String description,
+                @NonNull String uuid, int version, int maxSoundModels, int maxKeyphrases,
                 int maxUsers, int recognitionModes, boolean supportsCaptureTransition,
                 int maxBufferMs, boolean supportsConcurrentCapture,
                 int powerConsumptionMw, boolean returnsTriggerInEvent) {
             this.id = id;
-            this.implementor = implementor;
-            this.description = description;
-            this.uuid = UUID.fromString(uuid);
+            this.implementor = requireNonNull(implementor);
+            this.description = requireNonNull(description);
+            this.uuid = UUID.fromString(requireNonNull(uuid));
             this.version = version;
             this.maxSoundModels = maxSoundModels;
             this.maxKeyphrases = maxKeyphrases;
@@ -231,6 +243,7 @@
 
         /** Unique sound model identifier */
         @UnsupportedAppUsage
+        @NonNull
         public final UUID uuid;
 
         /** Sound model type (e.g. TYPE_KEYPHRASE); */
@@ -238,17 +251,20 @@
 
         /** Unique sound model vendor identifier */
         @UnsupportedAppUsage
+        @NonNull
         public final UUID vendorUuid;
 
         /** Opaque data. For use by vendor implementation and enrollment application */
         @UnsupportedAppUsage
+        @NonNull
         public final byte[] data;
 
-        public SoundModel(UUID uuid, UUID vendorUuid, int type, byte[] data) {
-            this.uuid = uuid;
-            this.vendorUuid = vendorUuid;
+        public SoundModel(@NonNull UUID uuid, @Nullable UUID vendorUuid, int type,
+                @Nullable byte[] data) {
+            this.uuid = requireNonNull(uuid);
+            this.vendorUuid = vendorUuid != null ? vendorUuid : new UUID(0, 0);
             this.type = type;
-            this.data = data;
+            this.data = data != null ? data : new byte[0];
         }
 
         @Override
@@ -271,8 +287,6 @@
             if (!(obj instanceof SoundModel))
                 return false;
             SoundModel other = (SoundModel) obj;
-            if (!Arrays.equals(data, other.data))
-                return false;
             if (type != other.type)
                 return false;
             if (uuid == null) {
@@ -285,6 +299,8 @@
                     return false;
             } else if (!vendorUuid.equals(other.vendorUuid))
                 return false;
+            if (!Arrays.equals(data, other.data))
+                return false;
             return true;
         }
     }
@@ -306,24 +322,28 @@
 
         /** Locale of the keyphrase. JAVA Locale string e.g en_US */
         @UnsupportedAppUsage
+        @NonNull
         public final String locale;
 
         /** Key phrase text */
         @UnsupportedAppUsage
+        @NonNull
         public final String text;
 
         /** Users this key phrase has been trained for. countains sound trigger specific user IDs
          * derived from system user IDs {@link android.os.UserHandle#getIdentifier()}. */
         @UnsupportedAppUsage
+        @NonNull
         public final int[] users;
 
         @UnsupportedAppUsage
-        public Keyphrase(int id, int recognitionModes, String locale, String text, int[] users) {
+        public Keyphrase(int id, int recognitionModes, @NonNull String locale, @NonNull String text,
+                @Nullable int[] users) {
             this.id = id;
             this.recognitionModes = recognitionModes;
-            this.locale = locale;
-            this.text = text;
-            this.users = users;
+            this.locale = requireNonNull(locale);
+            this.text = requireNonNull(text);
+            this.users = users != null ? users : new int[0];
         }
 
         public static final @android.annotation.NonNull Parcelable.Creator<Keyphrase> CREATOR
@@ -427,13 +447,15 @@
     public static class KeyphraseSoundModel extends SoundModel implements Parcelable {
         /** Key phrases in this sound model */
         @UnsupportedAppUsage
+        @NonNull
         public final Keyphrase[] keyphrases; // keyword phrases in model
 
         @UnsupportedAppUsage
         public KeyphraseSoundModel(
-                UUID uuid, UUID vendorUuid, byte[] data, Keyphrase[] keyphrases) {
+                @NonNull UUID uuid, @NonNull UUID vendorUuid, @Nullable byte[] data,
+                @Nullable Keyphrase[] keyphrases) {
             super(uuid, vendorUuid, TYPE_KEYPHRASE, data);
-            this.keyphrases = keyphrases;
+            this.keyphrases = keyphrases != null ? keyphrases : new Keyphrase[0];
         }
 
         public static final @android.annotation.NonNull Parcelable.Creator<KeyphraseSoundModel> CREATOR
@@ -528,7 +550,8 @@
         };
 
         @UnsupportedAppUsage
-        public GenericSoundModel(UUID uuid, UUID vendorUuid, byte[] data) {
+        public GenericSoundModel(@NonNull UUID uuid, @NonNull UUID vendorUuid,
+                @Nullable byte[] data) {
             super(uuid, vendorUuid, TYPE_GENERIC_SOUND, data);
         }
 
@@ -648,6 +671,12 @@
      * @hide
      */
     public static final int RECOGNITION_MODE_USER_AUTHENTICATION = 0x4;
+    /**
+     * Generic (non-speech) recognition.
+     *
+     * @hide
+     */
+    public static final int RECOGNITION_MODE_GENERIC = 0x8;
 
     /**
      *  Status codes for {@link RecognitionEvent}
@@ -739,6 +768,7 @@
          *
          * @hide
          */
+        @NonNull
         public final AudioFormat captureFormat;
         /**
          * Opaque data for use by system applications who know about voice engine internals,
@@ -747,13 +777,14 @@
          * @hide
          */
         @UnsupportedAppUsage
+        @NonNull
         public final byte[] data;
 
         /** @hide */
         @UnsupportedAppUsage
         public RecognitionEvent(int status, int soundModelHandle, boolean captureAvailable,
                 int captureSession, int captureDelayMs, int capturePreambleMs,
-                boolean triggerInData, AudioFormat captureFormat, byte[] data) {
+                boolean triggerInData, @NonNull AudioFormat captureFormat, @Nullable byte[] data) {
             this.status = status;
             this.soundModelHandle = soundModelHandle;
             this.captureAvailable = captureAvailable;
@@ -761,8 +792,8 @@
             this.captureDelayMs = captureDelayMs;
             this.capturePreambleMs = capturePreambleMs;
             this.triggerInData = triggerInData;
-            this.captureFormat = captureFormat;
-            this.data = data;
+            this.captureFormat = requireNonNull(captureFormat);
+            this.data = data != null ? data : new byte[0];
         }
 
         /**
@@ -965,19 +996,21 @@
         /** List of all keyphrases in the sound model for which recognition should be performed with
          * options for each keyphrase. */
         @UnsupportedAppUsage
+        @NonNull
         public final KeyphraseRecognitionExtra keyphrases[];
         /** Opaque data for use by system applications who know about voice engine internals,
          * typically during enrollment. */
         @UnsupportedAppUsage
+        @NonNull
         public final byte[] data;
 
         @UnsupportedAppUsage
         public RecognitionConfig(boolean captureRequested, boolean allowMultipleTriggers,
-                KeyphraseRecognitionExtra[] keyphrases, byte[] data) {
+                @Nullable KeyphraseRecognitionExtra[] keyphrases, @Nullable byte[] data) {
             this.captureRequested = captureRequested;
             this.allowMultipleTriggers = allowMultipleTriggers;
-            this.keyphrases = keyphrases;
-            this.data = data;
+            this.keyphrases = keyphrases != null ? keyphrases : new KeyphraseRecognitionExtra[0];
+            this.data = data != null ? data : new byte[0];
         }
 
         public static final @android.annotation.NonNull Parcelable.Creator<RecognitionConfig> CREATOR
@@ -1126,15 +1159,17 @@
         /** Confidence levels for all users recognized (KeyphraseRecognitionEvent) or to
          * be recognized (RecognitionConfig) */
         @UnsupportedAppUsage
+        @NonNull
         public final ConfidenceLevel[] confidenceLevels;
 
         @UnsupportedAppUsage
         public KeyphraseRecognitionExtra(int id, int recognitionModes, int coarseConfidenceLevel,
-                ConfidenceLevel[] confidenceLevels) {
+                @Nullable ConfidenceLevel[] confidenceLevels) {
             this.id = id;
             this.recognitionModes = recognitionModes;
             this.coarseConfidenceLevel = coarseConfidenceLevel;
-            this.confidenceLevels = confidenceLevels;
+            this.confidenceLevels =
+                    confidenceLevels != null ? confidenceLevels : new ConfidenceLevel[0];
         }
 
         public static final @android.annotation.NonNull Parcelable.Creator<KeyphraseRecognitionExtra> CREATOR
@@ -1217,16 +1252,18 @@
     public static class KeyphraseRecognitionEvent extends RecognitionEvent implements Parcelable {
         /** Indicates if the key phrase is present in the buffered audio available for capture */
         @UnsupportedAppUsage
+        @NonNull
         public final KeyphraseRecognitionExtra[] keyphraseExtras;
 
         @UnsupportedAppUsage
         public KeyphraseRecognitionEvent(int status, int soundModelHandle, boolean captureAvailable,
                int captureSession, int captureDelayMs, int capturePreambleMs,
-               boolean triggerInData, AudioFormat captureFormat, byte[] data,
-               KeyphraseRecognitionExtra[] keyphraseExtras) {
+               boolean triggerInData, @NonNull AudioFormat captureFormat, @Nullable byte[] data,
+               @Nullable KeyphraseRecognitionExtra[] keyphraseExtras) {
             super(status, soundModelHandle, captureAvailable, captureSession, captureDelayMs,
                   capturePreambleMs, triggerInData, captureFormat, data);
-            this.keyphraseExtras = keyphraseExtras;
+            this.keyphraseExtras =
+                    keyphraseExtras != null ? keyphraseExtras : new KeyphraseRecognitionExtra[0];
         }
 
         public static final @android.annotation.NonNull Parcelable.Creator<KeyphraseRecognitionEvent> CREATOR
@@ -1343,8 +1380,8 @@
         @UnsupportedAppUsage
         public GenericRecognitionEvent(int status, int soundModelHandle,
                 boolean captureAvailable, int captureSession, int captureDelayMs,
-                int capturePreambleMs, boolean triggerInData, AudioFormat captureFormat,
-                byte[] data) {
+                int capturePreambleMs, boolean triggerInData, @NonNull AudioFormat captureFormat,
+                @Nullable byte[] data) {
             super(status, soundModelHandle, captureAvailable, captureSession,
                     captureDelayMs, capturePreambleMs, triggerInData, captureFormat,
                     data);
@@ -1408,13 +1445,14 @@
         /** The updated sound model handle */
         public final int soundModelHandle;
         /** New sound model data */
+        @NonNull
         public final byte[] data;
 
         @UnsupportedAppUsage
-        SoundModelEvent(int status, int soundModelHandle, byte[] data) {
+        SoundModelEvent(int status, int soundModelHandle, @Nullable byte[] data) {
             this.status = status;
             this.soundModelHandle = soundModelHandle;
-            this.data = data;
+            this.data = data != null ? data : new byte[0];
         }
 
         public static final @android.annotation.NonNull Parcelable.Creator<SoundModelEvent> CREATOR
@@ -1498,8 +1536,9 @@
      * @hide
      */
     public static final int SERVICE_STATE_DISABLED = 1;
-
-    /**
+    private static Object mServiceLock = new Object();
+    private static ISoundTriggerMiddlewareService mService;
+   /**
      * @return returns current package name.
      */
     static String getCurrentOpPackageName() {
@@ -1523,25 +1562,22 @@
      * @hide
      */
     @UnsupportedAppUsage
-    public static int listModules(ArrayList<ModuleProperties> modules) {
-        return listModules(getCurrentOpPackageName(), modules);
+    public static int listModules(@NonNull ArrayList<ModuleProperties> modules) {
+        try {
+            SoundTriggerModuleDescriptor[] descs = getService().listModules();
+            modules.clear();
+            modules.ensureCapacity(descs.length);
+            for (SoundTriggerModuleDescriptor desc : descs) {
+                modules.add(ConversionUtil.aidl2apiModuleDescriptor(desc));
+            }
+            return STATUS_OK;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Exception caught", e);
+            return STATUS_DEAD_OBJECT;
+        }
     }
 
     /**
-     * Returns a list of descriptors for all hardware modules loaded.
-     * @param opPackageName
-     * @param modules A ModuleProperties array where the list will be returned.
-     * @return - {@link #STATUS_OK} in case of success
-     *         - {@link #STATUS_ERROR} in case of unspecified error
-     *         - {@link #STATUS_PERMISSION_DENIED} if the caller does not have system permission
-     *         - {@link #STATUS_NO_INIT} if the native service cannot be reached
-     *         - {@link #STATUS_BAD_VALUE} if modules is null
-     *         - {@link #STATUS_DEAD_OBJECT} if the binder transaction to the native service fails
-     */
-    private static native int listModules(String opPackageName,
-                                          ArrayList<ModuleProperties> modules);
-
-    /**
      * Get an interface on a hardware module to control sound models and recognition on
      * this module.
      * @param moduleId Sound module system identifier {@link ModuleProperties#id}. mandatory.
@@ -1553,14 +1589,40 @@
      * @hide
      */
     @UnsupportedAppUsage
-    public static SoundTriggerModule attachModule(int moduleId,
-                                                  StatusListener listener,
-                                                  Handler handler) {
-        if (listener == null) {
+    public static @NonNull SoundTriggerModule attachModule(int moduleId,
+            @NonNull StatusListener listener,
+            @Nullable Handler handler) {
+        Looper looper = handler != null ? handler.getLooper() : Looper.getMainLooper();
+        try {
+            return new SoundTriggerModule(getService(), moduleId, listener, looper);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
             return null;
         }
-        SoundTriggerModule module = new SoundTriggerModule(moduleId, listener, handler);
-        return module;
+    }
+
+    private static ISoundTriggerMiddlewareService getService() {
+        synchronized (mServiceLock) {
+            while (true) {
+                IBinder binder = null;
+                try {
+                    binder =
+                            ServiceManager.getServiceOrThrow(
+                                    Context.SOUND_TRIGGER_MIDDLEWARE_SERVICE);
+                    binder.linkToDeath(() -> {
+                        synchronized (mServiceLock) {
+                            mService = null;
+                        }
+                    }, 0);
+                    mService = ISoundTriggerMiddlewareService.Stub.asInterface(binder);
+                    break;
+                } catch (Exception e) {
+                    Log.e(TAG, "Failed to bind to soundtrigger service", e);
+                }
+            }
+            return  mService;
+        }
+
     }
 
     /**
diff --git a/core/java/android/hardware/soundtrigger/SoundTriggerModule.java b/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
index b16ef5c..7cf5600 100644
--- a/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
+++ b/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
@@ -16,14 +16,23 @@
 
 package android.hardware.soundtrigger;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
-import android.hardware.soundtrigger.SoundTrigger.ModelParamRange;
+import android.media.soundtrigger_middleware.ISoundTriggerCallback;
+import android.media.soundtrigger_middleware.ISoundTriggerMiddlewareService;
+import android.media.soundtrigger_middleware.ISoundTriggerModule;
+import android.media.soundtrigger_middleware.ModelParameterRange;
+import android.media.soundtrigger_middleware.PhraseRecognitionEvent;
+import android.media.soundtrigger_middleware.PhraseSoundModel;
+import android.media.soundtrigger_middleware.RecognitionEvent;
+import android.media.soundtrigger_middleware.SoundModel;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
-
-import java.lang.ref.WeakReference;
+import android.os.RemoteException;
+import android.util.Log;
 
 /**
  * The SoundTriggerModule provides APIs to control sound models and sound detection
@@ -32,39 +41,47 @@
  * @hide
  */
 public class SoundTriggerModule {
-    @UnsupportedAppUsage
-    private long mNativeContext;
+    private static final String TAG = "SoundTriggerModule";
 
-    @UnsupportedAppUsage
-    private int mId;
-    private NativeEventHandlerDelegate mEventHandlerDelegate;
-
-    // to be kept in sync with core/jni/android_hardware_SoundTrigger.cpp
     private static final int EVENT_RECOGNITION = 1;
     private static final int EVENT_SERVICE_DIED = 2;
-    private static final int EVENT_SOUNDMODEL = 3;
-    private static final int EVENT_SERVICE_STATE_CHANGE = 4;
+    private static final int EVENT_SERVICE_STATE_CHANGE = 3;
+    @UnsupportedAppUsage
+    private int mId;
+    private EventHandlerDelegate mEventHandlerDelegate;
+    private ISoundTriggerModule mService;
 
-    SoundTriggerModule(int moduleId, SoundTrigger.StatusListener listener, Handler handler) {
+    SoundTriggerModule(@NonNull ISoundTriggerMiddlewareService service,
+            int moduleId, @NonNull SoundTrigger.StatusListener listener, @NonNull Looper looper)
+            throws RemoteException {
         mId = moduleId;
-        mEventHandlerDelegate = new NativeEventHandlerDelegate(listener, handler);
-        native_setup(SoundTrigger.getCurrentOpPackageName(),
-                new WeakReference<SoundTriggerModule>(this));
+        mEventHandlerDelegate = new EventHandlerDelegate(listener, looper);
+        mService = service.attach(moduleId, mEventHandlerDelegate);
+        mService.asBinder().linkToDeath(mEventHandlerDelegate, 0);
     }
-    private native void native_setup(String opPackageName, Object moduleThis);
 
     @Override
     protected void finalize() {
-        native_finalize();
+        detach();
     }
-    private native void native_finalize();
 
     /**
      * Detach from this module. The {@link SoundTrigger.StatusListener} callback will not be called
      * anymore and associated resources will be released.
-     * */
+     * All models must have been unloaded prior to detaching.
+     */
     @UnsupportedAppUsage
-    public native void detach();
+    public synchronized void detach() {
+        try {
+            if (mService != null) {
+                mService.asBinder().unlinkToDeath(mEventHandlerDelegate, 0);
+                mService.detach();
+                mService = null;
+            }
+        } catch (Exception e) {
+            handleException(e);
+        }
+    }
 
     /**
      * Load a {@link SoundTrigger.SoundModel} to the hardware. A sound model must be loaded in
@@ -82,7 +99,26 @@
      *         - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence
      */
     @UnsupportedAppUsage
-    public native int loadSoundModel(SoundTrigger.SoundModel model, int[] soundModelHandle);
+    public synchronized int loadSoundModel(@NonNull SoundTrigger.SoundModel model,
+            @NonNull int[] soundModelHandle) {
+        try {
+            if (model instanceof SoundTrigger.GenericSoundModel) {
+                SoundModel aidlModel = ConversionUtil.api2aidlGenericSoundModel(
+                        (SoundTrigger.GenericSoundModel) model);
+                soundModelHandle[0] = mService.loadModel(aidlModel);
+                return SoundTrigger.STATUS_OK;
+            }
+            if (model instanceof SoundTrigger.KeyphraseSoundModel) {
+                PhraseSoundModel aidlModel = ConversionUtil.api2aidlPhraseSoundModel(
+                        (SoundTrigger.KeyphraseSoundModel) model);
+                soundModelHandle[0] = mService.loadPhraseModel(aidlModel);
+                return SoundTrigger.STATUS_OK;
+            }
+            return SoundTrigger.STATUS_BAD_VALUE;
+        } catch (Exception e) {
+            return handleException(e);
+        }
+    }
 
     /**
      * Unload a {@link SoundTrigger.SoundModel} and abort any pendiong recognition
@@ -97,7 +133,14 @@
      *         service fails
      */
     @UnsupportedAppUsage
-    public native int unloadSoundModel(int soundModelHandle);
+    public synchronized int unloadSoundModel(int soundModelHandle) {
+        try {
+            mService.unloadModel(soundModelHandle);
+            return SoundTrigger.STATUS_OK;
+        } catch (Exception e) {
+            return handleException(e);
+        }
+    }
 
     /**
      * Start listening to all key phrases in a {@link SoundTrigger.SoundModel}.
@@ -117,7 +160,16 @@
      *         - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence
      */
     @UnsupportedAppUsage
-    public native int startRecognition(int soundModelHandle, SoundTrigger.RecognitionConfig config);
+    public synchronized int startRecognition(int soundModelHandle,
+            SoundTrigger.RecognitionConfig config) {
+        try {
+            mService.startRecognition(soundModelHandle,
+                    ConversionUtil.api2aidlRecognitionConfig(config));
+            return SoundTrigger.STATUS_OK;
+        } catch (Exception e) {
+            return handleException(e);
+        }
+    }
 
     /**
      * Stop listening to all key phrases in a {@link SoundTrigger.SoundModel}
@@ -133,12 +185,20 @@
      *         - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence
      */
     @UnsupportedAppUsage
-    public native int stopRecognition(int soundModelHandle);
+    public synchronized int stopRecognition(int soundModelHandle) {
+        try {
+            mService.stopRecognition(soundModelHandle);
+            return SoundTrigger.STATUS_OK;
+        } catch (Exception e) {
+            return handleException(e);
+        }
+    }
 
     /**
      * Get the current state of a {@link SoundTrigger.SoundModel}.
-     * The state will be returned asynchronously as a {@link SoundTrigger#RecognitionEvent}
-     * in the callback registered in the {@link SoundTrigger.startRecognition} method.
+     * The state will be returned asynchronously as a {@link SoundTrigger.RecognitionEvent}
+     * in the callback registered in the
+     * {@link SoundTrigger#attachModule(int, SoundTrigger.StatusListener, Handler)} method.
      * @param soundModelHandle The sound model handle indicating which model's state to return
      * @return - {@link SoundTrigger#STATUS_OK} in case of success
      *         - {@link SoundTrigger#STATUS_ERROR} in case of unspecified error
@@ -150,46 +210,71 @@
      *         service fails
      *         - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence
      */
-    public native int getModelState(int soundModelHandle);
+    public synchronized int getModelState(int soundModelHandle) {
+        try {
+            mService.forceRecognitionEvent(soundModelHandle);
+            return SoundTrigger.STATUS_OK;
+        } catch (Exception e) {
+            return handleException(e);
+        }
+    }
 
     /**
      * Set a model specific {@link ModelParams} with the given value. This
-     * parameter will keep its value for the duration the model is loaded regardless of starting and
+     * parameter will keep its value for the duration the model is loaded regardless of starting
+     * and
      * stopping recognition. Once the model is unloaded, the value will be lost.
-     * {@link SoundTriggerModule#isParameterSupported} should be checked first before calling this
-     * method.
+     * {@link SoundTriggerModule#queryParameter(int, int)} should be checked first before calling
+     * this method.
      *
      * @param soundModelHandle handle of model to apply parameter
-     * @param modelParam   {@link ModelParams}
-     * @param value        Value to set
+     * @param modelParam       {@link ModelParams}
+     * @param value            Value to set
      * @return - {@link SoundTrigger#STATUS_OK} in case of success
-     *         - {@link SoundTrigger#STATUS_NO_INIT} if the native service cannot be reached
-     *         - {@link SoundTrigger#STATUS_BAD_VALUE} invalid input parameter
-     *         - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence or
-     *           if API is not supported by HAL
+     * - {@link SoundTrigger#STATUS_NO_INIT} if the native service cannot be reached
+     * - {@link SoundTrigger#STATUS_BAD_VALUE} invalid input parameter
+     * - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence or
+     * if API is not supported by HAL
      */
-    public native int setParameter(int soundModelHandle,
-            @ModelParams int modelParam, int value);
+    public synchronized int setParameter(int soundModelHandle, @ModelParams int modelParam,
+            int value) {
+        try {
+            mService.setModelParameter(soundModelHandle,
+                    ConversionUtil.api2aidlModelParameter(modelParam), value);
+            return SoundTrigger.STATUS_OK;
+        } catch (Exception e) {
+            return handleException(e);
+        }
+    }
 
     /**
      * Get a model specific {@link ModelParams}. This parameter will keep its value
      * for the duration the model is loaded regardless of starting and stopping recognition.
      * Once the model is unloaded, the value will be lost. If the value is not set, a default
      * value is returned. See {@link ModelParams} for parameter default values.
-     * {@link SoundTriggerModule#isParameterSupported} should be checked first before
+     * {@link SoundTriggerModule#queryParameter(int, int)} should be checked first before
      * calling this method. Otherwise, an exception can be thrown.
      *
      * @param soundModelHandle handle of model to get parameter
-     * @param modelParam   {@link ModelParams}
+     * @param modelParam       {@link ModelParams}
      * @return value of parameter
      * @throws UnsupportedOperationException if hal or model do not support this API.
-     *         {@link SoundTriggerModule#isParameterSupported} should be checked first.
-     * @throws IllegalArgumentException if invalid model handle or parameter is passed.
-     *         {@link SoundTriggerModule#isParameterSupported} should be checked first.
+     *                                       {@link SoundTriggerModule#queryParameter(int, int)}
+     *                                       should
+     *                                       be checked first.
+     * @throws IllegalArgumentException      if invalid model handle or parameter is passed.
+     *                                       {@link SoundTriggerModule#queryParameter(int, int)}
+     *                                       should be checked first.
      */
-    public native int getParameter(int soundModelHandle,
-            @ModelParams int modelParam)
-            throws UnsupportedOperationException, IllegalArgumentException;
+    public synchronized int getParameter(int soundModelHandle, @ModelParams int modelParam)
+            throws UnsupportedOperationException, IllegalArgumentException {
+        try {
+            return mService.getModelParameter(soundModelHandle,
+                    ConversionUtil.api2aidlModelParameter(modelParam));
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 
     /**
      * Determine if parameter control is supported for the given model handle.
@@ -197,85 +282,98 @@
      * {@link SoundTriggerModule#getParameter}.
      *
      * @param soundModelHandle handle of model to get parameter
-     * @param modelParam {@link ModelParams}
+     * @param modelParam       {@link ModelParams}
      * @return supported range of parameter, null if not supported
      */
     @Nullable
-    public native ModelParamRange queryParameter(int soundModelHandle, @ModelParams int modelParam);
-
-    private class NativeEventHandlerDelegate {
-        private final Handler mHandler;
-
-        NativeEventHandlerDelegate(final SoundTrigger.StatusListener listener,
-                                   Handler handler) {
-            // find the looper for our new event handler
-            Looper looper;
-            if (handler != null) {
-                looper = handler.getLooper();
-            } else {
-                looper = Looper.getMainLooper();
-            }
-
-            // construct the event handler with this looper
-            if (looper != null) {
-                // implement the event handler delegate
-                mHandler = new Handler(looper) {
-                    @Override
-                    public void handleMessage(Message msg) {
-                        switch(msg.what) {
-                        case EVENT_RECOGNITION:
-                            if (listener != null) {
-                                listener.onRecognition(
-                                        (SoundTrigger.RecognitionEvent)msg.obj);
-                            }
-                            break;
-                        case EVENT_SOUNDMODEL:
-                            if (listener != null) {
-                                listener.onSoundModelUpdate(
-                                        (SoundTrigger.SoundModelEvent)msg.obj);
-                            }
-                            break;
-                        case EVENT_SERVICE_STATE_CHANGE:
-                            if (listener != null) {
-                                listener.onServiceStateChange(msg.arg1);
-                            }
-                            break;
-                        case EVENT_SERVICE_DIED:
-                            if (listener != null) {
-                                listener.onServiceDied();
-                            }
-                            break;
-                        default:
-                            break;
-                        }
-                    }
-                };
-            } else {
-                mHandler = null;
-            }
-        }
-
-        Handler handler() {
-            return mHandler;
+    public synchronized SoundTrigger.ModelParamRange queryParameter(int soundModelHandle,
+            @ModelParams int modelParam) {
+        try {
+            return ConversionUtil.aidl2apiModelParameterRange(mService.queryModelParameterSupport(
+                    soundModelHandle,
+                    ConversionUtil.api2aidlModelParameter(modelParam)));
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
-    @SuppressWarnings("unused")
-    @UnsupportedAppUsage
-    private static void postEventFromNative(Object module_ref,
-                                            int what, int arg1, int arg2, Object obj) {
-        SoundTriggerModule module = (SoundTriggerModule)((WeakReference)module_ref).get();
-        if (module == null) {
-            return;
+    private int handleException(Exception e) {
+        Log.e(TAG, "", e);
+        if (e instanceof NullPointerException) {
+            return SoundTrigger.STATUS_NO_INIT;
+        }
+        if (e instanceof RemoteException) {
+            return SoundTrigger.STATUS_DEAD_OBJECT;
+        }
+        if (e instanceof IllegalArgumentException) {
+            return SoundTrigger.STATUS_BAD_VALUE;
+        }
+        if (e instanceof IllegalStateException) {
+            return SoundTrigger.STATUS_INVALID_OPERATION;
+        }
+        return SoundTrigger.STATUS_ERROR;
+    }
+
+    private class EventHandlerDelegate extends ISoundTriggerCallback.Stub implements
+            IBinder.DeathRecipient {
+        private final Handler mHandler;
+
+        EventHandlerDelegate(@NonNull final SoundTrigger.StatusListener listener,
+                @NonNull Looper looper) {
+
+            // construct the event handler with this looper
+            // implement the event handler delegate
+            mHandler = new Handler(looper) {
+                @Override
+                public void handleMessage(Message msg) {
+                    switch (msg.what) {
+                        case EVENT_RECOGNITION:
+                            listener.onRecognition(
+                                    (SoundTrigger.RecognitionEvent) msg.obj);
+                            break;
+                        case EVENT_SERVICE_STATE_CHANGE:
+                            listener.onServiceStateChange(msg.arg1);
+                            break;
+                        case EVENT_SERVICE_DIED:
+                            listener.onServiceDied();
+                            break;
+                        default:
+                            Log.e(TAG, "Unknown message: " + msg.toString());
+                            break;
+                    }
+                }
+            };
         }
 
-        NativeEventHandlerDelegate delegate = module.mEventHandlerDelegate;
-        if (delegate != null) {
-            Handler handler = delegate.handler();
-            if (handler != null) {
-                Message m = handler.obtainMessage(what, arg1, arg2, obj);
-                handler.sendMessage(m);
-            }
+        @Override
+        public synchronized void onRecognition(int handle, RecognitionEvent event)
+                throws RemoteException {
+            Message m = mHandler.obtainMessage(EVENT_RECOGNITION,
+                    ConversionUtil.aidl2apiRecognitionEvent(handle, event));
+            mHandler.sendMessage(m);
+        }
+
+        @Override
+        public synchronized void onPhraseRecognition(int handle, PhraseRecognitionEvent event)
+                throws RemoteException {
+            Message m = mHandler.obtainMessage(EVENT_RECOGNITION,
+                    ConversionUtil.aidl2apiPhraseRecognitionEvent(handle, event));
+            mHandler.sendMessage(m);
+        }
+
+        @Override
+        public synchronized void onRecognitionAvailabilityChange(boolean available)
+                throws RemoteException {
+            Message m = mHandler.obtainMessage(EVENT_SERVICE_STATE_CHANGE,
+                    available ? SoundTrigger.SERVICE_STATE_ENABLED
+                            : SoundTrigger.SERVICE_STATE_DISABLED);
+            mHandler.sendMessage(m);
+        }
+
+        @Override
+        public synchronized void binderDied() {
+            Message m = mHandler.obtainMessage(EVENT_SERVICE_DIED);
+            mHandler.sendMessage(m);
         }
     }
 }
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index b91d359..a2f6a62 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -177,7 +177,6 @@
                 "android_hardware_HardwareBuffer.cpp",
                 "android_hardware_SensorManager.cpp",
                 "android_hardware_SerialPort.cpp",
-                "android_hardware_SoundTrigger.cpp",
                 "android_hardware_UsbDevice.cpp",
                 "android_hardware_UsbDeviceConnection.cpp",
                 "android_hardware_UsbRequest.cpp",
@@ -259,7 +258,6 @@
                 "libpdfium",
                 "libimg_utils",
                 "libnetd_client",
-                "libsoundtrigger",
                 "libprocessgroup",
                 "libnativebridge_lazy",
                 "libnativeloader_lazy",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index b8fd3ad..f7a994f 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -80,7 +80,6 @@
 extern int register_android_hardware_HardwareBuffer(JNIEnv *env);
 extern int register_android_hardware_SensorManager(JNIEnv *env);
 extern int register_android_hardware_SerialPort(JNIEnv *env);
-extern int register_android_hardware_SoundTrigger(JNIEnv *env);
 extern int register_android_hardware_UsbDevice(JNIEnv *env);
 extern int register_android_hardware_UsbDeviceConnection(JNIEnv *env);
 extern int register_android_hardware_UsbRequest(JNIEnv *env);
@@ -1508,7 +1507,6 @@
     REG_JNI(register_android_hardware_HardwareBuffer),
     REG_JNI(register_android_hardware_SensorManager),
     REG_JNI(register_android_hardware_SerialPort),
-    REG_JNI(register_android_hardware_SoundTrigger),
     REG_JNI(register_android_hardware_UsbDevice),
     REG_JNI(register_android_hardware_UsbDeviceConnection),
     REG_JNI(register_android_hardware_UsbRequest),
diff --git a/core/jni/android_hardware_SoundTrigger.cpp b/core/jni/android_hardware_SoundTrigger.cpp
deleted file mode 100644
index 4376b0b..0000000
--- a/core/jni/android_hardware_SoundTrigger.cpp
+++ /dev/null
@@ -1,1071 +0,0 @@
-/*
-**
-** Copyright 2014, 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.
-*/
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "SoundTrigger-JNI"
-#include <utils/Log.h>
-
-#include "jni.h"
-#include <nativehelper/JNIHelp.h>
-#include <nativehelper/ScopedUtfChars.h>
-#include "core_jni_helpers.h"
-#include <system/sound_trigger.h>
-#include <soundtrigger/SoundTriggerCallback.h>
-#include <soundtrigger/SoundTrigger.h>
-#include <utils/RefBase.h>
-#include <utils/Vector.h>
-#include <binder/IMemory.h>
-#include <binder/MemoryDealer.h>
-#include "android_media_AudioFormat.h"
-
-using namespace android;
-
-static jclass gArrayListClass;
-static struct {
-    jmethodID    add;
-} gArrayListMethods;
-
-static jclass gUUIDClass;
-static struct {
-    jmethodID    toString;
-} gUUIDMethods;
-
-static const char* const kUnsupportedOperationExceptionClassPathName =
-     "java/lang/UnsupportedOperationException";
-static jclass gUnsupportedOperationExceptionClass;
-static const char* const kIllegalArgumentExceptionClassPathName =
-     "java/lang/IllegalArgumentException";
-static jclass gIllegalArgumentExceptionClass;
-
-static const char* const kSoundTriggerClassPathName = "android/hardware/soundtrigger/SoundTrigger";
-static jclass gSoundTriggerClass;
-
-static const char* const kModuleClassPathName = "android/hardware/soundtrigger/SoundTriggerModule";
-static jclass gModuleClass;
-static struct {
-    jfieldID    mNativeContext;
-    jfieldID    mId;
-} gModuleFields;
-static jmethodID   gPostEventFromNative;
-
-static const char* const kModulePropertiesClassPathName =
-                                     "android/hardware/soundtrigger/SoundTrigger$ModuleProperties";
-static jclass gModulePropertiesClass;
-static jmethodID   gModulePropertiesCstor;
-
-static const char* const kSoundModelClassPathName =
-                                     "android/hardware/soundtrigger/SoundTrigger$SoundModel";
-static jclass gSoundModelClass;
-static struct {
-    jfieldID    uuid;
-    jfieldID    vendorUuid;
-    jfieldID    data;
-} gSoundModelFields;
-
-static const char* const kGenericSoundModelClassPathName =
-                                     "android/hardware/soundtrigger/SoundTrigger$GenericSoundModel";
-static jclass gGenericSoundModelClass;
-
-static const char* const kKeyphraseClassPathName =
-                                     "android/hardware/soundtrigger/SoundTrigger$Keyphrase";
-static jclass gKeyphraseClass;
-static struct {
-    jfieldID id;
-    jfieldID recognitionModes;
-    jfieldID locale;
-    jfieldID text;
-    jfieldID users;
-} gKeyphraseFields;
-
-static const char* const kKeyphraseSoundModelClassPathName =
-                                 "android/hardware/soundtrigger/SoundTrigger$KeyphraseSoundModel";
-static jclass gKeyphraseSoundModelClass;
-static struct {
-    jfieldID    keyphrases;
-} gKeyphraseSoundModelFields;
-
-static const char* const kModelParamRangeClassPathName =
-                                "android/hardware/soundtrigger/SoundTrigger$ModelParamRange";
-static jclass gModelParamRangeClass;
-static jmethodID gModelParamRangeCstor;
-
-static const char* const kRecognitionConfigClassPathName =
-                                     "android/hardware/soundtrigger/SoundTrigger$RecognitionConfig";
-static jclass gRecognitionConfigClass;
-static struct {
-    jfieldID captureRequested;
-    jfieldID keyphrases;
-    jfieldID data;
-} gRecognitionConfigFields;
-
-static const char* const kRecognitionEventClassPathName =
-                                     "android/hardware/soundtrigger/SoundTrigger$RecognitionEvent";
-static jclass gRecognitionEventClass;
-static jmethodID   gRecognitionEventCstor;
-
-static const char* const kKeyphraseRecognitionEventClassPathName =
-                             "android/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionEvent";
-static jclass gKeyphraseRecognitionEventClass;
-static jmethodID   gKeyphraseRecognitionEventCstor;
-
-static const char* const kGenericRecognitionEventClassPathName =
-                             "android/hardware/soundtrigger/SoundTrigger$GenericRecognitionEvent";
-static jclass gGenericRecognitionEventClass;
-static jmethodID   gGenericRecognitionEventCstor;
-
-static const char* const kKeyphraseRecognitionExtraClassPathName =
-                             "android/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra";
-static jclass gKeyphraseRecognitionExtraClass;
-static jmethodID   gKeyphraseRecognitionExtraCstor;
-static struct {
-    jfieldID id;
-    jfieldID recognitionModes;
-    jfieldID coarseConfidenceLevel;
-    jfieldID confidenceLevels;
-} gKeyphraseRecognitionExtraFields;
-
-static const char* const kConfidenceLevelClassPathName =
-                             "android/hardware/soundtrigger/SoundTrigger$ConfidenceLevel";
-static jclass gConfidenceLevelClass;
-static jmethodID   gConfidenceLevelCstor;
-static struct {
-    jfieldID userId;
-    jfieldID confidenceLevel;
-} gConfidenceLevelFields;
-
-static const char* const kAudioFormatClassPathName =
-                             "android/media/AudioFormat";
-static jclass gAudioFormatClass;
-static jmethodID gAudioFormatCstor;
-
-static const char* const kSoundModelEventClassPathName =
-                                     "android/hardware/soundtrigger/SoundTrigger$SoundModelEvent";
-static jclass gSoundModelEventClass;
-static jmethodID   gSoundModelEventCstor;
-
-static Mutex gLock;
-
-enum {
-    SOUNDTRIGGER_STATUS_OK = 0,
-    SOUNDTRIGGER_STATUS_ERROR = INT_MIN,
-    SOUNDTRIGGER_PERMISSION_DENIED = -1,
-    SOUNDTRIGGER_STATUS_NO_INIT = -19,
-    SOUNDTRIGGER_STATUS_BAD_VALUE = -22,
-    SOUNDTRIGGER_STATUS_DEAD_OBJECT = -32,
-    SOUNDTRIGGER_INVALID_OPERATION = -38,
-};
-
-enum  {
-    SOUNDTRIGGER_EVENT_RECOGNITION = 1,
-    SOUNDTRIGGER_EVENT_SERVICE_DIED = 2,
-    SOUNDTRIGGER_EVENT_SOUNDMODEL = 3,
-    SOUNDTRIGGER_EVENT_SERVICE_STATE_CHANGE = 4,
-};
-
-static jint throwUnsupportedOperationException(JNIEnv *env)
-{
-    return env->ThrowNew(gUnsupportedOperationExceptionClass, nullptr);
-}
-
-static jint throwIllegalArgumentException(JNIEnv *env)
-{
-    return env->ThrowNew(gIllegalArgumentExceptionClass, nullptr);
-}
-
-// ----------------------------------------------------------------------------
-// ref-counted object for callbacks
-class JNISoundTriggerCallback: public SoundTriggerCallback
-{
-public:
-    JNISoundTriggerCallback(JNIEnv* env, jobject thiz, jobject weak_thiz);
-    ~JNISoundTriggerCallback();
-
-    virtual void onRecognitionEvent(struct sound_trigger_recognition_event *event);
-    virtual void onSoundModelEvent(struct sound_trigger_model_event *event);
-    virtual void onServiceStateChange(sound_trigger_service_state_t state);
-    virtual void onServiceDied();
-
-private:
-    jclass      mClass;     // Reference to SoundTrigger class
-    jobject     mObject;    // Weak ref to SoundTrigger Java object to call on
-};
-
-JNISoundTriggerCallback::JNISoundTriggerCallback(JNIEnv* env, jobject thiz, jobject weak_thiz)
-{
-
-    // Hold onto the SoundTriggerModule class for use in calling the static method
-    // that posts events to the application thread.
-    jclass clazz = env->GetObjectClass(thiz);
-    if (clazz == NULL) {
-        ALOGE("Can't find class %s", kModuleClassPathName);
-        return;
-    }
-    mClass = (jclass)env->NewGlobalRef(clazz);
-
-    // We use a weak reference so the SoundTriggerModule object can be garbage collected.
-    // The reference is only used as a proxy for callbacks.
-    mObject  = env->NewGlobalRef(weak_thiz);
-}
-
-JNISoundTriggerCallback::~JNISoundTriggerCallback()
-{
-    // remove global references
-    JNIEnv *env = AndroidRuntime::getJNIEnv();
-    env->DeleteGlobalRef(mObject);
-    env->DeleteGlobalRef(mClass);
-}
-
-void JNISoundTriggerCallback::onRecognitionEvent(struct sound_trigger_recognition_event *event)
-{
-    JNIEnv *env = AndroidRuntime::getJNIEnv();
-    jobject jEvent = NULL;
-    jbyteArray jData = NULL;
-
-    if (event->data_size) {
-        jData = env->NewByteArray(event->data_size);
-        jbyte *nData = env->GetByteArrayElements(jData, NULL);
-        memcpy(nData, (char *)event + event->data_offset, event->data_size);
-        env->ReleaseByteArrayElements(jData, nData, 0);
-    }
-
-    jobject jAudioFormat = NULL;
-    if (event->trigger_in_data || event->capture_available) {
-        jint channelMask = (jint)audio_channel_mask_get_bits(event->audio_config.channel_mask);
-        jint channelIndexMask = (jint)AUDIO_CHANNEL_NONE;
-
-        switch (audio_channel_mask_get_representation(event->audio_config.channel_mask)) {
-        case AUDIO_CHANNEL_REPRESENTATION_INDEX:
-            channelIndexMask = channelMask;
-            channelMask = (jint)AUDIO_CHANNEL_NONE;
-            break;
-        default:
-            break;
-        }
-        jAudioFormat = env->NewObject(gAudioFormatClass,
-                                    gAudioFormatCstor,
-                                    audioFormatFromNative(event->audio_config.format),
-                                    event->audio_config.sample_rate,
-                                    channelMask,
-                                    channelIndexMask);
-
-    }
-    if (event->type == SOUND_MODEL_TYPE_KEYPHRASE) {
-        struct sound_trigger_phrase_recognition_event *phraseEvent =
-                (struct sound_trigger_phrase_recognition_event *)event;
-
-        jobjectArray jExtras = env->NewObjectArray(phraseEvent->num_phrases,
-                                                  gKeyphraseRecognitionExtraClass, NULL);
-        if (jExtras == NULL) {
-            return;
-        }
-
-        for (size_t i = 0; i < phraseEvent->num_phrases; i++) {
-            jobjectArray jConfidenceLevels = env->NewObjectArray(
-                                                        phraseEvent->phrase_extras[i].num_levels,
-                                                        gConfidenceLevelClass, NULL);
-
-            if (jConfidenceLevels == NULL) {
-                return;
-            }
-            for (size_t j = 0; j < phraseEvent->phrase_extras[i].num_levels; j++) {
-                jobject jConfidenceLevel = env->NewObject(gConfidenceLevelClass,
-                                                  gConfidenceLevelCstor,
-                                                  phraseEvent->phrase_extras[i].levels[j].user_id,
-                                                  phraseEvent->phrase_extras[i].levels[j].level);
-                env->SetObjectArrayElement(jConfidenceLevels, j, jConfidenceLevel);
-                env->DeleteLocalRef(jConfidenceLevel);
-            }
-
-            jobject jNewExtra = env->NewObject(gKeyphraseRecognitionExtraClass,
-                                               gKeyphraseRecognitionExtraCstor,
-                                               phraseEvent->phrase_extras[i].id,
-                                               phraseEvent->phrase_extras[i].recognition_modes,
-                                               phraseEvent->phrase_extras[i].confidence_level,
-                                               jConfidenceLevels);
-
-            if (jNewExtra == NULL) {
-                return;
-            }
-            env->SetObjectArrayElement(jExtras, i, jNewExtra);
-            env->DeleteLocalRef(jNewExtra);
-            env->DeleteLocalRef(jConfidenceLevels);
-        }
-        jEvent = env->NewObject(gKeyphraseRecognitionEventClass, gKeyphraseRecognitionEventCstor,
-                                event->status, event->model, event->capture_available,
-                                event->capture_session, event->capture_delay_ms,
-                                event->capture_preamble_ms, event->trigger_in_data,
-                                jAudioFormat, jData, jExtras);
-        env->DeleteLocalRef(jExtras);
-    } else if (event->type == SOUND_MODEL_TYPE_GENERIC) {
-        jEvent = env->NewObject(gGenericRecognitionEventClass, gGenericRecognitionEventCstor,
-                                event->status, event->model, event->capture_available,
-                                event->capture_session, event->capture_delay_ms,
-                                event->capture_preamble_ms, event->trigger_in_data,
-                                jAudioFormat, jData);
-    } else {
-        jEvent = env->NewObject(gRecognitionEventClass, gRecognitionEventCstor,
-                                event->status, event->model, event->capture_available,
-                                event->capture_session, event->capture_delay_ms,
-                                event->capture_preamble_ms, event->trigger_in_data,
-                                jAudioFormat, jData);
-    }
-
-    if (jAudioFormat != NULL) {
-        env->DeleteLocalRef(jAudioFormat);
-    }
-    if (jData != NULL) {
-        env->DeleteLocalRef(jData);
-    }
-
-    env->CallStaticVoidMethod(mClass, gPostEventFromNative, mObject,
-                              SOUNDTRIGGER_EVENT_RECOGNITION, 0, 0, jEvent);
-
-    env->DeleteLocalRef(jEvent);
-    if (env->ExceptionCheck()) {
-        ALOGW("An exception occurred while notifying an event.");
-        env->ExceptionClear();
-    }
-}
-
-void JNISoundTriggerCallback::onSoundModelEvent(struct sound_trigger_model_event *event)
-{
-    JNIEnv *env = AndroidRuntime::getJNIEnv();
-    jobject jEvent = NULL;
-    jbyteArray jData = NULL;
-
-    if (event->data_size) {
-        jData = env->NewByteArray(event->data_size);
-        jbyte *nData = env->GetByteArrayElements(jData, NULL);
-        memcpy(nData, (char *)event + event->data_offset, event->data_size);
-        env->ReleaseByteArrayElements(jData, nData, 0);
-    }
-
-    jEvent = env->NewObject(gSoundModelEventClass, gSoundModelEventCstor,
-                            event->status, event->model, jData);
-
-    env->DeleteLocalRef(jData);
-    env->CallStaticVoidMethod(mClass, gPostEventFromNative, mObject,
-                              SOUNDTRIGGER_EVENT_SOUNDMODEL, 0, 0, jEvent);
-    env->DeleteLocalRef(jEvent);
-    if (env->ExceptionCheck()) {
-        ALOGW("An exception occurred while notifying an event.");
-        env->ExceptionClear();
-    }
-}
-
-void JNISoundTriggerCallback::onServiceStateChange(sound_trigger_service_state_t state)
-{
-    JNIEnv *env = AndroidRuntime::getJNIEnv();
-    env->CallStaticVoidMethod(mClass, gPostEventFromNative, mObject,
-                                        SOUNDTRIGGER_EVENT_SERVICE_STATE_CHANGE, state, 0, NULL);
-    if (env->ExceptionCheck()) {
-        ALOGW("An exception occurred while notifying an event.");
-        env->ExceptionClear();
-    }
-}
-
-void JNISoundTriggerCallback::onServiceDied()
-{
-    JNIEnv *env = AndroidRuntime::getJNIEnv();
-
-    env->CallStaticVoidMethod(mClass, gPostEventFromNative, mObject,
-                              SOUNDTRIGGER_EVENT_SERVICE_DIED, 0, 0, NULL);
-    if (env->ExceptionCheck()) {
-        ALOGW("An exception occurred while notifying an event.");
-        env->ExceptionClear();
-    }
-}
-
-// ----------------------------------------------------------------------------
-
-static sp<SoundTrigger> getSoundTrigger(JNIEnv* env, jobject thiz)
-{
-    Mutex::Autolock l(gLock);
-    SoundTrigger* const st = (SoundTrigger*)env->GetLongField(thiz,
-                                                         gModuleFields.mNativeContext);
-    return sp<SoundTrigger>(st);
-}
-
-static sp<SoundTrigger> setSoundTrigger(JNIEnv* env, jobject thiz, const sp<SoundTrigger>& module)
-{
-    Mutex::Autolock l(gLock);
-    sp<SoundTrigger> old = (SoundTrigger*)env->GetLongField(thiz,
-                                                         gModuleFields.mNativeContext);
-    if (module.get()) {
-        module->incStrong((void*)setSoundTrigger);
-    }
-    if (old != 0) {
-        old->decStrong((void*)setSoundTrigger);
-    }
-    env->SetLongField(thiz, gModuleFields.mNativeContext, (jlong)module.get());
-    return old;
-}
-
-
-static jint
-android_hardware_SoundTrigger_listModules(JNIEnv *env, jobject clazz,
-                                          jstring opPackageName, jobject jModules)
-{
-    ALOGV("listModules");
-
-    if (jModules == NULL) {
-        ALOGE("listModules NULL AudioPatch ArrayList");
-        return SOUNDTRIGGER_STATUS_BAD_VALUE;
-    }
-    if (!env->IsInstanceOf(jModules, gArrayListClass)) {
-        ALOGE("listModules not an arraylist");
-        return SOUNDTRIGGER_STATUS_BAD_VALUE;
-    }
-
-    unsigned int numModules = 0;
-    struct sound_trigger_module_descriptor *nModules = NULL;
-
-    ScopedUtfChars opPackageNameStr(env, opPackageName);
-    const String16 opPackageNameString16 = String16(opPackageNameStr.c_str());
-
-    status_t status = SoundTrigger::listModules(opPackageNameString16, nModules, &numModules);
-    if (status != NO_ERROR || numModules == 0) {
-        return (jint)status;
-    }
-
-    nModules = (struct sound_trigger_module_descriptor *)
-                            calloc(numModules, sizeof(struct sound_trigger_module_descriptor));
-
-    status = SoundTrigger::listModules(opPackageNameString16, nModules, &numModules);
-    ALOGV("listModules SoundTrigger::listModules status %d numModules %d", status, numModules);
-
-    if (status != NO_ERROR) {
-        numModules = 0;
-    }
-
-    for (size_t i = 0; i < numModules; i++) {
-        char str[SOUND_TRIGGER_MAX_STRING_LEN];
-
-        jstring implementor = env->NewStringUTF(nModules[i].properties.implementor);
-        jstring description = env->NewStringUTF(nModules[i].properties.description);
-        SoundTrigger::guidToString(&nModules[i].properties.uuid,
-                                   str,
-                                   SOUND_TRIGGER_MAX_STRING_LEN);
-        jstring uuid = env->NewStringUTF(str);
-
-        ALOGV("listModules module %zu id %d description %s maxSoundModels %d",
-              i, nModules[i].handle, nModules[i].properties.description,
-              nModules[i].properties.max_sound_models);
-
-        jobject newModuleDesc = env->NewObject(gModulePropertiesClass, gModulePropertiesCstor,
-                                               nModules[i].handle,
-                                               implementor, description, uuid,
-                                               nModules[i].properties.version,
-                                               nModules[i].properties.max_sound_models,
-                                               nModules[i].properties.max_key_phrases,
-                                               nModules[i].properties.max_users,
-                                               nModules[i].properties.recognition_modes,
-                                               nModules[i].properties.capture_transition,
-                                               nModules[i].properties.max_buffer_ms,
-                                               nModules[i].properties.concurrent_capture,
-                                               nModules[i].properties.power_consumption_mw,
-                                               nModules[i].properties.trigger_in_event);
-
-        env->DeleteLocalRef(implementor);
-        env->DeleteLocalRef(description);
-        env->DeleteLocalRef(uuid);
-        if (newModuleDesc == NULL) {
-            status = SOUNDTRIGGER_STATUS_ERROR;
-            goto exit;
-        }
-        env->CallBooleanMethod(jModules, gArrayListMethods.add, newModuleDesc);
-    }
-
-exit:
-    free(nModules);
-    return (jint) status;
-}
-
-static void
-android_hardware_SoundTrigger_setup(JNIEnv *env, jobject thiz,
-                                    jstring opPackageName, jobject weak_this)
-{
-    ALOGV("setup");
-
-    ScopedUtfChars opPackageNameStr(env, opPackageName);
-    const String16 opPackageNameString16 = String16(opPackageNameStr.c_str());
-
-    sp<JNISoundTriggerCallback> callback = new JNISoundTriggerCallback(env, thiz, weak_this);
-
-    sound_trigger_module_handle_t handle =
-            (sound_trigger_module_handle_t)env->GetIntField(thiz, gModuleFields.mId);
-
-    sp<SoundTrigger> module = SoundTrigger::attach(opPackageNameString16, handle, callback);
-    if (module == 0) {
-        return;
-    }
-
-    setSoundTrigger(env, thiz, module);
-}
-
-static void
-android_hardware_SoundTrigger_detach(JNIEnv *env, jobject thiz)
-{
-    ALOGV("detach");
-    sp<SoundTrigger> module = setSoundTrigger(env, thiz, 0);
-    ALOGV("detach module %p", module.get());
-    if (module != 0) {
-        ALOGV("detach module->detach()");
-        module->detach();
-    }
-}
-
-static void
-android_hardware_SoundTrigger_finalize(JNIEnv *env, jobject thiz)
-{
-    ALOGV("finalize");
-    sp<SoundTrigger> module = getSoundTrigger(env, thiz);
-    if (module != 0) {
-        ALOGW("SoundTrigger finalized without being detached");
-    }
-    android_hardware_SoundTrigger_detach(env, thiz);
-}
-
-static jint
-android_hardware_SoundTrigger_loadSoundModel(JNIEnv *env, jobject thiz,
-                                             jobject jSoundModel, jintArray jHandle)
-{
-    jint status = SOUNDTRIGGER_STATUS_OK;
-    jbyte *nData = NULL;
-    struct sound_trigger_sound_model *nSoundModel;
-    jbyteArray jData;
-    sp<MemoryDealer> memoryDealer;
-    sp<IMemory> memory;
-    size_t size;
-    sound_model_handle_t handle = 0;
-    jobject jUuid;
-    jstring jUuidString;
-    const char *nUuidString;
-
-    ALOGV("loadSoundModel");
-    sp<SoundTrigger> module = getSoundTrigger(env, thiz);
-    if (module == NULL) {
-        return SOUNDTRIGGER_STATUS_ERROR;
-    }
-    if (jHandle == NULL) {
-        return SOUNDTRIGGER_STATUS_BAD_VALUE;
-    }
-    jsize jHandleLen = env->GetArrayLength(jHandle);
-    if (jHandleLen == 0) {
-        return SOUNDTRIGGER_STATUS_BAD_VALUE;
-    }
-    jint *nHandle = env->GetIntArrayElements(jHandle, NULL);
-    if (nHandle == NULL) {
-        return SOUNDTRIGGER_STATUS_ERROR;
-    }
-    if (!env->IsInstanceOf(jSoundModel, gSoundModelClass)) {
-        status = SOUNDTRIGGER_STATUS_BAD_VALUE;
-        goto exit;
-    }
-    size_t offset;
-    sound_trigger_sound_model_type_t type;
-    if (env->IsInstanceOf(jSoundModel, gKeyphraseSoundModelClass)) {
-        offset = sizeof(struct sound_trigger_phrase_sound_model);
-        type = SOUND_MODEL_TYPE_KEYPHRASE;
-    } else if (env->IsInstanceOf(jSoundModel, gGenericSoundModelClass)) {
-        offset = sizeof(struct sound_trigger_generic_sound_model);
-        type = SOUND_MODEL_TYPE_GENERIC;
-    } else {
-        offset = sizeof(struct sound_trigger_sound_model);
-        type = SOUND_MODEL_TYPE_UNKNOWN;
-    }
-
-    jUuid = env->GetObjectField(jSoundModel, gSoundModelFields.uuid);
-    jUuidString = (jstring)env->CallObjectMethod(jUuid, gUUIDMethods.toString);
-    nUuidString = env->GetStringUTFChars(jUuidString, NULL);
-    sound_trigger_uuid_t nUuid;
-    SoundTrigger::stringToGuid(nUuidString, &nUuid);
-    env->ReleaseStringUTFChars(jUuidString, nUuidString);
-    env->DeleteLocalRef(jUuidString);
-
-    sound_trigger_uuid_t nVendorUuid;
-    jUuid = env->GetObjectField(jSoundModel, gSoundModelFields.vendorUuid);
-    if (jUuid != NULL) {
-        jUuidString = (jstring)env->CallObjectMethod(jUuid, gUUIDMethods.toString);
-        nUuidString = env->GetStringUTFChars(jUuidString, NULL);
-        SoundTrigger::stringToGuid(nUuidString, &nVendorUuid);
-        env->ReleaseStringUTFChars(jUuidString, nUuidString);
-        env->DeleteLocalRef(jUuidString);
-    } else {
-        SoundTrigger::stringToGuid("00000000-0000-0000-0000-000000000000", &nVendorUuid);
-    }
-
-    jData = (jbyteArray)env->GetObjectField(jSoundModel, gSoundModelFields.data);
-    if (jData == NULL) {
-        status = SOUNDTRIGGER_STATUS_BAD_VALUE;
-        goto exit;
-    }
-    size = env->GetArrayLength(jData);
-
-    nData = env->GetByteArrayElements(jData, NULL);
-    if (jData == NULL) {
-        status = SOUNDTRIGGER_STATUS_ERROR;
-        goto exit;
-    }
-
-    memoryDealer = new MemoryDealer(offset + size, "SoundTrigge-JNI::LoadModel");
-    if (memoryDealer == 0) {
-        status = SOUNDTRIGGER_STATUS_ERROR;
-        goto exit;
-    }
-    memory = memoryDealer->allocate(offset + size);
-    if (memory == 0 || memory->unsecurePointer() == NULL) {
-        status = SOUNDTRIGGER_STATUS_ERROR;
-        goto exit;
-    }
-
-    nSoundModel = (struct sound_trigger_sound_model *)memory->unsecurePointer();
-
-    nSoundModel->type = type;
-    nSoundModel->uuid = nUuid;
-    nSoundModel->vendor_uuid = nVendorUuid;
-    nSoundModel->data_size = size;
-    nSoundModel->data_offset = offset;
-    memcpy((char *)nSoundModel + offset, nData, size);
-    if (type == SOUND_MODEL_TYPE_KEYPHRASE) {
-        struct sound_trigger_phrase_sound_model *phraseModel =
-                (struct sound_trigger_phrase_sound_model *)nSoundModel;
-
-        jobjectArray jPhrases =
-            (jobjectArray)env->GetObjectField(jSoundModel, gKeyphraseSoundModelFields.keyphrases);
-        if (jPhrases == NULL) {
-            status = SOUNDTRIGGER_STATUS_BAD_VALUE;
-            goto exit;
-        }
-
-        size_t numPhrases = env->GetArrayLength(jPhrases);
-        phraseModel->num_phrases = numPhrases;
-        ALOGV("loadSoundModel numPhrases %zu", numPhrases);
-        for (size_t i = 0; i < numPhrases; i++) {
-            jobject jPhrase = env->GetObjectArrayElement(jPhrases, i);
-            phraseModel->phrases[i].id =
-                                    env->GetIntField(jPhrase,gKeyphraseFields.id);
-            phraseModel->phrases[i].recognition_mode =
-                                    env->GetIntField(jPhrase,gKeyphraseFields.recognitionModes);
-
-            jintArray jUsers = (jintArray)env->GetObjectField(jPhrase, gKeyphraseFields.users);
-            phraseModel->phrases[i].num_users = env->GetArrayLength(jUsers);
-            jint *nUsers = env->GetIntArrayElements(jUsers, NULL);
-            memcpy(phraseModel->phrases[i].users,
-                   nUsers,
-                   phraseModel->phrases[i].num_users * sizeof(int));
-            env->ReleaseIntArrayElements(jUsers, nUsers, 0);
-            env->DeleteLocalRef(jUsers);
-
-            jstring jLocale = (jstring)env->GetObjectField(jPhrase, gKeyphraseFields.locale);
-            const char *nLocale = env->GetStringUTFChars(jLocale, NULL);
-            strncpy(phraseModel->phrases[i].locale,
-                    nLocale,
-                    SOUND_TRIGGER_MAX_LOCALE_LEN);
-            jstring jText = (jstring)env->GetObjectField(jPhrase, gKeyphraseFields.text);
-            const char *nText = env->GetStringUTFChars(jText, NULL);
-            strncpy(phraseModel->phrases[i].text,
-                    nText,
-                    SOUND_TRIGGER_MAX_STRING_LEN);
-
-            env->ReleaseStringUTFChars(jLocale, nLocale);
-            env->DeleteLocalRef(jLocale);
-            env->ReleaseStringUTFChars(jText, nText);
-            env->DeleteLocalRef(jText);
-            ALOGV("loadSoundModel phrases %zu text %s locale %s",
-                  i, phraseModel->phrases[i].text, phraseModel->phrases[i].locale);
-            env->DeleteLocalRef(jPhrase);
-        }
-        env->DeleteLocalRef(jPhrases);
-    } else if (type == SOUND_MODEL_TYPE_GENERIC) {
-        /* No initialization needed */
-    }
-    status = module->loadSoundModel(memory, &handle);
-    ALOGV("loadSoundModel status %d handle %d", status, handle);
-
-exit:
-    if (nHandle != NULL) {
-        nHandle[0] = (jint)handle;
-        env->ReleaseIntArrayElements(jHandle, nHandle, NULL);
-    }
-    if (nData != NULL) {
-        env->ReleaseByteArrayElements(jData, nData, NULL);
-    }
-    return status;
-}
-
-static jint
-android_hardware_SoundTrigger_unloadSoundModel(JNIEnv *env, jobject thiz,
-                                               jint jHandle)
-{
-    jint status = SOUNDTRIGGER_STATUS_OK;
-    ALOGV("unloadSoundModel");
-    sp<SoundTrigger> module = getSoundTrigger(env, thiz);
-    if (module == NULL) {
-        return SOUNDTRIGGER_STATUS_ERROR;
-    }
-    status = module->unloadSoundModel((sound_model_handle_t)jHandle);
-
-    return status;
-}
-
-static jint
-android_hardware_SoundTrigger_startRecognition(JNIEnv *env, jobject thiz,
-                                               jint jHandle, jobject jConfig)
-{
-    jint status = SOUNDTRIGGER_STATUS_OK;
-    ALOGV("startRecognition");
-    sp<SoundTrigger> module = getSoundTrigger(env, thiz);
-    if (module == NULL) {
-        return SOUNDTRIGGER_STATUS_ERROR;
-    }
-
-    if (!env->IsInstanceOf(jConfig, gRecognitionConfigClass)) {
-        return SOUNDTRIGGER_STATUS_BAD_VALUE;
-    }
-
-    jbyteArray jData = (jbyteArray)env->GetObjectField(jConfig, gRecognitionConfigFields.data);
-    jsize dataSize = 0;
-    jbyte *nData = NULL;
-    if (jData != NULL) {
-        dataSize = env->GetArrayLength(jData);
-        if (dataSize == 0) {
-            return SOUNDTRIGGER_STATUS_BAD_VALUE;
-        }
-        nData = env->GetByteArrayElements(jData, NULL);
-        if (nData == NULL) {
-            return SOUNDTRIGGER_STATUS_ERROR;
-        }
-    }
-
-    size_t totalSize = sizeof(struct sound_trigger_recognition_config) + dataSize;
-    sp<MemoryDealer> memoryDealer =
-            new MemoryDealer(totalSize, "SoundTrigge-JNI::StartRecognition");
-    if (memoryDealer == 0) {
-        return SOUNDTRIGGER_STATUS_ERROR;
-    }
-    sp<IMemory> memory = memoryDealer->allocate(totalSize);
-    if (memory == 0 || memory->unsecurePointer() == NULL) {
-        return SOUNDTRIGGER_STATUS_ERROR;
-    }
-    if (dataSize != 0) {
-        memcpy((char *)memory->unsecurePointer() + sizeof(struct sound_trigger_recognition_config),
-                nData,
-                dataSize);
-        env->ReleaseByteArrayElements(jData, nData, 0);
-    }
-    env->DeleteLocalRef(jData);
-    struct sound_trigger_recognition_config *config =
-                                    (struct sound_trigger_recognition_config *)memory->unsecurePointer();
-    config->data_size = dataSize;
-    config->data_offset = sizeof(struct sound_trigger_recognition_config);
-    config->capture_requested = env->GetBooleanField(jConfig,
-                                                 gRecognitionConfigFields.captureRequested);
-
-    config->num_phrases = 0;
-    jobjectArray jPhrases =
-        (jobjectArray)env->GetObjectField(jConfig, gRecognitionConfigFields.keyphrases);
-    if (jPhrases != NULL) {
-        config->num_phrases = env->GetArrayLength(jPhrases);
-    }
-    ALOGV("startRecognition num phrases %d", config->num_phrases);
-    for (size_t i = 0; i < config->num_phrases; i++) {
-        jobject jPhrase = env->GetObjectArrayElement(jPhrases, i);
-        config->phrases[i].id = env->GetIntField(jPhrase,
-                                                gKeyphraseRecognitionExtraFields.id);
-        config->phrases[i].recognition_modes = env->GetIntField(jPhrase,
-                                                gKeyphraseRecognitionExtraFields.recognitionModes);
-        config->phrases[i].confidence_level = env->GetIntField(jPhrase,
-                                            gKeyphraseRecognitionExtraFields.coarseConfidenceLevel);
-        config->phrases[i].num_levels = 0;
-        jobjectArray jConfidenceLevels = (jobjectArray)env->GetObjectField(jPhrase,
-                                                gKeyphraseRecognitionExtraFields.confidenceLevels);
-        if (jConfidenceLevels != NULL) {
-            config->phrases[i].num_levels = env->GetArrayLength(jConfidenceLevels);
-        }
-        ALOGV("startRecognition phrase %zu num_levels %d", i, config->phrases[i].num_levels);
-        for (size_t j = 0; j < config->phrases[i].num_levels; j++) {
-            jobject jConfidenceLevel = env->GetObjectArrayElement(jConfidenceLevels, j);
-            config->phrases[i].levels[j].user_id = env->GetIntField(jConfidenceLevel,
-                                                                    gConfidenceLevelFields.userId);
-            config->phrases[i].levels[j].level = env->GetIntField(jConfidenceLevel,
-                                                          gConfidenceLevelFields.confidenceLevel);
-            env->DeleteLocalRef(jConfidenceLevel);
-        }
-        ALOGV("startRecognition phrases %zu", i);
-        env->DeleteLocalRef(jConfidenceLevels);
-        env->DeleteLocalRef(jPhrase);
-    }
-    env->DeleteLocalRef(jPhrases);
-
-    status = module->startRecognition(jHandle, memory);
-    return status;
-}
-
-static jint
-android_hardware_SoundTrigger_stopRecognition(JNIEnv *env, jobject thiz,
-                                               jint jHandle)
-{
-    jint status = SOUNDTRIGGER_STATUS_OK;
-    ALOGV("stopRecognition");
-    sp<SoundTrigger> module = getSoundTrigger(env, thiz);
-    if (module == NULL) {
-        return SOUNDTRIGGER_STATUS_ERROR;
-    }
-    status = module->stopRecognition(jHandle);
-    return status;
-}
-
-static jint
-android_hardware_SoundTrigger_getModelState(JNIEnv *env, jobject thiz,
-                                            jint jHandle)
-{
-    jint status = SOUNDTRIGGER_STATUS_OK;
-    ALOGV("getModelState");
-    sp<SoundTrigger> module = getSoundTrigger(env, thiz);
-    if (module == NULL) {
-        return SOUNDTRIGGER_STATUS_ERROR;
-    }
-    status = module->getModelState(jHandle);
-    return status;
-}
-
-static jint
-android_hardware_SoundTrigger_setParameter(JNIEnv *env, jobject thiz,
-                                            jint jHandle, jint jModelParam, jint jValue)
-{
-    ALOGV("setParameter");
-    sp<SoundTrigger> module = getSoundTrigger(env, thiz);
-    if (module == NULL) {
-        return SOUNDTRIGGER_STATUS_NO_INIT;
-    }
-    return module->setParameter(jHandle, (sound_trigger_model_parameter_t) jModelParam, jValue);
-}
-
-static jint
-android_hardware_SoundTrigger_getParameter(JNIEnv *env, jobject thiz,
-                                            jint jHandle, jint jModelParam)
-{
-    ALOGV("getParameter");
-    sp<SoundTrigger> module = getSoundTrigger(env, thiz);
-    if (module == NULL) {
-        throwUnsupportedOperationException(env);
-        return -1;
-    }
-
-    jint nValue;
-    jint status = module->getParameter(jHandle,
-            (sound_trigger_model_parameter_t) jModelParam, &nValue);
-
-    switch (status) {
-        case 0:
-            return nValue;
-        case -EINVAL:
-            throwIllegalArgumentException(env);
-            break;
-        default:
-            throwUnsupportedOperationException(env);
-            break;
-    }
-
-    return -1;
-}
-
-static jobject
-android_hardware_SoundTrigger_queryParameter(JNIEnv *env, jobject thiz,
-                                            jint jHandle, jint jModelParam)
-{
-    ALOGV("queryParameter");
-    sp<SoundTrigger> module = getSoundTrigger(env, thiz);
-    if (module == nullptr) {
-        return nullptr;
-    }
-
-    sound_trigger_model_parameter_range_t nRange;
-    jint nValue = module->queryParameter(jHandle,
-            (sound_trigger_model_parameter_t) jModelParam, &nRange);
-
-    if (nValue != 0) {
-        ALOGE("failed to query parameter error code: %d", nValue);
-        return nullptr;
-    }
-
-    return env->NewObject(gModelParamRangeClass, gModelParamRangeCstor, nRange.start, nRange.end);
-}
-
-static const JNINativeMethod gMethods[] = {
-    {"listModules",
-        "(Ljava/lang/String;Ljava/util/ArrayList;)I",
-        (void *)android_hardware_SoundTrigger_listModules},
-};
-
-
-static const JNINativeMethod gModuleMethods[] = {
-    {"native_setup",
-        "(Ljava/lang/String;Ljava/lang/Object;)V",
-        (void *)android_hardware_SoundTrigger_setup},
-    {"native_finalize",
-        "()V",
-        (void *)android_hardware_SoundTrigger_finalize},
-    {"detach",
-        "()V",
-        (void *)android_hardware_SoundTrigger_detach},
-    {"loadSoundModel",
-        "(Landroid/hardware/soundtrigger/SoundTrigger$SoundModel;[I)I",
-        (void *)android_hardware_SoundTrigger_loadSoundModel},
-    {"unloadSoundModel",
-        "(I)I",
-        (void *)android_hardware_SoundTrigger_unloadSoundModel},
-    {"startRecognition",
-        "(ILandroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;)I",
-        (void *)android_hardware_SoundTrigger_startRecognition},
-    {"stopRecognition",
-        "(I)I",
-        (void *)android_hardware_SoundTrigger_stopRecognition},
-    {"getModelState",
-        "(I)I",
-        (void *)android_hardware_SoundTrigger_getModelState},
-    {"setParameter",
-         "(III)I",
-         (void *)android_hardware_SoundTrigger_setParameter},
-    {"getParameter",
-         "(II)I",
-         (void *)android_hardware_SoundTrigger_getParameter},
-    {"queryParameter",
-         "(II)Landroid/hardware/soundtrigger/SoundTrigger$ModelParamRange;",
-         (void *)android_hardware_SoundTrigger_queryParameter}
-};
-
-int register_android_hardware_SoundTrigger(JNIEnv *env)
-{
-    jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList");
-    gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass);
-    gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z");
-
-    jclass uuidClass = FindClassOrDie(env, "java/util/UUID");
-    gUUIDClass = MakeGlobalRefOrDie(env, uuidClass);
-    gUUIDMethods.toString = GetMethodIDOrDie(env, uuidClass, "toString", "()Ljava/lang/String;");
-
-    jclass exUClass = FindClassOrDie(env, kUnsupportedOperationExceptionClassPathName);
-    gUnsupportedOperationExceptionClass = MakeGlobalRefOrDie(env, exUClass);
-
-    jclass exIClass = FindClassOrDie(env, kIllegalArgumentExceptionClassPathName);
-    gIllegalArgumentExceptionClass = MakeGlobalRefOrDie(env, exIClass);
-
-    jclass lClass = FindClassOrDie(env, kSoundTriggerClassPathName);
-    gSoundTriggerClass = MakeGlobalRefOrDie(env, lClass);
-
-    jclass moduleClass = FindClassOrDie(env, kModuleClassPathName);
-    gModuleClass = MakeGlobalRefOrDie(env, moduleClass);
-    gPostEventFromNative = GetStaticMethodIDOrDie(env, moduleClass, "postEventFromNative",
-                                                  "(Ljava/lang/Object;IIILjava/lang/Object;)V");
-    gModuleFields.mNativeContext = GetFieldIDOrDie(env, moduleClass, "mNativeContext", "J");
-    gModuleFields.mId = GetFieldIDOrDie(env, moduleClass, "mId", "I");
-
-    jclass modulePropertiesClass = FindClassOrDie(env, kModulePropertiesClassPathName);
-    gModulePropertiesClass = MakeGlobalRefOrDie(env, modulePropertiesClass);
-    gModulePropertiesCstor = GetMethodIDOrDie(env, modulePropertiesClass, "<init>",
-            "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;IIIIIZIZIZ)V");
-
-    jclass soundModelClass = FindClassOrDie(env, kSoundModelClassPathName);
-    gSoundModelClass = MakeGlobalRefOrDie(env, soundModelClass);
-    gSoundModelFields.uuid = GetFieldIDOrDie(env, soundModelClass, "uuid", "Ljava/util/UUID;");
-    gSoundModelFields.vendorUuid = GetFieldIDOrDie(env, soundModelClass, "vendorUuid",
-                                                   "Ljava/util/UUID;");
-    gSoundModelFields.data = GetFieldIDOrDie(env, soundModelClass, "data", "[B");
-
-    jclass genericSoundModelClass = FindClassOrDie(env, kGenericSoundModelClassPathName);
-    gGenericSoundModelClass = MakeGlobalRefOrDie(env, genericSoundModelClass);
-
-    jclass keyphraseClass = FindClassOrDie(env, kKeyphraseClassPathName);
-    gKeyphraseClass = MakeGlobalRefOrDie(env, keyphraseClass);
-    gKeyphraseFields.id = GetFieldIDOrDie(env, keyphraseClass, "id", "I");
-    gKeyphraseFields.recognitionModes = GetFieldIDOrDie(env, keyphraseClass, "recognitionModes",
-                                                        "I");
-    gKeyphraseFields.locale = GetFieldIDOrDie(env, keyphraseClass, "locale", "Ljava/lang/String;");
-    gKeyphraseFields.text = GetFieldIDOrDie(env, keyphraseClass, "text", "Ljava/lang/String;");
-    gKeyphraseFields.users = GetFieldIDOrDie(env, keyphraseClass, "users", "[I");
-
-    jclass keyphraseSoundModelClass = FindClassOrDie(env, kKeyphraseSoundModelClassPathName);
-    gKeyphraseSoundModelClass = MakeGlobalRefOrDie(env, keyphraseSoundModelClass);
-    gKeyphraseSoundModelFields.keyphrases = GetFieldIDOrDie(env, keyphraseSoundModelClass,
-                                         "keyphrases",
-                                         "[Landroid/hardware/soundtrigger/SoundTrigger$Keyphrase;");
-
-    jclass modelParamRangeClass = FindClassOrDie(env, kModelParamRangeClassPathName);
-    gModelParamRangeClass = MakeGlobalRefOrDie(env, modelParamRangeClass);
-    gModelParamRangeCstor = GetMethodIDOrDie(env, modelParamRangeClass, "<init>", "(II)V");
-
-    jclass recognitionEventClass = FindClassOrDie(env, kRecognitionEventClassPathName);
-    gRecognitionEventClass = MakeGlobalRefOrDie(env, recognitionEventClass);
-    gRecognitionEventCstor = GetMethodIDOrDie(env, recognitionEventClass, "<init>",
-                                              "(IIZIIIZLandroid/media/AudioFormat;[B)V");
-
-    jclass keyphraseRecognitionEventClass = FindClassOrDie(env,
-                                                           kKeyphraseRecognitionEventClassPathName);
-    gKeyphraseRecognitionEventClass = MakeGlobalRefOrDie(env, keyphraseRecognitionEventClass);
-    gKeyphraseRecognitionEventCstor = GetMethodIDOrDie(env, keyphraseRecognitionEventClass, "<init>",
-              "(IIZIIIZLandroid/media/AudioFormat;[B[Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;)V");
-
-    jclass genericRecognitionEventClass = FindClassOrDie(env,
-                                                           kGenericRecognitionEventClassPathName);
-    gGenericRecognitionEventClass = MakeGlobalRefOrDie(env, genericRecognitionEventClass);
-    gGenericRecognitionEventCstor = GetMethodIDOrDie(env, genericRecognitionEventClass, "<init>",
-                                              "(IIZIIIZLandroid/media/AudioFormat;[B)V");
-
-    jclass keyRecognitionConfigClass = FindClassOrDie(env, kRecognitionConfigClassPathName);
-    gRecognitionConfigClass = MakeGlobalRefOrDie(env, keyRecognitionConfigClass);
-    gRecognitionConfigFields.captureRequested = GetFieldIDOrDie(env, keyRecognitionConfigClass,
-                                                                "captureRequested", "Z");
-    gRecognitionConfigFields.keyphrases = GetFieldIDOrDie(env, keyRecognitionConfigClass,
-           "keyphrases", "[Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;");
-    gRecognitionConfigFields.data = GetFieldIDOrDie(env, keyRecognitionConfigClass, "data", "[B");
-
-    jclass keyphraseRecognitionExtraClass = FindClassOrDie(env,
-                                                           kKeyphraseRecognitionExtraClassPathName);
-    gKeyphraseRecognitionExtraClass = MakeGlobalRefOrDie(env, keyphraseRecognitionExtraClass);
-    gKeyphraseRecognitionExtraCstor = GetMethodIDOrDie(env, keyphraseRecognitionExtraClass,
-            "<init>", "(III[Landroid/hardware/soundtrigger/SoundTrigger$ConfidenceLevel;)V");
-    gKeyphraseRecognitionExtraFields.id = GetFieldIDOrDie(env, gKeyphraseRecognitionExtraClass,
-                                                          "id", "I");
-    gKeyphraseRecognitionExtraFields.recognitionModes = GetFieldIDOrDie(env,
-            gKeyphraseRecognitionExtraClass, "recognitionModes", "I");
-    gKeyphraseRecognitionExtraFields.coarseConfidenceLevel = GetFieldIDOrDie(env,
-            gKeyphraseRecognitionExtraClass, "coarseConfidenceLevel", "I");
-    gKeyphraseRecognitionExtraFields.confidenceLevels = GetFieldIDOrDie(env,
-            gKeyphraseRecognitionExtraClass, "confidenceLevels",
-            "[Landroid/hardware/soundtrigger/SoundTrigger$ConfidenceLevel;");
-
-    jclass confidenceLevelClass = FindClassOrDie(env, kConfidenceLevelClassPathName);
-    gConfidenceLevelClass = MakeGlobalRefOrDie(env, confidenceLevelClass);
-    gConfidenceLevelCstor = GetMethodIDOrDie(env, confidenceLevelClass, "<init>", "(II)V");
-    gConfidenceLevelFields.userId = GetFieldIDOrDie(env, confidenceLevelClass, "userId", "I");
-    gConfidenceLevelFields.confidenceLevel = GetFieldIDOrDie(env, confidenceLevelClass,
-                                                             "confidenceLevel", "I");
-
-    jclass audioFormatClass = FindClassOrDie(env, kAudioFormatClassPathName);
-    gAudioFormatClass = MakeGlobalRefOrDie(env, audioFormatClass);
-    gAudioFormatCstor = GetMethodIDOrDie(env, audioFormatClass, "<init>", "(IIII)V");
-
-    jclass soundModelEventClass = FindClassOrDie(env, kSoundModelEventClassPathName);
-    gSoundModelEventClass = MakeGlobalRefOrDie(env, soundModelEventClass);
-    gSoundModelEventCstor = GetMethodIDOrDie(env, soundModelEventClass, "<init>", "(II[B)V");
-
-
-    RegisterMethodsOrDie(env, kSoundTriggerClassPathName, gMethods, NELEM(gMethods));
-    return RegisterMethodsOrDie(env, kModuleClassPathName, gModuleMethods, NELEM(gModuleMethods));
-}