Merge "add audioCapabilities to SoundTrigger properties"
This commit is contained in:
committed by
Android (Google) Code Review
commit
55c162edcd
@@ -42770,14 +42770,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
|
||||
|
||||
@@ -3567,7 +3567,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;
|
||||
@@ -4363,6 +4366,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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) + "]";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.annotation.SystemApi;
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.hardware.soundtrigger.IRecognitionStatusCallback;
|
||||
import android.hardware.soundtrigger.SoundTrigger;
|
||||
import android.hardware.soundtrigger.SoundTrigger.ModuleProperties;
|
||||
import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
|
||||
import android.media.AudioFormat;
|
||||
import android.os.Handler;
|
||||
@@ -75,7 +76,9 @@ public final class SoundTriggerDetector {
|
||||
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 {}
|
||||
|
||||
@@ -100,10 +103,33 @@ public final class SoundTriggerDetector {
|
||||
* triggers after a call to {@link #startRecognition(int)}, if the model
|
||||
* triggers multiple times.
|
||||
* When this isn't specified, the default behavior is to stop recognition once the
|
||||
* trigger happenss, till the caller starts recognition again.
|
||||
* trigger happens, till the caller starts recognition again.
|
||||
*/
|
||||
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 SoundTriggerManager#getModuleProperties()} and checking
|
||||
* {@link ModuleProperties#audioCapabilities}. The corresponding capabilities field for
|
||||
* this flag is {@link SoundTrigger.ModuleProperties#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 SoundTriggerManager#getModuleProperties()} and checking
|
||||
* {@link ModuleProperties#audioCapabilities}. The corresponding capabilities field for
|
||||
* this flag is {@link SoundTrigger.ModuleProperties#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;
|
||||
|
||||
/**
|
||||
* Additional payload for {@link Callback#onDetected}.
|
||||
*/
|
||||
@@ -267,11 +293,20 @@ public final class SoundTriggerDetector {
|
||||
|
||||
boolean allowMultipleTriggers =
|
||||
(recognitionFlags & RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS) != 0;
|
||||
int status = STATUS_OK;
|
||||
|
||||
int audioCapabilities = 0;
|
||||
if ((recognitionFlags & RECOGNITION_FLAG_ENABLE_AUDIO_ECHO_CANCELLATION) != 0) {
|
||||
audioCapabilities |= SoundTrigger.ModuleProperties.CAPABILITY_ECHO_CANCELLATION;
|
||||
}
|
||||
if ((recognitionFlags & RECOGNITION_FLAG_ENABLE_AUDIO_NOISE_SUPPRESSION) != 0) {
|
||||
audioCapabilities |= SoundTrigger.ModuleProperties.CAPABILITY_NOISE_SUPPRESSION;
|
||||
}
|
||||
|
||||
int status;
|
||||
try {
|
||||
status = mSoundTriggerService.startRecognition(new ParcelUuid(mSoundModelId),
|
||||
mRecognitionCallback, new RecognitionConfig(captureTriggerAudio,
|
||||
allowMultipleTriggers, null, null));
|
||||
allowMultipleTriggers, null, null, audioCapabilities));
|
||||
} catch (RemoteException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.media.soundtrigger_middleware;
|
||||
|
||||
/**
|
||||
* AudioCapabilities supported by the implemented HAL driver.
|
||||
* @hide
|
||||
*/
|
||||
@Backing(type="int")
|
||||
enum AudioCapabilities {
|
||||
/**
|
||||
* If set the underlying module supports AEC.
|
||||
*/
|
||||
ECHO_CANCELLATION = 1 << 0,
|
||||
/**
|
||||
* If set, the underlying module supports noise suppression.
|
||||
*/
|
||||
NOISE_SUPPRESSION = 1 << 1,
|
||||
}
|
||||
@@ -28,6 +28,12 @@ parcelable RecognitionConfig {
|
||||
/* Configuration for each key phrase. */
|
||||
PhraseRecognitionExtra[] phraseRecognitionExtras;
|
||||
|
||||
/**
|
||||
* Bit field encoding of the AudioCapabilities
|
||||
* supported by the firmware.
|
||||
*/
|
||||
int audioCapabilities;
|
||||
|
||||
/** Opaque capture configuration data. */
|
||||
byte[] data;
|
||||
}
|
||||
|
||||
@@ -58,4 +58,11 @@ parcelable SoundTriggerModuleProperties {
|
||||
* Rated power consumption when detection is active with TDB
|
||||
* silence/sound/speech ratio */
|
||||
int powerConsumptionMw;
|
||||
/**
|
||||
* Bit field encoding of the AudioCapabilities
|
||||
* supported by the firmware.
|
||||
* This property is supported for soundtrigger HAL v2.3 and above.
|
||||
* If running a previous version, this value will be 0.
|
||||
*/
|
||||
int audioCapabilities;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.hardware.soundtrigger.V2_3.ISoundTriggerHw;
|
||||
import android.hardware.soundtrigger.V2_3.Properties;
|
||||
import android.media.audio.common.AudioConfig;
|
||||
import android.media.audio.common.AudioOffloadInfo;
|
||||
import android.media.soundtrigger_middleware.AudioCapabilities;
|
||||
import android.media.soundtrigger_middleware.ConfidenceLevel;
|
||||
import android.media.soundtrigger_middleware.ModelParameter;
|
||||
import android.media.soundtrigger_middleware.ModelParameterRange;
|
||||
@@ -74,6 +75,8 @@ class ConversionUtil {
|
||||
@NonNull Properties hidlProperties) {
|
||||
SoundTriggerModuleProperties aidlProperties = hidl2aidlProperties(hidlProperties.base);
|
||||
aidlProperties.supportedModelArch = hidlProperties.supportedModelArch;
|
||||
aidlProperties.audioCapabilities =
|
||||
hidl2aidlAudioCapabilities(hidlProperties.audioCapabilities);
|
||||
return aidlProperties;
|
||||
}
|
||||
|
||||
@@ -209,16 +212,17 @@ class ConversionUtil {
|
||||
return hidlModel;
|
||||
}
|
||||
|
||||
static @NonNull
|
||||
ISoundTriggerHw.RecognitionConfig aidl2hidlRecognitionConfig(
|
||||
static @NonNull android.hardware.soundtrigger.V2_3.RecognitionConfig aidl2hidlRecognitionConfig(
|
||||
@NonNull RecognitionConfig aidlConfig) {
|
||||
ISoundTriggerHw.RecognitionConfig hidlConfig = new ISoundTriggerHw.RecognitionConfig();
|
||||
hidlConfig.header.captureRequested = aidlConfig.captureRequested;
|
||||
android.hardware.soundtrigger.V2_3.RecognitionConfig hidlConfig =
|
||||
new android.hardware.soundtrigger.V2_3.RecognitionConfig();
|
||||
hidlConfig.base.header.captureRequested = aidlConfig.captureRequested;
|
||||
for (PhraseRecognitionExtra aidlPhraseExtra : aidlConfig.phraseRecognitionExtras) {
|
||||
hidlConfig.header.phrases.add(aidl2hidlPhraseRecognitionExtra(aidlPhraseExtra));
|
||||
hidlConfig.base.header.phrases.add(aidl2hidlPhraseRecognitionExtra(aidlPhraseExtra));
|
||||
}
|
||||
hidlConfig.data = HidlMemoryUtil.byteArrayToHidlMemory(aidlConfig.data,
|
||||
hidlConfig.base.data = HidlMemoryUtil.byteArrayToHidlMemory(aidlConfig.data,
|
||||
"SoundTrigger RecognitionConfig");
|
||||
hidlConfig.audioCapabilities = aidlConfig.audioCapabilities;
|
||||
return hidlConfig;
|
||||
}
|
||||
|
||||
@@ -395,4 +399,17 @@ class ConversionUtil {
|
||||
return android.hardware.soundtrigger.V2_3.ModelParameter.INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
static int hidl2aidlAudioCapabilities(int hidlCapabilities) {
|
||||
int aidlCapabilities = 0;
|
||||
if ((hidlCapabilities
|
||||
& android.hardware.soundtrigger.V2_3.AudioCapabilities.ECHO_CANCELLATION) != 0) {
|
||||
aidlCapabilities |= AudioCapabilities.ECHO_CANCELLATION;
|
||||
}
|
||||
if ((hidlCapabilities
|
||||
& android.hardware.soundtrigger.V2_3.AudioCapabilities.NOISE_SUPPRESSION) != 0) {
|
||||
aidlCapabilities |= AudioCapabilities.NOISE_SUPPRESSION;
|
||||
}
|
||||
return aidlCapabilities;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,12 +66,17 @@ class Hw2CompatUtil {
|
||||
return model_2_0;
|
||||
}
|
||||
|
||||
static android.hardware.soundtrigger.V2_0.ISoundTriggerHw.RecognitionConfig convertRecognitionConfig_2_1_to_2_0(
|
||||
android.hardware.soundtrigger.V2_1.ISoundTriggerHw.RecognitionConfig config) {
|
||||
static android.hardware.soundtrigger.V2_1.ISoundTriggerHw.RecognitionConfig convertRecognitionConfig_2_3_to_2_1(
|
||||
android.hardware.soundtrigger.V2_3.RecognitionConfig config) {
|
||||
return config.base;
|
||||
}
|
||||
|
||||
static android.hardware.soundtrigger.V2_0.ISoundTriggerHw.RecognitionConfig convertRecognitionConfig_2_3_to_2_0(
|
||||
android.hardware.soundtrigger.V2_3.RecognitionConfig config) {
|
||||
android.hardware.soundtrigger.V2_0.ISoundTriggerHw.RecognitionConfig config_2_0 =
|
||||
config.header;
|
||||
config.base.header;
|
||||
// Note: this mutates the input!
|
||||
config_2_0.data = HidlMemoryUtil.hidlMemoryToByteList(config.data);
|
||||
config_2_0.data = HidlMemoryUtil.hidlMemoryToByteList(config.base.data);
|
||||
return config_2_0;
|
||||
}
|
||||
|
||||
|
||||
@@ -92,12 +92,12 @@ public interface ISoundTriggerHw2 {
|
||||
void stopAllRecognitions();
|
||||
|
||||
/**
|
||||
* @see android.hardware.soundtrigger.V2_2.ISoundTriggerHw#startRecognition_2_1(int,
|
||||
* android.hardware.soundtrigger.V2_1.ISoundTriggerHw.RecognitionConfig,
|
||||
* @see android.hardware.soundtrigger.V2_3.ISoundTriggerHw#startRecognition_2_3(int,
|
||||
* android.hardware.soundtrigger.V2_3.RecognitionConfig,
|
||||
* android.hardware.soundtrigger.V2_1.ISoundTriggerHwCallback, int)
|
||||
*/
|
||||
void startRecognition(int modelHandle,
|
||||
android.hardware.soundtrigger.V2_1.ISoundTriggerHw.RecognitionConfig config,
|
||||
android.hardware.soundtrigger.V2_3.RecognitionConfig config,
|
||||
SoundTriggerHw2Compat.Callback callback, int cookie);
|
||||
|
||||
/**
|
||||
|
||||
@@ -217,16 +217,15 @@ final class SoundTriggerHw2Compat implements ISoundTriggerHw2 {
|
||||
|
||||
@Override
|
||||
public void startRecognition(int modelHandle,
|
||||
android.hardware.soundtrigger.V2_1.ISoundTriggerHw.RecognitionConfig config,
|
||||
android.hardware.soundtrigger.V2_3.RecognitionConfig config,
|
||||
Callback callback, int cookie) {
|
||||
try {
|
||||
try {
|
||||
int retval = as2_1().startRecognition_2_1(modelHandle, config,
|
||||
new SoundTriggerCallback(callback), cookie);
|
||||
handleHalStatus(retval, "startRecognition_2_1");
|
||||
int retval = as2_3().startRecognition_2_3(modelHandle, config);
|
||||
handleHalStatus(retval, "startRecognition_2_3");
|
||||
} catch (NotSupported e) {
|
||||
// Fall-back to the 2.0 version:
|
||||
startRecognition_2_0(modelHandle, config, callback, cookie);
|
||||
startRecognition_2_1(modelHandle, config, callback, cookie);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowAsRuntimeException();
|
||||
@@ -369,13 +368,31 @@ final class SoundTriggerHw2Compat implements ISoundTriggerHw2 {
|
||||
return handle.get();
|
||||
}
|
||||
|
||||
private void startRecognition_2_1(int modelHandle,
|
||||
android.hardware.soundtrigger.V2_3.RecognitionConfig config,
|
||||
Callback callback, int cookie) {
|
||||
try {
|
||||
try {
|
||||
android.hardware.soundtrigger.V2_1.ISoundTriggerHw.RecognitionConfig config_2_1 =
|
||||
Hw2CompatUtil.convertRecognitionConfig_2_3_to_2_1(config);
|
||||
int retval = as2_1().startRecognition_2_1(modelHandle, config_2_1,
|
||||
new SoundTriggerCallback(callback), cookie);
|
||||
handleHalStatus(retval, "startRecognition_2_1");
|
||||
} catch (NotSupported e) {
|
||||
// Fall-back to the 2.0 version:
|
||||
startRecognition_2_0(modelHandle, config, callback, cookie);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowAsRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
private void startRecognition_2_0(int modelHandle,
|
||||
android.hardware.soundtrigger.V2_1.ISoundTriggerHw.RecognitionConfig config,
|
||||
android.hardware.soundtrigger.V2_3.RecognitionConfig config,
|
||||
Callback callback, int cookie)
|
||||
throws RemoteException {
|
||||
|
||||
android.hardware.soundtrigger.V2_0.ISoundTriggerHw.RecognitionConfig config_2_0 =
|
||||
Hw2CompatUtil.convertRecognitionConfig_2_1_to_2_0(config);
|
||||
Hw2CompatUtil.convertRecognitionConfig_2_3_to_2_0(config);
|
||||
int retval = as2_0().startRecognition(modelHandle, config_2_0,
|
||||
new SoundTriggerCallback(callback), cookie);
|
||||
handleHalStatus(retval, "startRecognition");
|
||||
|
||||
@@ -401,10 +401,10 @@ class SoundTriggerModule {
|
||||
notifyAbort();
|
||||
return;
|
||||
}
|
||||
android.hardware.soundtrigger.V2_1.ISoundTriggerHw.RecognitionConfig hidlConfig =
|
||||
android.hardware.soundtrigger.V2_3.RecognitionConfig hidlConfig =
|
||||
ConversionUtil.aidl2hidlRecognitionConfig(config);
|
||||
hidlConfig.header.captureDevice = mSession.mDeviceHandle;
|
||||
hidlConfig.header.captureHandle = mSession.mIoHandle;
|
||||
hidlConfig.base.header.captureDevice = mSession.mDeviceHandle;
|
||||
hidlConfig.base.header.captureHandle = mSession.mIoHandle;
|
||||
mHalService.startRecognition(mHandle, hidlConfig, this, 0);
|
||||
setState(ModelState.ACTIVE);
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ import android.hardware.audio.common.V2_0.Uuid;
|
||||
import android.hardware.soundtrigger.V2_3.OptionalModelParameterRange;
|
||||
import android.media.audio.common.AudioChannelMask;
|
||||
import android.media.audio.common.AudioFormat;
|
||||
import android.media.soundtrigger_middleware.AudioCapabilities;
|
||||
import android.media.soundtrigger_middleware.ConfidenceLevel;
|
||||
import android.media.soundtrigger_middleware.ISoundTriggerCallback;
|
||||
import android.media.soundtrigger_middleware.ISoundTriggerModule;
|
||||
@@ -59,6 +60,7 @@ import android.os.HwParcel;
|
||||
import android.os.IHwBinder;
|
||||
import android.os.IHwInterface;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Pair;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -161,6 +163,9 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
new android.hardware.soundtrigger.V2_3.Properties();
|
||||
properties.base = createDefaultProperties(supportConcurrentCapture);
|
||||
properties.supportedModelArch = "supportedModelArch";
|
||||
properties.audioCapabilities =
|
||||
android.hardware.soundtrigger.V2_3.AudioCapabilities.ECHO_CANCELLATION
|
||||
| android.hardware.soundtrigger.V2_3.AudioCapabilities.NOISE_SUPPRESSION;
|
||||
return properties;
|
||||
}
|
||||
|
||||
@@ -185,8 +190,11 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
|
||||
if (mHalDriver instanceof android.hardware.soundtrigger.V2_3.ISoundTriggerHw) {
|
||||
assertEquals("supportedModelArch", properties.supportedModelArch);
|
||||
assertEquals(AudioCapabilities.ECHO_CANCELLATION | AudioCapabilities.NOISE_SUPPRESSION,
|
||||
properties.audioCapabilities);
|
||||
} else {
|
||||
assertEquals("", properties.supportedModelArch);
|
||||
assertEquals(0, properties.audioCapabilities);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,12 +338,17 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
mService = new SoundTriggerMiddlewareImpl(mHalDriver, mAudioSessionProvider);
|
||||
}
|
||||
|
||||
private int loadGenericModel_2_0(ISoundTriggerModule module, int hwHandle)
|
||||
throws RemoteException {
|
||||
private Pair<Integer, SoundTriggerHwCallback> loadGenericModel_2_0(ISoundTriggerModule module,
|
||||
int hwHandle) throws RemoteException {
|
||||
SoundModel model = createGenericSoundModel();
|
||||
ArgumentCaptor<android.hardware.soundtrigger.V2_0.ISoundTriggerHw.SoundModel> modelCaptor =
|
||||
ArgumentCaptor.forClass(
|
||||
android.hardware.soundtrigger.V2_0.ISoundTriggerHw.SoundModel.class);
|
||||
ArgumentCaptor<android.hardware.soundtrigger.V2_0.ISoundTriggerHwCallback> callbackCaptor =
|
||||
ArgumentCaptor.forClass(
|
||||
android.hardware.soundtrigger.V2_0.ISoundTriggerHwCallback.class);
|
||||
ArgumentCaptor<Integer> cookieCaptor = ArgumentCaptor.forClass(Integer.class);
|
||||
|
||||
doAnswer(invocation -> {
|
||||
android.hardware.soundtrigger.V2_0.ISoundTriggerHwCallback callback =
|
||||
invocation.getArgument(1);
|
||||
@@ -354,7 +367,8 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
modelEvent.model = hwHandle;
|
||||
callback.soundModelCallback(modelEvent, callbackCookie);
|
||||
return null;
|
||||
}).when(mHalDriver).loadSoundModel(modelCaptor.capture(), any(), anyInt(), any());
|
||||
}).when(mHalDriver).loadSoundModel(modelCaptor.capture(), callbackCaptor.capture(),
|
||||
cookieCaptor.capture(), any());
|
||||
|
||||
when(mAudioSessionProvider.acquireSession()).thenReturn(
|
||||
new SoundTriggerMiddlewareImpl.AudioSessionProvider.AudioSession(101, 102, 103));
|
||||
@@ -371,17 +385,23 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
assertEquals(model.vendorUuid, ConversionUtil.hidl2aidlUuid(hidlModel.vendorUuid));
|
||||
assertArrayEquals(new Byte[]{91, 92, 93, 94, 95}, hidlModel.data.toArray());
|
||||
|
||||
return handle;
|
||||
return new Pair<>(handle,
|
||||
new SoundTriggerHwCallback(callbackCaptor.getValue(), cookieCaptor.getValue()));
|
||||
}
|
||||
|
||||
private int loadGenericModel_2_1(ISoundTriggerModule module, int hwHandle)
|
||||
throws RemoteException {
|
||||
private Pair<Integer, SoundTriggerHwCallback> loadGenericModel_2_1(ISoundTriggerModule module,
|
||||
int hwHandle) throws RemoteException {
|
||||
android.hardware.soundtrigger.V2_1.ISoundTriggerHw driver =
|
||||
(android.hardware.soundtrigger.V2_1.ISoundTriggerHw) mHalDriver;
|
||||
SoundModel model = createGenericSoundModel();
|
||||
ArgumentCaptor<android.hardware.soundtrigger.V2_1.ISoundTriggerHw.SoundModel> modelCaptor =
|
||||
ArgumentCaptor.forClass(
|
||||
android.hardware.soundtrigger.V2_1.ISoundTriggerHw.SoundModel.class);
|
||||
ArgumentCaptor<android.hardware.soundtrigger.V2_1.ISoundTriggerHwCallback> callbackCaptor =
|
||||
ArgumentCaptor.forClass(
|
||||
android.hardware.soundtrigger.V2_1.ISoundTriggerHwCallback.class);
|
||||
ArgumentCaptor<Integer> cookieCaptor = ArgumentCaptor.forClass(Integer.class);
|
||||
|
||||
doAnswer(invocation -> {
|
||||
android.hardware.soundtrigger.V2_1.ISoundTriggerHwCallback callback =
|
||||
invocation.getArgument(1);
|
||||
@@ -400,7 +420,8 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
modelEvent.header.model = hwHandle;
|
||||
callback.soundModelCallback_2_1(modelEvent, callbackCookie);
|
||||
return null;
|
||||
}).when(driver).loadSoundModel_2_1(modelCaptor.capture(), any(), anyInt(), any());
|
||||
}).when(driver).loadSoundModel_2_1(modelCaptor.capture(), callbackCaptor.capture(),
|
||||
cookieCaptor.capture(), any());
|
||||
|
||||
when(mAudioSessionProvider.acquireSession()).thenReturn(
|
||||
new SoundTriggerMiddlewareImpl.AudioSessionProvider.AudioSession(101, 102, 103));
|
||||
@@ -418,10 +439,12 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
assertArrayEquals(new byte[]{91, 92, 93, 94, 95},
|
||||
HidlMemoryUtil.hidlMemoryToByteArray(hidlModel.data));
|
||||
|
||||
return handle;
|
||||
return new Pair<>(handle,
|
||||
new SoundTriggerHwCallback(callbackCaptor.getValue(), cookieCaptor.getValue()));
|
||||
}
|
||||
|
||||
private int loadGenericModel(ISoundTriggerModule module, int hwHandle) throws RemoteException {
|
||||
private Pair<Integer, SoundTriggerHwCallback> loadGenericModel(ISoundTriggerModule module,
|
||||
int hwHandle) throws RemoteException {
|
||||
if (mHalDriver instanceof android.hardware.soundtrigger.V2_1.ISoundTriggerHw) {
|
||||
return loadGenericModel_2_1(module, hwHandle);
|
||||
} else {
|
||||
@@ -429,12 +452,17 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
}
|
||||
}
|
||||
|
||||
private int loadPhraseModel_2_0(ISoundTriggerModule module, int hwHandle)
|
||||
throws RemoteException {
|
||||
private Pair<Integer, SoundTriggerHwCallback> loadPhraseModel_2_0(ISoundTriggerModule module,
|
||||
int hwHandle) throws RemoteException {
|
||||
PhraseSoundModel model = createPhraseSoundModel();
|
||||
ArgumentCaptor<android.hardware.soundtrigger.V2_0.ISoundTriggerHw.PhraseSoundModel>
|
||||
modelCaptor = ArgumentCaptor.forClass(
|
||||
android.hardware.soundtrigger.V2_0.ISoundTriggerHw.PhraseSoundModel.class);
|
||||
ArgumentCaptor<android.hardware.soundtrigger.V2_0.ISoundTriggerHwCallback> callbackCaptor =
|
||||
ArgumentCaptor.forClass(
|
||||
android.hardware.soundtrigger.V2_0.ISoundTriggerHwCallback.class);
|
||||
ArgumentCaptor<Integer> cookieCaptor = ArgumentCaptor.forClass(Integer.class);
|
||||
|
||||
doAnswer(invocation -> {
|
||||
android.hardware.soundtrigger.V2_0.ISoundTriggerHwCallback callback =
|
||||
invocation.getArgument(
|
||||
@@ -456,7 +484,8 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
modelEvent.model = hwHandle;
|
||||
callback.soundModelCallback(modelEvent, callbackCookie);
|
||||
return null;
|
||||
}).when(mHalDriver).loadPhraseSoundModel(modelCaptor.capture(), any(), anyInt(), any());
|
||||
}).when(mHalDriver).loadPhraseSoundModel(modelCaptor.capture(), callbackCaptor.capture(),
|
||||
cookieCaptor.capture(), any());
|
||||
|
||||
when(mAudioSessionProvider.acquireSession()).thenReturn(
|
||||
new SoundTriggerMiddlewareImpl.AudioSessionProvider.AudioSession(101, 102, 103));
|
||||
@@ -488,11 +517,12 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
| android.hardware.soundtrigger.V2_0.RecognitionMode.USER_IDENTIFICATION,
|
||||
hidlPhrase.recognitionModes);
|
||||
|
||||
return handle;
|
||||
return new Pair<>(handle,
|
||||
new SoundTriggerHwCallback(callbackCaptor.getValue(), cookieCaptor.getValue()));
|
||||
}
|
||||
|
||||
private int loadPhraseModel_2_1(ISoundTriggerModule module, int hwHandle)
|
||||
throws RemoteException {
|
||||
private Pair<Integer, SoundTriggerHwCallback> loadPhraseModel_2_1(ISoundTriggerModule module,
|
||||
int hwHandle) throws RemoteException {
|
||||
android.hardware.soundtrigger.V2_1.ISoundTriggerHw driver =
|
||||
(android.hardware.soundtrigger.V2_1.ISoundTriggerHw) mHalDriver;
|
||||
|
||||
@@ -500,6 +530,11 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
ArgumentCaptor<android.hardware.soundtrigger.V2_1.ISoundTriggerHw.PhraseSoundModel>
|
||||
modelCaptor = ArgumentCaptor.forClass(
|
||||
android.hardware.soundtrigger.V2_1.ISoundTriggerHw.PhraseSoundModel.class);
|
||||
ArgumentCaptor<android.hardware.soundtrigger.V2_1.ISoundTriggerHwCallback> callbackCaptor =
|
||||
ArgumentCaptor.forClass(
|
||||
android.hardware.soundtrigger.V2_1.ISoundTriggerHwCallback.class);
|
||||
ArgumentCaptor<Integer> cookieCaptor = ArgumentCaptor.forClass(Integer.class);
|
||||
|
||||
doAnswer(invocation -> {
|
||||
android.hardware.soundtrigger.V2_1.ISoundTriggerHwCallback callback =
|
||||
invocation.getArgument(
|
||||
@@ -521,7 +556,8 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
modelEvent.header.model = hwHandle;
|
||||
callback.soundModelCallback_2_1(modelEvent, callbackCookie);
|
||||
return null;
|
||||
}).when(driver).loadPhraseSoundModel_2_1(modelCaptor.capture(), any(), anyInt(), any());
|
||||
}).when(driver).loadPhraseSoundModel_2_1(modelCaptor.capture(), callbackCaptor.capture(),
|
||||
cookieCaptor.capture(), any());
|
||||
|
||||
when(mAudioSessionProvider.acquireSession()).thenReturn(
|
||||
new SoundTriggerMiddlewareImpl.AudioSessionProvider.AudioSession(101, 102, 103));
|
||||
@@ -554,10 +590,12 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
| android.hardware.soundtrigger.V2_0.RecognitionMode.USER_IDENTIFICATION,
|
||||
hidlPhrase.recognitionModes);
|
||||
|
||||
return handle;
|
||||
return new Pair<>(handle,
|
||||
new SoundTriggerHwCallback(callbackCaptor.getValue(), cookieCaptor.getValue()));
|
||||
}
|
||||
|
||||
private int loadPhraseModel(ISoundTriggerModule module, int hwHandle) throws RemoteException {
|
||||
private Pair<Integer, SoundTriggerHwCallback> loadPhraseModel(
|
||||
ISoundTriggerModule module, int hwHandle) throws RemoteException {
|
||||
if (mHalDriver instanceof android.hardware.soundtrigger.V2_1.ISoundTriggerHw) {
|
||||
return loadPhraseModel_2_1(module, hwHandle);
|
||||
} else {
|
||||
@@ -572,18 +610,14 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
verify(mAudioSessionProvider).releaseSession(101);
|
||||
}
|
||||
|
||||
private SoundTriggerHwCallback startRecognition_2_0(ISoundTriggerModule module, int handle,
|
||||
private void startRecognition_2_0(ISoundTriggerModule module, int handle,
|
||||
int hwHandle) throws RemoteException {
|
||||
ArgumentCaptor<android.hardware.soundtrigger.V2_0.ISoundTriggerHw.RecognitionConfig>
|
||||
configCaptor = ArgumentCaptor.forClass(
|
||||
android.hardware.soundtrigger.V2_0.ISoundTriggerHw.RecognitionConfig.class);
|
||||
ArgumentCaptor<android.hardware.soundtrigger.V2_0.ISoundTriggerHwCallback> callbackCaptor =
|
||||
ArgumentCaptor.forClass(
|
||||
android.hardware.soundtrigger.V2_0.ISoundTriggerHwCallback.class);
|
||||
ArgumentCaptor<Integer> cookieCaptor = ArgumentCaptor.forClass(Integer.class);
|
||||
|
||||
when(mHalDriver.startRecognition(eq(hwHandle), configCaptor.capture(),
|
||||
callbackCaptor.capture(), cookieCaptor.capture())).thenReturn(0);
|
||||
when(mHalDriver.startRecognition(eq(hwHandle), configCaptor.capture(), any(), anyInt()))
|
||||
.thenReturn(0);
|
||||
|
||||
RecognitionConfig config = createRecognitionConfig();
|
||||
|
||||
@@ -606,11 +640,9 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
assertEquals(234, halLevel.userId);
|
||||
assertEquals(34, halLevel.levelPercent);
|
||||
assertArrayEquals(new Byte[]{5, 4, 3, 2, 1}, halConfig.data.toArray());
|
||||
|
||||
return new SoundTriggerHwCallback(callbackCaptor.getValue(), cookieCaptor.getValue());
|
||||
}
|
||||
|
||||
private SoundTriggerHwCallback startRecognition_2_1(ISoundTriggerModule module, int handle,
|
||||
private void startRecognition_2_1(ISoundTriggerModule module, int handle,
|
||||
int hwHandle) throws RemoteException {
|
||||
android.hardware.soundtrigger.V2_1.ISoundTriggerHw driver =
|
||||
(android.hardware.soundtrigger.V2_1.ISoundTriggerHw) mHalDriver;
|
||||
@@ -618,13 +650,9 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
ArgumentCaptor<android.hardware.soundtrigger.V2_1.ISoundTriggerHw.RecognitionConfig>
|
||||
configCaptor = ArgumentCaptor.forClass(
|
||||
android.hardware.soundtrigger.V2_1.ISoundTriggerHw.RecognitionConfig.class);
|
||||
ArgumentCaptor<android.hardware.soundtrigger.V2_1.ISoundTriggerHwCallback> callbackCaptor =
|
||||
ArgumentCaptor.forClass(
|
||||
android.hardware.soundtrigger.V2_1.ISoundTriggerHwCallback.class);
|
||||
ArgumentCaptor<Integer> cookieCaptor = ArgumentCaptor.forClass(Integer.class);
|
||||
|
||||
when(driver.startRecognition_2_1(eq(hwHandle), configCaptor.capture(),
|
||||
callbackCaptor.capture(), cookieCaptor.capture())).thenReturn(0);
|
||||
when(driver.startRecognition_2_1(eq(hwHandle), configCaptor.capture(), any(), anyInt()))
|
||||
.thenReturn(0);
|
||||
|
||||
RecognitionConfig config = createRecognitionConfig();
|
||||
|
||||
@@ -648,16 +676,56 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
assertEquals(34, halLevel.levelPercent);
|
||||
assertArrayEquals(new byte[]{5, 4, 3, 2, 1},
|
||||
HidlMemoryUtil.hidlMemoryToByteArray(halConfig.data));
|
||||
|
||||
return new SoundTriggerHwCallback(callbackCaptor.getValue(), cookieCaptor.getValue());
|
||||
}
|
||||
|
||||
private SoundTriggerHwCallback startRecognition(ISoundTriggerModule module, int handle,
|
||||
private void startRecognition_2_3(ISoundTriggerModule module, int handle,
|
||||
int hwHandle) throws RemoteException {
|
||||
if (mHalDriver instanceof android.hardware.soundtrigger.V2_1.ISoundTriggerHw) {
|
||||
return startRecognition_2_1(module, handle, hwHandle);
|
||||
android.hardware.soundtrigger.V2_3.ISoundTriggerHw driver =
|
||||
(android.hardware.soundtrigger.V2_3.ISoundTriggerHw) mHalDriver;
|
||||
|
||||
ArgumentCaptor<android.hardware.soundtrigger.V2_3.RecognitionConfig>
|
||||
configCaptor = ArgumentCaptor.forClass(
|
||||
android.hardware.soundtrigger.V2_3.RecognitionConfig.class);
|
||||
|
||||
when(driver.startRecognition_2_3(eq(hwHandle), configCaptor.capture())).thenReturn(0);
|
||||
|
||||
RecognitionConfig config = createRecognitionConfig();
|
||||
|
||||
module.startRecognition(handle, config);
|
||||
verify(driver).startRecognition_2_3(eq(hwHandle), any());
|
||||
|
||||
android.hardware.soundtrigger.V2_3.RecognitionConfig halConfigExtended =
|
||||
configCaptor.getValue();
|
||||
android.hardware.soundtrigger.V2_1.ISoundTriggerHw.RecognitionConfig halConfig_2_1 =
|
||||
halConfigExtended.base;
|
||||
|
||||
assertTrue(halConfig_2_1.header.captureRequested);
|
||||
assertEquals(102, halConfig_2_1.header.captureHandle);
|
||||
assertEquals(103, halConfig_2_1.header.captureDevice);
|
||||
assertEquals(1, halConfig_2_1.header.phrases.size());
|
||||
android.hardware.soundtrigger.V2_0.PhraseRecognitionExtra halPhraseExtra =
|
||||
halConfig_2_1.header.phrases.get(0);
|
||||
assertEquals(123, halPhraseExtra.id);
|
||||
assertEquals(4, halPhraseExtra.confidenceLevel);
|
||||
assertEquals(5, halPhraseExtra.recognitionModes);
|
||||
assertEquals(1, halPhraseExtra.levels.size());
|
||||
android.hardware.soundtrigger.V2_0.ConfidenceLevel halLevel = halPhraseExtra.levels.get(0);
|
||||
assertEquals(234, halLevel.userId);
|
||||
assertEquals(34, halLevel.levelPercent);
|
||||
assertArrayEquals(new byte[]{5, 4, 3, 2, 1},
|
||||
HidlMemoryUtil.hidlMemoryToByteArray(halConfig_2_1.data));
|
||||
assertEquals(AudioCapabilities.ECHO_CANCELLATION
|
||||
| AudioCapabilities.NOISE_SUPPRESSION, halConfigExtended.audioCapabilities);
|
||||
}
|
||||
|
||||
private void startRecognition(ISoundTriggerModule module, int handle,
|
||||
int hwHandle) throws RemoteException {
|
||||
if (mHalDriver instanceof android.hardware.soundtrigger.V2_3.ISoundTriggerHw) {
|
||||
startRecognition_2_3(module, handle, hwHandle);
|
||||
} else if (mHalDriver instanceof android.hardware.soundtrigger.V2_1.ISoundTriggerHw) {
|
||||
startRecognition_2_1(module, handle, hwHandle);
|
||||
} else {
|
||||
return startRecognition_2_0(module, handle, hwHandle);
|
||||
startRecognition_2_0(module, handle, hwHandle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -672,6 +740,8 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
config.phraseRecognitionExtras[0].levels[0].userId = 234;
|
||||
config.phraseRecognitionExtras[0].levels[0].levelPercent = 34;
|
||||
config.data = new byte[]{5, 4, 3, 2, 1};
|
||||
config.audioCapabilities = AudioCapabilities.ECHO_CANCELLATION
|
||||
| AudioCapabilities.NOISE_SUPPRESSION;
|
||||
return config;
|
||||
}
|
||||
|
||||
@@ -687,6 +757,9 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
if (mHalDriver instanceof android.hardware.soundtrigger.V2_1.ISoundTriggerHw) {
|
||||
verify((android.hardware.soundtrigger.V2_1.ISoundTriggerHw) mHalDriver,
|
||||
never()).startRecognition_2_1(anyInt(), any(), any(), anyInt());
|
||||
} else if (mHalDriver instanceof android.hardware.soundtrigger.V2_3.ISoundTriggerHw) {
|
||||
verify((android.hardware.soundtrigger.V2_3.ISoundTriggerHw) mHalDriver,
|
||||
never()).startRecognition_2_3(anyInt(), any());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -798,7 +871,7 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
ISoundTriggerModule module = mService.attach(0, callback);
|
||||
|
||||
final int hwHandle = 7;
|
||||
int handle = loadGenericModel(module, hwHandle);
|
||||
int handle = loadGenericModel(module, hwHandle).first;
|
||||
unloadModel(module, handle, hwHandle);
|
||||
module.detach();
|
||||
}
|
||||
@@ -810,7 +883,7 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
ISoundTriggerModule module = mService.attach(0, callback);
|
||||
|
||||
final int hwHandle = 73;
|
||||
int handle = loadPhraseModel(module, hwHandle);
|
||||
int handle = loadPhraseModel(module, hwHandle).first;
|
||||
unloadModel(module, handle, hwHandle);
|
||||
module.detach();
|
||||
}
|
||||
@@ -823,7 +896,7 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
|
||||
// Load the model.
|
||||
final int hwHandle = 7;
|
||||
int handle = loadGenericModel(module, hwHandle);
|
||||
int handle = loadGenericModel(module, hwHandle).first;
|
||||
|
||||
// Initiate a recognition.
|
||||
startRecognition(module, handle, hwHandle);
|
||||
@@ -844,7 +917,7 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
|
||||
// Load the model.
|
||||
final int hwHandle = 67;
|
||||
int handle = loadPhraseModel(module, hwHandle);
|
||||
int handle = loadPhraseModel(module, hwHandle).first;
|
||||
|
||||
// Initiate a recognition.
|
||||
startRecognition(module, handle, hwHandle);
|
||||
@@ -865,10 +938,12 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
|
||||
// Load the model.
|
||||
final int hwHandle = 7;
|
||||
int handle = loadGenericModel(module, hwHandle);
|
||||
Pair<Integer, SoundTriggerHwCallback> modelHandles = loadGenericModel(module, hwHandle);
|
||||
int handle = modelHandles.first;
|
||||
SoundTriggerHwCallback hwCallback = modelHandles.second;
|
||||
|
||||
// Initiate a recognition.
|
||||
SoundTriggerHwCallback hwCallback = startRecognition(module, handle, hwHandle);
|
||||
startRecognition(module, handle, hwHandle);
|
||||
|
||||
// Signal a capture from the driver.
|
||||
hwCallback.sendRecognitionEvent(hwHandle,
|
||||
@@ -894,10 +969,12 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
|
||||
// Load the model.
|
||||
final int hwHandle = 7;
|
||||
int handle = loadPhraseModel(module, hwHandle);
|
||||
Pair<Integer, SoundTriggerHwCallback> modelHandles = loadPhraseModel(module, hwHandle);
|
||||
int handle = modelHandles.first;
|
||||
SoundTriggerHwCallback hwCallback = modelHandles.second;
|
||||
|
||||
// Initiate a recognition.
|
||||
SoundTriggerHwCallback hwCallback = startRecognition(module, handle, hwHandle);
|
||||
startRecognition(module, handle, hwHandle);
|
||||
|
||||
// Signal a capture from the driver.
|
||||
hwCallback.sendPhraseRecognitionEvent(hwHandle,
|
||||
@@ -930,10 +1007,12 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
|
||||
// Load the model.
|
||||
final int hwHandle = 17;
|
||||
int handle = loadGenericModel(module, hwHandle);
|
||||
Pair<Integer, SoundTriggerHwCallback> modelHandles = loadGenericModel(module, hwHandle);
|
||||
int handle = modelHandles.first;
|
||||
SoundTriggerHwCallback hwCallback = modelHandles.second;
|
||||
|
||||
// Initiate a recognition.
|
||||
SoundTriggerHwCallback hwCallback = startRecognition(module, handle, hwHandle);
|
||||
startRecognition(module, handle, hwHandle);
|
||||
|
||||
// Force a trigger.
|
||||
module.forceRecognitionEvent(handle);
|
||||
@@ -973,10 +1052,12 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
|
||||
// Load the model.
|
||||
final int hwHandle = 17;
|
||||
int handle = loadPhraseModel(module, hwHandle);
|
||||
Pair<Integer, SoundTriggerHwCallback> modelHandles = loadPhraseModel(module, hwHandle);
|
||||
int handle = modelHandles.first;
|
||||
SoundTriggerHwCallback hwCallback = modelHandles.second;
|
||||
|
||||
// Initiate a recognition.
|
||||
SoundTriggerHwCallback hwCallback = startRecognition(module, handle, hwHandle);
|
||||
startRecognition(module, handle, hwHandle);
|
||||
|
||||
// Force a trigger.
|
||||
module.forceRecognitionEvent(handle);
|
||||
@@ -1013,7 +1094,7 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
|
||||
// Load the model.
|
||||
final int hwHandle = 11;
|
||||
int handle = loadGenericModel(module, hwHandle);
|
||||
int handle = loadGenericModel(module, hwHandle).first;
|
||||
|
||||
// Initiate a recognition.
|
||||
startRecognition(module, handle, hwHandle);
|
||||
@@ -1061,7 +1142,7 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
|
||||
// Load the model.
|
||||
final int hwHandle = 11;
|
||||
int handle = loadPhraseModel(module, hwHandle);
|
||||
int handle = loadPhraseModel(module, hwHandle).first;
|
||||
|
||||
// Initiate a recognition.
|
||||
startRecognition(module, handle, hwHandle);
|
||||
@@ -1109,7 +1190,7 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
|
||||
// Load the model.
|
||||
final int hwHandle = 13;
|
||||
int handle = loadGenericModel(module, hwHandle);
|
||||
int handle = loadGenericModel(module, hwHandle).first;
|
||||
|
||||
// Initiate a recognition.
|
||||
startRecognition(module, handle, hwHandle);
|
||||
@@ -1145,7 +1226,7 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
|
||||
// Load the model.
|
||||
final int hwHandle = 13;
|
||||
int handle = loadPhraseModel(module, hwHandle);
|
||||
int handle = loadPhraseModel(module, hwHandle).first;
|
||||
|
||||
// Initiate a recognition.
|
||||
startRecognition(module, handle, hwHandle);
|
||||
@@ -1182,7 +1263,7 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
ISoundTriggerCallback callback = createCallbackMock();
|
||||
ISoundTriggerModule module = mService.attach(0, callback);
|
||||
final int hwHandle = 12;
|
||||
int modelHandle = loadGenericModel(module, hwHandle);
|
||||
int modelHandle = loadGenericModel(module, hwHandle).first;
|
||||
|
||||
doAnswer((Answer<Void>) invocation -> {
|
||||
android.hardware.soundtrigger.V2_3.ISoundTriggerHw.queryParameterCallback
|
||||
@@ -1218,7 +1299,7 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
ISoundTriggerCallback callback = createCallbackMock();
|
||||
ISoundTriggerModule module = mService.attach(0, callback);
|
||||
final int hwHandle = 13;
|
||||
int modelHandle = loadGenericModel(module, hwHandle);
|
||||
int modelHandle = loadGenericModel(module, hwHandle).first;
|
||||
|
||||
ModelParameterRange range = module.queryModelParameterSupport(modelHandle,
|
||||
ModelParameter.THRESHOLD_FACTOR);
|
||||
@@ -1239,7 +1320,7 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
ISoundTriggerCallback callback = createCallbackMock();
|
||||
ISoundTriggerModule module = mService.attach(0, callback);
|
||||
final int hwHandle = 13;
|
||||
int modelHandle = loadGenericModel(module, hwHandle);
|
||||
int modelHandle = loadGenericModel(module, hwHandle).first;
|
||||
|
||||
doAnswer(invocation -> {
|
||||
android.hardware.soundtrigger.V2_3.ISoundTriggerHw.queryParameterCallback
|
||||
@@ -1272,7 +1353,7 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
ISoundTriggerCallback callback = createCallbackMock();
|
||||
ISoundTriggerModule module = mService.attach(0, callback);
|
||||
final int hwHandle = 14;
|
||||
int modelHandle = loadGenericModel(module, hwHandle);
|
||||
int modelHandle = loadGenericModel(module, hwHandle).first;
|
||||
|
||||
doAnswer(invocation -> {
|
||||
android.hardware.soundtrigger.V2_3.ISoundTriggerHw.getParameterCallback
|
||||
@@ -1304,7 +1385,7 @@ public class SoundTriggerMiddlewareImplTest {
|
||||
ISoundTriggerCallback callback = createCallbackMock();
|
||||
ISoundTriggerModule module = mService.attach(0, callback);
|
||||
final int hwHandle = 17;
|
||||
int modelHandle = loadGenericModel(module, hwHandle);
|
||||
int modelHandle = loadGenericModel(module, hwHandle).first;
|
||||
|
||||
when(driver.setParameter(hwHandle,
|
||||
android.hardware.soundtrigger.V2_3.ModelParameter.THRESHOLD_FACTOR,
|
||||
|
||||
Reference in New Issue
Block a user