Add VIMService model enrollment override

In order to test voiceinteraction, we must be able to override the
persistent model enrollment database with an in-memory equivalent.
- Abstract DatabaseHelper into IEnrolledModelDb interface
- Implement the Test version of this interface as a hashmap
- Add VIMService APIs and client-side equivalent to override the Db with
the test version
- Remove incorrect GuardedBy annotations (no GuardedBy(this) on a
  public interface boundary)

Test: atest
AlwaysOnHotwordDetectorTest#testAlwaysOnHotwordDetector_startRecognitionWithData
Fixes: 273309878

Change-Id: Icf4f1aaf147519ef45534ee8c7ae26c6040fa4cd
This commit is contained in:
Atneya Nair
2023-03-09 17:35:00 -08:00
parent 31b112febf
commit b32371dde1
8 changed files with 344 additions and 80 deletions

View File

@@ -2093,6 +2093,14 @@ package android.media.tv.tuner {
}
package android.media.voice {
public final class KeyphraseModelManager {
method @RequiresPermission("android.permission.MANAGE_VOICE_KEYPHRASES") public void setModelDatabaseForTestEnabled(boolean);
}
}
package android.net {
public class NetworkPolicyManager {

View File

@@ -96,6 +96,21 @@ interface IVoiceInteractionManagerService {
* @RequiresPermission Manifest.permission.MANAGE_VOICE_KEYPHRASES
*/
int deleteKeyphraseSoundModel(int keyphraseId, in String bcp47Locale);
/**
* Override the persistent enrolled model database with an in-memory
* fake for testing purposes.
*
* @param enabled - {@code true} to enable the test database. {@code false} to enable
* the real, persistent database.
* @param token - IBinder used to register a death listener to clean-up the override
* if tests do not clean up gracefully.
*/
@EnforcePermission("MANAGE_VOICE_KEYPHRASES")
@JavaPassthrough(annotation= "@android.annotation.RequiresPermission(" +
"android.Manifest.permission.MANAGE_VOICE_KEYPHRASES)")
void setModelDatabaseForTestEnabled(boolean enabled, IBinder token);
/**
* Indicates if there's a keyphrase sound model available for the given keyphrase ID and the
* user ID of the caller.
@@ -106,6 +121,7 @@ interface IVoiceInteractionManagerService {
* @param bcp47Locale The BCP47 language tag for the keyphrase's locale.
*/
boolean isEnrolledForKeyphrase(int keyphraseId, String bcp47Locale);
/**
* Generates KeyphraseMetadata for an enrolled sound model based on keyphrase string, locale,
* and the user ID of the caller.

View File

@@ -21,7 +21,9 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.hardware.soundtrigger.SoundTrigger;
import android.os.Binder;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.util.Slog;
@@ -154,4 +156,23 @@ public final class KeyphraseModelManager {
throw e.rethrowFromSystemServer();
}
}
/**
* Override the persistent enrolled model database with an in-memory
* fake for testing purposes.
*
* @param enabled - {@code true} if the model enrollment database should be overridden with an
* in-memory fake. {@code false} if the real, persistent model enrollment database should be
* used.
* @hide
*/
@RequiresPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES)
@TestApi
public void setModelDatabaseForTestEnabled(boolean enabled) {
try {
mVoiceInteractionManagerService.setModelDatabaseForTestEnabled(enabled, new Binder());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}

View File

@@ -39,7 +39,7 @@ import java.util.UUID;
*
* @hide
*/
public class DatabaseHelper extends SQLiteOpenHelper {
public class DatabaseHelper extends SQLiteOpenHelper implements IEnrolledModelDb {
static final String TAG = "SoundModelDBHelper";
static final boolean DBG = false;
@@ -153,11 +153,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
}
}
/**
* Updates the given keyphrase model, adds it, if it doesn't already exist.
*
* TODO: We only support one keyphrase currently.
*/
@Override
public boolean updateKeyphraseSoundModel(KeyphraseSoundModel soundModel) {
synchronized(this) {
SQLiteDatabase db = getWritableDatabase();
@@ -193,9 +189,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
}
}
/**
* Deletes the sound model and associated keyphrases.
*/
@Override
public boolean deleteKeyphraseSoundModel(int keyphraseId, int userHandle, String bcp47Locale) {
// Normalize the locale to guard against SQL injection.
bcp47Locale = Locale.forLanguageTag(bcp47Locale).toLanguageTag();
@@ -218,12 +212,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
}
}
/**
* Returns a matching {@link KeyphraseSoundModel} for the keyphrase ID.
* Returns null if a match isn't found.
*
* TODO: We only support one keyphrase currently.
*/
@Override
public KeyphraseSoundModel getKeyphraseSoundModel(int keyphraseId, int userHandle,
String bcp47Locale) {
// Sanitize the locale to guard against SQL injection.
@@ -237,12 +226,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
}
}
/**
* Returns a matching {@link KeyphraseSoundModel} for the keyphrase string.
* Returns null if a match isn't found.
*
* TODO: We only support one keyphrase currently.
*/
@Override
public KeyphraseSoundModel getKeyphraseSoundModel(String keyphrase, int userHandle,
String bcp47Locale) {
// Sanitize the locale to guard against SQL injection.

View File

@@ -0,0 +1,90 @@
/**
* Copyright (C) 2023 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.server.voiceinteraction;
import android.hardware.soundtrigger.SoundTrigger.Keyphrase;
import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
import java.io.PrintWriter;
/**
* Interface for registering and querying the enrolled keyphrase model database for
* {@link VoiceInteractionManagerService}.
* This interface only supports one keyphrase per {@link KeyphraseSoundModel}.
* The non-update methods are uniquely keyed on fields of the first keyphrase
* {@link KeyphraseSoundModel#getKeyphrases()}.
* @hide
*/
public interface IEnrolledModelDb {
//TODO(273286174): We only support one keyphrase currently.
/**
* Register the given {@link KeyphraseSoundModel}, or updates it if it already exists.
*
* @param soundModel - The sound model to register in the database.
* Updates the sound model if the keyphrase id, users, locale match an existing entry.
* Must have one and only one associated {@link Keyphrase}.
* @return - {@code true} if successful, {@code false} if unsuccessful
*/
boolean updateKeyphraseSoundModel(KeyphraseSoundModel soundModel);
/**
* Deletes the previously registered keyphrase sound model from the database.
*
* @param keyphraseId - The (first) keyphrase ID of the KeyphraseSoundModel to delete.
* @param userHandle - The user handle making this request. Must be included in the user
* list of the registered sound model.
* @param bcp47Locale - The locale of the (first) keyphrase associated with this model.
* @return - {@code true} if successful, {@code false} if unsuccessful
*/
boolean deleteKeyphraseSoundModel(int keyphraseId, int userHandle, String bcp47Locale);
//TODO(273286174): We only support one keyphrase currently.
/**
* Returns the first matching {@link KeyphraseSoundModel} for the keyphrase ID, locale pair,
* contingent on the userHandle existing in the user list for the model.
* Returns null if a match isn't found.
*
* @param keyphraseId - The (first) keyphrase ID of the KeyphraseSoundModel to query.
* @param userHandle - The user handle making this request. Must be included in the user
* list of the registered sound model.
* @param bcp47Locale - The locale of the (first) keyphrase associated with this model.
* @return - {@code true} if successful, {@code false} if unsuccessful
*/
KeyphraseSoundModel getKeyphraseSoundModel(int keyphraseId, int userHandle,
String bcp47Locale);
//TODO(273286174): We only support one keyphrase currently.
/**
* Returns the first matching {@link KeyphraseSoundModel} for the keyphrase ID, locale pair,
* contingent on the userHandle existing in the user list for the model.
* Returns null if a match isn't found.
*
* @param keyphrase - The text of (the first) keyphrase of the KeyphraseSoundModel to query.
* @param userHandle - The user handle making this request. Must be included in the user
* list of the registered sound model.
* @param bcp47Locale - The locale of the (first) keyphrase associated with this model.
* @return - {@code true} if successful, {@code false} if unsuccessful
*/
KeyphraseSoundModel getKeyphraseSoundModel(String keyphrase, int userHandle,
String bcp47Locale);
/**
* Dumps contents of database for dumpsys
*/
void dump(PrintWriter pw);
}

View File

@@ -0,0 +1,148 @@
/**
* Copyright (C) 2023 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.server.voiceinteraction;
import android.annotation.NonNull;
import android.hardware.soundtrigger.SoundTrigger.Keyphrase;
import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.StringJoiner;
/**
* In memory model enrollment database for testing purposes.
* @hide
*/
public class TestModelEnrollmentDatabase implements IEnrolledModelDb {
// Record representing the primary key used in the real model database.
private static final class EnrollmentKey {
private final int mKeyphraseId;
private final List<Integer> mUserIds;
private final String mLocale;
EnrollmentKey(int keyphraseId,
@NonNull List<Integer> userIds, @NonNull String locale) {
mKeyphraseId = keyphraseId;
mUserIds = Objects.requireNonNull(userIds);
mLocale = Objects.requireNonNull(locale);
}
int keyphraseId() {
return mKeyphraseId;
}
List<Integer> userIds() {
return mUserIds;
}
String locale() {
return mLocale;
}
@Override
public String toString() {
StringJoiner sj = new StringJoiner(", ", "{", "}");
sj.add("keyphraseId: " + mKeyphraseId);
sj.add("userIds: " + mUserIds.toString());
sj.add("locale: " + mLocale.toString());
return "EnrollmentKey: " + sj.toString();
}
@Override
public int hashCode() {
final int prime = 31;
int res = 1;
res = prime * res + mKeyphraseId;
res = prime * res + mUserIds.hashCode();
res = prime * res + mLocale.hashCode();
return res;
}
@Override
public boolean equals(Object other) {
if (this == other) return true;
if (other == null) return false;
if (!(other instanceof EnrollmentKey)) return false;
EnrollmentKey that = (EnrollmentKey) other;
if (mKeyphraseId != that.mKeyphraseId) return false;
if (!mUserIds.equals(that.mUserIds)) return false;
if (!mLocale.equals(that.mLocale)) return false;
return true;
}
}
private final Map<EnrollmentKey, KeyphraseSoundModel> mModelMap = new HashMap<>();
@Override
public boolean updateKeyphraseSoundModel(KeyphraseSoundModel soundModel) {
final Keyphrase keyphrase = soundModel.getKeyphrases()[0];
mModelMap.put(new EnrollmentKey(keyphrase.getId(),
Arrays.stream(keyphrase.getUsers()).boxed().toList(),
keyphrase.getLocale().toLanguageTag()),
soundModel);
return true;
}
@Override
public boolean deleteKeyphraseSoundModel(int keyphraseId, int userHandle, String bcp47Locale) {
return mModelMap.keySet().removeIf(key -> (key.keyphraseId() == keyphraseId)
&& key.locale().equals(bcp47Locale)
&& key.userIds().contains(userHandle));
}
@Override
public KeyphraseSoundModel getKeyphraseSoundModel(int keyphraseId, int userHandle,
String bcp47Locale) {
return mModelMap.entrySet()
.stream()
.filter((entry) -> (entry.getKey().keyphraseId() == keyphraseId)
&& entry.getKey().locale().equals(bcp47Locale)
&& entry.getKey().userIds().contains(userHandle))
.findFirst()
.map((entry) -> entry.getValue())
.orElse(null);
}
@Override
public KeyphraseSoundModel getKeyphraseSoundModel(String keyphrase, int userHandle,
String bcp47Locale) {
return mModelMap.entrySet()
.stream()
.filter((entry) -> (entry.getValue().getKeyphrases()[0].getText().equals(keyphrase)
&& entry.getKey().locale().equals(bcp47Locale)
&& entry.getKey().userIds().contains(userHandle)))
.findFirst()
.map((entry) -> entry.getValue())
.orElse(null);
}
/**
* Dumps contents of database for dumpsys
*/
public void dump(PrintWriter pw) {
pw.println("Using test enrollment database, with enrolled models:");
pw.println(mModelMap);
}
}

View File

@@ -125,7 +125,9 @@ public class VoiceInteractionManagerService extends SystemService {
final Context mContext;
final ContentResolver mResolver;
final DatabaseHelper mDbHelper;
// Can be overridden for testing purposes
private IEnrolledModelDb mDbHelper;
private final IEnrolledModelDb mRealDbHelper;
final ActivityManagerInternal mAmInternal;
final ActivityTaskManagerInternal mAtmInternal;
final UserManagerInternal mUserManagerInternal;
@@ -143,7 +145,7 @@ public class VoiceInteractionManagerService extends SystemService {
mResolver = context.getContentResolver();
mUserManagerInternal = Objects.requireNonNull(
LocalServices.getService(UserManagerInternal.class));
mDbHelper = new DatabaseHelper(context);
mDbHelper = mRealDbHelper = new DatabaseHelper(context);
mServiceStub = new VoiceInteractionManagerServiceStub();
mAmInternal = Objects.requireNonNull(
LocalServices.getService(ActivityManagerInternal.class));
@@ -1605,6 +1607,42 @@ public class VoiceInteractionManagerService extends SystemService {
}
}
@Override
@android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_VOICE_KEYPHRASES)
public void setModelDatabaseForTestEnabled(boolean enabled, IBinder token) {
super.setModelDatabaseForTestEnabled_enforcePermission();
enforceCallerAllowedToEnrollVoiceModel();
synchronized (this) {
if (enabled) {
// Replace the dbhelper with a new test db
final var db = new TestModelEnrollmentDatabase();
try {
// Listen to our caller death, and make sure we revert to the real
// db if they left the model in a test state.
token.linkToDeath(() -> {
synchronized (this) {
if (mDbHelper == db) {
mDbHelper = mRealDbHelper;
mImpl.notifySoundModelsChangedLocked();
}
}
}, 0);
} catch (RemoteException e) {
// If the caller is already dead, nothing to do.
return;
}
mDbHelper = db;
mImpl.notifySoundModelsChangedLocked();
} else {
// Nothing to do if the db is already set to the real impl.
if (mDbHelper != mRealDbHelper) {
mDbHelper = mRealDbHelper;
mImpl.notifySoundModelsChangedLocked();
}
}
}
}
//----------------- SoundTrigger APIs --------------------------------//
@Override
public boolean isEnrolledForKeyphrase(int keyphraseId, String bcp47Locale) {
@@ -1712,28 +1750,27 @@ public class VoiceInteractionManagerService extends SystemService {
final long caller = Binder.clearCallingIdentity();
try {
KeyphraseSoundModel soundModel =
mDbHelper.getKeyphraseSoundModel(keyphraseId, callingUserId, bcp47Locale);
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);
if (mSessionExternalCallback == null
|| mSessionInternalCallback == null
|| callback.asBinder() != mSessionExternalCallback.asBinder()) {
mSessionInternalCallback = createSoundTriggerCallbackLocked(
callback);
mSessionExternalCallback = callback;
}
}
return mSession.startRecognition(keyphraseId, soundModel,
mSessionInternalCallback, recognitionConfig, runInBatterySaverMode);
}
// 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);
if (mSessionExternalCallback == null
|| mSessionInternalCallback == null
|| callback.asBinder() != mSessionExternalCallback.asBinder()) {
mSessionInternalCallback = createSoundTriggerCallbackLocked(callback);
mSessionExternalCallback = callback;
}
}
return mSession.startRecognition(keyphraseId, soundModel,
mSessionInternalCallback, recognitionConfig, runInBatterySaverMode);
} finally {
Binder.restoreCallingIdentity(caller);
}

