From a5fd0294c76c1faa3479a2093ae3e5f0838791ad Mon Sep 17 00:00:00 2001 From: "Philip P. Moltmann" Date: Tue, 6 Mar 2018 13:44:07 -0800 Subject: [PATCH] Expose SoundTriggerManager and SoundTrigger APIs These APIs require a system permissions, hence SystemAPI. As SoundTrigger is now partially SystemApi and partially internal API a lot of @hide tags are needed to keep hiding the still internal classes, fields and methods. As SoundTrigger is heavily used via reflection no structural change to this class can be made. The MANAGE_SOUND_TRIGGER permission should be visible to the apps as the apps need to know which permission to request in their manifest. If it wouldn't be exposed it would just be a magic string. Test: built Change-Id: Ic93d67639e2605c26c961acdd827c14cb0a68f47 Bug: 73829108, 71981721 --- api/system-current.txt | 16 ++ .../hardware/soundtrigger/SoundTrigger.java | 227 ++++++++++++++++++--- core/res/AndroidManifest.xml | 3 +- 3 files changed, 213 insertions(+), 33 deletions(-) diff --git a/api/system-current.txt b/api/system-current.txt index e1b576de15ac..d53e5baaf936 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -99,6 +99,7 @@ package android { field public static final java.lang.String MANAGE_CARRIER_OEM_UNLOCK_STATE = "android.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE"; field public static final java.lang.String MANAGE_CA_CERTIFICATES = "android.permission.MANAGE_CA_CERTIFICATES"; field public static final java.lang.String MANAGE_DEVICE_ADMINS = "android.permission.MANAGE_DEVICE_ADMINS"; + field public static final java.lang.String MANAGE_SOUND_TRIGGER = "android.permission.MANAGE_SOUND_TRIGGER"; field public static final java.lang.String MANAGE_SUBSCRIPTION_PLANS = "android.permission.MANAGE_SUBSCRIPTION_PLANS"; field public static final java.lang.String MANAGE_USB = "android.permission.MANAGE_USB"; field public static final java.lang.String MANAGE_USERS = "android.permission.MANAGE_USERS"; @@ -2219,6 +2220,21 @@ package android.hardware.radio { } +package android.hardware.soundtrigger { + + public class SoundTrigger { + field public static final int STATUS_OK = 0; // 0x0 + } + + public static class SoundTrigger.RecognitionEvent { + method public android.media.AudioFormat getCaptureFormat(); + method public int getCaptureSession(); + method public byte[] getData(); + method public boolean isCaptureAvailable(); + } + +} + package android.hardware.usb { public class UsbDeviceConnection { diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java index b635088cb11b..dde8a3327172 100644 --- a/core/java/android/hardware/soundtrigger/SoundTrigger.java +++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java @@ -16,6 +16,14 @@ package android.hardware.soundtrigger; +import static android.system.OsConstants.EINVAL; +import static android.system.OsConstants.ENODEV; +import static android.system.OsConstants.ENOSYS; +import static android.system.OsConstants.EPERM; +import static android.system.OsConstants.EPIPE; + +import android.annotation.Nullable; +import android.annotation.SystemApi; import android.media.AudioFormat; import android.os.Handler; import android.os.Parcel; @@ -25,22 +33,33 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.UUID; -import static android.system.OsConstants.*; - /** * The SoundTrigger class provides access via JNI to the native service managing * the sound trigger HAL. * * @hide */ +@SystemApi public class SoundTrigger { + private SoundTrigger() { + } + + /** + * Status code used when the operation succeeded + */ public static final int STATUS_OK = 0; + /** @hide */ public static final int STATUS_ERROR = Integer.MIN_VALUE; + /** @hide */ public static final int STATUS_PERMISSION_DENIED = -EPERM; + /** @hide */ public static final int STATUS_NO_INIT = -ENODEV; + /** @hide */ public static final int STATUS_BAD_VALUE = -EINVAL; + /** @hide */ public static final int STATUS_DEAD_OBJECT = -EPIPE; + /** @hide */ public static final int STATUS_INVALID_OPERATION = -ENOSYS; /***************************************************************************** @@ -48,6 +67,8 @@ public class SoundTrigger { * managed by the native sound trigger service. Each module has a unique * ID used to target any API call to this paricular module. Module * properties are returned by listModules() method. + * + * @hide ****************************************************************************/ public static class ModuleProperties implements Parcelable { /** Unique module ID provided by the native service */ @@ -187,6 +208,8 @@ public class SoundTrigger { * implementation to detect a particular sound pattern. * A specialized version {@link KeyphraseSoundModel} is defined for key phrase * sound models. + * + * @hide ****************************************************************************/ public static class SoundModel { /** Undefined sound model type */ @@ -261,6 +284,8 @@ public class SoundTrigger { /***************************************************************************** * A Keyphrase describes a key phrase that can be detected by a * {@link KeyphraseSoundModel} + * + * @hide ****************************************************************************/ public static class Keyphrase implements Parcelable { /** Unique identifier for this keyphrase */ @@ -382,6 +407,8 @@ public class SoundTrigger { * A KeyphraseSoundModel is a specialized {@link SoundModel} for key phrases. * It contains data needed by the hardware to detect a certain number of key phrases * and the list of corresponding {@link Keyphrase} descriptors. + * + * @hide ****************************************************************************/ public static class KeyphraseSoundModel extends SoundModel implements Parcelable { /** Key phrases in this sound model */ @@ -468,6 +495,8 @@ public class SoundTrigger { /***************************************************************************** * A GenericSoundModel is a specialized {@link SoundModel} for non-voice sound * patterns. + * + * @hide ****************************************************************************/ public static class GenericSoundModel extends SoundModel implements Parcelable { @@ -524,52 +553,115 @@ public class SoundTrigger { /** * Modes for key phrase recognition */ - /** Simple recognition of the key phrase */ + + /** + * Simple recognition of the key phrase + * + * @hide + */ public static final int RECOGNITION_MODE_VOICE_TRIGGER = 0x1; - /** Trigger only if one user is identified */ + /** + * Trigger only if one user is identified + * + * @hide + */ public static final int RECOGNITION_MODE_USER_IDENTIFICATION = 0x2; - /** Trigger only if one user is authenticated */ + /** + * Trigger only if one user is authenticated + * + * @hide + */ public static final int RECOGNITION_MODE_USER_AUTHENTICATION = 0x4; /** * Status codes for {@link RecognitionEvent} */ - /** Recognition success */ + /** + * Recognition success + * + * @hide + */ public static final int RECOGNITION_STATUS_SUCCESS = 0; - /** Recognition aborted (e.g. capture preempted by anotehr use case */ + /** + * Recognition aborted (e.g. capture preempted by anotehr use case + * + * @hide + */ public static final int RECOGNITION_STATUS_ABORT = 1; - /** Recognition failure */ + /** + * Recognition failure + * + * @hide + */ public static final int RECOGNITION_STATUS_FAILURE = 2; /** * A RecognitionEvent is provided by the - * {@link StatusListener#onRecognition(RecognitionEvent)} + * {@code StatusListener#onRecognition(RecognitionEvent)} * callback upon recognition success or failure. */ - public static class RecognitionEvent implements Parcelable { - /** Recognition status e.g {@link #RECOGNITION_STATUS_SUCCESS} */ + public static class RecognitionEvent { + /** + * Recognition status e.g RECOGNITION_STATUS_SUCCESS + * + * @hide + */ public final int status; - /** Sound Model corresponding to this event callback */ + /** + * + * Sound Model corresponding to this event callback + * + * @hide + */ public final int soundModelHandle; - /** True if it is possible to capture audio from this utterance buffered by the hardware */ + /** + * True if it is possible to capture audio from this utterance buffered by the hardware + * + * @hide + */ public final boolean captureAvailable; - /** Audio session ID to be used when capturing the utterance with an AudioRecord - * if captureAvailable() is true. */ + /** + * Audio session ID to be used when capturing the utterance with an AudioRecord + * if captureAvailable() is true. + * + * @hide + */ public final int captureSession; - /** Delay in ms between end of model detection and start of audio available for capture. - * A negative value is possible (e.g. if keyphrase is also available for capture) */ + /** + * Delay in ms between end of model detection and start of audio available for capture. + * A negative value is possible (e.g. if keyphrase is also available for capture) + * + * @hide + */ public final int captureDelayMs; - /** Duration in ms of audio captured before the start of the trigger. 0 if none. */ + /** + * Duration in ms of audio captured before the start of the trigger. 0 if none. + * + * @hide + */ public final int capturePreambleMs; - /** True if the trigger (key phrase capture is present in binary data */ + /** + * True if the trigger (key phrase capture is present in binary data + * + * @hide + */ public final boolean triggerInData; - /** Audio format of either the trigger in event data or to use for capture of the - * rest of the utterance */ - public AudioFormat captureFormat; - /** Opaque data for use by system applications who know about voice engine internals, - * typically during enrollment. */ + /** + * Audio format of either the trigger in event data or to use for capture of the + * rest of the utterance + * + * @hide + */ + public final AudioFormat captureFormat; + /** + * Opaque data for use by system applications who know about voice engine internals, + * typically during enrollment. + * + * @hide + */ public final byte[] data; + /** @hide */ public RecognitionEvent(int status, int soundModelHandle, boolean captureAvailable, int captureSession, int captureDelayMs, int capturePreambleMs, boolean triggerInData, AudioFormat captureFormat, byte[] data) { @@ -584,6 +676,46 @@ public class SoundTrigger { this.data = data; } + /** + * Check if is possible to capture audio from this utterance buffered by the hardware. + * + * @return {@code true} iff a capturing is possible + */ + public boolean isCaptureAvailable() { + return captureAvailable; + } + + /** + * Get the audio format of either the trigger in event data or to use for capture of the + * rest of the utterance + * + * @return the audio format + */ + @Nullable public AudioFormat getCaptureFormat() { + return captureFormat; + } + + /** + * Get Audio session ID to be used when capturing the utterance with an {@link AudioRecord} + * if {@link #isCaptureAvailable()} is true. + * + * @return The id of the capture session + */ + public int getCaptureSession() { + return captureSession; + } + + /** + * Get the opaque data for use by system applications who know about voice engine + * internals, typically during enrollment. + * + * @return The data of the event + */ + public byte[] getData() { + return data; + } + + /** @hide */ public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { public RecognitionEvent createFromParcel(Parcel in) { @@ -595,6 +727,7 @@ public class SoundTrigger { } }; + /** @hide */ protected static RecognitionEvent fromParcel(Parcel in) { int status = in.readInt(); int soundModelHandle = in.readInt(); @@ -619,12 +752,12 @@ public class SoundTrigger { captureDelayMs, capturePreambleMs, triggerInData, captureFormat, data); } - @Override + /** @hide */ public int describeContents() { return 0; } - @Override + /** @hide */ public void writeToParcel(Parcel dest, int flags) { dest.writeInt(status); dest.writeInt(soundModelHandle); @@ -726,6 +859,8 @@ public class SoundTrigger { * A RecognitionConfig is provided to * {@link SoundTriggerModule#startRecognition(int, RecognitionConfig)} to configure the * recognition request. + * + * @hide */ public static class RecognitionConfig implements Parcelable { /** True if the DSP should capture the trigger sound and make it available for further @@ -744,7 +879,7 @@ public class SoundTrigger { public final byte[] data; public RecognitionConfig(boolean captureRequested, boolean allowMultipleTriggers, - KeyphraseRecognitionExtra keyphrases[], byte[] data) { + KeyphraseRecognitionExtra[] keyphrases, byte[] data) { this.captureRequested = captureRequested; this.allowMultipleTriggers = allowMultipleTriggers; this.keyphrases = keyphrases; @@ -799,6 +934,8 @@ public class SoundTrigger { * When used in a {@link RecognitionConfig} it indicates the minimum confidence level that * should trigger a recognition. * - The user ID is derived from the system ID {@link android.os.UserHandle#getIdentifier()}. + * + * @hide */ public static class ConfidenceLevel implements Parcelable { public final int userId; @@ -872,6 +1009,8 @@ public class SoundTrigger { /** * Additional data conveyed by a {@link KeyphraseRecognitionEvent} * for a key phrase detection. + * + * @hide */ public static class KeyphraseRecognitionExtra implements Parcelable { /** The keyphrase ID */ @@ -970,8 +1109,10 @@ public class SoundTrigger { /** * Specialized {@link RecognitionEvent} for a key phrase detection. + * + * @hide */ - public static class KeyphraseRecognitionEvent extends RecognitionEvent { + public static class KeyphraseRecognitionEvent extends RecognitionEvent implements Parcelable { /** Indicates if the key phrase is present in the buffered audio available for capture */ public final KeyphraseRecognitionExtra[] keyphraseExtras; @@ -1091,8 +1232,10 @@ public class SoundTrigger { /** * Sub-class of RecognitionEvent specifically for sound-trigger based sound * models(non-keyphrase). Currently does not contain any additional fields. + * + * @hide */ - public static class GenericRecognitionEvent extends RecognitionEvent { + public static class GenericRecognitionEvent extends RecognitionEvent implements Parcelable { public GenericRecognitionEvent(int status, int soundModelHandle, boolean captureAvailable, int captureSession, int captureDelayMs, int capturePreambleMs, boolean triggerInData, AudioFormat captureFormat, @@ -1140,13 +1283,19 @@ public class SoundTrigger { /** * Status codes for {@link SoundModelEvent} */ - /** Sound Model was updated */ + /** + * Sound Model was updated + * + * @hide + */ public static final int SOUNDMODEL_STATUS_UPDATED = 0; /** * A SoundModelEvent is provided by the * {@link StatusListener#onSoundModelUpdate(SoundModelEvent)} * callback when a sound model has been updated by the implementation + * + * @hide */ public static class SoundModelEvent implements Parcelable { /** Status e.g {@link #SOUNDMODEL_STATUS_UPDATED} */ @@ -1231,9 +1380,17 @@ public class SoundTrigger { * Native service state. {@link StatusListener#onServiceStateChange(int)} */ // Keep in sync with system/core/include/system/sound_trigger.h - /** Sound trigger service is enabled */ + /** + * Sound trigger service is enabled + * + * @hide + */ public static final int SERVICE_STATE_ENABLED = 0; - /** Sound trigger service is disabled */ + /** + * Sound trigger service is disabled + * + * @hide + */ public static final int SERVICE_STATE_DISABLED = 1; /** @@ -1245,6 +1402,8 @@ public class SoundTrigger { * - {@link #STATUS_NO_INIT} if the native service cannot be reached * - {@link #STATUS_BAD_VALUE} if modules is null * - {@link #STATUS_DEAD_OBJECT} if the binder transaction to the native service fails + * + * @hide */ public static native int listModules(ArrayList modules); @@ -1256,6 +1415,8 @@ public class SoundTrigger { * @param handler the Handler that will receive the callabcks. Can be null if default handler * is OK. * @return a valid sound module in case of success or null in case of error. + * + * @hide */ public static SoundTriggerModule attachModule(int moduleId, StatusListener listener, @@ -1270,6 +1431,8 @@ public class SoundTrigger { /** * Interface provided by the client application when attaching to a {@link SoundTriggerModule} * to received recognition and error notifications. + * + * @hide */ public static interface StatusListener { /** diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 9b11a33593bd..ef0c92f4b27d 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -3754,7 +3754,8 @@ + @hide + @SystemApi --> -- 2.11.0