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

Commit d94f1f7c authored by Nicholas Ambur's avatar Nicholas Ambur
Browse files

add KeyphraseEnrollmentInfo to TestApi

KeyphraseEnrollmentInfo is used for testing the system enrollment
application support within GTS.

Bug: 153264697
Test: gts-tradefed run gts-dev -m GtsAssistIntentTestCases \
-t com.google.android.assist.gts.KeyphraseModelManagerTest# \
testAllSystemKeyphrasesAndLocales

Change-Id: I66558cf849f2815f2c917d128f9f9cc0673750ef
parent 3b99c79b
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
@@ -1311,6 +1311,34 @@ package android.hardware.lights {

}

package android.hardware.soundtrigger {

  public class KeyphraseEnrollmentInfo {
    ctor public KeyphraseEnrollmentInfo(@NonNull android.content.pm.PackageManager);
    method @Nullable public android.hardware.soundtrigger.KeyphraseMetadata getKeyphraseMetadata(@NonNull String, @NonNull java.util.Locale);
    method @Nullable public android.content.Intent getManageKeyphraseIntent(int, @NonNull String, @NonNull java.util.Locale);
    method @NonNull public String getParseError();
    method @NonNull public java.util.Collection<android.hardware.soundtrigger.KeyphraseMetadata> listKeyphraseMetadata();
    field public static final int MANAGE_ACTION_ENROLL = 0; // 0x0
    field public static final int MANAGE_ACTION_RE_ENROLL = 1; // 0x1
    field public static final int MANAGE_ACTION_UN_ENROLL = 2; // 0x2
  }

  public final class KeyphraseMetadata implements android.os.Parcelable {
    ctor public KeyphraseMetadata(int, @NonNull String, @NonNull java.util.Set<java.util.Locale>, int);
    method public int describeContents();
    method public int getId();
    method @NonNull public String getKeyphrase();
    method public int getRecognitionModeFlags();
    method @NonNull public java.util.Set<java.util.Locale> getSupportedLocales();
    method public boolean supportsLocale(@Nullable java.util.Locale);
    method public boolean supportsPhrase(@Nullable String);
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.soundtrigger.KeyphraseMetadata> CREATOR;
  }

}

