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

Commit f79a7ceb authored by Atneya Nair's avatar Atneya Nair Committed by Android (Google) Code Review
Browse files

Merge "Add VIService ST module selection TestApis"

parents c6784453 333b72b7
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -2800,6 +2800,12 @@ package android.service.voice {
    ctor public VisibleActivityInfo(int, @NonNull android.os.IBinder);
  }

  public class VoiceInteractionService extends android.app.Service {
    method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_HOTWORD_DETECTION) public final android.service.voice.AlwaysOnHotwordDetector createAlwaysOnHotwordDetectorForTest(@NonNull String, @NonNull java.util.Locale, @NonNull android.hardware.soundtrigger.SoundTrigger.ModuleProperties, @NonNull java.util.concurrent.Executor, @NonNull android.service.voice.AlwaysOnHotwordDetector.Callback);
    method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_HOTWORD_DETECTION) public final android.service.voice.AlwaysOnHotwordDetector createAlwaysOnHotwordDetectorForTest(@NonNull String, @NonNull java.util.Locale, @Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory, @NonNull android.hardware.soundtrigger.SoundTrigger.ModuleProperties, @NonNull java.util.concurrent.Executor, @NonNull android.service.voice.AlwaysOnHotwordDetector.Callback);
    method @NonNull public final java.util.List<android.hardware.soundtrigger.SoundTrigger.ModuleProperties> listModuleProperties();
  }

  public static class VoiceInteractionSession.ActivityId {
    method @NonNull public android.os.IBinder getAssistToken();
    method public int getTaskId();
+16 −2
Original line number Diff line number Diff line
@@ -784,8 +784,13 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
        mSupportSandboxedDetectionService = supportSandboxedDetectionService;
    }

    // Do nothing. This method should not be abstract.
    // TODO (b/269355519) un-subclass AOHD.
    @Override
    void initialize(@Nullable PersistableBundle options, @Nullable SharedMemory sharedMemory) {
    void initialize(@Nullable PersistableBundle options, @Nullable SharedMemory sharedMemory) {}

    void initialize(@Nullable PersistableBundle options, @Nullable SharedMemory sharedMemory,
            @Nullable SoundTrigger.ModuleProperties moduleProperties) {
        if (mSupportSandboxedDetectionService) {
            initAndVerifyDetector(options, sharedMemory, mInternalCallback,
                    DETECTOR_TYPE_TRUSTED_HOTWORD_DSP);
@@ -793,9 +798,18 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
        try {
            Identity identity = new Identity();
            identity.packageName = ActivityThread.currentOpPackageName();
            if (moduleProperties == null) {
                List<SoundTrigger.ModuleProperties> modulePropList =
                        mModelManagementService.listModuleProperties(identity);
                if (modulePropList.size() > 0) {
                    moduleProperties = modulePropList.get(0);
                }
                // (@atneya) intentionally let a null moduleProperties through until
                // all CTS tests are fixed
            }
            mSoundTriggerSession =
                    mModelManagementService.createSoundTriggerSessionAsOriginator(
                            identity, mBinder);
                            identity, mBinder, moduleProperties);
        } catch (RemoteException e) {
            throw e.rethrowAsRuntimeException();
        }
+85 −6
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@ import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.app.ActivityThread;
import android.app.Service;
import android.app.compat.CompatChanges;
import android.compat.annotation.ChangeId;
@@ -33,7 +35,9 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.hardware.soundtrigger.KeyphraseEnrollmentInfo;
import android.hardware.soundtrigger.SoundTrigger;
import android.media.voice.KeyphraseModelManager;
import android.media.permission.Identity;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
@@ -385,6 +389,22 @@ public class VoiceInteractionService extends Service {
        }
    }

    /**
     * List available ST modules to attach to for test purposes.
     * @hide
     */
    @TestApi
    @NonNull
    public final List<SoundTrigger.ModuleProperties> listModuleProperties() {
        Identity identity = new Identity();
        identity.packageName = ActivityThread.currentOpPackageName();
        try {
            return mSystemService.listModuleProperties(identity);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Creates an {@link AlwaysOnHotwordDetector} for the given keyphrase and locale.
     * This instance must be retained and used by the client.
@@ -422,7 +442,8 @@ public class VoiceInteractionService extends Service {
            @SuppressLint("MissingNullability") AlwaysOnHotwordDetector.Callback callback) {
        return createAlwaysOnHotwordDetectorInternal(keyphrase, locale,
                /* supportHotwordDetectionService= */ false, /* options= */ null,
                /* sharedMemory= */ null, /* executor= */ null, callback);
                /* sharedMemory= */ null, /* moduleProperties */ null,
                /* executor= */ null, callback);
    }

    /**
@@ -461,9 +482,36 @@ public class VoiceInteractionService extends Service {
        Objects.requireNonNull(callback);
        return createAlwaysOnHotwordDetectorInternal(keyphrase, locale,
                /* supportHotwordDetectionService= */ false, /* options= */ null,
                /* sharedMemory= */ null, executor, callback);
                /* sharedMemory= */ null, /* moduleProperties */ null, executor, callback);
    }

    /**
     * Same as {@link createAlwaysOnHotwordDetector(String, Locale, Executor,
     * AlwaysOnHotwordDetector.Callback)}, but allow explicit selection of the underlying ST
     * module to attach to.
     * Use {@link listModuleProperties} to get available modules to attach to.
     * @hide
     */
    @TestApi
    @RequiresPermission(Manifest.permission.MANAGE_HOTWORD_DETECTION)
    @NonNull
    public final AlwaysOnHotwordDetector createAlwaysOnHotwordDetectorForTest(
            @NonNull String keyphrase, @SuppressLint("UseIcu") @NonNull Locale locale,
            @NonNull SoundTrigger.ModuleProperties moduleProperties,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull AlwaysOnHotwordDetector.Callback callback) {

        Objects.requireNonNull(keyphrase);
        Objects.requireNonNull(locale);
        Objects.requireNonNull(moduleProperties);
        Objects.requireNonNull(executor);
        Objects.requireNonNull(callback);
        return createAlwaysOnHotwordDetectorInternal(keyphrase, locale,
                /* supportHotwordDetectionService= */ false, /* options= */ null,
                /* sharedMemory= */ null, moduleProperties, executor, callback);
    }


    /**
     * Create an {@link AlwaysOnHotwordDetector} and trigger a {@link HotwordDetectionService}
     * service, then it will also pass the read-only data to hotword detection service.
@@ -515,7 +563,7 @@ public class VoiceInteractionService extends Service {
            @SuppressLint("MissingNullability") AlwaysOnHotwordDetector.Callback callback) {
        return createAlwaysOnHotwordDetectorInternal(keyphrase, locale,
                /* supportHotwordDetectionService= */ true, options, sharedMemory,
                /* executor= */ null, callback);
                /* modulProperties */ null, /* executor= */ null, callback);
    }

    /**
@@ -566,16 +614,46 @@ public class VoiceInteractionService extends Service {
        Objects.requireNonNull(executor);
        Objects.requireNonNull(callback);
        return createAlwaysOnHotwordDetectorInternal(keyphrase, locale,
                /* supportHotwordDetectionService= */ true, options, sharedMemory, executor,
                callback);
                /* supportHotwordDetectionService= */ true, options, sharedMemory,
                /* moduleProperties */ null, executor, callback);
    }

    /**
     * Same as {@link createAlwaysOnHotwordDetector(String, Locale,
     * PersistableBundle, SharedMemory, Executor, AlwaysOnHotwordDetector.Callback)},
     * but allow explicit selection of the underlying ST module to attach to.
     * Use {@link listModuleProperties} to get available modules to attach to.
     * @hide
     */
    @TestApi
    @RequiresPermission(Manifest.permission.MANAGE_HOTWORD_DETECTION)
    @NonNull
    public final AlwaysOnHotwordDetector createAlwaysOnHotwordDetectorForTest(
            @NonNull String keyphrase, @SuppressLint("UseIcu") @NonNull Locale locale,
            @Nullable PersistableBundle options, @Nullable SharedMemory sharedMemory,
            @NonNull SoundTrigger.ModuleProperties moduleProperties,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull AlwaysOnHotwordDetector.Callback callback) {

        Objects.requireNonNull(keyphrase);
        Objects.requireNonNull(locale);
        Objects.requireNonNull(moduleProperties);
        Objects.requireNonNull(executor);
        Objects.requireNonNull(callback);
        return createAlwaysOnHotwordDetectorInternal(keyphrase, locale,
                /* supportHotwordDetectionService= */ true, options, sharedMemory,
                moduleProperties, executor, callback);
    }



    private AlwaysOnHotwordDetector createAlwaysOnHotwordDetectorInternal(
            @SuppressLint("MissingNullability") String keyphrase,  // TODO: nullability properly
            @SuppressLint({"MissingNullability", "UseIcu"}) Locale locale,
            boolean supportHotwordDetectionService,
            @Nullable PersistableBundle options,
            @Nullable SharedMemory sharedMemory,
            @Nullable SoundTrigger.ModuleProperties moduleProperties,
            @Nullable @CallbackExecutor Executor executor,
            @SuppressLint("MissingNullability") AlwaysOnHotwordDetector.Callback callback) {

@@ -609,7 +687,8 @@ public class VoiceInteractionService extends Service {

            try {
                dspDetector.registerOnDestroyListener(this::onHotwordDetectorDestroyed);
                dspDetector.initialize(options, sharedMemory);
                // If moduleProperties is null, the default STModule is used.
                dspDetector.initialize(options, sharedMemory, moduleProperties);
            } catch (Exception e) {
                mActiveDetectors.remove(dspDetector);
                dspDetector.destroy();
+8 −1
Original line number Diff line number Diff line
@@ -243,7 +243,14 @@ interface IVoiceInteractionManagerService {
     */
    IVoiceInteractionSoundTriggerSession createSoundTriggerSessionAsOriginator(
            in Identity originatorIdentity,
            IBinder client);
            IBinder client,
            in SoundTrigger.ModuleProperties moduleProperties);

    /**
     * Lists properties of SoundTrigger modules that can be attached to by
     * @{link createSoundTriggerSessionAsOriginator}.
     */
    List<SoundTrigger.ModuleProperties> listModuleProperties(in Identity originatorIdentity);

    /**
     * Set configuration and pass read-only data to hotword detection service.
+11 −13
Original line number Diff line number Diff line
@@ -377,7 +377,8 @@ public class VoiceInteractionManagerService extends SystemService {

        @Override
        public @NonNull IVoiceInteractionSoundTriggerSession createSoundTriggerSessionAsOriginator(
                @NonNull Identity originatorIdentity, IBinder client) {
                @NonNull Identity originatorIdentity, IBinder client,
                @NonNull ModuleProperties moduleProperties) {
            Objects.requireNonNull(originatorIdentity);
            boolean forHotwordDetectionService;
            synchronized (VoiceInteractionManagerServiceStub.this) {
@@ -396,7 +397,7 @@ public class VoiceInteractionManagerService extends SystemService {
                originatorIdentity.uid = Binder.getCallingUid();
                originatorIdentity.pid = Binder.getCallingPid();
                session = new SoundTriggerSessionPermissionsDecorator(
                        createSoundTriggerSessionForSelfIdentity(client),
                        createSoundTriggerSessionForSelfIdentity(client, moduleProperties),
                        mContext,
                        originatorIdentity);
            } else {
@@ -406,14 +407,14 @@ public class VoiceInteractionManagerService extends SystemService {
                try (SafeCloseable ignored = PermissionUtil.establishIdentityDirect(
                        originatorIdentity)) {
                    session = new SoundTriggerSession(mSoundTriggerInternal.attach(client,
                                getDefaultModuleProperties(originatorIdentity)));
                                moduleProperties));
                }
            }
            return new SoundTriggerSessionBinderProxy(session);
        }

        private IVoiceInteractionSoundTriggerSession createSoundTriggerSessionForSelfIdentity(
                IBinder client) {
                IBinder client, ModuleProperties moduleProperties) {
            Identity identity = new Identity();
            identity.uid = Process.myUid();
            identity.pid = Process.myPid();
@@ -421,20 +422,17 @@ public class VoiceInteractionManagerService extends SystemService {
            return Binder.withCleanCallingIdentity(() -> {
                try (SafeCloseable ignored = IdentityContext.create(identity)) {
                    return new SoundTriggerSession(
                            mSoundTriggerInternal.attach(client,
                                getDefaultModuleProperties(identity)));
                            mSoundTriggerInternal.attach(client, moduleProperties));
                }
            });
        }

        private ModuleProperties getDefaultModuleProperties(Identity originatorIdentity) {
            List<ModuleProperties> modulePropList = mSoundTriggerInternal
                    .listModuleProperties(originatorIdentity);
            if (modulePropList.isEmpty()) {
                return null;
            } else {
                return modulePropList.get(0);
        @Override
        public List<ModuleProperties> listModuleProperties(Identity originatorIdentity) {
            synchronized (VoiceInteractionManagerServiceStub.this) {
                enforceIsCurrentVoiceInteractionService();
            }
            return mSoundTriggerInternal.listModuleProperties(originatorIdentity);
        }

        // TODO: VI Make sure the caller is the current user or profile