Sessionize VoiceInteractionManagerService

This change associates an identity with every
VoiceInteractionManagerService session.

Change-Id: I6c87c2976a4409b8dda4480234d794db91cee374
Bug: 163865561
This commit is contained in:
Ytai Ben-Tsvi
2020-05-27 13:58:59 -07:00
parent 7558017301
commit 10c9b09f25
4 changed files with 285 additions and 188 deletions

View File

@@ -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();
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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