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

Commit 9407076f authored by Atneya Nair's avatar Atneya Nair
Browse files

Add TestAPI for VIService to create AOHD for test

Add test API which configures subsequent AlwaysOnHotwordDetector
creation methods in VoiceInteractionService to use the underlying
test ST module.

Fixes: 276478654
Test: atest CtsVoiceInteractionTestCases
Change-Id: I234199d5c874ff3145ef468cd40be3a07999f09e
parent 2fad91a2
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2944,6 +2944,7 @@ package android.service.voice {
    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();
    method public final void setTestModuleForAlwaysOnHotwordDetectorEnabled(boolean);
  }

  public static class VoiceInteractionSession.ActivityId {
+50 −4
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ import android.provider.Settings;
import android.util.ArraySet;
import android.util.Log;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IVoiceActionCheckCallback;
import com.android.internal.app.IVoiceInteractionManagerService;
@@ -200,6 +201,9 @@ public class VoiceInteractionService extends Service {

    private final Set<HotwordDetector> mActiveDetectors = new ArraySet<>();

    // True if any of the createAOHD methods should use the test ST module.
    @GuardedBy("mLock")
    private boolean mTestModuleForAlwaysOnHotwordDetectorEnabled = false;

    private void onDetectorRemoteException(@NonNull IBinder token, int detectorType) {
        Log.d(TAG, "onDetectorRemoteException for " + HotwordDetector.detectorTypeToString(
@@ -512,14 +516,14 @@ public class VoiceInteractionService extends Service {
        Objects.requireNonNull(callback);
        return createAlwaysOnHotwordDetectorInternal(keyphrase, locale,
                /* supportHotwordDetectionService= */ false, /* options= */ null,
                /* sharedMemory= */ null, /* moduleProperties */ 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.
     * Use {@link #listModuleProperties()} to get available modules to attach to.
     * @hide
     */
    @TestApi
@@ -645,14 +649,14 @@ public class VoiceInteractionService extends Service {
        Objects.requireNonNull(callback);
        return createAlwaysOnHotwordDetectorInternal(keyphrase, locale,
                /* supportHotwordDetectionService= */ true, options, sharedMemory,
                /* moduleProperties */ null, executor, callback);
                /* 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.
     * Use {@link #listModuleProperties()} to get available modules to attach to.
     * @hide
     */
    @TestApi
@@ -717,6 +721,10 @@ public class VoiceInteractionService extends Service {

            try {
                dspDetector.registerOnDestroyListener(this::onHotwordDetectorDestroyed);
                // Check if we are currently overridden, and should use the test module.
                if (mTestModuleForAlwaysOnHotwordDetectorEnabled) {
                    moduleProperties = getTestModuleProperties();
                }
                // If moduleProperties is null, the default STModule is used.
                dspDetector.initialize(options, sharedMemory, moduleProperties);
            } catch (Exception e) {
@@ -990,6 +998,44 @@ public class VoiceInteractionService extends Service {
        return mKeyphraseEnrollmentInfo;
    }


    /**
     * Configure {@link createAlwaysOnHotwordDetector(String, Locale,
     * SoundTrigger.ModuleProperties, Executor, AlwaysOnHotwordDetector.Callback)}
     * and similar overloads to utilize the test SoundTrigger module instead of the
     * actual DSP module.
     * @param isEnabled - {@code true} if subsequently created {@link AlwaysOnHotwordDetector}
     * objects should attach to a test module. {@code false} if subsequently created
     * {@link AlwaysOnHotwordDetector} should attach to the actual DSP module.
     * @hide
     */
    @TestApi
    public final void setTestModuleForAlwaysOnHotwordDetectorEnabled(boolean isEnabled) {
        synchronized (mLock) {
            mTestModuleForAlwaysOnHotwordDetectorEnabled = isEnabled;
        }
    }

    /**
     * Get the {@link SoundTrigger.ModuleProperties} representing the fake
     * STHAL to attach to via {@link createAlwaysOnHotwordDetector(String, Locale,
     * SoundTrigger.ModuleProperties, Executor, AlwaysOnHotwordDetector.Callback)} and
     * similar overloads for test purposes.
     * @return ModuleProperties to use for test purposes.
     */
    private final @NonNull SoundTrigger.ModuleProperties getTestModuleProperties() {
        var moduleProps = listModuleProperties()
                .stream()
                .filter((SoundTrigger.ModuleProperties prop)
                        -> prop.getSupportedModelArch().equals(SoundTrigger.FAKE_HAL_ARCH))
                .findFirst()
                .orElse(null);
        if (moduleProps == null) {
            throw new IllegalStateException("Fake ST HAL should always be available");
        }
        return moduleProps;
    }

    /**
     * Checks if a given keyphrase and locale are supported to create an
     * {@link AlwaysOnHotwordDetector}.