Merge "Add VIService ST module selection TestApis"
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user