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

Commit 05bd77c0 authored by Nicholas Ambur's avatar Nicholas Ambur Committed by Android (Google) Code Review
Browse files

Merge "Revert "update HotwordDetector exception throws"" into udc-dev

parents cc10548a 2ed6c794
Loading
Loading
Loading
Loading
+20 −23
Original line number Diff line number Diff line
@@ -12993,20 +12993,20 @@ package android.service.trust {
package android.service.voice {
  public class AlwaysOnHotwordDetector implements android.service.voice.HotwordDetector {
    method @Nullable public android.content.Intent createEnrollIntent() throws android.service.voice.HotwordDetector.IllegalDetectorStateException;
    method @Nullable public android.content.Intent createReEnrollIntent() throws android.service.voice.HotwordDetector.IllegalDetectorStateException;
    method @Nullable public android.content.Intent createUnEnrollIntent() throws android.service.voice.HotwordDetector.IllegalDetectorStateException;
    method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public int getParameter(int) throws android.service.voice.HotwordDetector.IllegalDetectorStateException;
    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() throws android.service.voice.HotwordDetector.IllegalDetectorStateException;
    method @Nullable @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public android.service.voice.AlwaysOnHotwordDetector.ModelParamRange queryParameter(int) throws android.service.voice.HotwordDetector.IllegalDetectorStateException;
    method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public int setParameter(int, int) throws android.service.voice.HotwordDetector.IllegalDetectorStateException;
    method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public boolean startRecognition(int, @NonNull byte[]) throws android.service.voice.HotwordDetector.IllegalDetectorStateException;
    method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public boolean startRecognition(int) throws android.service.voice.HotwordDetector.IllegalDetectorStateException;
    method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public boolean startRecognition() throws android.service.voice.HotwordDetector.IllegalDetectorStateException;
    method public boolean startRecognition(@NonNull android.os.ParcelFileDescriptor, @NonNull android.media.AudioFormat, @Nullable android.os.PersistableBundle) throws android.service.voice.HotwordDetector.IllegalDetectorStateException;
    method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public boolean stopRecognition() throws android.service.voice.HotwordDetector.IllegalDetectorStateException;
    method public final void updateState(@Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory) throws android.service.voice.HotwordDetector.IllegalDetectorStateException;
    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, @NonNull byte[]);
    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 startRecognition();
    method public boolean startRecognition(@NonNull android.os.ParcelFileDescriptor, @NonNull android.media.AudioFormat, @Nullable android.os.PersistableBundle);
    method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public boolean stopRecognition();
    method public final void updateState(@Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory);
    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
@@ -13185,10 +13185,10 @@ package android.service.voice {
  public interface HotwordDetector {
    method public default void destroy();
    method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public boolean startRecognition() throws android.service.voice.HotwordDetector.IllegalDetectorStateException;
    method public boolean startRecognition(@NonNull android.os.ParcelFileDescriptor, @NonNull android.media.AudioFormat, @Nullable android.os.PersistableBundle) throws android.service.voice.HotwordDetector.IllegalDetectorStateException;
    method public boolean stopRecognition() throws android.service.voice.HotwordDetector.IllegalDetectorStateException;
    method public void updateState(@Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory) throws android.service.voice.HotwordDetector.IllegalDetectorStateException;
    method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public boolean startRecognition();
    method public boolean startRecognition(@NonNull android.os.ParcelFileDescriptor, @NonNull android.media.AudioFormat, @Nullable android.os.PersistableBundle);
    method public boolean stopRecognition();
    method public void updateState(@Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory);
  }
  public static interface HotwordDetector.Callback {
@@ -13202,9 +13202,6 @@ package android.service.voice {
    method public void onRejected(@NonNull android.service.voice.HotwordRejectedResult);
  }
  public static class HotwordDetector.IllegalDetectorStateException extends android.util.AndroidException {
  }
  public final class HotwordRejectedResult implements android.os.Parcelable {
    method public int describeContents();
    method public int getConfidenceLevel();
@@ -13272,9 +13269,9 @@ package android.service.voice {
  public class VisualQueryDetector {
    method public void destroy();
    method @RequiresPermission(allOf={android.Manifest.permission.CAMERA, android.Manifest.permission.RECORD_AUDIO}) public boolean startRecognition() throws android.service.voice.HotwordDetector.IllegalDetectorStateException;
    method @RequiresPermission(allOf={android.Manifest.permission.CAMERA, android.Manifest.permission.RECORD_AUDIO}) public boolean stopRecognition() throws android.service.voice.HotwordDetector.IllegalDetectorStateException;
    method public void updateState(@Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory) throws android.service.voice.HotwordDetector.IllegalDetectorStateException;
    method @RequiresPermission(allOf={android.Manifest.permission.CAMERA, android.Manifest.permission.RECORD_AUDIO}) public boolean startRecognition();
    method @RequiresPermission(allOf={android.Manifest.permission.CAMERA, android.Manifest.permission.RECORD_AUDIO}) public boolean stopRecognition();
    method public void updateState(@Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory);
  }
  public static interface VisualQueryDetector.Callback {
+3 −13
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@ import android.annotation.CallSuper;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityThread;
import android.app.compat.CompatChanges;
import android.media.AudioFormat;
import android.media.permission.Identity;
import android.os.Binder;
@@ -100,7 +99,7 @@ abstract class AbstractDetector implements HotwordDetector {
    public boolean startRecognition(
            @NonNull ParcelFileDescriptor audioStream,
            @NonNull AudioFormat audioFormat,
            @Nullable PersistableBundle options) throws IllegalDetectorStateException {
            @Nullable PersistableBundle options) {
        if (DEBUG) {
            Slog.i(TAG, "#recognizeHotword");
        }
@@ -132,18 +131,13 @@ abstract class AbstractDetector implements HotwordDetector {
     * @param sharedMemory The unrestricted data blob to provide to the
     *        {@link VisualQueryDetectionService} and {@link HotwordDetectionService}. Use this to
     *         provide the hotword models data or other such data to the trusted process.
     * @throws IllegalDetectorStateException Thrown when a caller has a target SDK of
     *         Android Tiramisu or above and attempts to start a recognition when the detector is
     *         not able based on the state. Because the caller receives updates via an asynchronous
     *         callback and the state of the detector can change without caller's knowledge, a
     *         checked exception is thrown.
     * @throws IllegalStateException if this {@link HotwordDetector} wasn't specified to use a
     *         {@link HotwordDetectionService} or {@link VisualQueryDetectionService} when it was
     *         created.
     */
    @Override
    public void updateState(@Nullable PersistableBundle options,
            @Nullable SharedMemory sharedMemory) throws IllegalDetectorStateException {
            @Nullable SharedMemory sharedMemory) {
        if (DEBUG) {
            Slog.d(TAG, "updateState()");
        }
@@ -199,13 +193,9 @@ abstract class AbstractDetector implements HotwordDetector {
        }
    }

    protected void throwIfDetectorIsNoLongerActive() throws IllegalDetectorStateException {
    protected void throwIfDetectorIsNoLongerActive() {
        if (!mIsDetectorActive.get()) {
            Slog.e(TAG, "attempting to use a destroyed detector which is no longer active");
            if (CompatChanges.isChangeEnabled(HOTWORD_DETECTOR_THROW_CHECKED_EXCEPTION)) {
                throw new IllegalDetectorStateException(
                        "attempting to use a destroyed detector which is no longer active");
            }
            throw new IllegalStateException(
                    "attempting to use a destroyed detector which is no longer active");
        }
+73 −223

File changed.

Preview size limit exceeded, changes collapsed.

+4 −57
Original line number Diff line number Diff line
@@ -23,14 +23,10 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.media.AudioFormat;
import android.os.Build;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
import android.os.SharedMemory;
import android.util.AndroidException;

import java.io.PrintWriter;

@@ -43,23 +39,6 @@ import java.io.PrintWriter;
@SystemApi
public interface HotwordDetector {

    /**
     * Prior to API level 33, API calls of {@link android.service.voice.HotwordDetector} could
     * return both {@link java.lang.IllegalStateException} or
     * {@link java.lang.UnsupportedOperationException} depending on the detector's underlying state.
     * This lead to confusing behavior as the underlying state of the detector can be modified
     * without the knowledge of the caller via system service layer updates.
     *
     * This change ID, when enabled, changes the API calls to only throw checked exception
     * {@link android.service.voice.HotwordDetector.IllegalDetectorStateException} when checking
     * against state information modified by both the caller and the system services.
     *
     * @hide
     */
    @ChangeId
    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
    long HOTWORD_DETECTOR_THROW_CHECKED_EXCEPTION = 226355112L;

    /**
     * Indicates that it is a non-trusted hotword detector.
     *
@@ -109,26 +88,16 @@ public interface HotwordDetector {
     * Calling this again while recognition is active does nothing.
     *
     * @return {@code true} if the request to start recognition succeeded
     * @throws IllegalDetectorStateException Thrown when a caller has a target SDK of API level 33
     *         or above and attempts to start a recognition when the detector is not able based on
     *         the state. This can be thrown even if the state has been checked before calling this
     *         method because the caller receives updates via an asynchronous callback, and the
     *         state of the detector can change concurrently to the caller calling this method.
     */
    @RequiresPermission(allOf = {RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD})
    boolean startRecognition() throws IllegalDetectorStateException;
    boolean startRecognition();

    /**
     * Stops sandboxed detection recognition.
     *
     * @return {@code true} if the request to stop recognition succeeded
     * @throws IllegalDetectorStateException Thrown when a caller has a target SDK of API level 33
     *         or above and attempts to stop a recognition when the detector is not able based on
     *         the state. This can be thrown even if the state has been checked before calling this
     *         method because the caller receives updates via an asynchronous callback, and the
     *         state of the detector can change concurrently to the caller calling this method.
     */
    boolean stopRecognition() throws IllegalDetectorStateException;
    boolean stopRecognition();

    /**
     * Starts hotword recognition on audio coming from an external connected microphone.
@@ -142,16 +111,11 @@ public interface HotwordDetector {
     *         PersistableBundle does not allow any remotable objects or other contents that can be
     *         used to communicate with other processes.
     * @return {@code true} if the request to start recognition succeeded
     * @throws IllegalDetectorStateException Thrown when a caller has a target SDK of API level 33
     *         or above and attempts to start a recognition when the detector is not able based on
     *         the state. This can be thrown even if the state has been checked before calling this
     *         method because the caller receives updates via an asynchronous callback, and the
     *         state of the detector can change concurrently to the caller calling this method.
     */
    boolean startRecognition(
            @NonNull ParcelFileDescriptor audioStream,
            @NonNull AudioFormat audioFormat,
            @Nullable PersistableBundle options) throws IllegalDetectorStateException;
            @Nullable PersistableBundle options);

    /**
     * Set configuration and pass read-only data to sandboxed detection service.
@@ -161,17 +125,10 @@ public interface HotwordDetector {
     * communicate with other processes.
     * @param sharedMemory The unrestricted data blob to provide to sandboxed detection services.
     * Use this to provide model data or other such data to the trusted process.
     * @throws IllegalDetectorStateException Thrown when a caller has a target SDK of API level 33
     *         or above and the detector is not able to perform the operation based on the
     *         underlying state. This can be thrown even if the state has been checked before
     *         calling this method because the caller receives updates via an asynchronous callback,
     *         and the state of the detector can change concurrently to the caller calling this
     *         method.
     * @throws IllegalStateException if this HotwordDetector wasn't specified to use a
     *         sandboxed detection service when it was created.
     */
    void updateState(@Nullable PersistableBundle options, @Nullable SharedMemory sharedMemory)
            throws IllegalDetectorStateException;
    void updateState(@Nullable PersistableBundle options, @Nullable SharedMemory sharedMemory);

    /**
     * Invalidates this detector so that any future calls to this result
@@ -298,14 +255,4 @@ public interface HotwordDetector {
         */
        void onHotwordDetectionServiceRestarted();
    }

    /**
     * {@link HotwordDetector} specific exception thrown when the underlying state of the detector
     * is invalid for the given action.
     */
    class IllegalDetectorStateException extends AndroidException {
        IllegalDetectorStateException(String message) {
            super(message);
        }
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -86,7 +86,7 @@ class SoftwareHotwordDetector extends AbstractDetector {

    @RequiresPermission(RECORD_AUDIO)
    @Override
    public boolean startRecognition() throws IllegalDetectorStateException {
    public boolean startRecognition() {
        if (DEBUG) {
            Slog.i(TAG, "#startRecognition");
        }
@@ -109,7 +109,7 @@ class SoftwareHotwordDetector extends AbstractDetector {
    /** TODO: stopRecognition */
    @RequiresPermission(RECORD_AUDIO)
    @Override
    public boolean stopRecognition() throws IllegalDetectorStateException {
    public boolean stopRecognition() {
        if (DEBUG) {
            Slog.i(TAG, "#stopRecognition");
        }
Loading