1 /** 2 * Copyright (C) 2014 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.soundtrigger; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.annotation.RequiresPermission; 22 import android.annotation.SystemApi; 23 import android.annotation.SystemService; 24 import android.content.Context; 25 import android.hardware.soundtrigger.SoundTrigger; 26 import android.os.Handler; 27 import android.os.ParcelUuid; 28 import android.os.RemoteException; 29 import android.util.Slog; 30 31 import com.android.internal.app.ISoundTriggerService; 32 33 import java.util.HashMap; 34 import java.util.UUID; 35 36 /** 37 * This class provides management of non-voice (general sound trigger) based sound recognition 38 * models. Usage of this class is restricted to system or signature applications only. This allows 39 * OEMs to write apps that can manage non-voice based sound trigger models. 40 * 41 * @hide 42 */ 43 @SystemApi 44 @SystemService(Context.SOUND_TRIGGER_SERVICE) 45 public final class SoundTriggerManager { 46 private static final boolean DBG = false; 47 private static final String TAG = "SoundTriggerManager"; 48 49 private final Context mContext; 50 private final ISoundTriggerService mSoundTriggerService; 51 52 // Stores a mapping from the sound model UUID to the SoundTriggerInstance created by 53 // the createSoundTriggerDetector() call. 54 private final HashMap<UUID, SoundTriggerDetector> mReceiverInstanceMap; 55 56 /** 57 * @hide 58 */ SoundTriggerManager(Context context, ISoundTriggerService soundTriggerService )59 public SoundTriggerManager(Context context, ISoundTriggerService soundTriggerService ) { 60 if (DBG) { 61 Slog.i(TAG, "SoundTriggerManager created."); 62 } 63 mSoundTriggerService = soundTriggerService; 64 mContext = context; 65 mReceiverInstanceMap = new HashMap<UUID, SoundTriggerDetector>(); 66 } 67 68 /** 69 * Updates the given sound trigger model. 70 */ 71 @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) updateModel(Model model)72 public void updateModel(Model model) { 73 try { 74 mSoundTriggerService.updateSoundModel(model.getGenericSoundModel()); 75 } catch (RemoteException e) { 76 throw e.rethrowFromSystemServer(); 77 } 78 } 79 80 /** 81 * Returns the sound trigger model represented by the given UUID. An instance of {@link Model} 82 * is returned. 83 */ 84 @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) getModel(UUID soundModelId)85 public Model getModel(UUID soundModelId) { 86 try { 87 return new Model(mSoundTriggerService.getSoundModel( 88 new ParcelUuid(soundModelId))); 89 } catch (RemoteException e) { 90 throw e.rethrowFromSystemServer(); 91 } 92 } 93 94 /** 95 * Deletes the sound model represented by the provided UUID. 96 */ 97 @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) deleteModel(UUID soundModelId)98 public void deleteModel(UUID soundModelId) { 99 try { 100 mSoundTriggerService.deleteSoundModel(new ParcelUuid(soundModelId)); 101 } catch (RemoteException e) { 102 throw e.rethrowFromSystemServer(); 103 } 104 } 105 106 /** 107 * Creates an instance of {@link SoundTriggerDetector} which can be used to start/stop 108 * recognition on the model and register for triggers from the model. Note that this call 109 * invalidates any previously returned instances for the same sound model Uuid. 110 * 111 * @param soundModelId UUID of the sound model to create the receiver object for. 112 * @param callback Instance of the {@link SoundTriggerDetector#Callback} object for the 113 * callbacks for the given sound model. 114 * @param handler The Handler to use for the callback operations. A null value will use the 115 * current thread's Looper. 116 * @return Instance of {@link SoundTriggerDetector} or null on error. 117 */ 118 @Nullable 119 @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) createSoundTriggerDetector(UUID soundModelId, @NonNull SoundTriggerDetector.Callback callback, @Nullable Handler handler)120 public SoundTriggerDetector createSoundTriggerDetector(UUID soundModelId, 121 @NonNull SoundTriggerDetector.Callback callback, @Nullable Handler handler) { 122 if (soundModelId == null) { 123 return null; 124 } 125 126 SoundTriggerDetector oldInstance = mReceiverInstanceMap.get(soundModelId); 127 if (oldInstance != null) { 128 // Shutdown old instance. 129 } 130 SoundTriggerDetector newInstance = new SoundTriggerDetector(mSoundTriggerService, 131 soundModelId, callback, handler); 132 mReceiverInstanceMap.put(soundModelId, newInstance); 133 return newInstance; 134 } 135 136 /** 137 * Class captures the data and fields that represent a non-keyphrase sound model. Use the 138 * factory constructor {@link Model#create()} to create an instance. 139 */ 140 // We use encapsulation to expose the SoundTrigger.GenericSoundModel as a SystemApi. This 141 // prevents us from exposing SoundTrigger.GenericSoundModel as an Api. 142 public static class Model { 143 144 private SoundTrigger.GenericSoundModel mGenericSoundModel; 145 146 /** 147 * @hide 148 */ Model(SoundTrigger.GenericSoundModel soundTriggerModel)149 Model(SoundTrigger.GenericSoundModel soundTriggerModel) { 150 mGenericSoundModel = soundTriggerModel; 151 } 152 153 /** 154 * Factory constructor to create a SoundModel instance for use with methods in this 155 * class. 156 */ create(UUID modelUuid, UUID vendorUuid, byte[] data)157 public static Model create(UUID modelUuid, UUID vendorUuid, byte[] data) { 158 return new Model(new SoundTrigger.GenericSoundModel(modelUuid, 159 vendorUuid, data)); 160 } 161 getModelUuid()162 public UUID getModelUuid() { 163 return mGenericSoundModel.uuid; 164 } 165 getVendorUuid()166 public UUID getVendorUuid() { 167 return mGenericSoundModel.vendorUuid; 168 } 169 getModelData()170 public byte[] getModelData() { 171 return mGenericSoundModel.data; 172 } 173 174 /** 175 * @hide 176 */ getGenericSoundModel()177 SoundTrigger.GenericSoundModel getGenericSoundModel() { 178 return mGenericSoundModel; 179 } 180 } 181 } 182