Merge "Support back-to-back soundtrigger recognitions"

This commit is contained in:
Ytai Ben-tsvi
2021-10-18 20:11:00 +00:00
committed by Android (Google) Code Review
14 changed files with 187 additions and 62 deletions

View File

@@ -204,7 +204,7 @@ class ConversionUtil {
aidlEvent.status,
modelHandle, aidlEvent.captureAvailable, captureSession,
aidlEvent.captureDelayMs, aidlEvent.capturePreambleMs, aidlEvent.triggerInData,
audioFormat, aidlEvent.data);
audioFormat, aidlEvent.data, aidlEvent.recognitionStillActive);
}
public static SoundTrigger.RecognitionEvent aidl2apiPhraseRecognitionEvent(

View File

@@ -1175,6 +1175,11 @@ public class SoundTrigger {
@UnsupportedAppUsage
@NonNull
public final byte[] data;
/**
* Is recognition still active after this event.
* @hide
*/
public final boolean recognitionStillActive;
/** @hide */
@TestApi
@@ -1182,6 +1187,16 @@ public class SoundTrigger {
public RecognitionEvent(int status, int soundModelHandle, boolean captureAvailable,
int captureSession, int captureDelayMs, int capturePreambleMs,
boolean triggerInData, @NonNull AudioFormat captureFormat, @Nullable byte[] data) {
this(status, soundModelHandle, captureAvailable, captureSession, captureDelayMs,
capturePreambleMs, triggerInData, captureFormat, data,
status == RECOGNITION_STATUS_GET_STATE_RESPONSE);
}
/** @hide */
public RecognitionEvent(int status, int soundModelHandle, boolean captureAvailable,
int captureSession, int captureDelayMs, int capturePreambleMs,
boolean triggerInData, @NonNull AudioFormat captureFormat, @Nullable byte[] data,
boolean recognitionStillActive) {
this.status = status;
this.soundModelHandle = soundModelHandle;
this.captureAvailable = captureAvailable;
@@ -1191,6 +1206,7 @@ public class SoundTrigger {
this.triggerInData = triggerInData;
this.captureFormat = requireNonNull(captureFormat);
this.data = data != null ? data : new byte[0];
this.recognitionStillActive = recognitionStillActive;
}
/**
@@ -1266,8 +1282,10 @@ public class SoundTrigger {
.build();
}
byte[] data = in.readBlob();
boolean recognitionStillActive = in.readBoolean();
return new RecognitionEvent(status, soundModelHandle, captureAvailable, captureSession,
captureDelayMs, capturePreambleMs, triggerInData, captureFormat, data);
captureDelayMs, capturePreambleMs, triggerInData, captureFormat, data,
recognitionStillActive);
}
/** @hide */
@@ -1293,8 +1311,8 @@ public class SoundTrigger {
dest.writeByte((byte)0);
}
dest.writeBlob(data);
dest.writeBoolean(recognitionStillActive);
}
@Override
public int hashCode() {
final int prime = 31;
@@ -1312,6 +1330,7 @@ public class SoundTrigger {
result = prime * result + Arrays.hashCode(data);
result = prime * result + soundModelHandle;
result = prime * result + status;
result = result + (recognitionStillActive ? 1289 : 1291);
return result;
}
@@ -1334,6 +1353,8 @@ public class SoundTrigger {
return false;
if (!Arrays.equals(data, other.data))
return false;
if (recognitionStillActive != other.recognitionStillActive)
return false;
if (soundModelHandle != other.soundModelHandle)
return false;
if (status != other.status)
@@ -1370,7 +1391,9 @@ public class SoundTrigger {
(", encoding=" + captureFormat.getEncoding()))
+ ((captureFormat == null) ? "" :
(", channelMask=" + captureFormat.getChannelMask()))
+ ", data=" + (data == null ? 0 : data.length) + "]";
+ ", data=" + (data == null ? 0 : data.length)
+ ", recognitionStillActive=" + recognitionStillActive
+ "]";
}
}
@@ -1673,11 +1696,21 @@ public class SoundTrigger {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public KeyphraseRecognitionEvent(int status, int soundModelHandle, boolean captureAvailable,
int captureSession, int captureDelayMs, int capturePreambleMs,
boolean triggerInData, @NonNull AudioFormat captureFormat, @Nullable byte[] data,
@Nullable KeyphraseRecognitionExtra[] keyphraseExtras) {
int captureSession, int captureDelayMs, int capturePreambleMs,
boolean triggerInData, @NonNull AudioFormat captureFormat, @Nullable byte[] data,
@Nullable KeyphraseRecognitionExtra[] keyphraseExtras) {
this(status, soundModelHandle, captureAvailable, captureSession, captureDelayMs,
capturePreambleMs, triggerInData, captureFormat, data, keyphraseExtras,
status == RECOGNITION_STATUS_GET_STATE_RESPONSE);
}
public KeyphraseRecognitionEvent(int status, int soundModelHandle, boolean captureAvailable,
int captureSession, int captureDelayMs, int capturePreambleMs,
boolean triggerInData, @NonNull AudioFormat captureFormat, @Nullable byte[] data,
@Nullable KeyphraseRecognitionExtra[] keyphraseExtras,
boolean recognitionStillActive) {
super(status, soundModelHandle, captureAvailable, captureSession, captureDelayMs,
capturePreambleMs, triggerInData, captureFormat, data);
capturePreambleMs, triggerInData, captureFormat, data, recognitionStillActive);
this.keyphraseExtras =
keyphraseExtras != null ? keyphraseExtras : new KeyphraseRecognitionExtra[0];
}
@@ -1713,11 +1746,12 @@ public class SoundTrigger {
.build();
}
byte[] data = in.readBlob();
boolean recognitionStillActive = in.readBoolean();
KeyphraseRecognitionExtra[] keyphraseExtras =
in.createTypedArray(KeyphraseRecognitionExtra.CREATOR);
return new KeyphraseRecognitionEvent(status, soundModelHandle, captureAvailable,
captureSession, captureDelayMs, capturePreambleMs, triggerInData,
captureFormat, data, keyphraseExtras);
captureFormat, data, keyphraseExtras, recognitionStillActive);
}
@Override
@@ -1738,6 +1772,7 @@ public class SoundTrigger {
dest.writeByte((byte)0);
}
dest.writeBlob(data);
dest.writeBoolean(recognitionStillActive);
dest.writeTypedArray(keyphraseExtras, flags);
}
@@ -1782,7 +1817,9 @@ public class SoundTrigger {
(", encoding=" + captureFormat.getEncoding()))
+ ((captureFormat == null) ? "" :
(", channelMask=" + captureFormat.getChannelMask()))
+ ", data=" + (data == null ? 0 : data.length) + "]";
+ ", data=" + (data == null ? 0 : data.length)
+ ", recognitionStillActive=" + recognitionStillActive
+ "]";
}
}
@@ -1798,9 +1835,17 @@ public class SoundTrigger {
boolean captureAvailable, int captureSession, int captureDelayMs,
int capturePreambleMs, boolean triggerInData, @NonNull AudioFormat captureFormat,
@Nullable byte[] data) {
super(status, soundModelHandle, captureAvailable, captureSession,
captureDelayMs, capturePreambleMs, triggerInData, captureFormat,
data);
this(status, soundModelHandle, captureAvailable, captureSession, captureDelayMs,
capturePreambleMs, triggerInData, captureFormat, data,
status == RECOGNITION_STATUS_GET_STATE_RESPONSE);
}
public GenericRecognitionEvent(int status, int soundModelHandle,
boolean captureAvailable, int captureSession, int captureDelayMs,
int capturePreambleMs, boolean triggerInData, @NonNull AudioFormat captureFormat,
@Nullable byte[] data, boolean recognitionStillActive) {
super(status, soundModelHandle, captureAvailable, captureSession, captureDelayMs,
capturePreambleMs, triggerInData, captureFormat, data, recognitionStillActive);
}
public static final @android.annotation.NonNull Parcelable.Creator<GenericRecognitionEvent> CREATOR
@@ -1818,7 +1863,8 @@ public class SoundTrigger {
RecognitionEvent event = RecognitionEvent.fromParcel(in);
return new GenericRecognitionEvent(event.status, event.soundModelHandle,
event.captureAvailable, event.captureSession, event.captureDelayMs,
event.capturePreambleMs, event.triggerInData, event.captureFormat, event.data);
event.capturePreambleMs, event.triggerInData, event.captureFormat, event.data,
event.recognitionStillActive);
}
@Override

