add parameter control to AlwaysOnHotwordDetector
Per-model control to AlwaysOnHotwordDetector interface. Models are selected by keyphrase and locale associated with the AlwaysOnHotwordDetector instance. Bug: 141929369 Test: tested manually with test app Change-Id: Iffeb0954059fa030d8a4fefb934a3e665323be37
This commit is contained in:
@@ -42617,9 +42617,13 @@ package android.service.voice {
|
||||
method public android.content.Intent createEnrollIntent();
|
||||
method public android.content.Intent createReEnrollIntent();
|
||||
method public android.content.Intent createUnEnrollIntent();
|
||||
method public int getParameter(int);
|
||||
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 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_MODE_USER_IDENTIFICATION = 2; // 0x2
|
||||
@@ -42644,6 +42648,11 @@ package android.service.voice {
|
||||
method @Nullable public byte[] getTriggerAudio();
|
||||
}
|
||||
|
||||
public static final class AlwaysOnHotwordDetector.ModelParamRange {
|
||||
method public int end();
|
||||
method public int start();
|
||||
}
|
||||
|
||||
public class VoiceInteractionService extends android.app.Service {
|
||||
ctor public VoiceInteractionService();
|
||||
method public final android.service.voice.AlwaysOnHotwordDetector createAlwaysOnHotwordDetector(String, java.util.Locale, android.service.voice.AlwaysOnHotwordDetector.Callback);
|
||||
|
||||
@@ -3535,7 +3535,6 @@ package android.hardware.soundtrigger {
|
||||
}
|
||||
|
||||
public static final class SoundTrigger.ModelParamRange implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.hardware.soundtrigger.SoundTrigger.ModelParamRange> CREATOR;
|
||||
field public final int end;
|
||||
@@ -4349,9 +4348,9 @@ package android.media.soundtrigger {
|
||||
method public int getDetectionServiceOperationsTimeout();
|
||||
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public android.media.soundtrigger.SoundTriggerManager.Model getModel(java.util.UUID);
|
||||
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public android.hardware.soundtrigger.SoundTrigger.ModuleProperties getModuleProperties();
|
||||
method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public int getParameter(@NonNull java.util.UUID, int) throws java.lang.IllegalArgumentException, java.lang.UnsupportedOperationException;
|
||||
method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public int getParameter(@NonNull java.util.UUID, int);
|
||||
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public android.hardware.soundtrigger.SoundTrigger.ModelParamRange queryParameter(@Nullable java.util.UUID, int);
|
||||
method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public int setParameter(@Nullable java.util.UUID, int, int) throws java.lang.IllegalArgumentException, java.lang.UnsupportedOperationException;
|
||||
method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public int setParameter(@Nullable java.util.UUID, int, int);
|
||||
method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public void updateModel(android.media.soundtrigger.SoundTriggerManager.Model);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package android.hardware.soundtrigger;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.hardware.soundtrigger.ModelParams;
|
||||
import android.media.AudioFormat;
|
||||
import android.media.audio.common.AudioConfig;
|
||||
@@ -32,8 +33,6 @@ 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;
|
||||
|
||||
|
||||
@@ -588,19 +588,19 @@ public class SoundTrigger {
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
/**
|
||||
* A ModelParamRange is a representation of supported parameter range for a
|
||||
* given loaded model.
|
||||
****************************************************************************/
|
||||
*/
|
||||
public static final class ModelParamRange implements Parcelable {
|
||||
|
||||
/**
|
||||
* start of supported range inclusive
|
||||
* The inclusive start of supported range.
|
||||
*/
|
||||
public final int start;
|
||||
|
||||
/**
|
||||
* end of supported range inclusive
|
||||
* The inclusive end of supported range.
|
||||
*/
|
||||
public final int end;
|
||||
|
||||
@@ -609,31 +609,65 @@ public class SoundTrigger {
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
private ModelParamRange(@NonNull Parcel in) {
|
||||
this.start = in.readInt();
|
||||
this.end = in.readInt();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static final Creator<ModelParamRange> CREATOR = new Creator<ModelParamRange>() {
|
||||
@Override
|
||||
@NonNull
|
||||
public ModelParamRange createFromParcel(@NonNull Parcel in) {
|
||||
return new ModelParamRange(in);
|
||||
}
|
||||
public static final Creator<ModelParamRange> CREATOR =
|
||||
new Creator<ModelParamRange>() {
|
||||
@Override
|
||||
@NonNull
|
||||
public ModelParamRange createFromParcel(@NonNull Parcel in) {
|
||||
return new ModelParamRange(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public ModelParamRange[] newArray(int size) {
|
||||
return new ModelParamRange[size];
|
||||
}
|
||||
};
|
||||
@Override
|
||||
@NonNull
|
||||
public ModelParamRange[] newArray(int size) {
|
||||
return new ModelParamRange[size];
|
||||
}
|
||||
};
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (start);
|
||||
result = prime * result + (end);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
ModelParamRange other = (ModelParamRange) obj;
|
||||
if (start != other.start) {
|
||||
return false;
|
||||
}
|
||||
if (end != other.end) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeInt(start);
|
||||
|
||||
@@ -168,6 +168,22 @@ public class AlwaysOnHotwordDetector {
|
||||
public static final int RECOGNITION_MODE_USER_IDENTIFICATION
|
||||
= SoundTrigger.RECOGNITION_MODE_USER_IDENTIFICATION;
|
||||
|
||||
/** @hide */
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(flag = true, prefix = { "MODEL_PARAM_" }, value = {
|
||||
MODEL_PARAM_THRESHOLD_FACTOR,
|
||||
})
|
||||
public @interface ModelParams {}
|
||||
|
||||
/**
|
||||
* Controls the sensitivity threshold adjustment factor for a given model.
|
||||
* Negative value corresponds to less sensitive model (high threshold) and
|
||||
* a positive value corresponds to a more sensitive model (low threshold).
|
||||
* Default value is 0.
|
||||
*/
|
||||
public static final int MODEL_PARAM_THRESHOLD_FACTOR =
|
||||
android.hardware.soundtrigger.ModelParams.THRESHOLD_FACTOR;
|
||||
|
||||
static final String TAG = "AlwaysOnHotwordDetector";
|
||||
static final boolean DBG = false;
|
||||
|
||||
@@ -197,6 +213,53 @@ public class AlwaysOnHotwordDetector {
|
||||
|
||||
private int mAvailability = STATE_NOT_READY;
|
||||
|
||||
/**
|
||||
* A ModelParamRange is a representation of supported parameter range for a
|
||||
* given loaded model.
|
||||
*/
|
||||
public static final class ModelParamRange {
|
||||
private final SoundTrigger.ModelParamRange mModelParamRange;
|
||||
|
||||
/** @hide */
|
||||
ModelParamRange(SoundTrigger.ModelParamRange modelParamRange) {
|
||||
mModelParamRange = modelParamRange;
|
||||
}
|
||||
|
||||
/**
|
||||
* The inclusive start of supported range.
|
||||
*
|
||||
* @return start of range
|
||||
*/
|
||||
public int start() {
|
||||
return mModelParamRange.start;
|
||||
}
|
||||
|
||||
/**
|
||||
* The inclusive end of supported range.
|
||||
*
|
||||
* @return end of range
|
||||
*/
|
||||
public int end() {
|
||||
return mModelParamRange.end;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public String toString() {
|
||||
return mModelParamRange.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
return mModelParamRange.equals(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return mModelParamRange.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Additional payload for {@link Callback#onDetected}.
|
||||
*/
|
||||
@@ -444,6 +507,83 @@ public class AlwaysOnHotwordDetector {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* stopping recognition. Once the model is unloaded, the value will be lost.
|
||||
* {@link AlwaysOnHotwordDetector#queryParameter} should be checked first before calling this
|
||||
* method.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
public int setParameter(@ModelParams int modelParam, int value) {
|
||||
if (DBG) {
|
||||
Slog.d(TAG, "setParameter(" + modelParam + ", " + value + ")");
|
||||
}
|
||||
|
||||
synchronized (mLock) {
|
||||
if (mAvailability == STATE_INVALID) {
|
||||
throw new IllegalStateException("setParameter called on an invalid detector");
|
||||
}
|
||||
|
||||
return setParameterLocked(modelParam, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 AlwaysOnHotwordDetector#queryParameter} should be checked first before
|
||||
* calling this method.
|
||||
*
|
||||
* @param modelParam {@link ModelParams}
|
||||
* @return value of parameter
|
||||
*/
|
||||
public int getParameter(@ModelParams int modelParam) {
|
||||
if (DBG) {
|
||||
Slog.d(TAG, "getParameter(" + modelParam + ")");
|
||||
}
|
||||
|
||||
synchronized (mLock) {
|
||||
if (mAvailability == STATE_INVALID) {
|
||||
throw new IllegalStateException("getParameter called on an invalid detector");
|
||||
}
|
||||
|
||||
return getParameterLocked(modelParam);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if parameter control is supported for the given model handle.
|
||||
* This method should be checked prior to calling {@link AlwaysOnHotwordDetector#setParameter}
|
||||
* or {@link AlwaysOnHotwordDetector#getParameter}.
|
||||
*
|
||||
* @param modelParam {@link ModelParams}
|
||||
* @return supported range of parameter, null if not supported
|
||||
*/
|
||||
@Nullable
|
||||
public ModelParamRange queryParameter(@ModelParams int modelParam) {
|
||||
if (DBG) {
|
||||
Slog.d(TAG, "queryParameter(" + modelParam + ")");
|
||||
}
|
||||
|
||||
synchronized (mLock) {
|
||||
if (mAvailability == STATE_INVALID) {
|
||||
throw new IllegalStateException("queryParameter called on an invalid detector");
|
||||
}
|
||||
|
||||
return queryParameterLocked(modelParam);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an intent to start the enrollment for the associated keyphrase.
|
||||
* This intent must be invoked using {@link Context#startForegroundService(Intent)}.
|
||||
@@ -601,6 +741,47 @@ public class AlwaysOnHotwordDetector {
|
||||
return code;
|
||||
}
|
||||
|
||||
private int setParameterLocked(@ModelParams int modelParam, int value) {
|
||||
try {
|
||||
int code = mModelManagementService.setParameter(mVoiceInteractionService,
|
||||
mKeyphraseMetadata.id, modelParam, value);
|
||||
|
||||
if (code != STATUS_OK) {
|
||||
Slog.w(TAG, "setParameter failed with error code " + code);
|
||||
}
|
||||
|
||||
return code;
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
private int getParameterLocked(@ModelParams int modelParam) {
|
||||
try {
|
||||
return mModelManagementService.getParameter(mVoiceInteractionService,
|
||||
mKeyphraseMetadata.id, modelParam);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ModelParamRange queryParameterLocked(@ModelParams int modelParam) {
|
||||
try {
|
||||
SoundTrigger.ModelParamRange modelParamRange =
|
||||
mModelManagementService.queryParameter(mVoiceInteractionService,
|
||||
mKeyphraseMetadata.id, modelParam);
|
||||
|
||||
if (modelParamRange == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ModelParamRange(modelParamRange);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyStateChangedLocked() {
|
||||
Message message = Message.obtain(mHandler, MSG_AVAILABILITY_CHANGED);
|
||||
message.arg1 = mAvailability;
|
||||
|
||||
@@ -61,10 +61,6 @@ interface ISoundTriggerService {
|
||||
int setParameter(in ParcelUuid soundModelId, in ModelParams modelParam,
|
||||
int value);
|
||||
|
||||
/**
|
||||
* @throws UnsupportedOperationException if hal or model do not support this API.
|
||||
* @throws IllegalArgumentException if invalid model handle or parameter is passed.
|
||||
*/
|
||||
int getParameter(in ParcelUuid soundModelId, in ModelParams modelParam);
|
||||
|
||||
@nullable SoundTrigger.ModelParamRange queryParameter(in ParcelUuid soundModelId,
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.android.internal.app.IVoiceInteractionSessionShowCallback;
|
||||
import com.android.internal.app.IVoiceInteractor;
|
||||
import com.android.internal.app.IVoiceInteractionSessionListener;
|
||||
import android.hardware.soundtrigger.IRecognitionStatusCallback;
|
||||
import android.hardware.soundtrigger.ModelParams;
|
||||
import android.hardware.soundtrigger.SoundTrigger;
|
||||
import android.service.voice.IVoiceInteractionService;
|
||||
import android.service.voice.IVoiceInteractionSession;
|
||||
@@ -91,6 +92,49 @@ interface IVoiceInteractionManagerService {
|
||||
*/
|
||||
int stopRecognition(in IVoiceInteractionService service, int keyphraseId,
|
||||
in IRecognitionStatusCallback callback);
|
||||
/**
|
||||
* Set a model specific ModelParams with the given value. 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.
|
||||
* queryParameter should be checked first before calling this method.
|
||||
*
|
||||
* @param service The current VoiceInteractionService.
|
||||
* @param keyphraseId The unique identifier for the keyphrase.
|
||||
* @param modelParam 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
|
||||
*/
|
||||
int setParameter(in IVoiceInteractionService service, int keyphraseId,
|
||||
in ModelParams modelParam, int value);
|
||||
/**
|
||||
* Get a model specific 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 ModelParams for parameter default values.
|
||||
* queryParameter should be checked first before calling this method.
|
||||
*
|
||||
* @param service The current VoiceInteractionService.
|
||||
* @param keyphraseId The unique identifier for the keyphrase.
|
||||
* @param modelParam ModelParams
|
||||
* @return value of parameter
|
||||
*/
|
||||
int getParameter(in IVoiceInteractionService service, int keyphraseId,
|
||||
in ModelParams modelParam);
|
||||
/**
|
||||
* Determine if parameter control is supported for the given model handle.
|
||||
* This method should be checked prior to calling setParameter or getParameter.
|
||||
*
|
||||
* @param service The current VoiceInteractionService.
|
||||
* @param keyphraseId The unique identifier for the keyphrase.
|
||||
* @param modelParam ModelParams
|
||||
* @return supported range of parameter, null if not supported
|
||||
*/
|
||||
@nullable SoundTrigger.ModelParamRange queryParameter(in IVoiceInteractionService service,
|
||||
int keyphraseId, in ModelParams modelParam);
|
||||
|
||||
/**
|
||||
* @return the component name for the currently active voice interaction service
|
||||
|
||||
@@ -428,8 +428,7 @@ public final class SoundTriggerManager {
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
|
||||
public int setParameter(@Nullable UUID soundModelId,
|
||||
@ModelParams int modelParam, int value)
|
||||
throws UnsupportedOperationException, IllegalArgumentException {
|
||||
@ModelParams int modelParam, int value) {
|
||||
try {
|
||||
return mSoundTriggerService.setParameter(new ParcelUuid(soundModelId), modelParam,
|
||||
value);
|
||||
@@ -449,15 +448,10 @@ public final class SoundTriggerManager {
|
||||
* @param soundModelId UUID of model to get parameter
|
||||
* @param modelParam {@link ModelParams}
|
||||
* @return value of parameter
|
||||
* @throws UnsupportedOperationException if hal or model do not support this API.
|
||||
* {@link SoundTriggerManager#queryParameter} should be checked first.
|
||||
* @throws IllegalArgumentException if invalid model handle or parameter is passed.
|
||||
* {@link SoundTriggerManager#queryParameter} should be checked first.
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
|
||||
public int getParameter(@NonNull UUID soundModelId,
|
||||
@ModelParams int modelParam)
|
||||
throws UnsupportedOperationException, IllegalArgumentException {
|
||||
@ModelParams int modelParam) {
|
||||
try {
|
||||
return mSoundTriggerService.getParameter(new ParcelUuid(soundModelId), modelParam);
|
||||
} catch (RemoteException e) {
|
||||
@@ -479,8 +473,7 @@ public final class SoundTriggerManager {
|
||||
public ModelParamRange queryParameter(@Nullable UUID soundModelId,
|
||||
@ModelParams int modelParam) {
|
||||
try {
|
||||
return mSoundTriggerService.queryParameter(new ParcelUuid(soundModelId),
|
||||
modelParam);
|
||||
return mSoundTriggerService.queryParameter(new ParcelUuid(soundModelId), modelParam);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
|
||||
@@ -611,65 +611,91 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
|
||||
|
||||
int setParameter(UUID modelId, @ModelParams int modelParam, int value) {
|
||||
synchronized (mLock) {
|
||||
MetricsLogger.count(mContext, "sth_set_parameter", 1);
|
||||
if (modelId == null || mModule == null) {
|
||||
return SoundTrigger.STATUS_ERROR;
|
||||
}
|
||||
ModelData modelData = mModelDataMap.get(modelId);
|
||||
if (modelData == null) {
|
||||
Slog.w(TAG, "SetParameter: Invalid model id:" + modelId);
|
||||
return SoundTrigger.STATUS_BAD_VALUE;
|
||||
}
|
||||
if (!modelData.isModelLoaded()) {
|
||||
Slog.i(TAG, "SetParameter: Given model is not loaded:" + modelId);
|
||||
return SoundTrigger.STATUS_BAD_VALUE;
|
||||
}
|
||||
|
||||
return mModule.setParameter(modelData.getHandle(), modelParam, value);
|
||||
return setParameterLocked(mModelDataMap.get(modelId), modelParam, value);
|
||||
}
|
||||
}
|
||||
|
||||
int getParameter(@NonNull UUID modelId, @ModelParams int modelParam)
|
||||
throws UnsupportedOperationException, IllegalArgumentException {
|
||||
int setKeyphraseParameter(int keyphraseId, @ModelParams int modelParam, int value) {
|
||||
synchronized (mLock) {
|
||||
MetricsLogger.count(mContext, "sth_get_parameter", 1);
|
||||
if (mModule == null) {
|
||||
throw new UnsupportedOperationException("SoundTriggerModule not initialized");
|
||||
}
|
||||
|
||||
ModelData modelData = mModelDataMap.get(modelId);
|
||||
if (modelData == null) {
|
||||
throw new IllegalArgumentException("Invalid model id:" + modelId);
|
||||
}
|
||||
if (!modelData.isModelLoaded()) {
|
||||
throw new UnsupportedOperationException("Given model is not loaded:" + modelId);
|
||||
}
|
||||
|
||||
return mModule.getParameter(modelData.getHandle(), modelParam);
|
||||
return setParameterLocked(getKeyphraseModelDataLocked(keyphraseId), modelParam, value);
|
||||
}
|
||||
}
|
||||
|
||||
private int setParameterLocked(@Nullable ModelData modelData, @ModelParams int modelParam,
|
||||
int value) {
|
||||
MetricsLogger.count(mContext, "sth_set_parameter", 1);
|
||||
if (mModule == null) {
|
||||
return SoundTrigger.STATUS_NO_INIT;
|
||||
}
|
||||
if (modelData == null || !modelData.isModelLoaded()) {
|
||||
Slog.i(TAG, "SetParameter: Given model is not loaded:" + modelData);
|
||||
return SoundTrigger.STATUS_BAD_VALUE;
|
||||
}
|
||||
|
||||
return mModule.setParameter(modelData.getHandle(), modelParam, value);
|
||||
}
|
||||
|
||||
int getParameter(@NonNull UUID modelId, @ModelParams int modelParam) {
|
||||
synchronized (mLock) {
|
||||
return getParameterLocked(mModelDataMap.get(modelId), modelParam);
|
||||
}
|
||||
}
|
||||
|
||||
int getKeyphraseParameter(int keyphraseId, @ModelParams int modelParam) {
|
||||
synchronized (mLock) {
|
||||
return getParameterLocked(getKeyphraseModelDataLocked(keyphraseId), modelParam);
|
||||
}
|
||||
}
|
||||
|
||||
private int getParameterLocked(@Nullable ModelData modelData, @ModelParams int modelParam) {
|
||||
MetricsLogger.count(mContext, "sth_get_parameter", 1);
|
||||
if (mModule == null) {
|
||||
throw new UnsupportedOperationException("SoundTriggerModule not initialized");
|
||||
}
|
||||
|
||||
if (modelData == null) {
|
||||
throw new IllegalArgumentException("Invalid model id");
|
||||
}
|
||||
if (!modelData.isModelLoaded()) {
|
||||
throw new UnsupportedOperationException("Given model is not loaded:" + modelData);
|
||||
}
|
||||
|
||||
return mModule.getParameter(modelData.getHandle(), modelParam);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
ModelParamRange queryParameter(@NonNull UUID modelId, @ModelParams int modelParam) {
|
||||
synchronized (mLock) {
|
||||
MetricsLogger.count(mContext, "sth_query_parameter", 1);
|
||||
if (mModule == null) {
|
||||
return null;
|
||||
}
|
||||
ModelData modelData = mModelDataMap.get(modelId);
|
||||
if (modelData == null) {
|
||||
Slog.w(TAG, "queryParameter: Invalid model id:" + modelId);
|
||||
return null;
|
||||
}
|
||||
if (!modelData.isModelLoaded()) {
|
||||
Slog.i(TAG, "queryParameter: Given model is not loaded:" + modelId);
|
||||
return null;
|
||||
}
|
||||
|
||||
return mModule.queryParameter(modelData.getHandle(), modelParam);
|
||||
return queryParameterLocked(mModelDataMap.get(modelId), modelParam);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
ModelParamRange queryKeyphraseParameter(int keyphraseId, @ModelParams int modelParam) {
|
||||
synchronized (mLock) {
|
||||
return queryParameterLocked(getKeyphraseModelDataLocked(keyphraseId), modelParam);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ModelParamRange queryParameterLocked(@Nullable ModelData modelData,
|
||||
@ModelParams int modelParam) {
|
||||
MetricsLogger.count(mContext, "sth_query_parameter", 1);
|
||||
if (mModule == null) {
|
||||
return null;
|
||||
}
|
||||
if (modelData == null) {
|
||||
Slog.w(TAG, "queryParameter: Invalid model id");
|
||||
return null;
|
||||
}
|
||||
if (!modelData.isModelLoaded()) {
|
||||
Slog.i(TAG, "queryParameter: Given model is not loaded:" + modelData);
|
||||
return null;
|
||||
}
|
||||
|
||||
return mModule.queryParameter(modelData.getHandle(), modelParam);
|
||||
}
|
||||
|
||||
//---- SoundTrigger.StatusListener methods
|
||||
@Override
|
||||
public void onRecognition(RecognitionEvent event) {
|
||||
|
||||
@@ -16,17 +16,17 @@
|
||||
|
||||
package com.android.server.soundtrigger;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.hardware.soundtrigger.IRecognitionStatusCallback;
|
||||
import android.hardware.soundtrigger.ModelParams;
|
||||
import android.hardware.soundtrigger.SoundTrigger;
|
||||
import android.hardware.soundtrigger.SoundTrigger.Keyphrase;
|
||||
import android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionEvent;
|
||||
import android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra;
|
||||
import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
|
||||
import android.hardware.soundtrigger.SoundTrigger.ModelParamRange;
|
||||
import android.hardware.soundtrigger.SoundTrigger.ModuleProperties;
|
||||
import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
|
||||
import android.hardware.soundtrigger.SoundTrigger.RecognitionEvent;
|
||||
import android.hardware.soundtrigger.SoundTrigger.SoundModelEvent;
|
||||
import android.hardware.soundtrigger.SoundTriggerModule;
|
||||
|
||||
import com.android.server.voiceinteraction.VoiceInteractionManagerService;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
@@ -70,6 +70,58 @@ public abstract class SoundTriggerInternal {
|
||||
|
||||
public abstract ModuleProperties getModuleProperties();
|
||||
|
||||
/**
|
||||
* 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
|
||||
* stopping recognition. Once the model is unloaded, the value will be lost.
|
||||
* {@link SoundTriggerInternal#queryParameter} should be checked first before calling this
|
||||
* method.
|
||||
*
|
||||
* @param keyphraseId The identifier of the keyphrase for which
|
||||
* to modify model parameters
|
||||
* @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
|
||||
*/
|
||||
public abstract int setParameter(int keyphraseId, @ModelParams int modelParam, int value);
|
||||
|
||||
/**
|
||||
* 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 ModelParams for parameter default values.
|
||||
* {@link SoundTriggerInternal#queryParameter} should be checked first before calling this
|
||||
* method.
|
||||
*
|
||||
* @param keyphraseId The identifier of the keyphrase for which
|
||||
* to modify model parameters
|
||||
* @param modelParam {@link ModelParams}
|
||||
* @return value of parameter
|
||||
* @throws UnsupportedOperationException if hal or model do not support this API.
|
||||
* queryParameter should be checked first.
|
||||
* @throws IllegalArgumentException if invalid model handle or parameter is passed.
|
||||
* queryParameter should be checked first.
|
||||
*/
|
||||
public abstract int getParameter(int keyphraseId, @ModelParams int modelParam);
|
||||
|
||||
/**
|
||||
* Determine if parameter control is supported for the given model handle.
|
||||
* This method should be checked prior to calling {@link SoundTriggerInternal#setParameter}
|
||||
* or {@link SoundTriggerInternal#getParameter}.
|
||||
*
|
||||
* @param keyphraseId The identifier of the keyphrase for which
|
||||
* to modify model parameters
|
||||
* @param modelParam {@link ModelParams}
|
||||
* @return supported range of parameter, null if not supported
|
||||
*/
|
||||
@Nullable
|
||||
public abstract ModelParamRange queryParameter(int keyphraseId,
|
||||
@ModelParams int modelParam);
|
||||
|
||||
/**
|
||||
* Unloads (and stops if running) the given keyphraseId
|
||||
*/
|
||||
|
||||
@@ -1446,26 +1446,45 @@ public class SoundTriggerService extends SystemService {
|
||||
@Override
|
||||
public int startRecognition(int keyphraseId, KeyphraseSoundModel soundModel,
|
||||
IRecognitionStatusCallback listener, RecognitionConfig recognitionConfig) {
|
||||
if (!isInitialized()) return STATUS_ERROR;
|
||||
if (!isInitialized()) throw new UnsupportedOperationException();
|
||||
return mSoundTriggerHelper.startKeyphraseRecognition(keyphraseId, soundModel, listener,
|
||||
recognitionConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int stopRecognition(int keyphraseId, IRecognitionStatusCallback listener) {
|
||||
if (!isInitialized()) return STATUS_ERROR;
|
||||
if (!isInitialized()) throw new UnsupportedOperationException();
|
||||
return mSoundTriggerHelper.stopKeyphraseRecognition(keyphraseId, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModuleProperties getModuleProperties() {
|
||||
if (!isInitialized()) return null;
|
||||
if (!isInitialized()) throw new UnsupportedOperationException();
|
||||
return mSoundTriggerHelper.getModuleProperties();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setParameter(int keyphraseId, @ModelParams int modelParam, int value) {
|
||||
if (!isInitialized()) throw new UnsupportedOperationException();
|
||||
return mSoundTriggerHelper.setKeyphraseParameter(keyphraseId, modelParam, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getParameter(int keyphraseId, @ModelParams int modelParam) {
|
||||
if (!isInitialized()) throw new UnsupportedOperationException();
|
||||
return mSoundTriggerHelper.getKeyphraseParameter(keyphraseId, modelParam);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ModelParamRange queryParameter(int keyphraseId, @ModelParams int modelParam) {
|
||||
if (!isInitialized()) throw new UnsupportedOperationException();
|
||||
return mSoundTriggerHelper.queryKeyphraseParameter(keyphraseId, modelParam);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int unloadKeyphraseModel(int keyphraseId) {
|
||||
if (!isInitialized()) return STATUS_ERROR;
|
||||
if (!isInitialized()) throw new UnsupportedOperationException();
|
||||
return mSoundTriggerHelper.unloadKeyphraseSoundModel(keyphraseId);
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,9 @@ import android.content.pm.UserInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.database.ContentObserver;
|
||||
import android.hardware.soundtrigger.IRecognitionStatusCallback;
|
||||
import android.hardware.soundtrigger.ModelParams;
|
||||
import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
|
||||
import android.hardware.soundtrigger.SoundTrigger.ModelParamRange;
|
||||
import android.hardware.soundtrigger.SoundTrigger.ModuleProperties;
|
||||
import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
|
||||
import android.os.Binder;
|
||||
@@ -1084,6 +1086,55 @@ public class VoiceInteractionManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setParameter(IVoiceInteractionService service, int keyphraseId,
|
||||
@ModelParams int modelParam, int value) {
|
||||
// Allow the call if this is the current voice interaction service.
|
||||
synchronized (this) {
|
||||
enforceIsCurrentVoiceInteractionService(service);
|
||||
}
|
||||
|
||||
final long caller = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return mSoundTriggerInternal.setParameter(keyphraseId, modelParam, value);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(caller);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getParameter(IVoiceInteractionService service, int keyphraseId,
|
||||
@ModelParams int modelParam) {
|
||||
// Allow the call if this is the current voice interaction service.
|
||||
synchronized (this) {
|
||||
enforceIsCurrentVoiceInteractionService(service);
|
||||
}
|
||||
|
||||
final long caller = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return mSoundTriggerInternal.getParameter(keyphraseId, modelParam);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(caller);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ModelParamRange queryParameter(IVoiceInteractionService service,
|
||||
int keyphraseId, @ModelParams int modelParam) {
|
||||
// Allow the call if this is the current voice interaction service.
|
||||
synchronized (this) {
|
||||
enforceIsCurrentVoiceInteractionService(service);
|
||||
}
|
||||
|
||||
final long caller = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return mSoundTriggerInternal.queryParameter(keyphraseId, modelParam);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(caller);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void unloadAllKeyphraseModels() {
|
||||
for (int i = 0; i < mLoadedKeyphraseIds.size(); i++) {
|
||||
final long caller = Binder.clearCallingIdentity();
|
||||
|
||||
Reference in New Issue
Block a user