View File

@@ -71,7 +71,6 @@ import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.view.IWindowManager;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IHotwordRecognitionStatusCallback;
import com.android.internal.app.IVisualQueryDetectionAttentionListener;
import com.android.internal.app.IVoiceActionCheckCallback;
@@ -248,7 +247,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
Context.RECEIVER_EXPORTED);
}
@GuardedBy("this")
public void grantImplicitAccessLocked(int grantRecipientUid, @Nullable Intent intent) {
final int grantRecipientAppId = UserHandle.getAppId(grantRecipientUid);
final int grantRecipientUserId = UserHandle.getUserId(grantRecipientUid);
@@ -258,7 +256,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
/* direct= */ true);
}
@GuardedBy("this")
public boolean showSessionLocked(@Nullable Bundle args, int flags,
@Nullable String attributionTag,
@Nullable IVoiceInteractionSessionShowCallback showCallback,
@@ -331,7 +328,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
}
}
@GuardedBy("this")
public boolean hideSessionLocked() {
if (mActiveSession != null) {
return mActiveSession.hideLocked();
@@ -339,7 +335,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
return false;
}
@GuardedBy("this")
public boolean deliverNewSessionLocked(IBinder token,
IVoiceInteractionSession session, IVoiceInteractor interactor) {
if (mActiveSession == null || token != mActiveSession.mToken) {
@@ -350,7 +345,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
return true;
}
@GuardedBy("this")
public int startVoiceActivityLocked(@Nullable String callingFeatureId, int callingPid,
int callingUid, IBinder token, Intent intent, String resolvedType) {
try {
@@ -373,7 +367,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
}
}
@GuardedBy("this")
public int startAssistantActivityLocked(@Nullable String callingFeatureId, int callingPid,
int callingUid, IBinder token, Intent intent, String resolvedType,
@NonNull Bundle bundle) {
@@ -397,7 +390,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
}
}
@GuardedBy("this")
public void requestDirectActionsLocked(@NonNull IBinder token, int taskId,
@NonNull IBinder assistToken, @Nullable RemoteCallback cancellationCallback,
@NonNull RemoteCallback callback) {
@@ -453,7 +445,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
}
}
@GuardedBy("this")
void performDirectActionLocked(@NonNull IBinder token, @NonNull String actionId,
@Nullable Bundle arguments, int taskId, IBinder assistToken,
@Nullable RemoteCallback cancellationCallback,
@@ -480,7 +471,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
}
}
@GuardedBy("this")
public void setKeepAwakeLocked(IBinder token, boolean keepAwake) {
try {
if (mActiveSession == null || token != mActiveSession.mToken) {
@@ -493,7 +483,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
}
}
@GuardedBy("this")
public void closeSystemDialogsLocked(IBinder token) {
try {
if (mActiveSession == null || token != mActiveSession.mToken) {
@@ -506,7 +495,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
}
}
@GuardedBy("this")
public void finishLocked(IBinder token, boolean finishTask) {
if (mActiveSession == null || (!finishTask && token != mActiveSession.mToken)) {
Slog.w(TAG, "finish does not match active session");
@@ -516,7 +504,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
mActiveSession = null;
}
@GuardedBy("this")
public void setDisabledShowContextLocked(int callingUid, int flags) {
int activeUid = mInfo.getServiceInfo().applicationInfo.uid;
if (callingUid != activeUid) {
@@ -526,7 +513,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
mDisabledShowContext = flags;
}
@GuardedBy("this")
public int getDisabledShowContextLocked(int callingUid) {
int activeUid = mInfo.getServiceInfo().applicationInfo.uid;
if (callingUid != activeUid) {
@@ -536,7 +522,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
return mDisabledShowContext;
}
@GuardedBy("this")
public int getUserDisabledShowContextLocked(int callingUid) {
int activeUid = mInfo.getServiceInfo().applicationInfo.uid;
if (callingUid != activeUid) {
@@ -550,7 +535,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
return mInfo.getSupportsLocalInteraction();
}
@GuardedBy("this")
public void startListeningVisibleActivityChangedLocked(@NonNull IBinder token) {
if (DEBUG) {
Slog.d(TAG, "startListeningVisibleActivityChangedLocked: token=" + token);
@@ -563,7 +547,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
mActiveSession.startListeningVisibleActivityChangedLocked();
}
@GuardedBy("this")
public void stopListeningVisibleActivityChangedLocked(@NonNull IBinder token) {
if (DEBUG) {
Slog.d(TAG, "stopListeningVisibleActivityChangedLocked: token=" + token);
@@ -576,7 +559,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
mActiveSession.stopListeningVisibleActivityChangedLocked();
}
@GuardedBy("this")
public void notifyActivityDestroyedLocked(@NonNull IBinder activityToken) {
if (DEBUG) {
Slog.d(TAG, "notifyActivityDestroyedLocked activityToken=" + activityToken);
@@ -591,7 +573,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
mActiveSession.notifyActivityDestroyedLocked(activityToken);
}
@GuardedBy("this")
public void notifyActivityEventChangedLocked(@NonNull IBinder activityToken, int type) {
if (DEBUG) {
Slog.d(TAG, "notifyActivityEventChangedLocked type=" + type);
@@ -606,7 +587,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
mActiveSession.notifyActivityEventChangedLocked(activityToken, type);
}
@GuardedBy("this")
public void updateStateLocked(
@Nullable PersistableBundle options,
@Nullable SharedMemory sharedMemory,
@@ -627,7 +607,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
}
}
@GuardedBy("this")
private void verifyDetectorForHotwordDetectionLocked(
@Nullable SharedMemory sharedMemory,
IHotwordRecognitionStatusCallback callback,
@@ -685,7 +664,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
voiceInteractionServiceUid);
}
@GuardedBy("this")
private void verifyDetectorForVisualQueryDetectionLocked(@Nullable SharedMemory sharedMemory) {
Slog.v(TAG, "verifyDetectorForVisualQueryDetectionLocked");
@@ -724,7 +702,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
}
}
@GuardedBy("this")
public void initAndVerifyDetectorLocked(
@NonNull Identity voiceInteractorIdentity,
@Nullable PersistableBundle options,
@@ -769,7 +746,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
detectorType);
}
@GuardedBy("this")
public void destroyDetectorLocked(IBinder token) {
Slog.v(TAG, "destroyDetectorLocked");
@@ -788,7 +764,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
}
}
@GuardedBy("this")
public void shutdownHotwordDetectionServiceLocked() {
if (DEBUG) {
Slog.d(TAG, "shutdownHotwordDetectionServiceLocked");
@@ -801,7 +776,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
mHotwordDetectionConnection = null;
}
@GuardedBy("this")
public void setVisualQueryDetectionAttentionListenerLocked(
@Nullable IVisualQueryDetectionAttentionListener listener) {
if (mHotwordDetectionConnection == null) {
@@ -810,7 +784,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
mHotwordDetectionConnection.setVisualQueryDetectionAttentionListenerLocked(listener);
}
@GuardedBy("this")
public void startPerceivingLocked(IVisualQueryDetectionVoiceInteractionCallback callback) {
if (DEBUG) {
Slog.d(TAG, "startPerceivingLocked");
@@ -824,7 +797,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
mHotwordDetectionConnection.startPerceivingLocked(callback);
}
@GuardedBy("this")
public void stopPerceivingLocked() {
if (DEBUG) {
Slog.d(TAG, "stopPerceivingLocked");
@@ -838,7 +810,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
mHotwordDetectionConnection.stopPerceivingLocked();
}
@GuardedBy("this")
public void startListeningFromMicLocked(
AudioFormat audioFormat,
IMicrophoneHotwordDetectionVoiceInteractionCallback callback) {
@@ -854,7 +825,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
mHotwordDetectionConnection.startListeningFromMicLocked(audioFormat, callback);
}
@GuardedBy("this")
public void startListeningFromExternalSourceLocked(
ParcelFileDescriptor audioStream,
AudioFormat audioFormat,
@@ -879,7 +849,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
options, token, callback);
}
@GuardedBy("this")
public void stopListeningFromMicLocked() {
if (DEBUG) {
Slog.d(TAG, "stopListeningFromMicLocked");
@@ -893,7 +862,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
mHotwordDetectionConnection.stopListeningFromMicLocked();
}
@GuardedBy("this")
public void triggerHardwareRecognitionEventForTestLocked(
SoundTrigger.KeyphraseRecognitionEvent event,
IHotwordRecognitionStatusCallback callback) {
@@ -908,7 +876,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
mHotwordDetectionConnection.triggerHardwareRecognitionEventForTestLocked(event, callback);
}
@GuardedBy("this")
public IRecognitionStatusCallback createSoundTriggerCallbackLocked(
IHotwordRecognitionStatusCallback callback) {
if (DEBUG) {
@@ -933,12 +900,11 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
return null;
}
@GuardedBy("this")
boolean isIsolatedProcessLocked(@NonNull ServiceInfo serviceInfo) {
return (serviceInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0
&& (serviceInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) == 0;
}
@GuardedBy("this")
boolean verifyProcessSharingLocked() {
// only check this if both VQDS and HDS are declared in the app
ServiceInfo hotwordInfo = getServiceInfoLocked(mHotwordDetectionComponentName, mUser);
@@ -960,7 +926,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
mHotwordDetectionConnection.forceRestart();
}
@GuardedBy("this")
void setDebugHotwordLoggingLocked(boolean logging) {
if (mHotwordDetectionConnection == null) {
Slog.w(TAG, "Failed to set temporary debug logging: no hotword detection active");
@@ -969,7 +934,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
mHotwordDetectionConnection.setDebugHotwordLoggingLocked(logging);
}
@GuardedBy("this")
void resetHotwordDetectionConnectionLocked() {
if (DEBUG) {
Slog.d(TAG, "resetHotwordDetectionConnectionLocked");
@@ -984,7 +948,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
mHotwordDetectionConnection = null;
}
@GuardedBy("this")
public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!mValid) {
pw.print(" NOT VALID: ");
@@ -1023,7 +986,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
}
}
@GuardedBy("this")
void startLocked() {
Intent intent = new Intent(VoiceInteractionService.SERVICE_INTERFACE);
intent.setComponent(mComponent);
@@ -1048,7 +1010,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
}
}
@GuardedBy("this")
void shutdownLocked() {
// If there is an active session, cancel it to allow it to clean up its window and other
// state.
@@ -1076,7 +1037,6 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
}
}
@GuardedBy("this")
void notifySoundModelsChangedLocked() {
if (mService == null) {
Slog.w(TAG, "Not bound to voice interaction service " + mComponent);