package android.location {

  public final class GnssClock implements android.os.Parcelable {
+34 −14
Original line number Diff line number Diff line
@@ -18,6 +18,9 @@ package android.hardware.soundtrigger;

import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -37,18 +40,22 @@ import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;

/**
 * Enrollment information about the different available keyphrases.
 *
 * @hide
 */
@TestApi
public class KeyphraseEnrollmentInfo {
    private static final String TAG = "KeyphraseEnrollmentInfo";
    /**
@@ -63,6 +70,7 @@ public class KeyphraseEnrollmentInfo {
     * Intent Action: for managing the keyphrases for hotword detection.
     * This needs to be defined by a service that supports enrolling users for hotword/keyphrase
     * detection.
     * @hide
     */
    public static final String ACTION_MANAGE_VOICE_KEYPHRASES =
            "com.android.intent.action.MANAGE_VOICE_KEYPHRASES";
@@ -72,18 +80,21 @@ public class KeyphraseEnrollmentInfo {
     * @see #MANAGE_ACTION_ENROLL
     * @see #MANAGE_ACTION_RE_ENROLL
     * @see #MANAGE_ACTION_UN_ENROLL
     * @hide
     */
    public static final String EXTRA_VOICE_KEYPHRASE_ACTION =
            "com.android.intent.extra.VOICE_KEYPHRASE_ACTION";

    /**
     * Intent extra: The hint text to be shown on the voice keyphrase management UI.
     * @hide
     */
    public static final String EXTRA_VOICE_KEYPHRASE_HINT_TEXT =
            "com.android.intent.extra.VOICE_KEYPHRASE_HINT_TEXT";
    /**
     * Intent extra: The voice locale to use while managing the keyphrase.
     * This is a BCP-47 language tag.
     * @hide
     */
    public static final String EXTRA_VOICE_KEYPHRASE_LOCALE =
            "com.android.intent.extra.VOICE_KEYPHRASE_LOCALE";
@@ -125,7 +136,8 @@ public class KeyphraseEnrollmentInfo {

    private String mParseError;

    public KeyphraseEnrollmentInfo(PackageManager pm) {
    public KeyphraseEnrollmentInfo(@NonNull PackageManager pm) {
        Objects.requireNonNull(pm);
        // Find the apps that supports enrollment for hotword keyhphrases,
        // Pick a privileged app and obtain the information about the supported keyphrases
        // from its metadata.
@@ -134,13 +146,13 @@ public class KeyphraseEnrollmentInfo {
        if (ris == null || ris.isEmpty()) {
            // No application capable of enrolling for voice keyphrases is present.
            mParseError = "No enrollment applications found";
            mKeyphrasePackageMap = Collections.<KeyphraseMetadata, String>emptyMap();
            mKeyphrasePackageMap = Collections.emptyMap();
            mKeyphrases = null;
            return;
        }

        List<String> parseErrors = new LinkedList<String>();
        mKeyphrasePackageMap = new HashMap<KeyphraseMetadata, String>();
        List<String> parseErrors = new LinkedList<>();
        mKeyphrasePackageMap = new HashMap<>();
        for (ResolveInfo ri : ris) {
            try {
                ApplicationInfo ai = pm.getApplicationInfo(
@@ -178,7 +190,7 @@ public class KeyphraseEnrollmentInfo {
            mKeyphrases = null;
        } else {
            mKeyphrases = mKeyphrasePackageMap.keySet().toArray(
                    new KeyphraseMetadata[mKeyphrasePackageMap.size()]);
                    new KeyphraseMetadata[0]);
        }

        if (!parseErrors.isEmpty()) {
@@ -269,8 +281,8 @@ public class KeyphraseEnrollmentInfo {
        if (!TextUtils.isEmpty(searchKeyphraseSupportedLocales)) {
            try {
                String[] supportedLocalesDelimited = searchKeyphraseSupportedLocales.split(",");
                for (int i = 0; i < supportedLocalesDelimited.length; i++) {
                    locales.add(Locale.forLanguageTag(supportedLocalesDelimited[i]));
                for (String s : supportedLocalesDelimited) {
                    locales.add(Locale.forLanguageTag(s));
                }
            } catch (Exception ex) {
                // We catch a generic exception here because we don't want the system service
@@ -297,6 +309,7 @@ public class KeyphraseEnrollmentInfo {
        return new KeyphraseMetadata(searchKeyphraseId, searchKeyphrase, locales, recognitionModes);
    }

    @NonNull
    public String getParseError() {
        return mParseError;
    }
@@ -305,8 +318,9 @@ public class KeyphraseEnrollmentInfo {
     * @return An array of available keyphrases that can be enrolled on the system.
     *         It may be null if no keyphrases can be enrolled.
     */
    public KeyphraseMetadata[] listKeyphraseMetadata() {
        return mKeyphrases;
    @NonNull
    public Collection<KeyphraseMetadata> listKeyphraseMetadata() {
        return Arrays.asList(mKeyphrases);
    }

    /**
@@ -319,8 +333,11 @@ public class KeyphraseEnrollmentInfo {
     * @return An {@link Intent} to manage the keyphrase. This can be null if managing the
     *         given keyphrase/locale combination isn't possible.
     */
    public Intent getManageKeyphraseIntent(@ManageActions int action, String keyphrase,
            Locale locale) {
    @Nullable
    public Intent getManageKeyphraseIntent(@ManageActions int action, @NonNull String keyphrase,
            @NonNull Locale locale) {
        Objects.requireNonNull(keyphrase);
        Objects.requireNonNull(locale);
        if (mKeyphrasePackageMap == null || mKeyphrasePackageMap.isEmpty()) {
            Slog.w(TAG, "No enrollment application exists");
            return null;
@@ -328,12 +345,11 @@ public class KeyphraseEnrollmentInfo {

        KeyphraseMetadata keyphraseMetadata = getKeyphraseMetadata(keyphrase, locale);
        if (keyphraseMetadata != null) {
            Intent intent = new Intent(ACTION_MANAGE_VOICE_KEYPHRASES)
            return new Intent(ACTION_MANAGE_VOICE_KEYPHRASES)
                    .setPackage(mKeyphrasePackageMap.get(keyphraseMetadata))
                    .putExtra(EXTRA_VOICE_KEYPHRASE_HINT_TEXT, keyphrase)
                    .putExtra(EXTRA_VOICE_KEYPHRASE_LOCALE, locale.toLanguageTag())
                    .putExtra(EXTRA_VOICE_KEYPHRASE_ACTION, action);
            return intent;
        }
        return null;
    }
@@ -348,7 +364,11 @@ public class KeyphraseEnrollmentInfo {
     * @return The metadata, if the enrollment client supports the given keyphrase
     *         and locale, null otherwise.
     */
    public KeyphraseMetadata getKeyphraseMetadata(String keyphrase, Locale locale) {
    @Nullable
    public KeyphraseMetadata getKeyphraseMetadata(@NonNull String keyphrase,
            @NonNull Locale locale) {
        Objects.requireNonNull(keyphrase);
        Objects.requireNonNull(locale);
        if (mKeyphrases != null && mKeyphrases.length > 0) {
          for (KeyphraseMetadata keyphraseMetadata : mKeyphrases) {
              // Check if the given keyphrase is supported in the locale provided by
+62 −41
Original line number Diff line number Diff line
@@ -18,57 +18,78 @@ package android.hardware.soundtrigger;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.os.Parcelable;
import android.util.ArraySet;

import com.android.internal.util.DataClass;

import java.util.Locale;
import java.util.Set;

/**
 * A Voice Keyphrase metadata read from the enrollment application.
 *
 * @hide
 */
@TestApi
@DataClass(
        genEqualsHashCode = true,
        genToString = true,
        genConstructor = false,
        genHiddenConstDefs = true)
public final class KeyphraseMetadata implements Parcelable {
    public final int id;
    private final int mId;
    @NonNull
    public final String keyphrase;
    private final String mKeyphrase;
    @NonNull
    public final ArraySet<Locale> supportedLocales;
    public final int recognitionModeFlags;
    private final ArraySet<Locale> mSupportedLocales;
    private final int mRecognitionModeFlags;

    public KeyphraseMetadata(int id, @NonNull String keyphrase,
            @NonNull ArraySet<Locale> supportedLocales, int recognitionModeFlags) {
        this.id = id;
        this.keyphrase = keyphrase;
        this.supportedLocales = supportedLocales;
        this.recognitionModeFlags = recognitionModeFlags;
            @NonNull Set<Locale> supportedLocales, int recognitionModeFlags) {
        this.mId = id;
        this.mKeyphrase = keyphrase;
        this.mSupportedLocales = new ArraySet<>(supportedLocales);
        this.mRecognitionModeFlags = recognitionModeFlags;
    }

    public int getId() {
        return mId;
    }

    @NonNull
    public String getKeyphrase() {
        return mKeyphrase;
    }

    @NonNull
    public Set<Locale> getSupportedLocales() {
        return mSupportedLocales;
    }

    public int getRecognitionModeFlags() {
        return mRecognitionModeFlags;
    }

    /**
     * @return Indicates if we support the given phrase.
     */
    public boolean supportsPhrase(@Nullable String phrase) {
        return keyphrase.isEmpty() || keyphrase.equalsIgnoreCase(phrase);
        return getKeyphrase().isEmpty() || getKeyphrase().equalsIgnoreCase(phrase);
    }

    /**
     * @return Indicates if we support the given locale.
     */
    public boolean supportsLocale(@Nullable Locale locale) {
        return supportedLocales.isEmpty() || supportedLocales.contains(locale);
        return getSupportedLocales().isEmpty() || getSupportedLocales().contains(locale);
    }




    // Code below generated by codegen v1.0.14.
    // Code below generated by codegen v1.0.15.
    //
    // DO NOT MODIFY!
    // CHECKSTYLE:OFF Generated code
@@ -88,10 +109,10 @@ public final class KeyphraseMetadata implements Parcelable {
        // String fieldNameToString() { ... }

        return "KeyphraseMetadata { " +
                "id = " + id + ", " +
                "keyphrase = " + keyphrase + ", " +
                "supportedLocales = " + supportedLocales + ", " +
                "recognitionModeFlags = " + recognitionModeFlags +
                "id = " + mId + ", " +
                "keyphrase = " + mKeyphrase + ", " +
                "supportedLocales = " + mSupportedLocales + ", " +
                "recognitionModeFlags = " + mRecognitionModeFlags +
        " }";
    }

@@ -108,10 +129,10 @@ public final class KeyphraseMetadata implements Parcelable {
        KeyphraseMetadata that = (KeyphraseMetadata) o;
        //noinspection PointlessBooleanExpression
        return true
                && id == that.id
                && java.util.Objects.equals(keyphrase, that.keyphrase)
                && java.util.Objects.equals(supportedLocales, that.supportedLocales)
                && recognitionModeFlags == that.recognitionModeFlags;
                && mId == that.mId
                && java.util.Objects.equals(mKeyphrase, that.mKeyphrase)
                && java.util.Objects.equals(mSupportedLocales, that.mSupportedLocales)
                && mRecognitionModeFlags == that.mRecognitionModeFlags;
    }

    @Override
@@ -121,10 +142,10 @@ public final class KeyphraseMetadata implements Parcelable {
        // int fieldNameHashCode() { ... }

        int _hash = 1;
        _hash = 31 * _hash + id;
        _hash = 31 * _hash + java.util.Objects.hashCode(keyphrase);
        _hash = 31 * _hash + java.util.Objects.hashCode(supportedLocales);
        _hash = 31 * _hash + recognitionModeFlags;
        _hash = 31 * _hash + mId;
        _hash = 31 * _hash + java.util.Objects.hashCode(mKeyphrase);
        _hash = 31 * _hash + java.util.Objects.hashCode(mSupportedLocales);
        _hash = 31 * _hash + mRecognitionModeFlags;
        return _hash;
    }

@@ -134,10 +155,10 @@ public final class KeyphraseMetadata implements Parcelable {
        // You can override field parcelling by defining methods like:
        // void parcelFieldName(Parcel dest, int flags) { ... }

        dest.writeInt(id);
        dest.writeString(keyphrase);
        dest.writeArraySet(supportedLocales);
        dest.writeInt(recognitionModeFlags);
        dest.writeInt(mId);
        dest.writeString(mKeyphrase);
        dest.writeArraySet(mSupportedLocales);
        dest.writeInt(mRecognitionModeFlags);
    }

    @Override
@@ -151,19 +172,19 @@ public final class KeyphraseMetadata implements Parcelable {
        // You can override field unparcelling by defining methods like:
        // static FieldType unparcelFieldName(Parcel in) { ... }

        int _id = in.readInt();
        String _keyphrase = in.readString();
        ArraySet<Locale> _supportedLocales = (ArraySet) in.readArraySet(null);
        int _recognitionModeFlags = in.readInt();
        int id = in.readInt();
        String keyphrase = in.readString();
        ArraySet<Locale> supportedLocales = (ArraySet) in.readArraySet(null);
        int recognitionModeFlags = in.readInt();

        this.id = _id;
        this.keyphrase = _keyphrase;
        this.mId = id;
        this.mKeyphrase = keyphrase;
        com.android.internal.util.AnnotationValidations.validate(
                NonNull.class, null, keyphrase);
        this.supportedLocales = _supportedLocales;
                NonNull.class, null, mKeyphrase);
        this.mSupportedLocales = supportedLocales;
        com.android.internal.util.AnnotationValidations.validate(
                NonNull.class, null, supportedLocales);
        this.recognitionModeFlags = _recognitionModeFlags;
                NonNull.class, null, mSupportedLocales);
        this.mRecognitionModeFlags = recognitionModeFlags;

        // onConstructed(); // You can define this method to get a callback
    }
@@ -183,10 +204,10 @@ public final class KeyphraseMetadata implements Parcelable {
    };

    @DataClass.Generated(
            time = 1579290593964L,
            codegenVersion = "1.0.14",
            time = 1586191622057L,
            codegenVersion = "1.0.15",
            sourceFile = "frameworks/base/core/java/android/hardware/soundtrigger/KeyphraseMetadata.java",
            inputSignatures = "public final  int id\npublic final @android.annotation.NonNull java.lang.String keyphrase\npublic final @android.annotation.NonNull android.util.ArraySet<java.util.Locale> supportedLocales\npublic final  int recognitionModeFlags\npublic  boolean supportsPhrase(java.lang.String)\npublic  boolean supportsLocale(java.util.Locale)\nclass KeyphraseMetadata extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genConstructor=false, genHiddenConstDefs=true)")
            inputSignatures = "private final  int mId\nprivate final @android.annotation.NonNull java.lang.String mKeyphrase\nprivate final @android.annotation.NonNull android.util.ArraySet<java.util.Locale> mSupportedLocales\nprivate final  int mRecognitionModeFlags\npublic  int getId()\npublic @android.annotation.NonNull java.lang.String getKeyphrase()\npublic @android.annotation.NonNull java.util.Set<java.util.Locale> getSupportedLocales()\npublic  int getRecognitionModeFlags()\npublic  boolean supportsPhrase(java.lang.String)\npublic  boolean supportsLocale(java.util.Locale)\nclass KeyphraseMetadata extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genConstructor=false, genHiddenConstDefs=true)")
    @Deprecated
    private void __metadata() {}

+8 −8
Original line number Diff line number Diff line
@@ -460,7 +460,7 @@ public class AlwaysOnHotwordDetector {
                    "Getting supported recognition modes for the keyphrase is not supported");
        }

        return mKeyphraseMetadata.recognitionModeFlags;
        return mKeyphraseMetadata.getRecognitionModeFlags();
    }

    /**
@@ -765,8 +765,8 @@ public class AlwaysOnHotwordDetector {
    private int startRecognitionLocked(int recognitionFlags) {
        KeyphraseRecognitionExtra[] recognitionExtra = new KeyphraseRecognitionExtra[1];
        // TODO: Do we need to do something about the confidence level here?
        recognitionExtra[0] = new KeyphraseRecognitionExtra(mKeyphraseMetadata.id,
                mKeyphraseMetadata.recognitionModeFlags, 0, new ConfidenceLevel[0]);
        recognitionExtra[0] = new KeyphraseRecognitionExtra(mKeyphraseMetadata.getId(),
                mKeyphraseMetadata.getRecognitionModeFlags(), 0, new ConfidenceLevel[0]);
        boolean captureTriggerAudio =
                (recognitionFlags&RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO) != 0;
        boolean allowMultipleTriggers =
@@ -783,7 +783,7 @@ public class AlwaysOnHotwordDetector {
        int code;
        try {
            code = mModelManagementService.startRecognition(
                    mKeyphraseMetadata.id, mLocale.toLanguageTag(), mInternalCallback,
                    mKeyphraseMetadata.getId(), mLocale.toLanguageTag(), mInternalCallback,
                    new RecognitionConfig(captureTriggerAudio, allowMultipleTriggers,
                            recognitionExtra, null /* additional data */, audioCapabilities));
        } catch (RemoteException e) {
@@ -799,7 +799,7 @@ public class AlwaysOnHotwordDetector {
    private int stopRecognitionLocked() {
        int code;
        try {
            code = mModelManagementService.stopRecognition(mKeyphraseMetadata.id,
            code = mModelManagementService.stopRecognition(mKeyphraseMetadata.getId(),
                    mInternalCallback);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
@@ -813,7 +813,7 @@ public class AlwaysOnHotwordDetector {

    private int setParameterLocked(@ModelParams int modelParam, int value) {
        try {
            int code = mModelManagementService.setParameter(mKeyphraseMetadata.id, modelParam,
            int code = mModelManagementService.setParameter(mKeyphraseMetadata.getId(), modelParam,
                    value);

            if (code != STATUS_OK) {
@@ -828,7 +828,7 @@ public class AlwaysOnHotwordDetector {

    private int getParameterLocked(@ModelParams int modelParam) {
        try {
            return mModelManagementService.getParameter(mKeyphraseMetadata.id, modelParam);
            return mModelManagementService.getParameter(mKeyphraseMetadata.getId(), modelParam);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
@@ -838,7 +838,7 @@ public class AlwaysOnHotwordDetector {
    private ModelParamRange queryParameterLocked(@ModelParams int modelParam) {
        try {
            SoundTrigger.ModelParamRange modelParamRange =
                    mModelManagementService.queryParameter(mKeyphraseMetadata.id, modelParam);
                    mModelManagementService.queryParameter(mKeyphraseMetadata.getId(), modelParam);

            if (modelParamRange == null) {
                return null;
+2 −4
Original line number Diff line number Diff line
@@ -16,14 +16,11 @@

package com.android.test.voiceinteraction;

import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
import android.service.voice.AlwaysOnHotwordDetector;
import android.service.voice.AlwaysOnHotwordDetector.Callback;
import android.service.voice.AlwaysOnHotwordDetector.EventPayload;
import android.service.voice.VoiceInteractionService;
import android.service.voice.VoiceInteractionSession;
import android.util.Log;

import java.util.Arrays;
@@ -68,7 +65,8 @@ public class MainInteractionService extends VoiceInteractionService {
        Log.i(TAG, "Creating " + this);
        Log.i(TAG, "Keyphrase enrollment error? " + getKeyphraseEnrollmentInfo().getParseError());
        Log.i(TAG, "Keyphrase enrollment meta-data: "
                + Arrays.toString(getKeyphraseEnrollmentInfo().listKeyphraseMetadata()));
                + Arrays.toString(getKeyphraseEnrollmentInfo().listKeyphraseMetadata().toArray(
                new android.hardware.soundtrigger.KeyphraseMetadata[0])));

        mHotwordDetector = createAlwaysOnHotwordDetector(
                "Hello There", Locale.forLanguageTag("en-US"), mHotwordCallback);