Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c4d23a48 authored by Ytai Ben-Tsvi's avatar Ytai Ben-Tsvi
Browse files

Demote AlwaysOnHotwordDetector to SystemApi

AlwaysOnHotwordDetector gets demoted from public to SystemApi and
new permissions are enforced on its methods that imply usage of the
microphone via sound trigger.

Bug: 163865561
Change-Id: I113d69e569962b20d9d7dd1c6815daa6fb0650c5
parent 10c9b09f
Loading
Loading
Loading
Loading
+0 −46
Original line number Diff line number Diff line
@@ -44242,54 +44242,8 @@ package android.service.textservice {
package android.service.voice {
  public class AlwaysOnHotwordDetector {
    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 getSupportedAudioCapabilities();
    method public int getSupportedRecognitionModes();
    method @Nullable public android.service.voice.AlwaysOnHotwordDetector.ModelParamRange queryParameter(int);
    method public int setParameter(int, int);
    method public boolean startRecognition(int);
    method public boolean stopRecognition();
    field public static final int AUDIO_CAPABILITY_ECHO_CANCELLATION = 1; // 0x1
    field public static final int AUDIO_CAPABILITY_NOISE_SUPPRESSION = 2; // 0x2
    field public static final int MODEL_PARAM_THRESHOLD_FACTOR = 0; // 0x0
    field public static final int RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS = 2; // 0x2
    field public static final int RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO = 1; // 0x1
    field public static final int RECOGNITION_FLAG_ENABLE_AUDIO_ECHO_CANCELLATION = 4; // 0x4
    field public static final int RECOGNITION_FLAG_ENABLE_AUDIO_NOISE_SUPPRESSION = 8; // 0x8
    field public static final int RECOGNITION_MODE_USER_IDENTIFICATION = 2; // 0x2
    field public static final int RECOGNITION_MODE_VOICE_TRIGGER = 1; // 0x1
    field public static final int STATE_HARDWARE_UNAVAILABLE = -2; // 0xfffffffe
    field public static final int STATE_KEYPHRASE_ENROLLED = 2; // 0x2
    field public static final int STATE_KEYPHRASE_UNENROLLED = 1; // 0x1
    field @Deprecated public static final int STATE_KEYPHRASE_UNSUPPORTED = -1; // 0xffffffff
  }
  public abstract static class AlwaysOnHotwordDetector.Callback {
    ctor public AlwaysOnHotwordDetector.Callback();
    method public abstract void onAvailabilityChanged(int);
    method public abstract void onDetected(@NonNull android.service.voice.AlwaysOnHotwordDetector.EventPayload);
    method public abstract void onError();
    method public abstract void onRecognitionPaused();
    method public abstract void onRecognitionResumed();
  }
  public static class AlwaysOnHotwordDetector.EventPayload {
    method @Nullable public android.media.AudioFormat getCaptureAudioFormat();
    method @Nullable public byte[] getTriggerAudio();
  }
  public static final class AlwaysOnHotwordDetector.ModelParamRange {
    method public int getEnd();
    method public int getStart();
  }
  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);
    method public int getDisabledShowContext();
    method public static boolean isActiveService(android.content.Context, android.content.ComponentName);
    method public android.os.IBinder onBind(android.content.Intent);
+46 −0
Original line number Diff line number Diff line
@@ -10249,7 +10249,53 @@ package android.service.trust {
package android.service.voice {
  public class AlwaysOnHotwordDetector {
    method @Nullable public android.content.Intent createEnrollIntent();
    method @Nullable public android.content.Intent createReEnrollIntent();
    method @Nullable public android.content.Intent createUnEnrollIntent();
    method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public int getParameter(int);
    method public int getSupportedAudioCapabilities();
    method public int getSupportedRecognitionModes();
    method @Nullable @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public android.service.voice.AlwaysOnHotwordDetector.ModelParamRange queryParameter(int);
    method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public int setParameter(int, int);
    method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public boolean startRecognition(int);
    method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public boolean stopRecognition();
    field public static final int AUDIO_CAPABILITY_ECHO_CANCELLATION = 1; // 0x1
    field public static final int AUDIO_CAPABILITY_NOISE_SUPPRESSION = 2; // 0x2
    field public static final int MODEL_PARAM_THRESHOLD_FACTOR = 0; // 0x0
    field public static final int RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS = 2; // 0x2
    field public static final int RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO = 1; // 0x1
    field public static final int RECOGNITION_FLAG_ENABLE_AUDIO_ECHO_CANCELLATION = 4; // 0x4
    field public static final int RECOGNITION_FLAG_ENABLE_AUDIO_NOISE_SUPPRESSION = 8; // 0x8
    field public static final int RECOGNITION_MODE_USER_IDENTIFICATION = 2; // 0x2
    field public static final int RECOGNITION_MODE_VOICE_TRIGGER = 1; // 0x1
    field public static final int STATE_HARDWARE_UNAVAILABLE = -2; // 0xfffffffe
    field public static final int STATE_KEYPHRASE_ENROLLED = 2; // 0x2
    field public static final int STATE_KEYPHRASE_UNENROLLED = 1; // 0x1
    field @Deprecated public static final int STATE_KEYPHRASE_UNSUPPORTED = -1; // 0xffffffff
  }
  public abstract static class AlwaysOnHotwordDetector.Callback {
    ctor public AlwaysOnHotwordDetector.Callback();
    method public abstract void onAvailabilityChanged(int);
    method public abstract void onDetected(@NonNull android.service.voice.AlwaysOnHotwordDetector.EventPayload);
    method public abstract void onError();
    method public abstract void onRecognitionPaused();
    method public abstract void onRecognitionResumed();
  }
  public static class AlwaysOnHotwordDetector.EventPayload {
    method @Nullable public android.media.AudioFormat getCaptureAudioFormat();
    method @Nullable public byte[] getTriggerAudio();
  }
  public static final class AlwaysOnHotwordDetector.ModelParamRange {
    method public int getEnd();
    method public int getStart();
  }
  public class VoiceInteractionService extends android.app.Service {
    method @NonNull public final android.service.voice.AlwaysOnHotwordDetector createAlwaysOnHotwordDetector(String, java.util.Locale, android.service.voice.AlwaysOnHotwordDetector.Callback);
    method @NonNull @RequiresPermission("android.permission.MANAGE_VOICE_KEYPHRASES") public final android.media.voice.KeyphraseModelManager createKeyphraseModelManager();
  }
+18 −0
Original line number Diff line number Diff line
@@ -16,10 +16,15 @@

package android.service.voice;

import static android.Manifest.permission.CAPTURE_AUDIO_HOTWORD;
import static android.Manifest.permission.RECORD_AUDIO;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityThread;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
@@ -51,7 +56,12 @@ import java.util.Locale;
/**
 * A class that lets a VoiceInteractionService implementation interact with
 * always-on keyphrase detection APIs.
 *
 * @hide
 * TODO(b/168605867): Once Metalava supports expressing a removed public, but current system API,
 *                    mark and track it as such.
 */
@SystemApi
public class AlwaysOnHotwordDetector {
    //---- States of Keyphrase availability. Return codes for onAvailabilityChanged() ----//
    /**
@@ -525,6 +535,7 @@ public class AlwaysOnHotwordDetector {
     *         This may happen if another detector has been instantiated or the
     *         {@link VoiceInteractionService} hosting this detector has been shut down.
     */
    @RequiresPermission(allOf = {RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD})
    public boolean startRecognition(@RecognitionFlags int recognitionFlags) {
        if (DBG) Slog.d(TAG, "startRecognition(" + recognitionFlags + ")");
        synchronized (mLock) {
@@ -555,6 +566,7 @@ public class AlwaysOnHotwordDetector {
     *         This may happen if another detector has been instantiated or the
     *         {@link VoiceInteractionService} hosting this detector has been shut down.
     */
    @RequiresPermission(allOf = {RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD})
    public boolean stopRecognition() {
        if (DBG) Slog.d(TAG, "stopRecognition()");
        synchronized (mLock) {
@@ -589,6 +601,7 @@ public class AlwaysOnHotwordDetector {
     *         - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence or
     *           if API is not supported by HAL
     */
    @RequiresPermission(allOf = {RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD})
    public int setParameter(@ModelParams int modelParam, int value) {
        if (DBG) {
            Slog.d(TAG, "setParameter(" + modelParam + ", " + value + ")");
@@ -616,6 +629,7 @@ public class AlwaysOnHotwordDetector {
     * @param modelParam   {@link ModelParams}
     * @return value of parameter
     */
    @RequiresPermission(allOf = {RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD})
    public int getParameter(@ModelParams int modelParam) {
        if (DBG) {
            Slog.d(TAG, "getParameter(" + modelParam + ")");
@@ -640,6 +654,7 @@ public class AlwaysOnHotwordDetector {
     * @param modelParam {@link ModelParams}
     * @return supported range of parameter, null if not supported
     */
    @RequiresPermission(allOf = {RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD})
    @Nullable
    public ModelParamRange queryParameter(@ModelParams int modelParam) {
        if (DBG) {
@@ -670,6 +685,7 @@ public class AlwaysOnHotwordDetector {
     *         This may happen if another detector has been instantiated or the
     *         {@link VoiceInteractionService} hosting this detector has been shut down.
     */
    @Nullable
    public Intent createEnrollIntent() {
        if (DBG) Slog.d(TAG, "createEnrollIntent");
        synchronized (mLock) {
@@ -691,6 +707,7 @@ public class AlwaysOnHotwordDetector {
     *         This may happen if another detector has been instantiated or the
     *         {@link VoiceInteractionService} hosting this detector has been shut down.
     */
    @Nullable
    public Intent createUnEnrollIntent() {
        if (DBG) Slog.d(TAG, "createUnEnrollIntent");
        synchronized (mLock) {
@@ -712,6 +729,7 @@ public class AlwaysOnHotwordDetector {
     *         This may happen if another detector has been instantiated or the
     *         {@link VoiceInteractionService} hosting this detector has been shut down.
     */
    @Nullable
    public Intent createReEnrollIntent() {
        if (DBG) Slog.d(TAG, "createReEnrollIntent");
        synchronized (mLock) {
+10 −4
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.Manifest;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.app.Service;
import android.compat.annotation.UnsupportedAppUsage;
@@ -237,9 +238,8 @@ public class VoiceInteractionService extends Service {
    /**
     * Called during service initialization to tell you when the system is ready
     * to receive interaction from it. You should generally do initialization here
     * rather than in {@link #onCreate}. Methods such as {@link #showSession} and
     * {@link #createAlwaysOnHotwordDetector}
     * will not be operational until this point.
     * rather than in {@link #onCreate}. Methods such as {@link #showSession} will
     * not be operational until this point.
     */
    public void onReady() {
        mSystemService = IVoiceInteractionManagerService.Stub.asInterface(
@@ -309,9 +309,15 @@ public class VoiceInteractionService extends Service {
     * @param locale The locale for which the enrollment needs to be performed.
     * @param callback The callback to notify of detection events.
     * @return An always-on hotword detector for the given keyphrase and locale.
     *
     * @hide
     */
    @SystemApi
    @NonNull
    public final AlwaysOnHotwordDetector createAlwaysOnHotwordDetector(
            String keyphrase, Locale locale, AlwaysOnHotwordDetector.Callback callback) {
            @SuppressLint("MissingNullability") String keyphrase,  // TODO: annotate nullability properly
            @SuppressLint({"MissingNullability", "UseIcu"}) Locale locale,
            @SuppressLint("MissingNullability") AlwaysOnHotwordDetector.Callback callback) {
        if (mSystemService == null) {
            throw new IllegalStateException("Not available until onReady() is called");
        }
+0 −46
Original line number Diff line number Diff line
@@ -42385,54 +42385,8 @@ package android.service.textservice {
package android.service.voice {
  public class AlwaysOnHotwordDetector {
    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 getSupportedAudioCapabilities();
    method public int getSupportedRecognitionModes();
    method @Nullable public android.service.voice.AlwaysOnHotwordDetector.ModelParamRange queryParameter(int);
    method public int setParameter(int, int);
    method public boolean startRecognition(int);
    method public boolean stopRecognition();
    field public static final int AUDIO_CAPABILITY_ECHO_CANCELLATION = 1; // 0x1
    field public static final int AUDIO_CAPABILITY_NOISE_SUPPRESSION = 2; // 0x2
    field public static final int MODEL_PARAM_THRESHOLD_FACTOR = 0; // 0x0
    field public static final int RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS = 2; // 0x2
    field public static final int RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO = 1; // 0x1
    field public static final int RECOGNITION_FLAG_ENABLE_AUDIO_ECHO_CANCELLATION = 4; // 0x4
    field public static final int RECOGNITION_FLAG_ENABLE_AUDIO_NOISE_SUPPRESSION = 8; // 0x8
    field public static final int RECOGNITION_MODE_USER_IDENTIFICATION = 2; // 0x2
    field public static final int RECOGNITION_MODE_VOICE_TRIGGER = 1; // 0x1
    field public static final int STATE_HARDWARE_UNAVAILABLE = -2; // 0xfffffffe
    field public static final int STATE_KEYPHRASE_ENROLLED = 2; // 0x2
    field public static final int STATE_KEYPHRASE_UNENROLLED = 1; // 0x1
    field @Deprecated public static final int STATE_KEYPHRASE_UNSUPPORTED = -1; // 0xffffffff
  }
  public abstract static class AlwaysOnHotwordDetector.Callback {
    ctor public AlwaysOnHotwordDetector.Callback();
    method public abstract void onAvailabilityChanged(int);
    method public abstract void onDetected(@NonNull android.service.voice.AlwaysOnHotwordDetector.EventPayload);
    method public abstract void onError();
    method public abstract void onRecognitionPaused();
    method public abstract void onRecognitionResumed();
  }
  public static class AlwaysOnHotwordDetector.EventPayload {
    method @Nullable public android.media.AudioFormat getCaptureAudioFormat();
    method @Nullable public byte[] getTriggerAudio();
  }
  public static final class AlwaysOnHotwordDetector.ModelParamRange {
    method public int getEnd();
    method public int getStart();
  }
  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);
    method public int getDisabledShowContext();
    method public static boolean isActiveService(android.content.Context, android.content.ComponentName);
    method public android.os.IBinder onBind(android.content.Intent);
Loading