Merge changes from topic "cherrypicker-L13400000959215506:N79400001348786532" into udc-dev
* changes: RecognitionEvent.getHalEventTimestampMillis API AOHD.EventPayload.getHalEventTimestampMillis API
This commit is contained in:
committed by
Android (Google) Code Review
commit
65a2a1e7fd
@@ -5967,6 +5967,7 @@ package android.hardware.soundtrigger {
|
||||
method @Nullable public android.media.AudioFormat getCaptureFormat();
|
||||
method public int getCaptureSession();
|
||||
method public byte[] getData();
|
||||
method public long getHalEventReceivedMillis();
|
||||
method public boolean isCaptureAvailable();
|
||||
}
|
||||
|
||||
@@ -13042,6 +13043,7 @@ package android.service.voice {
|
||||
method @Nullable public android.media.AudioFormat getCaptureAudioFormat();
|
||||
method @Nullable public byte[] getData();
|
||||
method public int getDataFormat();
|
||||
method public long getHalEventReceivedMillis();
|
||||
method @Nullable public android.service.voice.HotwordDetectedResult getHotwordDetectedResult();
|
||||
method @NonNull public java.util.List<android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra> getKeyphraseRecognitionExtras();
|
||||
method @Deprecated @Nullable public byte[] getTriggerAudio();
|
||||
|
||||
@@ -1639,7 +1639,7 @@ package android.hardware.soundtrigger {
|
||||
}
|
||||
|
||||
public static class SoundTrigger.RecognitionEvent {
|
||||
ctor public SoundTrigger.RecognitionEvent(int, int, boolean, int, int, int, boolean, @NonNull android.media.AudioFormat, @Nullable byte[]);
|
||||
ctor public SoundTrigger.RecognitionEvent(int, int, boolean, int, int, int, boolean, @NonNull android.media.AudioFormat, @Nullable byte[], long);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2876,7 +2876,7 @@ package android.service.voice {
|
||||
public class AlwaysOnHotwordDetector implements android.service.voice.HotwordDetector {
|
||||
method public void overrideAvailability(int);
|
||||
method public void resetAvailability();
|
||||
method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public void triggerHardwareRecognitionEventForTest(int, int, boolean, int, int, int, boolean, @NonNull android.media.AudioFormat, @Nullable byte[], @NonNull java.util.List<android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra>);
|
||||
method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public void triggerHardwareRecognitionEventForTest(int, int, long, boolean, int, int, int, boolean, @NonNull android.media.AudioFormat, @Nullable byte[], @NonNull java.util.List<android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra>);
|
||||
}
|
||||
|
||||
public static final class AlwaysOnHotwordDetector.EventPayload.Builder {
|
||||
@@ -2888,6 +2888,7 @@ package android.service.voice {
|
||||
method @NonNull public android.service.voice.AlwaysOnHotwordDetector.EventPayload.Builder setCaptureSession(int);
|
||||
method @NonNull public android.service.voice.AlwaysOnHotwordDetector.EventPayload.Builder setData(@NonNull byte[]);
|
||||
method @NonNull public android.service.voice.AlwaysOnHotwordDetector.EventPayload.Builder setDataFormat(int);
|
||||
method @NonNull public android.service.voice.AlwaysOnHotwordDetector.EventPayload.Builder setHalEventReceivedMillis(long);
|
||||
method @NonNull public android.service.voice.AlwaysOnHotwordDetector.EventPayload.Builder setHotwordDetectedResult(@NonNull android.service.voice.HotwordDetectedResult);
|
||||
method @NonNull public android.service.voice.AlwaysOnHotwordDetector.EventPayload.Builder setKeyphraseRecognitionExtras(@NonNull java.util.List<android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra>);
|
||||
}
|
||||
|
||||
@@ -223,13 +223,13 @@ public class ConversionUtil {
|
||||
int modelHandle, int captureSession, RecognitionEvent aidlEvent) {
|
||||
// The API recognition event doesn't allow for a null audio format, even though it doesn't
|
||||
// always make sense. We thus replace it with a default.
|
||||
AudioFormat audioFormat = aidl2apiAudioFormatWithDefault(
|
||||
aidlEvent.audioConfig, true /*isInput*/);
|
||||
return new SoundTrigger.GenericRecognitionEvent(
|
||||
aidlEvent.status,
|
||||
modelHandle, aidlEvent.captureAvailable, captureSession,
|
||||
aidlEvent.captureDelayMs, aidlEvent.capturePreambleMs, aidlEvent.triggerInData,
|
||||
audioFormat, aidlEvent.data, aidlEvent.recognitionStillActive);
|
||||
AudioFormat audioFormat = aidl2apiAudioFormatWithDefault(aidlEvent.audioConfig,
|
||||
true /*isInput*/);
|
||||
// TODO(b/265852186) propagate a timestamp from aidl interfaces
|
||||
return new SoundTrigger.GenericRecognitionEvent(aidlEvent.status, modelHandle,
|
||||
aidlEvent.captureAvailable, captureSession, aidlEvent.captureDelayMs,
|
||||
aidlEvent.capturePreambleMs, aidlEvent.triggerInData, audioFormat, aidlEvent.data,
|
||||
aidlEvent.recognitionStillActive, -1 /* halEventReceivedMillis */);
|
||||
}
|
||||
|
||||
public static SoundTrigger.RecognitionEvent aidl2apiPhraseRecognitionEvent(
|
||||
@@ -242,14 +242,13 @@ public class ConversionUtil {
|
||||
}
|
||||
// The API recognition event doesn't allow for a null audio format, even though it doesn't
|
||||
// always make sense. We thus replace it with a default.
|
||||
AudioFormat audioFormat = aidl2apiAudioFormatWithDefault(
|
||||
aidlEvent.common.audioConfig, true /*isInput*/);
|
||||
AudioFormat audioFormat = aidl2apiAudioFormatWithDefault(aidlEvent.common.audioConfig,
|
||||
true /*isInput*/);
|
||||
// TODO(b/265852186) propagate a timestamp from aidl interfaces
|
||||
return new SoundTrigger.KeyphraseRecognitionEvent(aidlEvent.common.status, modelHandle,
|
||||
aidlEvent.common.captureAvailable,
|
||||
captureSession, aidlEvent.common.captureDelayMs,
|
||||
aidlEvent.common.capturePreambleMs, aidlEvent.common.triggerInData,
|
||||
audioFormat, aidlEvent.common.data,
|
||||
apiExtras);
|
||||
aidlEvent.common.captureAvailable, captureSession, aidlEvent.common.captureDelayMs,
|
||||
aidlEvent.common.capturePreambleMs, aidlEvent.common.triggerInData, audioFormat,
|
||||
aidlEvent.common.data, apiExtras, -1 /* halEventReceivedMillis */);
|
||||
}
|
||||
|
||||
// In case of a null input returns a non-null valid output.
|
||||
|
||||
@@ -28,6 +28,7 @@ import static android.system.OsConstants.EPIPE;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import android.annotation.ElapsedRealtimeLong;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.IntRange;
|
||||
import android.annotation.NonNull;
|
||||
@@ -36,17 +37,13 @@ import android.annotation.RequiresPermission;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.SystemApi;
|
||||
import android.annotation.TestApi;
|
||||
import android.app.ActivityThread;
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.content.Context;
|
||||
import android.media.AudioFormat;
|
||||
import android.media.permission.ClearCallingIdentityContext;
|
||||
import android.media.permission.Identity;
|
||||
import android.media.permission.SafeCloseable;
|
||||
import android.media.soundtrigger.Status;
|
||||
import android.media.soundtrigger_middleware.ISoundTriggerMiddlewareService;
|
||||
import android.media.soundtrigger_middleware.SoundTriggerModuleDescriptor;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
@@ -56,6 +53,7 @@ import android.os.Parcelable;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.ServiceSpecificException;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
@@ -1187,23 +1185,38 @@ public class SoundTrigger {
|
||||
* @hide
|
||||
*/
|
||||
public final boolean recognitionStillActive;
|
||||
/**
|
||||
* Timestamp of when the trigger event from SoundTriggerHal was received by the
|
||||
* framework.
|
||||
*
|
||||
* <p>Clock monotonic including suspend time or its equivalent on the system,
|
||||
* in the same units and timebase as {@link SystemClock#elapsedRealtime()}.
|
||||
*
|
||||
* <p>Value represents elapsed realtime in milliseconds when the event was received from the
|
||||
* HAL. The value will be -1 if the event was not generated from the HAL.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@ElapsedRealtimeLong
|
||||
public final long halEventReceivedMillis;
|
||||
|
||||
/** @hide */
|
||||
@TestApi
|
||||
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
||||
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);
|
||||
boolean triggerInData, @NonNull AudioFormat captureFormat, @Nullable byte[] data,
|
||||
@ElapsedRealtimeLong long halEventReceivedMillis) {
|
||||
this(status, soundModelHandle, captureAvailable,
|
||||
captureSession, captureDelayMs, capturePreambleMs, triggerInData, captureFormat,
|
||||
data, status == RECOGNITION_STATUS_GET_STATE_RESPONSE, halEventReceivedMillis);
|
||||
}
|
||||
|
||||
/** @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) {
|
||||
boolean recognitionStillActive, @ElapsedRealtimeLong long halEventReceivedMillis) {
|
||||
this.status = status;
|
||||
this.soundModelHandle = soundModelHandle;
|
||||
this.captureAvailable = captureAvailable;
|
||||
@@ -1214,6 +1227,7 @@ public class SoundTrigger {
|
||||
this.captureFormat = requireNonNull(captureFormat);
|
||||
this.data = data != null ? data : new byte[0];
|
||||
this.recognitionStillActive = recognitionStillActive;
|
||||
this.halEventReceivedMillis = halEventReceivedMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1256,6 +1270,21 @@ public class SoundTrigger {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Timestamp of when the trigger event from SoundTriggerHal was received by the
|
||||
* framework.
|
||||
*
|
||||
* Clock monotonic including suspend time or its equivalent on the system,
|
||||
* in the same units and timebase as {@link SystemClock#elapsedRealtime()}.
|
||||
*
|
||||
* @return Elapsed realtime in milliseconds when the event was received from the HAL.
|
||||
* Returns -1 if the event was not generated from the HAL.
|
||||
*/
|
||||
@ElapsedRealtimeLong
|
||||
public long getHalEventReceivedMillis() {
|
||||
return halEventReceivedMillis;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static final @android.annotation.NonNull Parcelable.Creator<RecognitionEvent> CREATOR
|
||||
= new Parcelable.Creator<RecognitionEvent>() {
|
||||
@@ -1290,9 +1319,10 @@ public class SoundTrigger {
|
||||
}
|
||||
byte[] data = in.readBlob();
|
||||
boolean recognitionStillActive = in.readBoolean();
|
||||
long halEventReceivedMillis = in.readLong();
|
||||
return new RecognitionEvent(status, soundModelHandle, captureAvailable, captureSession,
|
||||
captureDelayMs, capturePreambleMs, triggerInData, captureFormat, data,
|
||||
recognitionStillActive);
|
||||
recognitionStillActive, halEventReceivedMillis);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@@ -1319,6 +1349,7 @@ public class SoundTrigger {
|
||||
}
|
||||
dest.writeBlob(data);
|
||||
dest.writeBoolean(recognitionStillActive);
|
||||
dest.writeLong(halEventReceivedMillis);
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
@@ -1338,6 +1369,7 @@ public class SoundTrigger {
|
||||
result = prime * result + soundModelHandle;
|
||||
result = prime * result + status;
|
||||
result = result + (recognitionStillActive ? 1289 : 1291);
|
||||
result = prime * result + Long.hashCode(halEventReceivedMillis);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1364,6 +1396,9 @@ public class SoundTrigger {
|
||||
return false;
|
||||
if (soundModelHandle != other.soundModelHandle)
|
||||
return false;
|
||||
if (halEventReceivedMillis != other.halEventReceivedMillis) {
|
||||
return false;
|
||||
}
|
||||
if (status != other.status)
|
||||
return false;
|
||||
if (triggerInData != other.triggerInData)
|
||||
@@ -1400,6 +1435,7 @@ public class SoundTrigger {
|
||||
(", channelMask=" + captureFormat.getChannelMask()))
|
||||
+ ", data=" + (data == null ? 0 : data.length)
|
||||
+ ", recognitionStillActive=" + recognitionStillActive
|
||||
+ ", halEventReceivedMillis=" + halEventReceivedMillis
|
||||
+ "]";
|
||||
}
|
||||
}
|
||||
@@ -1820,19 +1856,22 @@ public class SoundTrigger {
|
||||
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) {
|
||||
@Nullable KeyphraseRecognitionExtra[] keyphraseExtras,
|
||||
@ElapsedRealtimeLong long halEventReceivedMillis) {
|
||||
this(status, soundModelHandle, captureAvailable, captureSession, captureDelayMs,
|
||||
capturePreambleMs, triggerInData, captureFormat, data, keyphraseExtras,
|
||||
status == RECOGNITION_STATUS_GET_STATE_RESPONSE);
|
||||
status == RECOGNITION_STATUS_GET_STATE_RESPONSE, halEventReceivedMillis);
|
||||
}
|
||||
|
||||
public KeyphraseRecognitionEvent(int status, int soundModelHandle, boolean captureAvailable,
|
||||
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, recognitionStillActive);
|
||||
boolean recognitionStillActive, @ElapsedRealtimeLong long halEventReceivedMillis) {
|
||||
super(status, soundModelHandle, captureAvailable,
|
||||
captureSession, captureDelayMs, capturePreambleMs, triggerInData, captureFormat,
|
||||
data, recognitionStillActive, halEventReceivedMillis);
|
||||
this.keyphraseExtras =
|
||||
keyphraseExtras != null ? keyphraseExtras : new KeyphraseRecognitionExtra[0];
|
||||
}
|
||||
@@ -1869,11 +1908,13 @@ public class SoundTrigger {
|
||||
}
|
||||
byte[] data = in.readBlob();
|
||||
boolean recognitionStillActive = in.readBoolean();
|
||||
long halEventReceivedMillis = in.readLong();
|
||||
KeyphraseRecognitionExtra[] keyphraseExtras =
|
||||
in.createTypedArray(KeyphraseRecognitionExtra.CREATOR);
|
||||
return new KeyphraseRecognitionEvent(status, soundModelHandle, captureAvailable,
|
||||
captureSession, captureDelayMs, capturePreambleMs, triggerInData,
|
||||
captureFormat, data, keyphraseExtras, recognitionStillActive);
|
||||
return new KeyphraseRecognitionEvent(status, soundModelHandle,
|
||||
captureAvailable, captureSession, captureDelayMs, capturePreambleMs,
|
||||
triggerInData, captureFormat, data, keyphraseExtras, recognitionStillActive,
|
||||
halEventReceivedMillis);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1895,6 +1936,7 @@ public class SoundTrigger {
|
||||
}
|
||||
dest.writeBlob(data);
|
||||
dest.writeBoolean(recognitionStillActive);
|
||||
dest.writeLong(halEventReceivedMillis);
|
||||
dest.writeTypedArray(keyphraseExtras, flags);
|
||||
}
|
||||
|
||||
@@ -1929,9 +1971,11 @@ public class SoundTrigger {
|
||||
public String toString() {
|
||||
return "KeyphraseRecognitionEvent [keyphraseExtras=" + Arrays.toString(keyphraseExtras)
|
||||
+ ", status=" + status
|
||||
+ ", soundModelHandle=" + soundModelHandle + ", captureAvailable="
|
||||
+ captureAvailable + ", captureSession=" + captureSession + ", captureDelayMs="
|
||||
+ captureDelayMs + ", capturePreambleMs=" + capturePreambleMs
|
||||
+ ", soundModelHandle=" + soundModelHandle
|
||||
+ ", captureAvailable=" + captureAvailable
|
||||
+ ", captureSession=" + captureSession
|
||||
+ ", captureDelayMs=" + captureDelayMs
|
||||
+ ", capturePreambleMs=" + capturePreambleMs
|
||||
+ ", triggerInData=" + triggerInData
|
||||
+ ((captureFormat == null) ? "" :
|
||||
(", sampleRate=" + captureFormat.getSampleRate()))
|
||||
@@ -1941,6 +1985,7 @@ public class SoundTrigger {
|
||||
(", channelMask=" + captureFormat.getChannelMask()))
|
||||
+ ", data=" + (data == null ? 0 : data.length)
|
||||
+ ", recognitionStillActive=" + recognitionStillActive
|
||||
+ ", halEventReceivedMillis=" + halEventReceivedMillis
|
||||
+ "]";
|
||||
}
|
||||
}
|
||||
@@ -1953,21 +1998,23 @@ public class SoundTrigger {
|
||||
*/
|
||||
public static class GenericRecognitionEvent extends RecognitionEvent implements Parcelable {
|
||||
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
||||
public GenericRecognitionEvent(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,
|
||||
public GenericRecognitionEvent(int status, int soundModelHandle, boolean captureAvailable,
|
||||
int captureSession, int captureDelayMs, int capturePreambleMs,
|
||||
boolean triggerInData, @NonNull AudioFormat captureFormat, @Nullable byte[] data,
|
||||
@ElapsedRealtimeLong long halEventReceivedMillis) {
|
||||
this(status, soundModelHandle, captureAvailable,
|
||||
captureSession, captureDelayMs,
|
||||
capturePreambleMs, triggerInData, captureFormat, data,
|
||||
status == RECOGNITION_STATUS_GET_STATE_RESPONSE);
|
||||
status == RECOGNITION_STATUS_GET_STATE_RESPONSE, halEventReceivedMillis);
|
||||
}
|
||||
|
||||
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 GenericRecognitionEvent(int status, int soundModelHandle, boolean captureAvailable,
|
||||
int captureSession, int captureDelayMs, int capturePreambleMs,
|
||||
boolean triggerInData, @NonNull AudioFormat captureFormat, @Nullable byte[] data,
|
||||
boolean recognitionStillActive, @ElapsedRealtimeLong long halEventReceivedMillis) {
|
||||
super(status, soundModelHandle, captureAvailable,
|
||||
captureSession, captureDelayMs, capturePreambleMs, triggerInData, captureFormat,
|
||||
data, recognitionStillActive, halEventReceivedMillis);
|
||||
}
|
||||
|
||||
public static final @android.annotation.NonNull Parcelable.Creator<GenericRecognitionEvent> CREATOR
|
||||
@@ -1986,7 +2033,7 @@ public class SoundTrigger {
|
||||
return new GenericRecognitionEvent(event.status, event.soundModelHandle,
|
||||
event.captureAvailable, event.captureSession, event.captureDelayMs,
|
||||
event.capturePreambleMs, event.triggerInData, event.captureFormat, event.data,
|
||||
event.recognitionStillActive);
|
||||
event.recognitionStillActive, event.halEventReceivedMillis);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -20,6 +20,7 @@ import static android.Manifest.permission.CAPTURE_AUDIO_HOTWORD;
|
||||
import static android.Manifest.permission.RECORD_AUDIO;
|
||||
import static android.service.voice.VoiceInteractionService.MULTIPLE_ACTIVE_HOTWORD_DETECTORS;
|
||||
|
||||
import android.annotation.ElapsedRealtimeLong;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
@@ -54,6 +55,7 @@ import android.os.ParcelFileDescriptor;
|
||||
import android.os.PersistableBundle;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SharedMemory;
|
||||
import android.os.SystemClock;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
@@ -401,6 +403,9 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
|
||||
private final ParcelFileDescriptor mAudioStream;
|
||||
private final List<KeyphraseRecognitionExtra> mKephraseExtras;
|
||||
|
||||
@ElapsedRealtimeLong
|
||||
private final long mHalEventReceivedMillis;
|
||||
|
||||
private EventPayload(boolean captureAvailable,
|
||||
@Nullable AudioFormat audioFormat,
|
||||
int captureSession,
|
||||
@@ -408,7 +413,8 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
|
||||
@Nullable byte[] data,
|
||||
@Nullable HotwordDetectedResult hotwordDetectedResult,
|
||||
@Nullable ParcelFileDescriptor audioStream,
|
||||
@NonNull List<KeyphraseRecognitionExtra> keyphraseExtras) {
|
||||
@NonNull List<KeyphraseRecognitionExtra> keyphraseExtras,
|
||||
@ElapsedRealtimeLong long halEventReceivedMillis) {
|
||||
mCaptureAvailable = captureAvailable;
|
||||
mCaptureSession = captureSession;
|
||||
mAudioFormat = audioFormat;
|
||||
@@ -417,6 +423,7 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
|
||||
mHotwordDetectedResult = hotwordDetectedResult;
|
||||
mAudioStream = audioStream;
|
||||
mKephraseExtras = keyphraseExtras;
|
||||
mHalEventReceivedMillis = halEventReceivedMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -545,6 +552,21 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
|
||||
return mKephraseExtras;
|
||||
}
|
||||
|
||||
/**
|
||||
* Timestamp of when the trigger event from SoundTriggerHal was received by the system
|
||||
* server.
|
||||
*
|
||||
* Clock monotonic including suspend time or its equivalent on the system,
|
||||
* in the same units and timebase as {@link SystemClock#elapsedRealtime()}.
|
||||
*
|
||||
* @return Elapsed realtime in milliseconds when the event was received from the HAL.
|
||||
* Returns -1 if the event was not generated from the HAL.
|
||||
*/
|
||||
@ElapsedRealtimeLong
|
||||
public long getHalEventReceivedMillis() {
|
||||
return mHalEventReceivedMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder class for {@link EventPayload} objects
|
||||
*
|
||||
@@ -561,6 +583,8 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
|
||||
private HotwordDetectedResult mHotwordDetectedResult = null;
|
||||
private ParcelFileDescriptor mAudioStream = null;
|
||||
private List<KeyphraseRecognitionExtra> mKeyphraseExtras = Collections.emptyList();
|
||||
@ElapsedRealtimeLong
|
||||
private long mHalEventReceivedMillis = -1;
|
||||
|
||||
public Builder() {}
|
||||
|
||||
@@ -579,6 +603,7 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
|
||||
setKeyphraseRecognitionExtras(
|
||||
Arrays.asList(keyphraseRecognitionEvent.keyphraseExtras));
|
||||
}
|
||||
setHalEventReceivedMillis(keyphraseRecognitionEvent.getHalEventReceivedMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -681,6 +706,20 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Timestamp of when the trigger event from SoundTriggerHal was received by the
|
||||
* framework.
|
||||
*
|
||||
* Clock monotonic including suspend time or its equivalent on the system,
|
||||
* in the same units and timebase as {@link SystemClock#elapsedRealtime()}.
|
||||
*/
|
||||
@NonNull
|
||||
public Builder setHalEventReceivedMillis(
|
||||
@ElapsedRealtimeLong long halEventReceivedMillis) {
|
||||
mHalEventReceivedMillis = halEventReceivedMillis;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an {@link EventPayload} instance
|
||||
*/
|
||||
@@ -688,7 +727,7 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
|
||||
public EventPayload build() {
|
||||
return new EventPayload(mCaptureAvailable, mAudioFormat, mCaptureSession,
|
||||
mDataFormat, mData, mHotwordDetectedResult, mAudioStream,
|
||||
mKeyphraseExtras);
|
||||
mKeyphraseExtras, mHalEventReceivedMillis);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -897,8 +936,9 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
|
||||
@TestApi
|
||||
@RequiresPermission(allOf = {RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD})
|
||||
public void triggerHardwareRecognitionEventForTest(int status, int soundModelHandle,
|
||||
boolean captureAvailable, int captureSession, int captureDelayMs, int capturePreambleMs,
|
||||
boolean triggerInData, @NonNull AudioFormat captureFormat, @Nullable byte[] data,
|
||||
@ElapsedRealtimeLong long halEventReceivedMillis, boolean captureAvailable,
|
||||
int captureSession, int captureDelayMs, int capturePreambleMs, boolean triggerInData,
|
||||
@NonNull AudioFormat captureFormat, @Nullable byte[] data,
|
||||
@NonNull List<KeyphraseRecognitionExtra> keyphraseRecognitionExtras) {
|
||||
Log.d(TAG, "triggerHardwareRecognitionEventForTest()");
|
||||
synchronized (mLock) {
|
||||
@@ -911,7 +951,7 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
|
||||
new KeyphraseRecognitionEvent(status, soundModelHandle, captureAvailable,
|
||||
captureSession, captureDelayMs, capturePreambleMs, triggerInData,
|
||||
captureFormat, data, keyphraseRecognitionExtras.toArray(
|
||||
new KeyphraseRecognitionExtra[0])),
|
||||
new KeyphraseRecognitionExtra[0]), halEventReceivedMillis),
|
||||
mInternalCallback);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
|
||||
@@ -219,10 +219,18 @@ public class SoundTriggerTest extends InstrumentationTestCase {
|
||||
|
||||
@SmallTest
|
||||
public void testRecognitionEventParcelUnparcel_noData() throws Exception {
|
||||
RecognitionEvent re = new RecognitionEvent(SoundTrigger.RECOGNITION_STATUS_SUCCESS, 1,
|
||||
true, 2, 3, 4, false, null, null);
|
||||
RecognitionEvent re = new RecognitionEvent(SoundTrigger.RECOGNITION_STATUS_SUCCESS,
|
||||
1 /* soundModelHandle */,
|
||||
true /* captureAvailable */,
|
||||
2 /* captureSession */,
|
||||
3 /* captureDelayMs */,
|
||||
4 /* capturePreambleMs */,
|
||||
false /* triggerInData */,
|
||||
null /* captureFormat */,
|
||||
null /* data */,
|
||||
12345678 /* halEventReceivedMillis */);
|
||||
|
||||
// Write to a parcel
|
||||
// Write to a parcel
|
||||
Parcel parcel = Parcel.obtain();
|
||||
re.writeToParcel(parcel, 0);
|
||||
|
||||
@@ -236,10 +244,18 @@ public class SoundTriggerTest extends InstrumentationTestCase {
|
||||
|
||||
@SmallTest
|
||||
public void testRecognitionEventParcelUnparcel_zeroData() throws Exception {
|
||||
RecognitionEvent re = new RecognitionEvent(SoundTrigger.RECOGNITION_STATUS_FAILURE, 1,
|
||||
true, 2, 3, 4, false, null, new byte[1]);
|
||||
RecognitionEvent re = new RecognitionEvent(SoundTrigger.RECOGNITION_STATUS_FAILURE,
|
||||
1 /* soundModelHandle */,
|
||||
true /* captureAvailable */,
|
||||
2 /* captureSession */,
|
||||
3 /* captureDelayMs */,
|
||||
4 /* capturePreambleMs */,
|
||||
false /* triggerInData */,
|
||||
null /* captureFormat */,
|
||||
new byte[1] /* data */,
|
||||
12345678 /* halEventReceivedMillis */);
|
||||
|
||||
// Write to a parcel
|
||||
// Write to a parcel
|
||||
Parcel parcel = Parcel.obtain();
|
||||
re.writeToParcel(parcel, 0);
|
||||
|
||||
@@ -255,10 +271,18 @@ public class SoundTriggerTest extends InstrumentationTestCase {
|
||||
public void testRecognitionEventParcelUnparcel_largeData() throws Exception {
|
||||
byte[] data = new byte[200 * 1024];
|
||||
mRandom.nextBytes(data);
|
||||
RecognitionEvent re = new RecognitionEvent(SoundTrigger.RECOGNITION_STATUS_ABORT, 1,
|
||||
false, 2, 3, 4, false, null, data);
|
||||
RecognitionEvent re = new RecognitionEvent(SoundTrigger.RECOGNITION_STATUS_ABORT,
|
||||
1 /* soundModelHandle */,
|
||||
false /* captureAvailable */,
|
||||
2 /* captureSession */,
|
||||
3 /* captureDelayMs */,
|
||||
4 /* capturePreambleMs */,
|
||||
false /* triggerInData */,
|
||||
null /* captureFormat */,
|
||||
data,
|
||||
12345678 /* halEventReceivedMillis */);
|
||||
|
||||
// Write to a parcel
|
||||
// Write to a parcel
|
||||
Parcel parcel = Parcel.obtain();
|
||||
re.writeToParcel(parcel, 0);
|
||||
|
||||
@@ -274,14 +298,20 @@ public class SoundTriggerTest extends InstrumentationTestCase {
|
||||
public void testRecognitionEventParcelUnparcel_largeAudioData() throws Exception {
|
||||
byte[] data = new byte[200 * 1024];
|
||||
mRandom.nextBytes(data);
|
||||
RecognitionEvent re = new RecognitionEvent(SoundTrigger.RECOGNITION_STATUS_ABORT, 1,
|
||||
false, 2, 3, 4, true,
|
||||
(new AudioFormat.Builder())
|
||||
.setChannelMask(AudioFormat.CHANNEL_IN_MONO)
|
||||
.setEncoding(AudioFormat.ENCODING_PCM_16BIT)
|
||||
.setSampleRate(16000)
|
||||
.build(),
|
||||
data);
|
||||
RecognitionEvent re = new RecognitionEvent(SoundTrigger.RECOGNITION_STATUS_ABORT,
|
||||
1 /* soundModelHandle */,
|
||||
false /* captureAvailable */,
|
||||
2 /* captureSession */,
|
||||
3 /* captureDelayMs */,
|
||||
4 /* capturePreambleMs */,
|
||||
true /* triggerInData */,
|
||||
new AudioFormat.Builder()
|
||||
.setChannelMask(AudioFormat.CHANNEL_IN_MONO)
|
||||
.setEncoding(AudioFormat.ENCODING_PCM_16BIT)
|
||||
.setSampleRate(16000)
|
||||
.build(),
|
||||
data,
|
||||
12345678 /* halEventReceivedMillis */);
|
||||
|
||||
// Write to a parcel
|
||||
Parcel parcel = Parcel.obtain();
|
||||
@@ -298,7 +328,17 @@ public class SoundTriggerTest extends InstrumentationTestCase {
|
||||
@SmallTest
|
||||
public void testKeyphraseRecognitionEventParcelUnparcel_noKeyphrases() throws Exception {
|
||||
KeyphraseRecognitionEvent re = new KeyphraseRecognitionEvent(
|
||||
SoundTrigger.RECOGNITION_STATUS_SUCCESS, 1, true, 2, 3, 4, false, null, null, null);
|
||||
SoundTrigger.RECOGNITION_STATUS_SUCCESS,
|
||||
1 /* soundModelHandle */,
|
||||
true /* captureAvailable */,
|
||||
2 /* captureSession */,
|
||||
3 /* captureDelayMs */,
|
||||
4 /* capturePreambleMs */,
|
||||
false /* triggerInData */,
|
||||
null /* captureFormat */,
|
||||
null /* data */,
|
||||
null /* keyphraseExtras */,
|
||||
12345678 /* halEventReceivedMillis */);
|
||||
|
||||
// Write to a parcel
|
||||
Parcel parcel = Parcel.obtain();
|
||||
@@ -317,8 +357,17 @@ public class SoundTriggerTest extends InstrumentationTestCase {
|
||||
public void testKeyphraseRecognitionEventParcelUnparcel_zeroData() throws Exception {
|
||||
KeyphraseRecognitionExtra[] kpExtra = new KeyphraseRecognitionExtra[0];
|
||||
KeyphraseRecognitionEvent re = new KeyphraseRecognitionEvent(
|
||||
SoundTrigger.RECOGNITION_STATUS_FAILURE, 2, true, 2, 3, 4, false, null, new byte[1],
|
||||
kpExtra);
|
||||
SoundTrigger.RECOGNITION_STATUS_FAILURE,
|
||||
2 /* soundModelHandle */,
|
||||
true /* captureAvailable */,
|
||||
2 /* captureSession */,
|
||||
3 /* captureDelayMs */,
|
||||
4 /* capturePreambleMs */,
|
||||
false /* triggerInData */,
|
||||
null /* captureFormat */,
|
||||
new byte[1] /* data */,
|
||||
kpExtra,
|
||||
12345678 /* halEventReceivedMillis */);
|
||||
|
||||
// Write to a parcel
|
||||
Parcel parcel = Parcel.obtain();
|
||||
@@ -353,8 +402,17 @@ public class SoundTriggerTest extends InstrumentationTestCase {
|
||||
new ConfidenceLevel[0]);
|
||||
|
||||
KeyphraseRecognitionEvent re = new KeyphraseRecognitionEvent(
|
||||
SoundTrigger.RECOGNITION_STATUS_FAILURE, 1, true, 2, 3, 4, false, null, data,
|
||||
kpExtra);
|
||||
SoundTrigger.RECOGNITION_STATUS_FAILURE,
|
||||
1 /* soundModelHandle */,
|
||||
true /* captureAvailable */,
|
||||
2 /* captureSession */,
|
||||
3 /* captureDelayMs */,
|
||||
4 /* capturePreambleMs */,
|
||||
false /* triggerInData */,
|
||||
null /* captureFormat */,
|
||||
data,
|
||||
kpExtra,
|
||||
12345678 /* halEventReceivedMillis */);
|
||||
|
||||
// Write to a parcel
|
||||
Parcel parcel = Parcel.obtain();
|
||||
|
||||
Reference in New Issue
Block a user