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:
@@ -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 {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user