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

Commit 7092a561 authored by Nicholas Ambur's avatar Nicholas Ambur
Browse files

add audioCapabilities to SoundTrigger properties

Bug: 146363190
Test: atest SoundTriggerMiddlewareImplTest
&& GTS assist test suite

Change-Id: Ib8a3b809fa6738152d31499b5072a2e9d39ab0a0
parent 2f1b6c41
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -42684,14 +42684,19 @@ package android.service.voice {
    method public android.content.Intent createReEnrollIntent();
    method public android.content.Intent createUnEnrollIntent();
    method public int getParameter(int);
    method public int getSupportedAudioCapabilities();
    method public int getSupportedRecognitionModes();
    method @Nullable public android.service.voice.AlwaysOnHotwordDetector.ModelParamRange queryParameter(int);
    method public int setParameter(int, int);
    method public boolean startRecognition(int);
    method public boolean stopRecognition();
    field public static final int AUDIO_CAPABILITY_ECHO_CANCELLATION = 1; // 0x1
    field public static final int AUDIO_CAPABILITY_NOISE_SUPPRESSION = 2; // 0x2
    field public static final int MODEL_PARAM_THRESHOLD_FACTOR = 0; // 0x0
    field public static final int RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS = 2; // 0x2
    field public static final int RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO = 1; // 0x1
    field public static final int RECOGNITION_FLAG_ENABLE_AUDIO_ECHO_CANCELLATION = 4; // 0x4
    field public static final int RECOGNITION_FLAG_ENABLE_AUDIO_NOISE_SUPPRESSION = 8; // 0x8
    field public static final int RECOGNITION_MODE_USER_IDENTIFICATION = 2; // 0x2
    field public static final int RECOGNITION_MODE_VOICE_TRIGGER = 1; // 0x1
    field public static final int STATE_HARDWARE_UNAVAILABLE = -2; // 0xfffffffe
+5 −0
Original line number Diff line number Diff line
@@ -3566,7 +3566,10 @@ package android.hardware.soundtrigger {
  public static final class SoundTrigger.ModuleProperties implements android.os.Parcelable {
    method public int describeContents();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final int CAPABILITY_ECHO_CANCELLATION = 1; // 0x1
    field public static final int CAPABILITY_NOISE_SUPPRESSION = 2; // 0x2
    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.soundtrigger.SoundTrigger.ModuleProperties> CREATOR;
    field public final int audioCapabilities;
    field @NonNull public final String description;
    field public final int id;
    field @NonNull public final String implementor;
@@ -4357,6 +4360,8 @@ package android.media.soundtrigger {
    method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public boolean stopRecognition();
    field public static final int RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS = 2; // 0x2
    field public static final int RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO = 1; // 0x1
    field public static final int RECOGNITION_FLAG_ENABLE_AUDIO_ECHO_CANCELLATION = 4; // 0x4
    field public static final int RECOGNITION_FLAG_ENABLE_AUDIO_NOISE_SUPPRESSION = 8; // 0x8
  }
  public abstract static class SoundTriggerDetector.Callback {
+26 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.annotation.Nullable;
import android.hardware.soundtrigger.ModelParams;
import android.media.AudioFormat;
import android.media.audio.common.AudioConfig;
import android.media.soundtrigger_middleware.AudioCapabilities;
import android.media.soundtrigger_middleware.ConfidenceLevel;
import android.media.soundtrigger_middleware.ModelParameterRange;
import android.media.soundtrigger_middleware.Phrase;
@@ -56,7 +57,8 @@ class ConversionUtil {
                properties.maxBufferMs,
                properties.concurrentCapture,
                properties.powerConsumptionMw,
                properties.triggerInEvent
                properties.triggerInEvent,
                aidl2apiAudioCapabilities(properties.audioCapabilities)
        );
    }

@@ -145,6 +147,7 @@ class ConversionUtil {
                    apiConfig.keyphrases[i]);
        }
        aidlConfig.data = Arrays.copyOf(apiConfig.data, apiConfig.data.length);
        aidlConfig.audioCapabilities = api2aidlAudioCapabilities(apiConfig.audioCapabilities);
        return aidlConfig;
    }

@@ -326,4 +329,26 @@ class ConversionUtil {
        }
        return new SoundTrigger.ModelParamRange(aidlRange.minInclusive, aidlRange.maxInclusive);
    }

    public static int aidl2apiAudioCapabilities(int aidlCapabilities) {
        int result = 0;
        if ((aidlCapabilities & AudioCapabilities.ECHO_CANCELLATION) != 0) {
            result |= SoundTrigger.ModuleProperties.CAPABILITY_ECHO_CANCELLATION;
        }
        if ((aidlCapabilities & AudioCapabilities.NOISE_SUPPRESSION) != 0) {
            result |= SoundTrigger.ModuleProperties.CAPABILITY_NOISE_SUPPRESSION;
        }
        return result;
    }

    public static int api2aidlAudioCapabilities(int apiCapabilities) {
        int result = 0;
        if ((apiCapabilities & SoundTrigger.ModuleProperties.CAPABILITY_ECHO_CANCELLATION) != 0) {
            result |= AudioCapabilities.ECHO_CANCELLATION;
        }
        if ((apiCapabilities & SoundTrigger.ModuleProperties.CAPABILITY_NOISE_SUPPRESSION) != 0) {
            result |= AudioCapabilities.NOISE_SUPPRESSION;
        }
        return result;
    }
}
+63 −7
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static android.system.OsConstants.EPIPE;

