1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.media.voice; 18 19 import android.Manifest; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.RequiresPermission; 23 import android.annotation.SystemApi; 24 import android.hardware.soundtrigger.SoundTrigger; 25 import android.os.RemoteException; 26 import android.os.ServiceSpecificException; 27 import android.util.Slog; 28 29 import com.android.internal.app.IVoiceInteractionManagerService; 30 31 import java.util.Locale; 32 import java.util.Objects; 33 34 /** 35 * This class provides management of voice based sound recognition models. Usage of this class is 36 * restricted to system or signature applications only. This allows OEMs to write apps that can 37 * manage voice based sound trigger models. 38 * Callers of this class are expected to have whitelist manifest permission MANAGE_VOICE_KEYPHRASES. 39 * Callers of this class are expected to be the designated voice interaction service via 40 * {@link Settings.Secure.VOICE_INTERACTION_SERVICE} or a bundled voice model enrollment application 41 * detected by {@link android.hardware.soundtrigger.KeyphraseEnrollmentInfo}. 42 * @hide 43 */ 44 @SystemApi 45 public final class KeyphraseModelManager { 46 private static final boolean DBG = false; 47 private static final String TAG = "KeyphraseModelManager"; 48 49 private final IVoiceInteractionManagerService mVoiceInteractionManagerService; 50 51 /** 52 * @hide 53 */ KeyphraseModelManager( IVoiceInteractionManagerService voiceInteractionManagerService)54 public KeyphraseModelManager( 55 IVoiceInteractionManagerService voiceInteractionManagerService) { 56 if (DBG) { 57 Slog.i(TAG, "KeyphraseModelManager created."); 58 } 59 mVoiceInteractionManagerService = voiceInteractionManagerService; 60 } 61 62 63 /** 64 * Gets the registered sound model for keyphrase detection for the current user. 65 * The keyphraseId and locale passed must match a supported model passed in via 66 * {@link #updateKeyphraseSoundModel}. 67 * If the active voice interaction service changes from the current user, all requests will be 68 * rejected, and any registered models will be unregistered. 69 * Caller must either be the active voice interaction service via 70 * {@link Settings.Secure.VOICE_INTERACTION_SERVICE}, or the caller must be a voice model 71 * enrollment application detected by 72 * {@link android.hardware.soundtrigger.KeyphraseEnrollmentInfo}. 73 * 74 * @param keyphraseId The unique identifier for the keyphrase. 75 * @param locale The locale language tag supported by the desired model. 76 * @return Registered keyphrase sound model matching the keyphrase ID and locale. May be null if 77 * no matching sound model exists. 78 * @throws SecurityException Thrown when caller does not have MANAGE_VOICE_KEYPHRASES permission 79 * or if the caller is not the active voice interaction service. 80 */ 81 @RequiresPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES) 82 @Nullable getKeyphraseSoundModel(int keyphraseId, @NonNull Locale locale)83 public SoundTrigger.KeyphraseSoundModel getKeyphraseSoundModel(int keyphraseId, 84 @NonNull Locale locale) { 85 Objects.requireNonNull(locale); 86 try { 87 return mVoiceInteractionManagerService.getKeyphraseSoundModel(keyphraseId, 88 locale.toLanguageTag()); 89 } catch (RemoteException e) { 90 throw e.rethrowFromSystemServer(); 91 } 92 } 93 94 /** 95 * Add or update the given keyphrase sound model to the registered models pool for the current 96 * user. 97 * If a model exists with the same Keyphrase ID, locale, and user list. The registered model 98 * will be overwritten with the new model. 99 * If the active voice interaction service changes from the current user, all requests will be 100 * rejected, and any registered models will be unregistered. 101 * Caller must either be the active voice interaction service via 102 * {@link Settings.Secure.VOICE_INTERACTION_SERVICE}, or the caller must be a voice model 103 * enrollment application detected by 104 * {@link android.hardware.soundtrigger.KeyphraseEnrollmentInfo}. 105 * 106 * @param model Keyphrase sound model to be updated. 107 * @throws ServiceSpecificException Thrown with error code if failed to update the keyphrase 108 * sound model. 109 * @throws SecurityException Thrown when caller does not have MANAGE_VOICE_KEYPHRASES permission 110 * or if the caller is not the active voice interaction service. 111 */ 112 @RequiresPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES) updateKeyphraseSoundModel(@onNull SoundTrigger.KeyphraseSoundModel model)113 public void updateKeyphraseSoundModel(@NonNull SoundTrigger.KeyphraseSoundModel model) { 114 Objects.requireNonNull(model); 115 try { 116 int status = mVoiceInteractionManagerService.updateKeyphraseSoundModel(model); 117 if (status != SoundTrigger.STATUS_OK) { 118 throw new ServiceSpecificException(status); 119 } 120 } catch (RemoteException e) { 121 throw e.rethrowFromSystemServer(); 122 } 123 } 124 125 /** 126 * Delete keyphrase sound model from the registered models pool for the current user matching\ 127 * the keyphrase ID and locale. 128 * The keyphraseId and locale passed must match a supported model passed in via 129 * {@link #updateKeyphraseSoundModel}. 130 * If the active voice interaction service changes from the current user, all requests will be 131 * rejected, and any registered models will be unregistered. 132 * Caller must either be the active voice interaction service via 133 * {@link Settings.Secure.VOICE_INTERACTION_SERVICE}, or the caller must be a voice model 134 * enrollment application detected by 135 * {@link android.hardware.soundtrigger.KeyphraseEnrollmentInfo}. 136 * 137 * @param keyphraseId The unique identifier for the keyphrase. 138 * @param locale The locale language tag supported by the desired model. 139 * @throws ServiceSpecificException Thrown with error code if failed to delete the keyphrase 140 * sound model. 141 * @throws SecurityException Thrown when caller does not have MANAGE_VOICE_KEYPHRASES permission 142 * or if the caller is not the active voice interaction service. 143 */ 144 @RequiresPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES) deleteKeyphraseSoundModel(int keyphraseId, @NonNull Locale locale)145 public void deleteKeyphraseSoundModel(int keyphraseId, @NonNull Locale locale) { 146 Objects.requireNonNull(locale); 147 try { 148 int status = mVoiceInteractionManagerService.deleteKeyphraseSoundModel(keyphraseId, 149 locale.toLanguageTag()); 150 if (status != SoundTrigger.STATUS_OK) { 151 throw new ServiceSpecificException(status); 152 } 153 } catch (RemoteException e) { 154 throw e.rethrowFromSystemServer(); 155 } 156 } 157 } 158