1a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra/* 2a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * Copyright (C) 2014 The Android Open Source Project 3a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * 4a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * Licensed under the Apache License, Version 2.0 (the "License"); 5a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * you may not use this file except in compliance with the License. 6a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * You may obtain a copy of the License at 7a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * 8a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * http://www.apache.org/licenses/LICENSE-2.0 9a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * 10a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * Unless required by applicable law or agreed to in writing, software 11a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * distributed under the License is distributed on an "AS IS" BASIS, 12a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * See the License for the specific language governing permissions and 14a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * limitations under the License. 15a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra */ 16a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 17a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishrapackage com.android.server.soundtrigger; 183fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishraimport static android.hardware.soundtrigger.SoundTrigger.STATUS_ERROR; 19a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 20a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.content.Context; 21a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.content.pm.PackageManager; 22a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.Manifest; 23a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.hardware.soundtrigger.IRecognitionStatusCallback; 24a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.hardware.soundtrigger.SoundTrigger; 25c722ec4105f7a4733a22fb9004e784347ee36663Arunesh Mishraimport android.hardware.soundtrigger.SoundTrigger.GenericSoundModel; 26a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel; 2755a9b0089c12dd657a8dc8551c79cf3e0f25d7e4Arunesh Mishraimport android.hardware.soundtrigger.SoundTrigger.ModuleProperties; 28a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.hardware.soundtrigger.SoundTrigger.RecognitionConfig; 29a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.os.Parcel; 30a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.os.ParcelUuid; 31a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.os.RemoteException; 32a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport android.util.Slog; 33a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 34a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport com.android.server.SystemService; 35a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport com.android.internal.app.ISoundTriggerService; 36a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 37a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport java.io.FileDescriptor; 38a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport java.io.PrintWriter; 39a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishraimport java.util.UUID; 40a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 41a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra/** 42a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * A single SystemService to manage all sound/voice-based sound models on the DSP. 43a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * This services provides apis to manage sound trigger-based sound models via 44a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * the ISoundTriggerService interface. This class also publishes a local interface encapsulating 45a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * the functionality provided by {@link SoundTriggerHelper} for use by 46a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * {@link VoiceInteractionManagerService}. 47a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * 48a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra * @hide 49a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra */ 50a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishrapublic class SoundTriggerService extends SystemService { 513fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra private static final String TAG = "SoundTriggerService"; 523fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra private static final boolean DEBUG = true; 53a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 54a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra final Context mContext; 55a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra private final SoundTriggerServiceStub mServiceStub; 56a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra private final LocalSoundTriggerService mLocalSoundTriggerService; 57a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra private SoundTriggerDbHelper mDbHelper; 583fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra private SoundTriggerHelper mSoundTriggerHelper; 59a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 60a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra public SoundTriggerService(Context context) { 61a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra super(context); 62a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra mContext = context; 63a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra mServiceStub = new SoundTriggerServiceStub(); 64a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra mLocalSoundTriggerService = new LocalSoundTriggerService(context); 65a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 66a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 67a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra @Override 68a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra public void onStart() { 69a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra publishBinderService(Context.SOUND_TRIGGER_SERVICE, mServiceStub); 70a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra publishLocalService(SoundTriggerInternal.class, mLocalSoundTriggerService); 71a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 72a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 73a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra @Override 74a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra public void onBootPhase(int phase) { 75a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra if (PHASE_SYSTEM_SERVICES_READY == phase) { 763fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra initSoundTriggerHelper(); 773fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra mLocalSoundTriggerService.setSoundTriggerHelper(mSoundTriggerHelper); 78a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } else if (PHASE_THIRD_PARTY_APPS_CAN_START == phase) { 79a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra mDbHelper = new SoundTriggerDbHelper(mContext); 80a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 81a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 82a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 83a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra @Override 84a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra public void onStartUser(int userHandle) { 85a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 86a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 87a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra @Override 88a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra public void onSwitchUser(int userHandle) { 89a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 90a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 913fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra private synchronized void initSoundTriggerHelper() { 923fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra if (mSoundTriggerHelper == null) { 933fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra mSoundTriggerHelper = new SoundTriggerHelper(mContext); 943fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra } 953fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra } 963fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra 973fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra private synchronized boolean isInitialized() { 983fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra if (mSoundTriggerHelper == null ) { 993fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra Slog.e(TAG, "SoundTriggerHelper not initialized."); 1003fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra return false; 1013fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra } 1023fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra return true; 1033fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra } 1043fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra 105a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra class SoundTriggerServiceStub extends ISoundTriggerService.Stub { 106a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra @Override 107a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 108a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra throws RemoteException { 109a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra try { 110a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra return super.onTransact(code, data, reply, flags); 111a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } catch (RuntimeException e) { 112a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra // The activity manager only throws security exceptions, so let's 113a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra // log all others. 114a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra if (!(e instanceof SecurityException)) { 115a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra Slog.wtf(TAG, "SoundTriggerService Crash", e); 116a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 117a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra throw e; 118a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 119a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 120a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 121a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra @Override 1223fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra public int startRecognition(ParcelUuid parcelUuid, IRecognitionStatusCallback callback, 1233fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra RecognitionConfig config) { 124a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER); 1252d1de78a4c8fc224329a9622c9326e42a42ddaddArunesh Mishra if (!isInitialized()) return STATUS_ERROR; 126a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra if (DEBUG) { 127a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra Slog.i(TAG, "startRecognition(): Uuid : " + parcelUuid); 128a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 1293fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra 1303fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra GenericSoundModel model = getSoundModel(parcelUuid); 1313fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra if (model == null) { 1323fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra Slog.e(TAG, "Null model in database for id: " + parcelUuid); 1333fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra return STATUS_ERROR; 1343fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra } 1353fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra 1363fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra return mSoundTriggerHelper.startGenericRecognition(parcelUuid.getUuid(), model, 1373fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra callback, config); 138a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 139a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 140a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra @Override 1413fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra public int stopRecognition(ParcelUuid parcelUuid, IRecognitionStatusCallback callback) { 142a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER); 143a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra if (DEBUG) { 144a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra Slog.i(TAG, "stopRecognition(): Uuid : " + parcelUuid); 145a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 1463fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra if (!isInitialized()) return STATUS_ERROR; 1473fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra return mSoundTriggerHelper.stopGenericRecognition(parcelUuid.getUuid(), callback); 148a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 149a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 150a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra @Override 151c722ec4105f7a4733a22fb9004e784347ee36663Arunesh Mishra public SoundTrigger.GenericSoundModel getSoundModel(ParcelUuid soundModelId) { 152a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER); 153a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra if (DEBUG) { 154a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra Slog.i(TAG, "getSoundModel(): id = " + soundModelId); 155a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 1563fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra SoundTrigger.GenericSoundModel model = mDbHelper.getGenericSoundModel( 1573fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra soundModelId.getUuid()); 158a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra return model; 159a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 160a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 161a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra @Override 162c722ec4105f7a4733a22fb9004e784347ee36663Arunesh Mishra public void updateSoundModel(SoundTrigger.GenericSoundModel soundModel) { 163a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER); 164a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra if (DEBUG) { 165a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra Slog.i(TAG, "updateSoundModel(): model = " + soundModel); 166a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 167c722ec4105f7a4733a22fb9004e784347ee36663Arunesh Mishra mDbHelper.updateGenericSoundModel(soundModel); 168a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 169a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 170a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra @Override 171a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra public void deleteSoundModel(ParcelUuid soundModelId) { 172a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER); 173a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra if (DEBUG) { 174a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra Slog.i(TAG, "deleteSoundModel(): id = " + soundModelId); 175a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 1762d1de78a4c8fc224329a9622c9326e42a42ddaddArunesh Mishra // Unload the model if it is loaded. 1772d1de78a4c8fc224329a9622c9326e42a42ddaddArunesh Mishra mSoundTriggerHelper.unloadGenericSoundModel(soundModelId.getUuid()); 178c722ec4105f7a4733a22fb9004e784347ee36663Arunesh Mishra mDbHelper.deleteGenericSoundModel(soundModelId.getUuid()); 179a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 180a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 181a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 182a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra public final class LocalSoundTriggerService extends SoundTriggerInternal { 183a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra private final Context mContext; 184a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra private SoundTriggerHelper mSoundTriggerHelper; 185a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 186a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra LocalSoundTriggerService(Context context) { 187a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra mContext = context; 188a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 189a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 1903fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra synchronized void setSoundTriggerHelper(SoundTriggerHelper helper) { 1913fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra mSoundTriggerHelper = helper; 192a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 193a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 194a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra @Override 195a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra public int startRecognition(int keyphraseId, KeyphraseSoundModel soundModel, 196a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra IRecognitionStatusCallback listener, RecognitionConfig recognitionConfig) { 1973fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra if (!isInitialized()) return STATUS_ERROR; 1983fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra return mSoundTriggerHelper.startKeyphraseRecognition(keyphraseId, soundModel, listener, 199a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra recognitionConfig); 200a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 201a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 202a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra @Override 2033fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra public synchronized int stopRecognition(int keyphraseId, IRecognitionStatusCallback listener) { 2043fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra if (!isInitialized()) return STATUS_ERROR; 2053fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra return mSoundTriggerHelper.stopKeyphraseRecognition(keyphraseId, listener); 206a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 207a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 208a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra @Override 20955a9b0089c12dd657a8dc8551c79cf3e0f25d7e4Arunesh Mishra public ModuleProperties getModuleProperties() { 2103fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra if (!isInitialized()) return null; 21155a9b0089c12dd657a8dc8551c79cf3e0f25d7e4Arunesh Mishra return mSoundTriggerHelper.getModuleProperties(); 21255a9b0089c12dd657a8dc8551c79cf3e0f25d7e4Arunesh Mishra } 21355a9b0089c12dd657a8dc8551c79cf3e0f25d7e4Arunesh Mishra 21455a9b0089c12dd657a8dc8551c79cf3e0f25d7e4Arunesh Mishra @Override 2152d1de78a4c8fc224329a9622c9326e42a42ddaddArunesh Mishra public int unloadKeyphraseModel(int keyphraseId) { 2162d1de78a4c8fc224329a9622c9326e42a42ddaddArunesh Mishra if (!isInitialized()) return STATUS_ERROR; 2172d1de78a4c8fc224329a9622c9326e42a42ddaddArunesh Mishra return mSoundTriggerHelper.unloadKeyphraseSoundModel(keyphraseId); 2182d1de78a4c8fc224329a9622c9326e42a42ddaddArunesh Mishra } 2192d1de78a4c8fc224329a9622c9326e42a42ddaddArunesh Mishra 2202d1de78a4c8fc224329a9622c9326e42a42ddaddArunesh Mishra @Override 221a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2223fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra if (!isInitialized()) return; 223a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra mSoundTriggerHelper.dump(fd, pw, args); 224a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 2253fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra 2263fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra private synchronized boolean isInitialized() { 2273fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra if (mSoundTriggerHelper == null ) { 2283fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra Slog.e(TAG, "SoundTriggerHelper not initialized."); 2293fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra return false; 2303fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra } 2313fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra return true; 2323fff7f5634ca788c1c84b6f1b316819ffd4c7cb2Arunesh Mishra } 233a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 234a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra 235a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra private void enforceCallingPermission(String permission) { 236a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra if (mContext.checkCallingOrSelfPermission(permission) 237a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra != PackageManager.PERMISSION_GRANTED) { 238a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra throw new SecurityException("Caller does not hold the permission " + permission); 239a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 240a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra } 241a772e5fc062c8de48cb9c1d61755110f6b2e189bArunesh Mishra} 242