Sessionize VoiceInteractionManagerService
This change associates an identity with every VoiceInteractionManagerService session. Change-Id: I6c87c2976a4409b8dda4480234d794db91cee374 Bug: 163865561
This commit is contained in:
@@ -19,6 +19,7 @@ package android.service.voice;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ActivityThread;
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -32,6 +33,7 @@ import android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra;
|
||||
import android.hardware.soundtrigger.SoundTrigger.ModuleProperties;
|
||||
import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
|
||||
import android.media.AudioFormat;
|
||||
import android.media.permission.Identity;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
@@ -39,6 +41,7 @@ import android.os.RemoteException;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.app.IVoiceInteractionManagerService;
|
||||
import com.android.internal.app.IVoiceInteractionSoundTriggerSession;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.annotation.Retention;
|
||||
@@ -228,6 +231,7 @@ public class AlwaysOnHotwordDetector {
|
||||
private KeyphraseMetadata mKeyphraseMetadata;
|
||||
private final KeyphraseEnrollmentInfo mKeyphraseEnrollmentInfo;
|
||||
private final IVoiceInteractionManagerService mModelManagementService;
|
||||
private final IVoiceInteractionSoundTriggerSession mSoundTriggerSession;
|
||||
private final SoundTriggerListener mInternalCallback;
|
||||
private final Callback mExternalCallback;
|
||||
private final Object mLock = new Object();
|
||||
@@ -425,6 +429,14 @@ public class AlwaysOnHotwordDetector {
|
||||
mHandler = new MyHandler();
|
||||
mInternalCallback = new SoundTriggerListener(mHandler);
|
||||
mModelManagementService = modelManagementService;
|
||||
try {
|
||||
Identity identity = new Identity();
|
||||
identity.packageName = ActivityThread.currentOpPackageName();
|
||||
mSoundTriggerSession = mModelManagementService.createSoundTriggerSessionAsOriginator(
|
||||
identity);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowAsRuntimeException();
|
||||
}
|
||||
new RefreshAvailabiltyTask().execute();
|
||||
}
|
||||
|
||||
@@ -485,7 +497,7 @@ public class AlwaysOnHotwordDetector {
|
||||
private int getSupportedAudioCapabilitiesLocked() {
|
||||
try {
|
||||
ModuleProperties properties =
|
||||
mModelManagementService.getDspModuleProperties();
|
||||
mSoundTriggerSession.getDspModuleProperties();
|
||||
if (properties != null) {
|
||||
return properties.getAudioCapabilities();
|
||||
}
|
||||
@@ -782,7 +794,7 @@ public class AlwaysOnHotwordDetector {
|
||||
|
||||
int code;
|
||||
try {
|
||||
code = mModelManagementService.startRecognition(
|
||||
code = mSoundTriggerSession.startRecognition(
|
||||
mKeyphraseMetadata.getId(), mLocale.toLanguageTag(), mInternalCallback,
|
||||
new RecognitionConfig(captureTriggerAudio, allowMultipleTriggers,
|
||||
recognitionExtra, null /* additional data */, audioCapabilities));
|
||||
@@ -799,7 +811,7 @@ public class AlwaysOnHotwordDetector {
|
||||
private int stopRecognitionLocked() {
|
||||
int code;
|
||||
try {
|
||||
code = mModelManagementService.stopRecognition(mKeyphraseMetadata.getId(),
|
||||
code = mSoundTriggerSession.stopRecognition(mKeyphraseMetadata.getId(),
|
||||
mInternalCallback);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
@@ -813,7 +825,7 @@ public class AlwaysOnHotwordDetector {
|
||||
|
||||
private int setParameterLocked(@ModelParams int modelParam, int value) {
|
||||
try {
|
||||
int code = mModelManagementService.setParameter(mKeyphraseMetadata.getId(), modelParam,
|
||||
int code = mSoundTriggerSession.setParameter(mKeyphraseMetadata.getId(), modelParam,
|
||||
value);
|
||||
|
||||
if (code != STATUS_OK) {
|
||||
@@ -828,7 +840,7 @@ public class AlwaysOnHotwordDetector {
|
||||
|
||||
private int getParameterLocked(@ModelParams int modelParam) {
|
||||
try {
|
||||
return mModelManagementService.getParameter(mKeyphraseMetadata.getId(), modelParam);
|
||||
return mSoundTriggerSession.getParameter(mKeyphraseMetadata.getId(), modelParam);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
@@ -838,7 +850,7 @@ public class AlwaysOnHotwordDetector {
|
||||
private ModelParamRange queryParameterLocked(@ModelParams int modelParam) {
|
||||
try {
|
||||
SoundTrigger.ModelParamRange modelParamRange =
|
||||
mModelManagementService.queryParameter(mKeyphraseMetadata.getId(), modelParam);
|
||||
mSoundTriggerSession.queryParameter(mKeyphraseMetadata.getId(), modelParam);
|
||||
|
||||
if (modelParamRange == null) {
|
||||
return null;
|
||||
@@ -972,7 +984,7 @@ public class AlwaysOnHotwordDetector {
|
||||
ModuleProperties dspModuleProperties;
|
||||
try {
|
||||
dspModuleProperties =
|
||||
mModelManagementService.getDspModuleProperties();
|
||||
mSoundTriggerSession.getDspModuleProperties();
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.internal.app;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.media.permission.Identity;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteCallback;
|
||||
|
||||
@@ -25,9 +26,8 @@ import com.android.internal.app.IVoiceActionCheckCallback;
|
||||
import com.android.internal.app.IVoiceInteractionSessionShowCallback;
|
||||
import com.android.internal.app.IVoiceInteractor;
|
||||
import com.android.internal.app.IVoiceInteractionSessionListener;
|
||||
import android.hardware.soundtrigger.IRecognitionStatusCallback;
|
||||
import com.android.internal.app.IVoiceInteractionSoundTriggerSession;
|
||||
import android.hardware.soundtrigger.KeyphraseMetadata;
|
||||
import android.hardware.soundtrigger.ModelParams;
|
||||
import android.hardware.soundtrigger.SoundTrigger;
|
||||
import android.service.voice.IVoiceInteractionService;
|
||||
import android.service.voice.IVoiceInteractionSession;
|
||||
@@ -86,13 +86,6 @@ interface IVoiceInteractionManagerService {
|
||||
* @RequiresPermission Manifest.permission.MANAGE_VOICE_KEYPHRASES
|
||||
*/
|
||||
int deleteKeyphraseSoundModel(int keyphraseId, in String bcp47Locale);
|
||||
|
||||
/**
|
||||
* Gets the properties of the DSP hardware on this device, null if not present.
|
||||
* Caller must be the active voice interaction service via
|
||||
* {@link Settings.Secure.VOICE_INTERACTION_SERVICE}.
|
||||
*/
|
||||
SoundTrigger.ModuleProperties getDspModuleProperties();
|
||||
/**
|
||||
* Indicates if there's a keyphrase sound model available for the given keyphrase ID and the
|
||||
* user ID of the caller.
|
||||
@@ -115,65 +108,6 @@ interface IVoiceInteractionManagerService {
|
||||
* no matching voice model exists.
|
||||
*/
|
||||
KeyphraseMetadata getEnrolledKeyphraseMetadata(String keyphrase, String bcp47Locale);
|
||||
/**
|
||||
* Starts a recognition for the given keyphrase.
|
||||
* Caller must be the active voice interaction service via
|
||||
* {@link Settings.Secure.VOICE_INTERACTION_SERVICE}.
|
||||
*/
|
||||
int startRecognition(int keyphraseId, in String bcp47Locale,
|
||||
in IRecognitionStatusCallback callback,
|
||||
in SoundTrigger.RecognitionConfig recognitionConfig);
|
||||
/**
|
||||
* Stops a recognition for the given keyphrase.
|
||||
* Caller must be the active voice interaction service via
|
||||
* {@link Settings.Secure.VOICE_INTERACTION_SERVICE}.
|
||||
*/
|
||||
int stopRecognition(int keyphraseId, in IRecognitionStatusCallback callback);
|
||||
/**
|
||||
* Set a model specific ModelParams with the given value. This
|
||||
* parameter will keep its value for the duration the model is loaded regardless of starting and
|
||||
* stopping recognition. Once the model is unloaded, the value will be lost.
|
||||
* queryParameter should be checked first before calling this method.
|
||||
* Caller must be the active voice interaction service via
|
||||
* {@link Settings.Secure.VOICE_INTERACTION_SERVICE}.
|
||||
*
|
||||
* @param keyphraseId The unique identifier for the keyphrase.
|
||||
* @param modelParam ModelParams
|
||||
* @param value Value to set
|
||||
* @return - {@link SoundTrigger#STATUS_OK} in case of success
|
||||
* - {@link SoundTrigger#STATUS_NO_INIT} if the native service cannot be reached
|
||||
* - {@link SoundTrigger#STATUS_BAD_VALUE} invalid input parameter
|
||||
* - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence or
|
||||
* if API is not supported by HAL
|
||||
*/
|
||||
int setParameter(int keyphraseId, in ModelParams modelParam, int value);
|
||||
/**
|
||||
* Get a model specific ModelParams. This parameter will keep its value
|
||||
* for the duration the model is loaded regardless of starting and stopping recognition.
|
||||
* Once the model is unloaded, the value will be lost. If the value is not set, a default
|
||||
* value is returned. See ModelParams for parameter default values.
|
||||
* queryParameter should be checked first before calling this method.
|
||||
* Caller must be the active voice interaction service via
|
||||
* {@link Settings.Secure.VOICE_INTERACTION_SERVICE}.
|
||||
*
|
||||
* @param keyphraseId The unique identifier for the keyphrase.
|
||||
* @param modelParam ModelParams
|
||||
* @return value of parameter
|
||||
*/
|
||||
int getParameter(int keyphraseId, in ModelParams modelParam);
|
||||
/**
|
||||
* Determine if parameter control is supported for the given model handle.
|
||||
* This method should be checked prior to calling setParameter or getParameter.
|
||||
* Caller must be the active voice interaction service via
|
||||
* {@link Settings.Secure.VOICE_INTERACTION_SERVICE}.
|
||||
*
|
||||
* @param keyphraseId The unique identifier for the keyphrase.
|
||||
* @param modelParam ModelParams
|
||||
* @return supported range of parameter, null if not supported
|
||||
*/
|
||||
@nullable SoundTrigger.ModelParamRange queryParameter(int keyphraseId,
|
||||
in ModelParams modelParam);
|
||||
|
||||
/**
|
||||
* @return the component name for the currently active voice interaction service
|
||||
* @RequiresPermission Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE
|
||||
@@ -277,4 +211,12 @@ interface IVoiceInteractionManagerService {
|
||||
*/
|
||||
void setDisabled(boolean disabled);
|
||||
|
||||
/**
|
||||
* Creates a session, allowing controlling running sound models on detection hardware.
|
||||
* Caller must provide an identity, used for permission tracking purposes.
|
||||
* The uid/pid elements of the identity will be ignored by the server and replaced with the ones
|
||||
* provided by binder.
|
||||
*/
|
||||
IVoiceInteractionSoundTriggerSession createSoundTriggerSessionAsOriginator(
|
||||
in Identity originatorIdentity);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.internal.app;
|
||||
|
||||
import android.hardware.soundtrigger.IRecognitionStatusCallback;
|
||||
import android.hardware.soundtrigger.ModelParams;
|
||||
import android.hardware.soundtrigger.SoundTrigger;
|
||||
|
||||
/**
|
||||
* This interface allows performing sound-trigger related operations with the actual sound trigger
|
||||
* hardware.
|
||||
*
|
||||
* Every instance of this interface is associated with a client identity ("originator"), established
|
||||
* upon the creation of the instance and used for permission accounting.
|
||||
*/
|
||||
interface IVoiceInteractionSoundTriggerSession {
|
||||
/**
|
||||
* Gets the properties of the DSP hardware on this device, null if not present.
|
||||
* Caller must be the active voice interaction service via
|
||||
* {@link Settings.Secure.VOICE_INTERACTION_SERVICE}.
|
||||
*/
|
||||
SoundTrigger.ModuleProperties getDspModuleProperties();
|
||||
/**
|
||||
* Starts a recognition for the given keyphrase.
|
||||
* Caller must be the active voice interaction service via
|
||||
* {@link Settings.Secure.VOICE_INTERACTION_SERVICE}.
|
||||
*/
|
||||
int startRecognition(int keyphraseId, in String bcp47Locale,
|
||||
in IRecognitionStatusCallback callback,
|
||||
in SoundTrigger.RecognitionConfig recognitionConfig);
|
||||
/**
|
||||
* Stops a recognition for the given keyphrase.
|
||||
* Caller must be the active voice interaction service via
|
||||
* {@link Settings.Secure.VOICE_INTERACTION_SERVICE}.
|
||||
*/
|
||||
int stopRecognition(int keyphraseId, in IRecognitionStatusCallback callback);
|
||||
/**
|
||||
* Set a model specific ModelParams with the given value. This
|
||||
* parameter will keep its value for the duration the model is loaded regardless of starting and
|
||||
* stopping recognition. Once the model is unloaded, the value will be lost.
|
||||
* queryParameter should be checked first before calling this method.
|
||||
* Caller must be the active voice interaction service via
|
||||
* {@link Settings.Secure.VOICE_INTERACTION_SERVICE}.
|
||||
*
|
||||
* @param keyphraseId The unique identifier for the keyphrase.
|
||||
* @param modelParam ModelParams
|
||||
* @param value Value to set
|
||||
* @return - {@link SoundTrigger#STATUS_OK} in case of success
|
||||
* - {@link SoundTrigger#STATUS_NO_INIT} if the native service cannot be reached
|
||||
* - {@link SoundTrigger#STATUS_BAD_VALUE} invalid input parameter
|
||||
* - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence or
|
||||
* if API is not supported by HAL
|
||||
*/
|
||||
int setParameter(int keyphraseId, in ModelParams modelParam, int value);
|
||||
/**
|
||||
* Get a model specific ModelParams. This parameter will keep its value
|
||||
* for the duration the model is loaded regardless of starting and stopping recognition.
|
||||
* Once the model is unloaded, the value will be lost. If the value is not set, a default
|
||||
* value is returned. See ModelParams for parameter default values.
|
||||
* queryParameter should be checked first before calling this method.
|
||||
* Caller must be the active voice interaction service via
|
||||
* {@link Settings.Secure.VOICE_INTERACTION_SERVICE}.
|
||||
*
|
||||
* @param keyphraseId The unique identifier for the keyphrase.
|
||||
* @param modelParam ModelParams
|
||||
* @return value of parameter
|
||||
*/
|
||||
int getParameter(int keyphraseId, in ModelParams modelParam);
|
||||
/**
|
||||
* Determine if parameter control is supported for the given model handle.
|
||||
* This method should be checked prior to calling setParameter or getParameter.
|
||||
* Caller must be the active voice interaction service via
|
||||
* {@link Settings.Secure.VOICE_INTERACTION_SERVICE}.
|
||||
*
|
||||
* @param keyphraseId The unique identifier for the keyphrase.
|
||||
* @param modelParam ModelParams
|
||||
* @return supported range of parameter, null if not supported
|
||||
*/
|
||||
@nullable SoundTrigger.ModelParamRange queryParameter(int keyphraseId,
|
||||
in ModelParams modelParam);
|
||||
}
|
||||
@@ -51,6 +51,8 @@ import android.hardware.soundtrigger.SoundTrigger.ModuleProperties;
|
||||
import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
|
||||
import android.media.permission.ClearCallingIdentityContext;
|
||||
import android.media.permission.Identity;
|
||||
import android.media.permission.IdentityContext;
|
||||
import android.media.permission.PermissionUtil;
|
||||
import android.media.permission.SafeCloseable;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
@@ -73,6 +75,7 @@ import android.service.voice.VoiceInteractionServiceInfo;
|
||||
import android.service.voice.VoiceInteractionSession;
|
||||
import android.speech.RecognitionService;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
@@ -82,6 +85,7 @@ import com.android.internal.app.IVoiceActionCheckCallback;
|
||||
import com.android.internal.app.IVoiceInteractionManagerService;
|
||||
import com.android.internal.app.IVoiceInteractionSessionListener;
|
||||
import com.android.internal.app.IVoiceInteractionSessionShowCallback;
|
||||
import com.android.internal.app.IVoiceInteractionSoundTriggerSession;
|
||||
import com.android.internal.app.IVoiceInteractor;
|
||||
import com.android.internal.content.PackageMonitor;
|
||||
import com.android.internal.os.BackgroundThread;
|
||||
@@ -97,7 +101,10 @@ import com.android.server.wm.ActivityTaskManagerInternal;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Executor;
|
||||
@@ -115,10 +122,10 @@ public class VoiceInteractionManagerService extends SystemService {
|
||||
final ActivityManagerInternal mAmInternal;
|
||||
final ActivityTaskManagerInternal mAtmInternal;
|
||||
final UserManagerInternal mUserManagerInternal;
|
||||
final ArraySet<Integer> mLoadedKeyphraseIds = new ArraySet<>();
|
||||
final ArrayMap<Integer, VoiceInteractionManagerServiceStub.SoundTriggerSession>
|
||||
mLoadedKeyphraseIds = new ArrayMap<>();
|
||||
ShortcutServiceInternal mShortcutServiceInternal;
|
||||
SoundTriggerInternal mSoundTriggerInternal;
|
||||
SoundTriggerInternal.Session mSoundTriggerSession;
|
||||
|
||||
private final RemoteCallbackList<IVoiceInteractionSessionListener>
|
||||
mVoiceInteractionSessionListeners = new RemoteCallbackList<>();
|
||||
@@ -163,14 +170,7 @@ public class VoiceInteractionManagerService extends SystemService {
|
||||
if (PHASE_SYSTEM_SERVICES_READY == phase) {
|
||||
mShortcutServiceInternal = Objects.requireNonNull(
|
||||
LocalServices.getService(ShortcutServiceInternal.class));
|
||||
// TODO(ytai): temporary hack
|
||||
Identity identity = new Identity();
|
||||
identity.packageName = ActivityThread.currentOpPackageName();
|
||||
try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
|
||||
mSoundTriggerInternal = LocalServices.getService(
|
||||
SoundTriggerInternal.class);
|
||||
mSoundTriggerSession = mSoundTriggerInternal.attachAsOriginator(identity);
|
||||
}
|
||||
mSoundTriggerInternal = LocalServices.getService(SoundTriggerInternal.class);
|
||||
} else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
|
||||
mServiceStub.systemRunning(isSafeMode());
|
||||
}
|
||||
@@ -248,12 +248,28 @@ public class VoiceInteractionManagerService extends SystemService {
|
||||
private boolean mTemporarilyDisabled;
|
||||
|
||||
private final boolean mEnableService;
|
||||
private final List<WeakReference<SoundTriggerSession>> mSessions = new LinkedList<>();
|
||||
|
||||
VoiceInteractionManagerServiceStub() {
|
||||
mEnableService = shouldEnableService(mContext);
|
||||
new RoleObserver(mContext.getMainExecutor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull IVoiceInteractionSoundTriggerSession createSoundTriggerSessionAsOriginator(
|
||||
@NonNull Identity originatorIdentity) {
|
||||
Objects.requireNonNull(originatorIdentity);
|
||||
try (SafeCloseable ignored = PermissionUtil.establishIdentityDirect(
|
||||
originatorIdentity)) {
|
||||
SoundTriggerSession session = new SoundTriggerSession(
|
||||
mSoundTriggerInternal.attachAsOriginator(IdentityContext.getNonNull()));
|
||||
synchronized (mSessions) {
|
||||
mSessions.add(new WeakReference<>(session));
|
||||
}
|
||||
return session;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: VI Make sure the caller is the current user or profile
|
||||
void startLocalVoiceInteraction(final IBinder token, Bundle options) {
|
||||
if (mImpl == null) return;
|
||||
@@ -1026,12 +1042,15 @@ public class VoiceInteractionManagerService extends SystemService {
|
||||
final long caller = Binder.clearCallingIdentity();
|
||||
boolean deleted = false;
|
||||
try {
|
||||
int unloadStatus = mSoundTriggerSession.unloadKeyphraseModel(keyphraseId);
|
||||
if (unloadStatus != SoundTriggerInternal.STATUS_OK) {
|
||||
Slog.w(TAG, "Unable to unload keyphrase sound model:" + unloadStatus);
|
||||
SoundTriggerSession session = mLoadedKeyphraseIds.get(keyphraseId);
|
||||
if (session != null) {
|
||||
int unloadStatus = session.unloadKeyphraseModel(keyphraseId);
|
||||
if (unloadStatus != SoundTriggerInternal.STATUS_OK) {
|
||||
Slog.w(TAG, "Unable to unload keyphrase sound model:" + unloadStatus);
|
||||
}
|
||||
deleted = mDbHelper.deleteKeyphraseSoundModel(keyphraseId, callingUserId,
|
||||
bcp47Locale);
|
||||
}
|
||||
deleted = mDbHelper.deleteKeyphraseSoundModel(
|
||||
keyphraseId, callingUserId, bcp47Locale);
|
||||
return deleted ? SoundTriggerInternal.STATUS_OK : SoundTriggerInternal.STATUS_ERROR;
|
||||
} finally {
|
||||
if (deleted) {
|
||||
@@ -1104,130 +1123,143 @@ public class VoiceInteractionManagerService extends SystemService {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModuleProperties getDspModuleProperties() {
|
||||
// Allow the call if this is the current voice interaction service.
|
||||
synchronized (this) {
|
||||
enforceIsCurrentVoiceInteractionService();
|
||||
class SoundTriggerSession extends IVoiceInteractionSoundTriggerSession.Stub {
|
||||
final SoundTriggerInternal.Session mSession;
|
||||
|
||||
SoundTriggerSession(
|
||||
SoundTriggerInternal.Session session) {
|
||||
mSession = session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModuleProperties getDspModuleProperties() {
|
||||
// Allow the call if this is the current voice interaction service.
|
||||
synchronized (VoiceInteractionManagerServiceStub.this) {
|
||||
enforceIsCurrentVoiceInteractionService();
|
||||
|
||||
final long caller = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return mSession.getModuleProperties();
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(caller);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int startRecognition(int keyphraseId, String bcp47Locale,
|
||||
IRecognitionStatusCallback callback, RecognitionConfig recognitionConfig) {
|
||||
// Allow the call if this is the current voice interaction service.
|
||||
synchronized (VoiceInteractionManagerServiceStub.this) {
|
||||
enforceIsCurrentVoiceInteractionService();
|
||||
|
||||
if (callback == null || recognitionConfig == null || bcp47Locale == null) {
|
||||
throw new IllegalArgumentException("Illegal argument(s) in startRecognition");
|
||||
}
|
||||
}
|
||||
|
||||
final int callingUserId = UserHandle.getCallingUserId();
|
||||
final long caller = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return mSoundTriggerSession.getModuleProperties();
|
||||
KeyphraseSoundModel soundModel =
|
||||
mDbHelper.getKeyphraseSoundModel(keyphraseId, callingUserId, bcp47Locale);
|
||||
if (soundModel == null
|
||||
|| soundModel.getUuid() == null
|
||||
|| soundModel.getKeyphrases() == null) {
|
||||
Slog.w(TAG, "No matching sound model found in startRecognition");
|
||||
return SoundTriggerInternal.STATUS_ERROR;
|
||||
} else {
|
||||
// Regardless of the status of the start recognition, we need to make sure
|
||||
// that we unload this model if needed later.
|
||||
synchronized (VoiceInteractionManagerServiceStub.this) {
|
||||
mLoadedKeyphraseIds.put(keyphraseId, this);
|
||||
}
|
||||
return mSession.startRecognition(
|
||||
keyphraseId, soundModel, callback, recognitionConfig);
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(caller);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int startRecognition(int keyphraseId, String bcp47Locale,
|
||||
IRecognitionStatusCallback callback, RecognitionConfig recognitionConfig) {
|
||||
// Allow the call if this is the current voice interaction service.
|
||||
synchronized (this) {
|
||||
enforceIsCurrentVoiceInteractionService();
|
||||
@Override
|
||||
public int stopRecognition(int keyphraseId, IRecognitionStatusCallback callback) {
|
||||
// Allow the call if this is the current voice interaction service.
|
||||
synchronized (VoiceInteractionManagerServiceStub.this) {
|
||||
enforceIsCurrentVoiceInteractionService();
|
||||
}
|
||||
|
||||
if (callback == null || recognitionConfig == null || bcp47Locale == null) {
|
||||
throw new IllegalArgumentException("Illegal argument(s) in startRecognition");
|
||||
final long caller = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return mSession.stopRecognition(keyphraseId, callback);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(caller);
|
||||
}
|
||||
}
|
||||
|
||||
final int callingUserId = UserHandle.getCallingUserId();
|
||||
final long caller = Binder.clearCallingIdentity();
|
||||
try {
|
||||
KeyphraseSoundModel soundModel =
|
||||
mDbHelper.getKeyphraseSoundModel(keyphraseId, callingUserId, bcp47Locale);
|
||||
if (soundModel == null
|
||||
|| soundModel.getUuid() == null
|
||||
|| soundModel.getKeyphrases() == null) {
|
||||
Slog.w(TAG, "No matching sound model found in startRecognition");
|
||||
return SoundTriggerInternal.STATUS_ERROR;
|
||||
} else {
|
||||
// Regardless of the status of the start recognition, we need to make sure
|
||||
// that we unload this model if needed later.
|
||||
synchronized (this) {
|
||||
mLoadedKeyphraseIds.add(keyphraseId);
|
||||
}
|
||||
return mSoundTriggerSession.startRecognition(
|
||||
keyphraseId, soundModel, callback, recognitionConfig);
|
||||
@Override
|
||||
public int setParameter(int keyphraseId, @ModelParams int modelParam, int value) {
|
||||
// Allow the call if this is the current voice interaction service.
|
||||
synchronized (VoiceInteractionManagerServiceStub.this) {
|
||||
enforceIsCurrentVoiceInteractionService();
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(caller);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int stopRecognition(int keyphraseId, IRecognitionStatusCallback callback) {
|
||||
// Allow the call if this is the current voice interaction service.
|
||||
synchronized (this) {
|
||||
enforceIsCurrentVoiceInteractionService();
|
||||
final long caller = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return mSession.setParameter(keyphraseId, modelParam, value);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(caller);
|
||||
}
|
||||
}
|
||||
|
||||
final long caller = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return mSoundTriggerSession.stopRecognition(keyphraseId, callback);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(caller);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public int getParameter(int keyphraseId, @ModelParams int modelParam) {
|
||||
// Allow the call if this is the current voice interaction service.
|
||||
synchronized (VoiceInteractionManagerServiceStub.this) {
|
||||
enforceIsCurrentVoiceInteractionService();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setParameter(int keyphraseId, @ModelParams int modelParam, int value) {
|
||||
// Allow the call if this is the current voice interaction service.
|
||||
synchronized (this) {
|
||||
enforceIsCurrentVoiceInteractionService();
|
||||
final long caller = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return mSession.getParameter(keyphraseId, modelParam);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(caller);
|
||||
}
|
||||
}
|
||||
|
||||
final long caller = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return mSoundTriggerSession.setParameter(keyphraseId, modelParam, value);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(caller);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
@Nullable
|
||||
public ModelParamRange queryParameter(int keyphraseId, @ModelParams int modelParam) {
|
||||
// Allow the call if this is the current voice interaction service.
|
||||
synchronized (VoiceInteractionManagerServiceStub.this) {
|
||||
enforceIsCurrentVoiceInteractionService();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getParameter(int keyphraseId, @ModelParams int modelParam) {
|
||||
// Allow the call if this is the current voice interaction service.
|
||||
synchronized (this) {
|
||||
enforceIsCurrentVoiceInteractionService();
|
||||
final long caller = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return mSession.queryParameter(keyphraseId, modelParam);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(caller);
|
||||
}
|
||||
}
|
||||
|
||||
final long caller = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return mSoundTriggerSession.getParameter(keyphraseId, modelParam);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(caller);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ModelParamRange queryParameter(int keyphraseId, @ModelParams int modelParam) {
|
||||
// Allow the call if this is the current voice interaction service.
|
||||
synchronized (this) {
|
||||
enforceIsCurrentVoiceInteractionService();
|
||||
}
|
||||
|
||||
final long caller = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return mSoundTriggerSession.queryParameter(keyphraseId, modelParam);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(caller);
|
||||
private int unloadKeyphraseModel(int keyphraseId) {
|
||||
final long caller = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return mSession.unloadKeyphraseModel(keyphraseId);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(caller);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void unloadAllKeyphraseModels() {
|
||||
for (int i = 0; i < mLoadedKeyphraseIds.size(); i++) {
|
||||
final long caller = Binder.clearCallingIdentity();
|
||||
try {
|
||||
int status = mSoundTriggerSession.unloadKeyphraseModel(
|
||||
mLoadedKeyphraseIds.valueAt(i));
|
||||
if (status != SoundTriggerInternal.STATUS_OK) {
|
||||
Slog.w(TAG, "Failed to unload keyphrase " + mLoadedKeyphraseIds.valueAt(i)
|
||||
+ ":" + status);
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(caller);
|
||||
int id = mLoadedKeyphraseIds.keyAt(i);
|
||||
SoundTriggerSession session = mLoadedKeyphraseIds.valueAt(i);
|
||||
int status = session.unloadKeyphraseModel(id);
|
||||
if (status != SoundTriggerInternal.STATUS_OK) {
|
||||
Slog.w(TAG, "Failed to unload keyphrase " + id + ":" + status);
|
||||
}
|
||||
}
|
||||
mLoadedKeyphraseIds.clear();
|
||||
@@ -1432,8 +1464,24 @@ public class VoiceInteractionManagerService extends SystemService {
|
||||
mImpl.dumpLocked(fd, pw, args);
|
||||
}
|
||||
}
|
||||
|
||||
mSoundTriggerInternal.dump(fd, pw, args);
|
||||
mSoundTriggerSession.dump(fd, pw, args);
|
||||
|
||||
// Dump all sessions.
|
||||
synchronized (mSessions) {
|
||||
ListIterator<WeakReference<SoundTriggerSession>> iter =
|
||||
mSessions.listIterator();
|
||||
while (iter.hasNext()) {
|
||||
SoundTriggerSession session = iter.next().get();
|
||||
if (session != null) {
|
||||
session.dump(fd, args);
|
||||
} else {
|
||||
// Session is obsolete, now is a good chance to remove it from the list.
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user