View File

@@ -48,4 +48,13 @@ parcelable RecognitionEvent {
@nullable AudioConfig audioConfig;
/** Additional data. */
byte[] data;
/**
* If true, recognition is still active after this event.
* For compatibility with earlier versions of this data type, when the status field is set to
* RecognitionStatus.FORCED, the value of this field should be treated as 'true', regardless of
* the actual value.
* When the status is RecognitionStatus.ABORTED or RecognitionStatus.FAILURE, this must be set
* to false.
*/
boolean recognitionStillActive;
}

View File

@@ -43,4 +43,5 @@ parcelable RecognitionEvent {
boolean triggerInData;
@nullable android.media.audio.common.AudioConfig audioConfig;
byte[] data;
boolean recognitionStillActive;
}

View File

@@ -310,6 +310,7 @@ class ConversionUtil {
for (int i = 0; i < aidlEvent.data.length; ++i) {
aidlEvent.data[i] = hidlEvent.data.get(i);
}
aidlEvent.recognitionStillActive = aidlEvent.status == RecognitionStatus.FORCED;
return aidlEvent;
}

View File

@@ -226,8 +226,7 @@ public class SoundTriggerHalConcurrentCaptureHandler implements ISoundTriggerHal
public void recognitionCallback(int modelHandle, RecognitionEvent event) {
// A recognition event must be the last one for its model, unless it is a forced one
// (those leave the model active).
mCallbackThread.pushWithDedupe(modelHandle,
event.status != RecognitionStatus.FORCED,
mCallbackThread.pushWithDedupe(modelHandle, !event.recognitionStillActive,
() -> mDelegateCallback.recognitionCallback(modelHandle, event));
}
@@ -235,8 +234,7 @@ public class SoundTriggerHalConcurrentCaptureHandler implements ISoundTriggerHal
public void phraseRecognitionCallback(int modelHandle, PhraseRecognitionEvent event) {
// A recognition event must be the last one for its model, unless it is a forced one
// (those leave the model active).
mCallbackThread.pushWithDedupe(modelHandle,
event.common.status != RecognitionStatus.FORCED,
mCallbackThread.pushWithDedupe(modelHandle, !event.common.recognitionStillActive,
() -> mDelegateCallback.phraseRecognitionCallback(modelHandle, event));
}

View File

@@ -55,8 +55,7 @@ public class SoundTriggerHalEnforcer implements ISoundTriggerHal {
private final ISoundTriggerHal mUnderlying;
private final Map<Integer, ModelState> mModelStates = new HashMap<>();
public SoundTriggerHalEnforcer(
ISoundTriggerHal underlying) {
public SoundTriggerHalEnforcer(ISoundTriggerHal underlying) {
mUnderlying = underlying;
}
@@ -239,15 +238,12 @@ public class SoundTriggerHalEnforcer implements ISoundTriggerHal {
private class ModelCallbackEnforcer implements ModelCallback {
private final ModelCallback mUnderlying;
private ModelCallbackEnforcer(
ModelCallback underlying) {
private ModelCallbackEnforcer(ModelCallback underlying) {
mUnderlying = underlying;
}
@Override
public void recognitionCallback(int model, RecognitionEvent event) {
int status = event.status;
synchronized (mModelStates) {
ModelState state = mModelStates.get(model);
if (state == null || state == ModelState.INACTIVE) {
@@ -255,7 +251,15 @@ public class SoundTriggerHalEnforcer implements ISoundTriggerHal {
reboot();
return;
}
if (status != RecognitionStatus.FORCED) {
if (event.recognitionStillActive && event.status != RecognitionStatus.SUCCESS
&& event.status != RecognitionStatus.FORCED) {
Log.wtfStack(TAG,
"recognitionStillActive is only allowed when the recognition status "
+ "is SUCCESS");
reboot();
return;
}
if (!event.recognitionStillActive) {
mModelStates.replace(model, ModelState.INACTIVE);
}
}
@@ -265,7 +269,6 @@ public class SoundTriggerHalEnforcer implements ISoundTriggerHal {
@Override
public void phraseRecognitionCallback(int model, PhraseRecognitionEvent event) {
int status = event.common.status;
synchronized (mModelStates) {
ModelState state = mModelStates.get(model);
if (state == null || state == ModelState.INACTIVE) {
@@ -273,7 +276,16 @@ public class SoundTriggerHalEnforcer implements ISoundTriggerHal {
reboot();
return;
}
if (status != RecognitionStatus.FORCED) {
if (event.common.recognitionStillActive
&& event.common.status != RecognitionStatus.SUCCESS
&& event.common.status != RecognitionStatus.FORCED) {
Log.wtfStack(TAG,
"recognitionStillActive is only allowed when the recognition status "
+ "is SUCCESS");
reboot();
return;
}
if (!event.common.recognitionStillActive) {
mModelStates.replace(model, ModelState.INACTIVE);
}
}

View File

@@ -26,6 +26,7 @@ import android.media.soundtrigger.PhraseSoundModel;
import android.media.soundtrigger.Properties;
import android.media.soundtrigger.RecognitionConfig;
import android.media.soundtrigger.RecognitionEvent;
import android.media.soundtrigger.RecognitionStatus;
import android.media.soundtrigger.SoundModel;
import android.media.soundtrigger.Status;
import android.os.IBinder;
@@ -221,11 +222,15 @@ public class SoundTriggerHw3Compat implements ISoundTriggerHal {
@Override
public void phraseRecognitionCallback(int model, PhraseRecognitionEvent event) {
// A FORCED status implies that recognition is still active after the event.
event.common.recognitionStillActive |= event.common.status == RecognitionStatus.FORCED;
mDelegate.phraseRecognitionCallback(model, event);
}
@Override
public void recognitionCallback(int model, RecognitionEvent event) {
// A FORCED status implies that recognition is still active after the event.
event.recognitionStillActive |= event.status == RecognitionStatus.FORCED;
mDelegate.recognitionCallback(model, event);
}
}

View File

@@ -731,7 +731,7 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
int captureSession) {
synchronized (SoundTriggerMiddlewareValidation.this) {
ModelState modelState = mLoadedModels.get(modelHandle);
if (event.status != RecognitionStatus.FORCED) {
if (!event.recognitionStillActive) {
modelState.activityState = ModelState.Activity.LOADED;
}
}
@@ -760,7 +760,7 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
@NonNull PhraseRecognitionEvent event, int captureSession) {
synchronized (SoundTriggerMiddlewareValidation.this) {
ModelState modelState = mLoadedModels.get(modelHandle);
if (event.common.status != RecognitionStatus.FORCED) {
if (!event.common.recognitionStillActive) {
modelState.activityState = ModelState.Activity.LOADED;
}
}
@@ -772,7 +772,7 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
Log.w(TAG, "Client callback exception.", e);
synchronized (SoundTriggerMiddlewareValidation.this) {
ModelState modelState = mLoadedModels.get(modelHandle);
if (event.common.status != RecognitionStatus.FORCED) {
if (!event.common.recognitionStillActive) {
modelState.activityState = ModelState.Activity.INTERCEPTED;
// If we failed to deliver an actual event to the client, they would
// never know to restart it whenever circumstances change. Thus, we

View File

@@ -24,7 +24,6 @@ import android.media.soundtrigger.PhraseSoundModel;
import android.media.soundtrigger.Properties;
import android.media.soundtrigger.RecognitionConfig;
import android.media.soundtrigger.RecognitionEvent;
import android.media.soundtrigger.RecognitionStatus;
import android.media.soundtrigger.SoundModel;
import android.media.soundtrigger.Status;
import android.media.soundtrigger_middleware.ISoundTriggerCallback;
@@ -461,7 +460,7 @@ class SoundTriggerModule implements IBinder.DeathRecipient, ISoundTriggerHal.Glo
@NonNull RecognitionEvent recognitionEvent) {
ISoundTriggerCallback callback;
synchronized (SoundTriggerModule.this) {
if (recognitionEvent.status != RecognitionStatus.FORCED) {
if (!recognitionEvent.recognitionStillActive) {
setState(ModelState.LOADED);
}
callback = mCallback;
@@ -482,7 +481,7 @@ class SoundTriggerModule implements IBinder.DeathRecipient, ISoundTriggerHal.Glo
@NonNull PhraseRecognitionEvent phraseRecognitionEvent) {
ISoundTriggerCallback callback;
synchronized (SoundTriggerModule.this) {
if (phraseRecognitionEvent.common.status != RecognitionStatus.FORCED) {
if (!phraseRecognitionEvent.common.recognitionStillActive) {
setState(ModelState.LOADED);
}
callback = mCallback;

View File

@@ -717,7 +717,8 @@ public class SoundHw2CompatTest {
hwCallback.recognitionCallback(TestUtil.createRecognitionEvent_2_0(handle, status), 99);
mCanonical.flushCallbacks();
verify(canonicalCallback).recognitionCallback(eq(handle), eventCaptor.capture());
TestUtil.validateRecognitionEvent(eventCaptor.getValue(), RecognitionStatus.ABORTED);
TestUtil.validateRecognitionEvent(eventCaptor.getValue(), RecognitionStatus.ABORTED,
false);
}
{
@@ -732,7 +733,7 @@ public class SoundHw2CompatTest {
mCanonical.flushCallbacks();
verify(canonicalCallback).phraseRecognitionCallback(eq(handle), eventCaptor.capture());
TestUtil.validatePhraseRecognitionEvent(eventCaptor.getValue(),
RecognitionStatus.SUCCESS);
RecognitionStatus.SUCCESS, false);
}
verifyNoMoreInteractions(canonicalCallback);
clearInvocations(canonicalCallback);
@@ -752,7 +753,22 @@ public class SoundHw2CompatTest {
99);
mCanonical.flushCallbacks();
verify(canonicalCallback).recognitionCallback(eq(handle), eventCaptor.capture());
TestUtil.validateRecognitionEvent(eventCaptor.getValue(), RecognitionStatus.ABORTED);
TestUtil.validateRecognitionEvent(eventCaptor.getValue(), RecognitionStatus.ABORTED,
false);
}
{
final int handle = 87;
final int status = 3; // FORCED;
ArgumentCaptor<RecognitionEvent> eventCaptor = ArgumentCaptor.forClass(
RecognitionEvent.class);
hwCallback.recognitionCallback_2_1(TestUtil.createRecognitionEvent_2_1(handle, status),
99);
mCanonical.flushCallbacks();
verify(canonicalCallback).recognitionCallback(eq(handle), eventCaptor.capture());
TestUtil.validateRecognitionEvent(eventCaptor.getValue(), RecognitionStatus.FORCED,
true);
}
{
@@ -767,7 +783,21 @@ public class SoundHw2CompatTest {
mCanonical.flushCallbacks();
verify(canonicalCallback).phraseRecognitionCallback(eq(handle), eventCaptor.capture());
TestUtil.validatePhraseRecognitionEvent(eventCaptor.getValue(),
RecognitionStatus.SUCCESS);
RecognitionStatus.SUCCESS, false);
}
{
final int handle = 102;
final int status = 3; // FORCED;
ArgumentCaptor<PhraseRecognitionEvent> eventCaptor = ArgumentCaptor.forClass(
PhraseRecognitionEvent.class);
hwCallback.phraseRecognitionCallback_2_1(
TestUtil.createPhraseRecognitionEvent_2_1(handle, status), 99);
mCanonical.flushCallbacks();
verify(canonicalCallback).phraseRecognitionCallback(eq(handle), eventCaptor.capture());
TestUtil.validatePhraseRecognitionEvent(eventCaptor.getValue(),
RecognitionStatus.FORCED, true);
}
verifyNoMoreInteractions(canonicalCallback);
clearInvocations(canonicalCallback);

View File

@@ -26,6 +26,7 @@ import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -286,16 +287,31 @@ public class SoundTriggerMiddlewareImplTest {
// Initiate a recognition.
startRecognition(module, handle, hwHandle);
// Signal a capture from the driver.
RecognitionEvent event = hwCallback.sendRecognitionEvent(hwHandle,
RecognitionStatus.SUCCESS);
{
// Signal a capture from the driver (with "still active").
RecognitionEvent event = hwCallback.sendRecognitionEvent(hwHandle,
RecognitionStatus.SUCCESS, true);
ArgumentCaptor<RecognitionEvent> eventCaptor = ArgumentCaptor.forClass(
RecognitionEvent.class);
verify(callback).onRecognition(eq(handle), eventCaptor.capture(), eq(101));
ArgumentCaptor<RecognitionEvent> eventCaptor = ArgumentCaptor.forClass(
RecognitionEvent.class);
verify(callback).onRecognition(eq(handle), eventCaptor.capture(), eq(101));
// Validate the event.
assertEquals(event, eventCaptor.getValue());
// Validate the event.
assertEquals(event, eventCaptor.getValue());
}
{
// Signal a capture from the driver (without "still active").
RecognitionEvent event = hwCallback.sendRecognitionEvent(hwHandle,
RecognitionStatus.SUCCESS, false);
ArgumentCaptor<RecognitionEvent> eventCaptor = ArgumentCaptor.forClass(
RecognitionEvent.class);
verify(callback, times(2)).onRecognition(eq(handle), eventCaptor.capture(), eq(101));
// Validate the event.
assertEquals(event, eventCaptor.getValue());
}
// Unload the model.
unloadModel(module, handle, hwHandle);
@@ -318,7 +334,7 @@ public class SoundTriggerMiddlewareImplTest {
// Signal a capture from the driver.
PhraseRecognitionEvent event = hwCallback.sendPhraseRecognitionEvent(hwHandle,
RecognitionStatus.SUCCESS);
RecognitionStatus.SUCCESS, false);
ArgumentCaptor<PhraseRecognitionEvent> eventCaptor = ArgumentCaptor.forClass(
PhraseRecognitionEvent.class);
@@ -352,7 +368,7 @@ public class SoundTriggerMiddlewareImplTest {
// Signal a capture from the driver.
RecognitionEvent event = hwCallback.sendRecognitionEvent(hwHandle,
RecognitionStatus.FORCED);
RecognitionStatus.FORCED, true);
ArgumentCaptor<RecognitionEvent> eventCaptor = ArgumentCaptor.forClass(
RecognitionEvent.class);
@@ -420,7 +436,7 @@ public class SoundTriggerMiddlewareImplTest {
// Signal a capture from the driver.
PhraseRecognitionEvent event = hwCallback.sendPhraseRecognitionEvent(hwHandle,
RecognitionStatus.FORCED);
RecognitionStatus.FORCED, true);
ArgumentCaptor<PhraseRecognitionEvent> eventCaptor = ArgumentCaptor.forClass(
PhraseRecognitionEvent.class);
@@ -484,7 +500,7 @@ public class SoundTriggerMiddlewareImplTest {
startRecognition(module, handle, hwHandle);
// Abort.
hwCallback.sendRecognitionEvent(hwHandle, RecognitionStatus.ABORTED);
hwCallback.sendRecognitionEvent(hwHandle, RecognitionStatus.ABORTED, false);
ArgumentCaptor<RecognitionEvent> eventCaptor = ArgumentCaptor.forClass(
RecognitionEvent.class);
@@ -514,7 +530,7 @@ public class SoundTriggerMiddlewareImplTest {
startRecognition(module, handle, hwHandle);
// Abort.
hwCallback.sendPhraseRecognitionEvent(hwHandle, RecognitionStatus.ABORTED);
hwCallback.sendPhraseRecognitionEvent(hwHandle, RecognitionStatus.ABORTED, false);
ArgumentCaptor<PhraseRecognitionEvent> eventCaptor = ArgumentCaptor.forClass(
PhraseRecognitionEvent.class);
@@ -604,15 +620,18 @@ public class SoundTriggerMiddlewareImplTest {
mCallback = callback;
}
private RecognitionEvent sendRecognitionEvent(int hwHandle, @RecognitionStatus int status) {
RecognitionEvent event = TestUtil.createRecognitionEvent(status);
private RecognitionEvent sendRecognitionEvent(int hwHandle, @RecognitionStatus int status,
boolean recognitionStillActive) {
RecognitionEvent event = TestUtil.createRecognitionEvent(status,
recognitionStillActive);
mCallback.recognitionCallback(hwHandle, event);
return event;
}
private PhraseRecognitionEvent sendPhraseRecognitionEvent(int hwHandle,
@RecognitionStatus int status) {
PhraseRecognitionEvent event = TestUtil.createPhraseRecognitionEvent(status);
@RecognitionStatus int status, boolean recognitionStillActive) {
PhraseRecognitionEvent event = TestUtil.createPhraseRecognitionEvent(status,
recognitionStillActive);
mCallback.phraseRecognitionCallback(hwHandle, event);
return event;
}

View File

@@ -330,7 +330,8 @@ class TestUtil {
return format;
}
static RecognitionEvent createRecognitionEvent(@RecognitionStatus int status) {
static RecognitionEvent createRecognitionEvent(@RecognitionStatus int status,
boolean recognitionStillActive) {
RecognitionEvent event = new RecognitionEvent();
event.status = status;
event.type = SoundModelType.GENERIC;
@@ -346,6 +347,7 @@ class TestUtil {
event.audioConfig.base.format = createAudioFormatMp3();
//event.audioConfig.offloadInfo is irrelevant.
event.data = new byte[]{31, 32, 33};
event.recognitionStillActive = recognitionStillActive;
return event;
}
@@ -360,7 +362,8 @@ class TestUtil {
return halEvent;
}
static void validateRecognitionEvent(RecognitionEvent event, @RecognitionStatus int status) {
static void validateRecognitionEvent(RecognitionEvent event, @RecognitionStatus int status,
boolean recognitionStillActive) {
assertEquals(status, event.status);
assertEquals(SoundModelType.GENERIC, event.type);
assertTrue(event.captureAvailable);
@@ -372,11 +375,13 @@ class TestUtil {
event.audioConfig.base.channelMask);
assertEquals(createAudioFormatMp3(), event.audioConfig.base.format);
assertArrayEquals(new byte[]{31, 32, 33}, event.data);
assertEquals(recognitionStillActive, event.recognitionStillActive);
}
static PhraseRecognitionEvent createPhraseRecognitionEvent(@RecognitionStatus int status) {
static PhraseRecognitionEvent createPhraseRecognitionEvent(@RecognitionStatus int status,
boolean recognitionStillActive) {
PhraseRecognitionEvent event = new PhraseRecognitionEvent();
event.common = createRecognitionEvent(status);
event.common = createRecognitionEvent(status, recognitionStillActive);
PhraseRecognitionExtra extra = new PhraseRecognitionExtra();
extra.id = 123;
@@ -434,8 +439,8 @@ class TestUtil {
}
static void validatePhraseRecognitionEvent(PhraseRecognitionEvent event,
@RecognitionStatus int status) {
validateRecognitionEvent(event.common, status);
@RecognitionStatus int status, boolean recognitionStillActive) {
validateRecognitionEvent(event.common, status, recognitionStillActive);
assertEquals(1, event.phraseExtras.length);
assertEquals(123, event.phraseExtras[0].id);

View File

@@ -830,7 +830,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
return;
}
if (event.status != SoundTrigger.RECOGNITION_STATUS_GET_STATE_RESPONSE) {
if (!event.recognitionStillActive) {
model.setStopped();
}
@@ -971,7 +971,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
return;
}
if (event.status != SoundTrigger.RECOGNITION_STATUS_GET_STATE_RESPONSE) {
if (!event.recognitionStillActive) {
modelData.setStopped();
}