From 1cfbb3b4059fa50f0d6a974dc094de41b7c53fcc Mon Sep 17 00:00:00 2001 From: Atneya Nair Date: Fri, 10 Feb 2023 09:46:35 -0800 Subject: [PATCH 1/2] Add module selection APIs to ST Configure underlying ST module selection when connecting to STService. This enables connection to a test HAL implementation. 1. Add listModuleProperties to STService interface. 2. Add ModuleProp argument to STService session attach methods. 3. Existing STService clients select the first module, to retain existing behavior. 4. Remove module props cacheing in STHelper. 5. Remove module re-attach on prepareForRec in STHelper, detach is now final. Module now re-attaches immediately on HAL death. 6. Explicitly error when no ST module is available in STManager. Test: Manual verification of assistant/aiai phrase reco Test: ST clients gracefully reconnect after HAL restart Test: Manual verification of getModuleProp result Bug: 269165331 Bug: 269166643 Change-Id: I1be9773aa20d68562154eb9fb9ec9e46583231c9 --- .../internal/app/ISoundTriggerService.aidl | 9 ++ .../soundtrigger/SoundTriggerManager.java | 57 ++++++++++--- .../soundtrigger/SoundTriggerHelper.java | 84 +++++++------------ .../soundtrigger/SoundTriggerInternal.java | 8 +- .../soundtrigger/SoundTriggerService.java | 82 ++++++++++++------ .../VoiceInteractionManagerService.java | 17 +++- 6 files changed, 162 insertions(+), 95 deletions(-) diff --git a/core/java/com/android/internal/app/ISoundTriggerService.aidl b/core/java/com/android/internal/app/ISoundTriggerService.aidl index 3874de395bea5..ab7f602e2dfcc 100644 --- a/core/java/com/android/internal/app/ISoundTriggerService.aidl +++ b/core/java/com/android/internal/app/ISoundTriggerService.aidl @@ -17,6 +17,7 @@ package com.android.internal.app; import android.media.permission.Identity; +import android.hardware.soundtrigger.SoundTrigger; import com.android.internal.app.ISoundTriggerSession; /** @@ -43,6 +44,7 @@ interface ISoundTriggerService { * to clean-up whenever that happens. */ ISoundTriggerSession attachAsOriginator(in Identity originatorIdentity, + in SoundTrigger.ModuleProperties moduleProperties, IBinder client); /** @@ -64,5 +66,12 @@ interface ISoundTriggerService { */ ISoundTriggerSession attachAsMiddleman(in Identity middlemanIdentity, in Identity originatorIdentity, + in SoundTrigger.ModuleProperties moduleProperties, IBinder client); + + /** + * Get available underlying SoundTrigger modules to attach to. + */ + List listModuleProperties(in Identity originatorIdentity); + } diff --git a/media/java/android/media/soundtrigger/SoundTriggerManager.java b/media/java/android/media/soundtrigger/SoundTriggerManager.java index c473a013d3b5f..0e9ef4c0c8ddb 100644 --- a/media/java/android/media/soundtrigger/SoundTriggerManager.java +++ b/media/java/android/media/soundtrigger/SoundTriggerManager.java @@ -32,6 +32,7 @@ import android.hardware.soundtrigger.SoundTrigger; import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel; import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel; import android.hardware.soundtrigger.SoundTrigger.ModelParamRange; +import android.hardware.soundtrigger.SoundTrigger.ModuleProperties; import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig; import android.hardware.soundtrigger.SoundTrigger.SoundModel; import android.media.permission.ClearCallingIdentityContext; @@ -52,6 +53,7 @@ import com.android.internal.app.ISoundTriggerSession; import com.android.internal.util.Preconditions; import java.util.HashMap; +import java.util.List; import java.util.Objects; import java.util.UUID; @@ -92,8 +94,16 @@ public final class SoundTriggerManager { originatorIdentity.packageName = ActivityThread.currentOpPackageName(); try (SafeCloseable ignored = ClearCallingIdentityContext.create()) { - mSoundTriggerSession = soundTriggerService.attachAsOriginator(originatorIdentity, - mBinderToken); + List modulePropertiesList = soundTriggerService + .listModuleProperties(originatorIdentity); + if (!modulePropertiesList.isEmpty()) { + mSoundTriggerSession = soundTriggerService.attachAsOriginator( + originatorIdentity, + modulePropertiesList.get(0), + mBinderToken); + } else { + mSoundTriggerSession = null; + } } } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); @@ -110,6 +120,9 @@ public final class SoundTriggerManager { @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) @Deprecated public void updateModel(Model model) { + if (mSoundTriggerSession == null) { + throw new IllegalStateException("No underlying SoundTriggerModule available"); + } try { mSoundTriggerSession.updateSoundModel(model.getGenericSoundModel()); } catch (RemoteException e) { @@ -128,6 +141,9 @@ public final class SoundTriggerManager { @Nullable @Deprecated public Model getModel(UUID soundModelId) { + if (mSoundTriggerSession == null) { + throw new IllegalStateException("No underlying SoundTriggerModule available"); + } try { GenericSoundModel model = mSoundTriggerSession.getSoundModel(new ParcelUuid(soundModelId)); @@ -149,6 +165,10 @@ public final class SoundTriggerManager { @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) @Deprecated public void deleteModel(UUID soundModelId) { + if (mSoundTriggerSession == null) { + throw new IllegalStateException("No underlying SoundTriggerModule available"); + } + try { mSoundTriggerSession.deleteSoundModel(new ParcelUuid(soundModelId)); } catch (RemoteException e) { @@ -176,7 +196,7 @@ public final class SoundTriggerManager { @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public SoundTriggerDetector createSoundTriggerDetector(UUID soundModelId, @NonNull SoundTriggerDetector.Callback callback, @Nullable Handler handler) { - if (soundModelId == null) { + if (soundModelId == null || mSoundTriggerSession == null) { return null; } @@ -342,7 +362,7 @@ public final class SoundTriggerManager { @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) @UnsupportedAppUsage public int loadSoundModel(SoundModel soundModel) { - if (soundModel == null) { + if (soundModel == null || mSoundTriggerSession == null) { return STATUS_ERROR; } @@ -389,7 +409,9 @@ public final class SoundTriggerManager { Preconditions.checkNotNull(soundModelId); Preconditions.checkNotNull(detectionService); Preconditions.checkNotNull(config); - + if (mSoundTriggerSession == null) { + return STATUS_ERROR; + } try { return mSoundTriggerSession.startRecognitionForService(new ParcelUuid(soundModelId), params, detectionService, config); @@ -405,7 +427,7 @@ public final class SoundTriggerManager { @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public int stopRecognition(UUID soundModelId) { - if (soundModelId == null) { + if (soundModelId == null || mSoundTriggerSession == null) { return STATUS_ERROR; } try { @@ -422,7 +444,7 @@ public final class SoundTriggerManager { @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public int unloadSoundModel(UUID soundModelId) { - if (soundModelId == null) { + if (soundModelId == null || mSoundTriggerSession == null) { return STATUS_ERROR; } try { @@ -440,7 +462,7 @@ public final class SoundTriggerManager { @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) @UnsupportedAppUsage public boolean isRecognitionActive(UUID soundModelId) { - if (soundModelId == null) { + if (soundModelId == null || mSoundTriggerSession == null) { return false; } try { @@ -475,7 +497,7 @@ public final class SoundTriggerManager { @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) @UnsupportedAppUsage public int getModelState(UUID soundModelId) { - if (soundModelId == null) { + if (soundModelId == null || mSoundTriggerSession == null) { return STATUS_ERROR; } try { @@ -492,8 +514,10 @@ public final class SoundTriggerManager { */ @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) @Nullable - public SoundTrigger.ModuleProperties getModuleProperties() { - + public ModuleProperties getModuleProperties() { + if (mSoundTriggerSession == null) { + return null; + } try { return mSoundTriggerSession.getModuleProperties(); } catch (RemoteException e) { @@ -520,6 +544,10 @@ public final class SoundTriggerManager { @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public int setParameter(@Nullable UUID soundModelId, @ModelParams int modelParam, int value) { + if (mSoundTriggerSession == null) { + return SoundTrigger.STATUS_INVALID_OPERATION; + } + try { return mSoundTriggerSession.setParameter(new ParcelUuid(soundModelId), modelParam, value); @@ -543,6 +571,10 @@ public final class SoundTriggerManager { @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public int getParameter(@NonNull UUID soundModelId, @ModelParams int modelParam) { + if (mSoundTriggerSession == null) { + throw new IllegalArgumentException("Sound model is not loaded: " + + soundModelId.toString()); + } try { return mSoundTriggerSession.getParameter(new ParcelUuid(soundModelId), modelParam); } catch (RemoteException e) { @@ -563,6 +595,9 @@ public final class SoundTriggerManager { @Nullable public ModelParamRange queryParameter(@Nullable UUID soundModelId, @ModelParams int modelParam) { + if (mSoundTriggerSession == null) { + return null; + } try { return mSoundTriggerSession.queryParameter(new ParcelUuid(soundModelId), modelParam); } catch (RemoteException e) { diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java index b71669046ee9e..86893cbc9f1e5 100644 --- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java +++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java @@ -56,9 +56,12 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.UUID; +import java.util.function.Function; +import java.util.function.Supplier; /** * Helper for {@link SoundTrigger} APIs. Supports two types of models: @@ -84,10 +87,6 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { private static final int INVALID_VALUE = Integer.MIN_VALUE; - /** The {@link ModuleProperties} for the system, or null if none exists. */ - final ModuleProperties mModuleProperties; - - /** The properties for the DSP module */ private SoundTriggerModule mModule; private final Object mLock = new Object(); private final Context mContext; @@ -114,7 +113,6 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { private PowerSaveModeListener mPowerSaveModeListener; - private final SoundTriggerModuleProvider mModuleProvider; // Handler to process call state changes will delay to allow time for the audio // and sound trigger HALs to process the end of call notifications @@ -123,46 +121,24 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { private static final int MSG_CALL_STATE_CHANGED = 0; private static final int CALL_INACTIVE_MSG_DELAY_MS = 1000; - /** - * Provider interface for retrieving SoundTriggerModule instances - */ - public interface SoundTriggerModuleProvider { - /** - * Populate module properties for all available modules - * - * @param modules List of ModuleProperties to be populated - * @return Status int 0 on success. - */ - int listModuleProperties(@NonNull ArrayList modules); + // TODO(b/269366605) Temporary solution to query correct moduleProperties + private final int mModuleId; + private final Function mModuleProvider; + private final Supplier> mModulePropertiesProvider; - /** - * Get SoundTriggerModule based on {@link SoundTrigger.ModuleProperties#getId()} - * - * @param moduleId Module ID - * @param statusListener Client listener to be associated with the returned module - * @return Module associated with moduleId - */ - SoundTriggerModule getModule(int moduleId, SoundTrigger.StatusListener statusListener); - } - - SoundTriggerHelper(Context context, SoundTriggerModuleProvider moduleProvider) { - ArrayList modules = new ArrayList<>(); - mModuleProvider = moduleProvider; - int status = mModuleProvider.listModuleProperties(modules); + SoundTriggerHelper(Context context, + @NonNull Function moduleProvider, + int moduleId, + @NonNull Supplier> modulePropertiesProvider) { + mModuleId = moduleId; mContext = context; mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); mModelDataMap = new HashMap(); mKeyphraseUuidMap = new HashMap(); - if (status != SoundTrigger.STATUS_OK || modules.size() == 0) { - Slog.w(TAG, "listModules status=" + status + ", # of modules=" + modules.size()); - mModuleProperties = null; - mModule = null; - } else { - // TODO: Figure out how to determine which module corresponds to the DSP hardware. - mModuleProperties = modules.get(0); - } - + mModuleProvider = moduleProvider; + mModulePropertiesProvider = modulePropertiesProvider; + mModule = mModuleProvider.apply(this); Looper looper = Looper.myLooper(); if (looper == null) { looper = Looper.getMainLooper(); @@ -245,7 +221,6 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { + " soundModel=" + soundModel + ", callback=" + callback.asBinder() + ", recognitionConfig=" + recognitionConfig + ", runInBatterySaverMode=" + runInBatterySaverMode); - Slog.d(TAG, "moduleProperties=" + mModuleProperties); dumpModelStateLocked(); } @@ -290,11 +265,8 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { private int prepareForRecognition(ModelData modelData) { if (mModule == null) { - mModule = mModuleProvider.getModule(mModuleProperties.getId(), this); - if (mModule == null) { - Slog.w(TAG, "prepareForRecognition: cannot attach to sound trigger module"); - return STATUS_ERROR; - } + Slog.w(TAG, "prepareForRecognition: cannot attach to sound trigger module"); + return STATUS_ERROR; } // Load the model if it is not loaded. if (!modelData.isModelLoaded()) { @@ -336,11 +308,6 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { IRecognitionStatusCallback callback, RecognitionConfig recognitionConfig, int keyphraseId, boolean runInBatterySaverMode) { synchronized (mLock) { - if (mModuleProperties == null) { - Slog.w(TAG, "Attempting startRecognition without the capability"); - return STATUS_ERROR; - } - IRecognitionStatusCallback oldCallback = modelData.getCallback(); if (oldCallback != null && oldCallback.asBinder() != callback.asBinder()) { Slog.w(TAG, "Canceling previous recognition for model id: " @@ -486,8 +453,8 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { if (callback == null) { return STATUS_ERROR; } - if (mModuleProperties == null || mModule == null) { - Slog.w(TAG, "Attempting stopRecognition without the capability"); + if (mModule == null) { + Slog.w(TAG, "Attempting stopRecognition after detach"); return STATUS_ERROR; } @@ -563,7 +530,13 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { } public ModuleProperties getModuleProperties() { - return mModuleProperties; + for (ModuleProperties moduleProperties : mModulePropertiesProvider.get()) { + if (moduleProperties.getId() == mModuleId) { + return moduleProperties; + } + } + Slog.e(TAG, "Module properties not found for existing moduleId " + mModuleId); + return null; } int unloadKeyphraseSoundModel(int keyphraseId) { @@ -1027,7 +1000,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { internalClearGlobalStateLocked(); if (mModule != null) { mModule.detach(); - mModule = null; + mModule = mModuleProvider.apply(this); } } } @@ -1098,7 +1071,6 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { void dump(FileDescriptor fd, PrintWriter pw, String[] args) { synchronized (mLock) { pw.print(" module properties="); - pw.println(mModuleProperties == null ? "null" : mModuleProperties); pw.print(" call active="); pw.println(mCallActive); pw.println(" SoundTrigger Power State=" + mSoundTriggerPowerSaveMode); @@ -1444,7 +1416,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { // Computes whether we have any recognition running at all (voice or generic). Sets // the mRecognitionRequested variable with the result. private boolean computeRecognitionRequestedLocked() { - if (mModuleProperties == null || mModule == null) { + if (mModule == null) { mRecognitionRequested = false; return mRecognitionRequested; } diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java index 7071e23a5ebb8..cc398d930c7e8 100644 --- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java +++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java @@ -26,12 +26,14 @@ import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel; import android.hardware.soundtrigger.SoundTrigger.ModelParamRange; import android.hardware.soundtrigger.SoundTrigger.ModuleProperties; import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig; +import android.media.permission.Identity; import android.os.IBinder; import com.android.server.voiceinteraction.VoiceInteractionManagerService; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.List; /** * Provides a local service for managing voice-related recoginition models. This is primarily used @@ -46,7 +48,11 @@ public interface SoundTriggerInternal { int STATUS_ERROR = SoundTrigger.STATUS_ERROR; int STATUS_OK = SoundTrigger.STATUS_OK; - Session attach(@NonNull IBinder client); + // Attach to a specific underlying STModule + Session attach(@NonNull IBinder client, ModuleProperties underlyingModule); + + // Enumerate possible STModules to attach to + List listModuleProperties(Identity originatorIdentity); /** * Dumps service-wide information. diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java index 7824c69c0aa15..ddd8a26b118e6 100644 --- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java +++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java @@ -51,7 +51,6 @@ import android.hardware.soundtrigger.SoundTrigger.ModelParamRange; import android.hardware.soundtrigger.SoundTrigger.ModuleProperties; import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig; import android.hardware.soundtrigger.SoundTrigger.SoundModel; -import android.hardware.soundtrigger.SoundTriggerModule; import android.media.AudioAttributes; import android.media.AudioFormat; import android.media.AudioRecord; @@ -89,6 +88,7 @@ import com.android.server.utils.EventLogger; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.TreeMap; @@ -215,47 +215,69 @@ public class SoundTriggerService extends SystemService { } } - private SoundTriggerHelper newSoundTriggerHelper() { + private SoundTriggerHelper newSoundTriggerHelper(@NonNull ModuleProperties moduleProperties) { Identity middlemanIdentity = new Identity(); middlemanIdentity.packageName = ActivityThread.currentOpPackageName(); - Identity originatorIdentity = IdentityContext.getNonNull(); - return new SoundTriggerHelper(mContext, - new SoundTriggerHelper.SoundTriggerModuleProvider() { - @Override - public int listModuleProperties(ArrayList modules) { - return SoundTrigger.listModulesAsMiddleman(modules, middlemanIdentity, - originatorIdentity); - } + ArrayList moduleList = new ArrayList<>(); + SoundTrigger.listModulesAsMiddleman(moduleList, middlemanIdentity, + originatorIdentity); - @Override - public SoundTriggerModule getModule(int moduleId, - SoundTrigger.StatusListener statusListener) { - return SoundTrigger.attachModuleAsMiddleman(moduleId, statusListener, null, - middlemanIdentity, originatorIdentity); - } + if (!moduleList.contains(moduleProperties)) { + throw new IllegalArgumentException("Invalid module properties"); + } + + int moduleId = moduleProperties.getId(); + + return new SoundTriggerHelper( + mContext, + (SoundTrigger.StatusListener statusListener) -> + SoundTrigger.attachModuleAsMiddleman( + moduleId, statusListener, null /* handler */, + middlemanIdentity, originatorIdentity), + moduleId, + () -> { + ArrayList modulePropList = new ArrayList<>(); + SoundTrigger.listModulesAsMiddleman(modulePropList, middlemanIdentity, + originatorIdentity); + return modulePropList; }); } class SoundTriggerServiceStub extends ISoundTriggerService.Stub { @Override - public ISoundTriggerSession attachAsOriginator(Identity originatorIdentity, + public ISoundTriggerSession attachAsOriginator(@NonNull Identity originatorIdentity, + @NonNull ModuleProperties moduleProperties, @NonNull IBinder client) { try (SafeCloseable ignored = PermissionUtil.establishIdentityDirect( originatorIdentity)) { - return new SoundTriggerSessionStub(client); + return new SoundTriggerSessionStub(client, newSoundTriggerHelper(moduleProperties)); } } @Override - public ISoundTriggerSession attachAsMiddleman(Identity originatorIdentity, - Identity middlemanIdentity, + public ISoundTriggerSession attachAsMiddleman(@NonNull Identity originatorIdentity, + @NonNull Identity middlemanIdentity, + @NonNull ModuleProperties moduleProperties, @NonNull IBinder client) { try (SafeCloseable ignored = PermissionUtil.establishIdentityIndirect(mContext, SOUNDTRIGGER_DELEGATE_IDENTITY, middlemanIdentity, originatorIdentity)) { - return new SoundTriggerSessionStub(client); + return new SoundTriggerSessionStub(client, newSoundTriggerHelper(moduleProperties)); + } + } + + @Override + public List listModuleProperties(@NonNull Identity originatorIdentity) { + try (SafeCloseable ignored = PermissionUtil.establishIdentityDirect( + originatorIdentity)) { + Identity middlemanIdentity = new Identity(); + middlemanIdentity.packageName = ActivityThread.currentOpPackageName(); + ArrayList moduleList = new ArrayList<>(); + SoundTrigger.listModulesAsMiddleman(moduleList, middlemanIdentity, + originatorIdentity); + return moduleList; } } } @@ -269,8 +291,8 @@ public class SoundTriggerService extends SystemService { private final Object mCallbacksLock = new Object(); private final TreeMap mCallbacks = new TreeMap<>(); - SoundTriggerSessionStub(@NonNull IBinder client) { - mSoundTriggerHelper = newSoundTriggerHelper(); + SoundTriggerSessionStub(@NonNull IBinder client, SoundTriggerHelper soundTriggerHelper) { + mSoundTriggerHelper = soundTriggerHelper; mClient = client; mOriginatorIdentity = IdentityContext.getNonNull(); try { @@ -1615,8 +1637,18 @@ public class SoundTriggerService extends SystemService { } @Override - public Session attach(@NonNull IBinder client) { - return new SessionImpl(newSoundTriggerHelper(), client); + public Session attach(@NonNull IBinder client, ModuleProperties underlyingModule) { + return new SessionImpl(newSoundTriggerHelper(underlyingModule), client); + } + + @Override + public List listModuleProperties(Identity originatorIdentity) { + Identity middlemanIdentity = new Identity(); + middlemanIdentity.packageName = ActivityThread.currentOpPackageName(); + ArrayList moduleList = new ArrayList<>(); + SoundTrigger.listModulesAsMiddleman(moduleList, middlemanIdentity, + originatorIdentity); + return moduleList; } @Override diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java index 717f4e706719f..a08eaca25713a 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java @@ -405,7 +405,8 @@ public class VoiceInteractionManagerService extends SystemService { } try (SafeCloseable ignored = PermissionUtil.establishIdentityDirect( originatorIdentity)) { - session = new SoundTriggerSession(mSoundTriggerInternal.attach(client)); + session = new SoundTriggerSession(mSoundTriggerInternal.attach(client, + getDefaultModuleProperties(originatorIdentity))); } } return new SoundTriggerSessionBinderProxy(session); @@ -419,11 +420,23 @@ public class VoiceInteractionManagerService extends SystemService { identity.packageName = ActivityThread.currentOpPackageName(); return Binder.withCleanCallingIdentity(() -> { try (SafeCloseable ignored = IdentityContext.create(identity)) { - return new SoundTriggerSession(mSoundTriggerInternal.attach(client)); + return new SoundTriggerSession( + mSoundTriggerInternal.attach(client, + getDefaultModuleProperties(identity))); } }); } + private ModuleProperties getDefaultModuleProperties(Identity originatorIdentity) { + List modulePropList = mSoundTriggerInternal + .listModuleProperties(originatorIdentity); + if (modulePropList.isEmpty()) { + return null; + } else { + return modulePropList.get(0); + } + } + // TODO: VI Make sure the caller is the current user or profile void startLocalVoiceInteraction(@NonNull final IBinder token, @Nullable String attributionTag, @Nullable Bundle options) { From 9e31351327f707a9c13be5736988d99a2179c529 Mon Sep 17 00:00:00 2001 From: Atneya Nair Date: Sat, 11 Feb 2023 17:35:24 -0800 Subject: [PATCH 2/2] Temporarily allow STHelper without module This is required to pass CTS tests which run on devices which do not have a STHAL. This workaround should be removed when the tests are changed to use a mock HAL. Tracking bug: b/269165460 Test: VIS CTS tests Change-Id: I0b2dbfb6d415a1e89eed55c1db249ba7ebebb893 --- .../server/soundtrigger/SoundTriggerHelper.java | 9 ++++++++- .../server/soundtrigger/SoundTriggerService.java | 14 +++++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java index 86893cbc9f1e5..5efd158133edf 100644 --- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java +++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java @@ -77,6 +77,9 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { static final String TAG = "SoundTriggerHelper"; static final boolean DBG = false; + // Module ID if there is no available module to connect to. + public static final int INVALID_MODULE_ID = -1; + /** * Return codes for {@link #startRecognition(int, KeyphraseSoundModel, * IRecognitionStatusCallback, RecognitionConfig)}, @@ -138,7 +141,11 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { mKeyphraseUuidMap = new HashMap(); mModuleProvider = moduleProvider; mModulePropertiesProvider = modulePropertiesProvider; - mModule = mModuleProvider.apply(this); + if (moduleId == INVALID_MODULE_ID) { + mModule = null; + } else { + mModule = mModuleProvider.apply(this); + } Looper looper = Looper.myLooper(); if (looper == null) { looper = Looper.getMainLooper(); diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java index ddd8a26b118e6..495a433701638 100644 --- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java +++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java @@ -215,7 +215,7 @@ public class SoundTriggerService extends SystemService { } } - private SoundTriggerHelper newSoundTriggerHelper(@NonNull ModuleProperties moduleProperties) { + private SoundTriggerHelper newSoundTriggerHelper(ModuleProperties moduleProperties) { Identity middlemanIdentity = new Identity(); middlemanIdentity.packageName = ActivityThread.currentOpPackageName(); Identity originatorIdentity = IdentityContext.getNonNull(); @@ -224,11 +224,15 @@ public class SoundTriggerService extends SystemService { SoundTrigger.listModulesAsMiddleman(moduleList, middlemanIdentity, originatorIdentity); - if (!moduleList.contains(moduleProperties)) { - throw new IllegalArgumentException("Invalid module properties"); - } + // Don't fail existing CTS tests which run without a ST module + final int moduleId = (moduleProperties != null) ? + moduleProperties.getId() : SoundTriggerHelper.INVALID_MODULE_ID; - int moduleId = moduleProperties.getId(); + if (moduleId != SoundTriggerHelper.INVALID_MODULE_ID) { + if (!moduleList.contains(moduleProperties)) { + throw new IllegalArgumentException("Invalid module properties"); + } + } return new SoundTriggerHelper( mContext,