import static java.util.Objects.requireNonNull;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -42,6 +43,8 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.UUID;
@@ -83,6 +86,30 @@ public class SoundTrigger {
     *
     ****************************************************************************/
    public static final class ModuleProperties implements Parcelable {

        /**
         * Bit field values of AudioCapabilities supported by the implemented HAL
         * driver.
         * @hide
         */
        @Retention(RetentionPolicy.SOURCE)
        @IntDef(flag = true, prefix = { "AUDIO_CAPABILITY_" }, value = {
                CAPABILITY_ECHO_CANCELLATION,
                CAPABILITY_NOISE_SUPPRESSION
        })
        public @interface AudioCapabilities {}

        /**
         * If set the underlying module supports AEC.
         * Describes bit field {@link ModuleProperties#audioCapabilities}
         */
        public static final int CAPABILITY_ECHO_CANCELLATION = 0x1;
        /**
         * If set, the underlying module supports noise suppression.
         * Describes bit field {@link ModuleProperties#audioCapabilities}
         */
        public static final int CAPABILITY_NOISE_SUPPRESSION = 0x2;

        /** Unique module ID provided by the native service */
        public final int id;

@@ -137,12 +164,19 @@ public class SoundTrigger {
         * recognition callback event */
        public final boolean returnsTriggerInEvent;

        /**
         * Bit field encoding of the AudioCapabilities
         * supported by the firmware.
         */
        @AudioCapabilities
        public final int audioCapabilities;

        ModuleProperties(int id, @NonNull String implementor, @NonNull String description,
                @NonNull String uuid, int version, @NonNull String supportedModelArch,
                int maxSoundModels, int maxKeyphrases, int maxUsers, int recognitionModes,
                boolean supportsCaptureTransition, int maxBufferMs,
                boolean supportsConcurrentCapture, int powerConsumptionMw,
                boolean returnsTriggerInEvent) {
                boolean returnsTriggerInEvent, int audioCapabilities) {
            this.id = id;
            this.implementor = requireNonNull(implementor);
            this.description = requireNonNull(description);
@@ -158,6 +192,7 @@ public class SoundTrigger {
            this.supportsConcurrentCapture = supportsConcurrentCapture;
            this.powerConsumptionMw = powerConsumptionMw;
            this.returnsTriggerInEvent = returnsTriggerInEvent;
            this.audioCapabilities = audioCapabilities;
        }

        public static final @android.annotation.NonNull Parcelable.Creator<ModuleProperties> CREATOR
@@ -187,10 +222,11 @@ public class SoundTrigger {
            boolean supportsConcurrentCapture = in.readByte() == 1;
            int powerConsumptionMw = in.readInt();
            boolean returnsTriggerInEvent = in.readByte() == 1;
            int audioCapabilities = in.readInt();
            return new ModuleProperties(id, implementor, description, uuid, version,
                    supportedModelArch, maxSoundModels, maxKeyphrases, maxUsers, recognitionModes,
                    supportsCaptureTransition, maxBufferMs, supportsConcurrentCapture,
                    powerConsumptionMw, returnsTriggerInEvent);
                    powerConsumptionMw, returnsTriggerInEvent, audioCapabilities);
        }

        @Override
@@ -210,6 +246,7 @@ public class SoundTrigger {
            dest.writeByte((byte) (supportsConcurrentCapture ? 1 : 0));
            dest.writeInt(powerConsumptionMw);
            dest.writeByte((byte) (returnsTriggerInEvent ? 1 : 0));
            dest.writeInt(audioCapabilities);
        }

        @Override
@@ -227,7 +264,8 @@ public class SoundTrigger {
                    + ", supportsCaptureTransition=" + supportsCaptureTransition + ", maxBufferMs="
                    + maxBufferMs + ", supportsConcurrentCapture=" + supportsConcurrentCapture
                    + ", powerConsumptionMw=" + powerConsumptionMw
                    + ", returnsTriggerInEvent=" + returnsTriggerInEvent + "]";
                    + ", returnsTriggerInEvent=" + returnsTriggerInEvent
                    + ", audioCapabilities=" + audioCapabilities + "]";
        }
    }

@@ -1049,13 +1087,27 @@ public class SoundTrigger {
        @NonNull
        public final byte[] data;

        @UnsupportedAppUsage
        /**
         * Bit field encoding of the AudioCapabilities
         * supported by the firmware.
         */
        @ModuleProperties.AudioCapabilities
        public final int audioCapabilities;

        public RecognitionConfig(boolean captureRequested, boolean allowMultipleTriggers,
                @Nullable KeyphraseRecognitionExtra[] keyphrases, @Nullable byte[] data) {
                @Nullable KeyphraseRecognitionExtra[] keyphrases, @Nullable byte[] data,
                int audioCapabilities) {
            this.captureRequested = captureRequested;
            this.allowMultipleTriggers = allowMultipleTriggers;
            this.keyphrases = keyphrases != null ? keyphrases : new KeyphraseRecognitionExtra[0];
            this.data = data != null ? data : new byte[0];
            this.audioCapabilities = audioCapabilities;
        }

        @UnsupportedAppUsage
        public RecognitionConfig(boolean captureRequested, boolean allowMultipleTriggers,
                @Nullable KeyphraseRecognitionExtra[] keyphrases, @Nullable byte[] data) {
            this(captureRequested, allowMultipleTriggers, keyphrases, data, 0);
        }

        public static final @android.annotation.NonNull Parcelable.Creator<RecognitionConfig> CREATOR
@@ -1075,7 +1127,9 @@ public class SoundTrigger {
            KeyphraseRecognitionExtra[] keyphrases =
                    in.createTypedArray(KeyphraseRecognitionExtra.CREATOR);
            byte[] data = in.readBlob();
            return new RecognitionConfig(captureRequested, allowMultipleTriggers, keyphrases, data);
            int audioCapabilities = in.readInt();
            return new RecognitionConfig(captureRequested, allowMultipleTriggers, keyphrases, data,
                    audioCapabilities);
        }

        @Override
@@ -1084,6 +1138,7 @@ public class SoundTrigger {
            dest.writeByte((byte) (allowMultipleTriggers ? 1 : 0));
            dest.writeTypedArray(keyphrases, flags);
            dest.writeBlob(data);
            dest.writeInt(audioCapabilities);
        }

        @Override
@@ -1095,7 +1150,8 @@ public class SoundTrigger {
        public String toString() {
            return "RecognitionConfig [captureRequested=" + captureRequested
                    + ", allowMultipleTriggers=" + allowMultipleTriggers + ", keyphrases="
                    + Arrays.toString(keyphrases) + ", data=" + Arrays.toString(data) + "]";
                    + Arrays.toString(keyphrases) + ", data=" + Arrays.toString(data)
                    + ", audioCapabilities=" + Integer.toHexString(audioCapabilities) + "]";
        }
    }

+88 −2
Original line number Diff line number Diff line
@@ -119,7 +119,9 @@ public class AlwaysOnHotwordDetector {
    @IntDef(flag = true, prefix = { "RECOGNITION_FLAG_" }, value = {
            RECOGNITION_FLAG_NONE,
            RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO,
            RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS
            RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS,
            RECOGNITION_FLAG_ENABLE_AUDIO_ECHO_CANCELLATION,
            RECOGNITION_FLAG_ENABLE_AUDIO_NOISE_SUPPRESSION,
    })
    public @interface RecognitionFlags {}

@@ -144,6 +146,26 @@ public class AlwaysOnHotwordDetector {
     */
    public static final int RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS = 0x2;

    /**
     * Audio capabilities flag for {@link #startRecognition(int)} that indicates
     * if the underlying recognition should use AEC.
     * This capability may or may not be supported by the system, and support can be queried
     * by calling {@link #getSupportedAudioCapabilities()}. The corresponding capabilities field for
     * this flag is {@link #AUDIO_CAPABILITY_ECHO_CANCELLATION}. If this flag is passed without the
     * audio capability supported, there will be no audio effect applied.
     */
    public static final int RECOGNITION_FLAG_ENABLE_AUDIO_ECHO_CANCELLATION = 0x4;

    /**
     * Audio capabilities flag for {@link #startRecognition(int)} that indicates
     * if the underlying recognition should use noise suppression.
     * This capability may or may not be supported by the system, and support can be queried
     * by calling {@link #getSupportedAudioCapabilities()}. The corresponding capabilities field for
     * this flag is {@link #AUDIO_CAPABILITY_NOISE_SUPPRESSION}. If this flag is passed without the
     * audio capability supported, there will be no audio effect applied.
     */
    public static final int RECOGNITION_FLAG_ENABLE_AUDIO_NOISE_SUPPRESSION = 0x8;

    //---- Recognition mode flags. Return codes for getSupportedRecognitionModes() ----//
    // Must be kept in sync with the related attribute defined as searchKeyphraseRecognitionFlags.

@@ -168,6 +190,30 @@ public class AlwaysOnHotwordDetector {
    public static final int RECOGNITION_MODE_USER_IDENTIFICATION
            = SoundTrigger.RECOGNITION_MODE_USER_IDENTIFICATION;

    //-- Audio capabilities. Values in returned bit field for getSupportedAudioCapabilities() --//

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(flag = true, prefix = { "AUDIO_CAPABILITY_" }, value = {
            AUDIO_CAPABILITY_ECHO_CANCELLATION,
            AUDIO_CAPABILITY_NOISE_SUPPRESSION,
    })
    public @interface AudioCapabilities {}

    /**
     * If set the underlying module supports AEC.
     * Returned by {@link #getSupportedAudioCapabilities()}
     */
    public static final int AUDIO_CAPABILITY_ECHO_CANCELLATION =
            SoundTrigger.ModuleProperties.CAPABILITY_ECHO_CANCELLATION;

    /**
     * If set, the underlying module supports noise suppression.
     * Returned by {@link #getSupportedAudioCapabilities()}
     */
    public static final int AUDIO_CAPABILITY_NOISE_SUPPRESSION =
            SoundTrigger.ModuleProperties.CAPABILITY_NOISE_SUPPRESSION;

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(flag = true, prefix = { "MODEL_PARAM_" }, value = {
@@ -447,6 +493,37 @@ public class AlwaysOnHotwordDetector {
        return mKeyphraseMetadata.recognitionModeFlags;
    }

    /**
     * Get the audio capabilities supported by the platform which can be enabled when
     * starting a recognition.
     *
     * @see #AUDIO_CAPABILITY_ECHO_CANCELLATION
     * @see #AUDIO_CAPABILITY_NOISE_SUPPRESSION
     *
     * @return Bit field encoding of the AudioCapabilities supported.
     */
    @AudioCapabilities
    public int getSupportedAudioCapabilities() {
        if (DBG) Slog.d(TAG, "getSupportedAudioCapabilities()");
        synchronized (mLock) {
            return getSupportedAudioCapabilitiesLocked();
        }
    }

    private int getSupportedAudioCapabilitiesLocked() {
        try {
            ModuleProperties properties =
                    mModelManagementService.getDspModuleProperties(mVoiceInteractionService);
            if (properties != null) {
                return properties.audioCapabilities;
            }

            return 0;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Starts recognition for the associated keyphrase.
     *
@@ -711,12 +788,21 @@ public class AlwaysOnHotwordDetector {
                (recognitionFlags&RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO) != 0;
        boolean allowMultipleTriggers =
                (recognitionFlags&RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS) != 0;

        int audioCapabilities = 0;
        if ((recognitionFlags & RECOGNITION_FLAG_ENABLE_AUDIO_ECHO_CANCELLATION) != 0) {
            audioCapabilities |= AUDIO_CAPABILITY_ECHO_CANCELLATION;
        }
        if ((recognitionFlags & RECOGNITION_FLAG_ENABLE_AUDIO_NOISE_SUPPRESSION) != 0) {
            audioCapabilities |= AUDIO_CAPABILITY_NOISE_SUPPRESSION;
        }

        int code = STATUS_ERROR;
        try {
            code = mModelManagementService.startRecognition(mVoiceInteractionService,
                    mKeyphraseMetadata.id, mLocale.toLanguageTag(), mInternalCallback,
                    new RecognitionConfig(captureTriggerAudio, allowMultipleTriggers,
                            recognitionExtra, null /* additional data */));
                            recognitionExtra, null /* additional data */, audioCapabilities));
        } catch (RemoteException e) {
            Slog.w(TAG, "RemoteException in startRecognition!", e);
        }
Loading