1 /* 2 * Copyright (C) 2021 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 com.android.server.soundtrigger_middleware; 18 19 import static org.junit.Assert.assertArrayEquals; 20 import static org.junit.Assert.assertEquals; 21 import static org.junit.Assert.assertTrue; 22 23 import android.annotation.NonNull; 24 import android.hardware.soundtrigger.V2_1.ISoundTriggerHw; 25 import android.hardware.soundtrigger.V2_1.ISoundTriggerHwCallback; 26 import android.media.AudioFormat; 27 import android.media.MediaFormat; 28 import android.media.audio.common.AudioChannelLayout; 29 import android.media.audio.common.AudioConfig; 30 import android.media.audio.common.AudioConfigBase; 31 import android.media.audio.common.AudioFormatDescription; 32 import android.media.audio.common.AudioFormatType; 33 import android.media.soundtrigger.AudioCapabilities; 34 import android.media.soundtrigger.ConfidenceLevel; 35 import android.media.soundtrigger.Phrase; 36 import android.media.soundtrigger.PhraseRecognitionEvent; 37 import android.media.soundtrigger.PhraseRecognitionExtra; 38 import android.media.soundtrigger.PhraseSoundModel; 39 import android.media.soundtrigger.Properties; 40 import android.media.soundtrigger.RecognitionConfig; 41 import android.media.soundtrigger.RecognitionEvent; 42 import android.media.soundtrigger.RecognitionMode; 43 import android.media.soundtrigger.RecognitionStatus; 44 import android.media.soundtrigger.SoundModel; 45 import android.media.soundtrigger.SoundModelType; 46 import android.os.HidlMemoryUtil; 47 import android.os.ParcelFileDescriptor; 48 import android.os.SharedMemory; 49 50 import java.io.IOException; 51 import java.nio.ByteBuffer; 52 import java.util.List; 53 54 /** 55 * Test utilities, aimed at generating populated objects of the various types and validating 56 * corresponding objects generated by the system under test. 57 */ 58 class TestUtil { 59 private static final int AUDIO_FORMAT_MP3 = 0x01000000; // matches native 60 createGenericSoundModel()61 static SoundModel createGenericSoundModel() { 62 return createSoundModel(SoundModelType.GENERIC); 63 } 64 createSoundModel(@oundModelType int type)65 private static SoundModel createSoundModel(@SoundModelType int type) { 66 SoundModel model = new SoundModel(); 67 model.type = type; 68 model.uuid = "12345678-2345-3456-4567-abcdef987654"; 69 model.vendorUuid = "87654321-5432-6543-7654-456789fedcba"; 70 byte[] data = new byte[]{91, 92, 93, 94, 95}; 71 model.data = byteArrayToParcelFileDescriptor(data); 72 model.dataSize = data.length; 73 return model; 74 } 75 validateSoundModel_2_1(ISoundTriggerHw.SoundModel model, int type)76 private static void validateSoundModel_2_1(ISoundTriggerHw.SoundModel model, int type) { 77 assertEquals(type, model.header.type); 78 assertEquals("12345678-2345-3456-4567-abcdef987654", 79 ConversionUtil.hidl2aidlUuid(model.header.uuid)); 80 assertEquals("87654321-5432-6543-7654-456789fedcba", 81 ConversionUtil.hidl2aidlUuid(model.header.vendorUuid)); 82 assertArrayEquals(new byte[]{91, 92, 93, 94, 95}, 83 HidlMemoryUtil.hidlMemoryToByteArray(model.data)); 84 } 85 dupModel_2_1( android.hardware.soundtrigger.V2_1.ISoundTriggerHw.SoundModel model)86 static android.hardware.soundtrigger.V2_1.ISoundTriggerHw.SoundModel dupModel_2_1( 87 android.hardware.soundtrigger.V2_1.ISoundTriggerHw.SoundModel model) { 88 android.hardware.soundtrigger.V2_1.ISoundTriggerHw.SoundModel dup = 89 new android.hardware.soundtrigger.V2_1.ISoundTriggerHw.SoundModel(); 90 dup.header = model.header; 91 try { 92 dup.data = model.data.dup(); 93 } catch (IOException e) { 94 throw new RuntimeException(e); 95 } 96 return dup; 97 } 98 validateSoundModel_2_0( android.hardware.soundtrigger.V2_0.ISoundTriggerHw.SoundModel model, int type)99 private static void validateSoundModel_2_0( 100 android.hardware.soundtrigger.V2_0.ISoundTriggerHw.SoundModel model, int type) { 101 assertEquals(type, model.type); 102 assertEquals("12345678-2345-3456-4567-abcdef987654", 103 ConversionUtil.hidl2aidlUuid(model.uuid)); 104 assertEquals("87654321-5432-6543-7654-456789fedcba", 105 ConversionUtil.hidl2aidlUuid(model.vendorUuid)); 106 assertArrayEquals(new Byte[]{91, 92, 93, 94, 95}, model.data.toArray()); 107 } 108 validateGenericSoundModel_2_1(ISoundTriggerHw.SoundModel model)109 static void validateGenericSoundModel_2_1(ISoundTriggerHw.SoundModel model) { 110 validateSoundModel_2_1(model, android.hardware.soundtrigger.V2_0.SoundModelType.GENERIC); 111 } 112 validateGenericSoundModel_2_0( android.hardware.soundtrigger.V2_0.ISoundTriggerHw.SoundModel model)113 static void validateGenericSoundModel_2_0( 114 android.hardware.soundtrigger.V2_0.ISoundTriggerHw.SoundModel model) { 115 validateSoundModel_2_0(model, android.hardware.soundtrigger.V2_0.SoundModelType.GENERIC); 116 } 117 createPhraseSoundModel()118 static PhraseSoundModel createPhraseSoundModel() { 119 PhraseSoundModel model = new PhraseSoundModel(); 120 model.common = createSoundModel(SoundModelType.KEYPHRASE); 121 model.phrases = new Phrase[1]; 122 model.phrases[0] = new Phrase(); 123 model.phrases[0].id = 123; 124 model.phrases[0].users = new int[]{5, 6, 7}; 125 model.phrases[0].locale = "locale"; 126 model.phrases[0].text = "text"; 127 model.phrases[0].recognitionModes = 128 RecognitionMode.USER_AUTHENTICATION | RecognitionMode.USER_IDENTIFICATION; 129 return model; 130 } 131 validatePhraseSoundModel_2_1(ISoundTriggerHw.PhraseSoundModel model)132 static void validatePhraseSoundModel_2_1(ISoundTriggerHw.PhraseSoundModel model) { 133 validateSoundModel_2_1(model.common, 134 android.hardware.soundtrigger.V2_0.SoundModelType.KEYPHRASE); 135 validatePhrases_2_0(model.phrases); 136 } 137 dupPhraseModel_2_1( android.hardware.soundtrigger.V2_1.ISoundTriggerHw.PhraseSoundModel model)138 static android.hardware.soundtrigger.V2_1.ISoundTriggerHw.PhraseSoundModel dupPhraseModel_2_1( 139 android.hardware.soundtrigger.V2_1.ISoundTriggerHw.PhraseSoundModel model) { 140 android.hardware.soundtrigger.V2_1.ISoundTriggerHw.PhraseSoundModel dup = 141 new android.hardware.soundtrigger.V2_1.ISoundTriggerHw.PhraseSoundModel(); 142 dup.common = dupModel_2_1(model.common); 143 dup.phrases = model.phrases; 144 return dup; 145 } 146 validatePhraseSoundModel_2_0( android.hardware.soundtrigger.V2_0.ISoundTriggerHw.PhraseSoundModel model)147 static void validatePhraseSoundModel_2_0( 148 android.hardware.soundtrigger.V2_0.ISoundTriggerHw.PhraseSoundModel model) { 149 validateSoundModel_2_0(model.common, 150 android.hardware.soundtrigger.V2_0.SoundModelType.KEYPHRASE); 151 validatePhrases_2_0(model.phrases); 152 } 153 validatePhrases_2_0( List<android.hardware.soundtrigger.V2_0.ISoundTriggerHw.Phrase> phrases)154 private static void validatePhrases_2_0( 155 List<android.hardware.soundtrigger.V2_0.ISoundTriggerHw.Phrase> phrases) { 156 assertEquals(1, phrases.size()); 157 assertEquals(123, phrases.get(0).id); 158 assertArrayEquals(new Integer[]{5, 6, 7}, phrases.get(0).users.toArray()); 159 assertEquals("locale", phrases.get(0).locale); 160 assertEquals("text", phrases.get(0).text); 161 assertEquals(RecognitionMode.USER_AUTHENTICATION | RecognitionMode.USER_IDENTIFICATION, 162 phrases.get(0).recognitionModes); 163 } 164 165 static android.hardware.soundtrigger.V2_0.ISoundTriggerHw.Properties createDefaultProperties_2_0()166 createDefaultProperties_2_0() { 167 android.hardware.soundtrigger.V2_0.ISoundTriggerHw.Properties properties = 168 new android.hardware.soundtrigger.V2_0.ISoundTriggerHw.Properties(); 169 properties.implementor = "implementor"; 170 properties.description = "description"; 171 properties.version = 123; 172 properties.uuid.timeLow = 1; 173 properties.uuid.timeMid = 2; 174 properties.uuid.versionAndTimeHigh = 3; 175 properties.uuid.variantAndClockSeqHigh = 4; 176 properties.uuid.node = new byte[]{5, 6, 7, 8, 9, 10}; 177 178 properties.maxSoundModels = 456; 179 properties.maxKeyPhrases = 567; 180 properties.maxUsers = 678; 181 properties.recognitionModes = 182 android.hardware.soundtrigger.V2_0.RecognitionMode.VOICE_TRIGGER 183 | android.hardware.soundtrigger.V2_0.RecognitionMode.USER_IDENTIFICATION 184 | android.hardware.soundtrigger.V2_0.RecognitionMode.USER_AUTHENTICATION 185 | android.hardware.soundtrigger.V2_0.RecognitionMode.GENERIC_TRIGGER; 186 properties.captureTransition = true; 187 properties.maxBufferMs = 321; 188 properties.concurrentCapture = true; 189 properties.triggerInEvent = true; 190 properties.powerConsumptionMw = 432; 191 return properties; 192 } 193 createDefaultProperties_2_3()194 static android.hardware.soundtrigger.V2_3.Properties createDefaultProperties_2_3() { 195 android.hardware.soundtrigger.V2_3.Properties properties = 196 new android.hardware.soundtrigger.V2_3.Properties(); 197 properties.base = createDefaultProperties_2_0(); 198 properties.supportedModelArch = "supportedModelArch"; 199 properties.audioCapabilities = 200 android.hardware.soundtrigger.V2_3.AudioCapabilities.ECHO_CANCELLATION 201 | android.hardware.soundtrigger.V2_3.AudioCapabilities.NOISE_SUPPRESSION; 202 return properties; 203 } 204 createDefaultProperties()205 static Properties createDefaultProperties() { 206 Properties properties = new Properties(); 207 properties.implementor = "implementor"; 208 properties.description = "description"; 209 properties.version = 123; 210 properties.uuid = "00000001-0002-0003-0004-05060708090a"; 211 properties.maxSoundModels = 456; 212 properties.maxKeyPhrases = 567; 213 properties.maxUsers = 678; 214 properties.recognitionModes = 215 RecognitionMode.VOICE_TRIGGER | RecognitionMode.USER_IDENTIFICATION 216 | RecognitionMode.USER_AUTHENTICATION | RecognitionMode.GENERIC_TRIGGER; 217 properties.captureTransition = true; 218 properties.maxBufferMs = 321; 219 properties.concurrentCapture = true; 220 properties.triggerInEvent = true; 221 properties.powerConsumptionMw = 432; 222 properties.supportedModelArch = "supportedModelArch"; 223 properties.audioCapabilities = 224 AudioCapabilities.ECHO_CANCELLATION | AudioCapabilities.NOISE_SUPPRESSION; 225 return properties; 226 } 227 validateDefaultProperties(Properties properties)228 static void validateDefaultProperties(Properties properties) { 229 validateDefaultProperties(properties, 230 AudioCapabilities.ECHO_CANCELLATION | AudioCapabilities.NOISE_SUPPRESSION, 231 "supportedModelArch"); 232 } 233 validateDefaultProperties(Properties properties, @AudioCapabilities int audioCapabilities, @NonNull String supportedModelArch)234 static void validateDefaultProperties(Properties properties, 235 @AudioCapabilities int audioCapabilities, @NonNull String supportedModelArch) { 236 assertEquals("implementor", properties.implementor); 237 assertEquals("description", properties.description); 238 assertEquals(123, properties.version); 239 assertEquals("00000001-0002-0003-0004-05060708090a", properties.uuid); 240 assertEquals(456, properties.maxSoundModels); 241 assertEquals(567, properties.maxKeyPhrases); 242 assertEquals(678, properties.maxUsers); 243 assertEquals(RecognitionMode.GENERIC_TRIGGER | RecognitionMode.USER_AUTHENTICATION 244 | RecognitionMode.USER_IDENTIFICATION | RecognitionMode.VOICE_TRIGGER, 245 properties.recognitionModes); 246 assertTrue(properties.captureTransition); 247 assertEquals(321, properties.maxBufferMs); 248 assertEquals(true, properties.concurrentCapture); 249 assertTrue(properties.triggerInEvent); 250 assertEquals(432, properties.powerConsumptionMw); 251 assertEquals(supportedModelArch, properties.supportedModelArch); 252 assertEquals(audioCapabilities, properties.audioCapabilities); 253 } 254 createRecognitionConfig()255 static RecognitionConfig createRecognitionConfig() { 256 RecognitionConfig config = new RecognitionConfig(); 257 config.captureRequested = true; 258 config.phraseRecognitionExtras = new PhraseRecognitionExtra[]{new PhraseRecognitionExtra()}; 259 config.phraseRecognitionExtras[0].id = 123; 260 config.phraseRecognitionExtras[0].confidenceLevel = 4; 261 config.phraseRecognitionExtras[0].recognitionModes = 5; 262 config.phraseRecognitionExtras[0].levels = new ConfidenceLevel[]{new ConfidenceLevel()}; 263 config.phraseRecognitionExtras[0].levels[0].userId = 234; 264 config.phraseRecognitionExtras[0].levels[0].levelPercent = 34; 265 config.data = new byte[]{5, 4, 3, 2, 1}; 266 config.audioCapabilities = 267 AudioCapabilities.ECHO_CANCELLATION | AudioCapabilities.NOISE_SUPPRESSION; 268 return config; 269 } 270 validateRecognitionConfig_2_0( android.hardware.soundtrigger.V2_0.ISoundTriggerHw.RecognitionConfig config, int captureDevice, int captureHandle)271 static void validateRecognitionConfig_2_0( 272 android.hardware.soundtrigger.V2_0.ISoundTriggerHw.RecognitionConfig config, 273 int captureDevice, int captureHandle) { 274 assertTrue(config.captureRequested); 275 assertEquals(captureDevice, config.captureDevice); 276 assertEquals(captureHandle, config.captureHandle); 277 assertEquals(1, config.phrases.size()); 278 android.hardware.soundtrigger.V2_0.PhraseRecognitionExtra halPhraseExtra = 279 config.phrases.get(0); 280 assertEquals(123, halPhraseExtra.id); 281 assertEquals(4, halPhraseExtra.confidenceLevel); 282 assertEquals(5, halPhraseExtra.recognitionModes); 283 assertEquals(1, halPhraseExtra.levels.size()); 284 android.hardware.soundtrigger.V2_0.ConfidenceLevel halLevel = halPhraseExtra.levels.get(0); 285 assertEquals(234, halLevel.userId); 286 assertEquals(34, halLevel.levelPercent); 287 assertArrayEquals(new Byte[]{5, 4, 3, 2, 1}, config.data.toArray()); 288 } 289 validateRecognitionConfig_2_1( android.hardware.soundtrigger.V2_1.ISoundTriggerHw.RecognitionConfig config, int captureDevice, int captureHandle)290 static void validateRecognitionConfig_2_1( 291 android.hardware.soundtrigger.V2_1.ISoundTriggerHw.RecognitionConfig config, 292 int captureDevice, int captureHandle) { 293 assertTrue(config.header.captureRequested); 294 assertEquals(captureDevice, config.header.captureDevice); 295 assertEquals(captureHandle, config.header.captureHandle); 296 assertEquals(1, config.header.phrases.size()); 297 android.hardware.soundtrigger.V2_0.PhraseRecognitionExtra halPhraseExtra = 298 config.header.phrases.get(0); 299 assertEquals(123, halPhraseExtra.id); 300 assertEquals(4, halPhraseExtra.confidenceLevel); 301 assertEquals(5, halPhraseExtra.recognitionModes); 302 assertEquals(1, halPhraseExtra.levels.size()); 303 android.hardware.soundtrigger.V2_0.ConfidenceLevel halLevel = halPhraseExtra.levels.get(0); 304 assertEquals(234, halLevel.userId); 305 assertEquals(34, halLevel.levelPercent); 306 assertArrayEquals(new byte[]{5, 4, 3, 2, 1}, 307 HidlMemoryUtil.hidlMemoryToByteArray(config.data)); 308 } 309 validateRecognitionConfig_2_3( android.hardware.soundtrigger.V2_3.RecognitionConfig config, int captureDevice, int captureHandle)310 static void validateRecognitionConfig_2_3( 311 android.hardware.soundtrigger.V2_3.RecognitionConfig config, int captureDevice, 312 int captureHandle) { 313 validateRecognitionConfig_2_1(config.base, captureDevice, captureHandle); 314 315 assertEquals(AudioCapabilities.ECHO_CANCELLATION | AudioCapabilities.NOISE_SUPPRESSION, 316 config.audioCapabilities); 317 } 318 createRecognitionEvent_2_0( int hwHandle, int status)319 static android.hardware.soundtrigger.V2_0.ISoundTriggerHwCallback.RecognitionEvent createRecognitionEvent_2_0( 320 int hwHandle, int status) { 321 android.hardware.soundtrigger.V2_0.ISoundTriggerHwCallback.RecognitionEvent halEvent = 322 new android.hardware.soundtrigger.V2_0.ISoundTriggerHwCallback.RecognitionEvent(); 323 halEvent.status = status; 324 halEvent.type = SoundModelType.GENERIC; 325 halEvent.model = hwHandle; 326 halEvent.captureAvailable = true; 327 // This field is ignored. 328 halEvent.captureSession = 9999; 329 halEvent.captureDelayMs = 234; 330 halEvent.capturePreambleMs = 345; 331 halEvent.triggerInData = true; 332 halEvent.audioConfig.sampleRateHz = 456; 333 halEvent.audioConfig.channelMask = AudioFormat.CHANNEL_IN_MONO; // matches native 334 halEvent.audioConfig.format = AUDIO_FORMAT_MP3; 335 // hwEvent.audioConfig.offloadInfo is irrelevant. 336 halEvent.data.add((byte) 31); 337 halEvent.data.add((byte) 32); 338 halEvent.data.add((byte) 33); 339 return halEvent; 340 } 341 createAudioFormatMp3()342 static AudioFormatDescription createAudioFormatMp3() { 343 AudioFormatDescription format = new AudioFormatDescription(); 344 format.type = AudioFormatType.NON_PCM; 345 format.encoding = MediaFormat.MIMETYPE_AUDIO_MPEG; // MP3 346 return format; 347 } 348 createRecognitionEvent(@ecognitionStatus int status, boolean recognitionStillActive)349 static RecognitionEvent createRecognitionEvent(@RecognitionStatus int status, 350 boolean recognitionStillActive) { 351 RecognitionEvent event = new RecognitionEvent(); 352 event.status = status; 353 event.type = SoundModelType.GENERIC; 354 event.captureAvailable = true; 355 event.captureDelayMs = 234; 356 event.capturePreambleMs = 345; 357 event.triggerInData = true; 358 event.audioConfig = new AudioConfig(); 359 event.audioConfig.base = new AudioConfigBase(); 360 event.audioConfig.base.sampleRate = 456; 361 event.audioConfig.base.channelMask = AudioChannelLayout.layoutMask( 362 AudioChannelLayout.LAYOUT_MONO); 363 event.audioConfig.base.format = createAudioFormatMp3(); 364 //event.audioConfig.offloadInfo is irrelevant. 365 event.data = new byte[]{31, 32, 33}; 366 event.recognitionStillActive = recognitionStillActive; 367 return event; 368 } 369 createRecognitionEvent_2_1(int hwHandle, int status)370 static ISoundTriggerHwCallback.RecognitionEvent createRecognitionEvent_2_1(int hwHandle, 371 int status) { 372 ISoundTriggerHwCallback.RecognitionEvent halEvent = 373 new ISoundTriggerHwCallback.RecognitionEvent(); 374 halEvent.header = createRecognitionEvent_2_0(hwHandle, status); 375 halEvent.header.data.clear(); 376 halEvent.data = HidlMemoryUtil.byteArrayToHidlMemory(new byte[]{31, 32, 33}); 377 return halEvent; 378 } 379 validateRecognitionEvent(RecognitionEvent event, @RecognitionStatus int status, boolean recognitionStillActive)380 static void validateRecognitionEvent(RecognitionEvent event, @RecognitionStatus int status, 381 boolean recognitionStillActive) { 382 assertEquals(status, event.status); 383 assertEquals(SoundModelType.GENERIC, event.type); 384 assertTrue(event.captureAvailable); 385 assertEquals(234, event.captureDelayMs); 386 assertEquals(345, event.capturePreambleMs); 387 assertTrue(event.triggerInData); 388 assertEquals(456, event.audioConfig.base.sampleRate); 389 assertEquals(AudioChannelLayout.layoutMask(AudioChannelLayout.LAYOUT_MONO), 390 event.audioConfig.base.channelMask); 391 assertEquals(createAudioFormatMp3(), event.audioConfig.base.format); 392 assertArrayEquals(new byte[]{31, 32, 33}, event.data); 393 assertEquals(recognitionStillActive, event.recognitionStillActive); 394 } 395 createPhraseRecognitionEvent(@ecognitionStatus int status, boolean recognitionStillActive)396 static PhraseRecognitionEvent createPhraseRecognitionEvent(@RecognitionStatus int status, 397 boolean recognitionStillActive) { 398 PhraseRecognitionEvent event = new PhraseRecognitionEvent(); 399 event.common = createRecognitionEvent(status, recognitionStillActive); 400 401 PhraseRecognitionExtra extra = new PhraseRecognitionExtra(); 402 extra.id = 123; 403 extra.confidenceLevel = 52; 404 extra.recognitionModes = RecognitionMode.VOICE_TRIGGER | RecognitionMode.GENERIC_TRIGGER; 405 ConfidenceLevel level = new ConfidenceLevel(); 406 level.userId = 31; 407 level.levelPercent = 43; 408 extra.levels = new ConfidenceLevel[]{level}; 409 event.phraseExtras = new PhraseRecognitionExtra[]{extra}; 410 return event; 411 } 412 createPhraseRecognitionEvent_2_0( int hwHandle, int status)413 static android.hardware.soundtrigger.V2_0.ISoundTriggerHwCallback.PhraseRecognitionEvent createPhraseRecognitionEvent_2_0( 414 int hwHandle, int status) { 415 android.hardware.soundtrigger.V2_0.ISoundTriggerHwCallback.PhraseRecognitionEvent halEvent = 416 new android.hardware.soundtrigger.V2_0.ISoundTriggerHwCallback.PhraseRecognitionEvent(); 417 halEvent.common = createRecognitionEvent_2_0(hwHandle, status); 418 419 android.hardware.soundtrigger.V2_0.PhraseRecognitionExtra halExtra = 420 new android.hardware.soundtrigger.V2_0.PhraseRecognitionExtra(); 421 halExtra.id = 123; 422 halExtra.confidenceLevel = 52; 423 halExtra.recognitionModes = android.hardware.soundtrigger.V2_0.RecognitionMode.VOICE_TRIGGER 424 | android.hardware.soundtrigger.V2_0.RecognitionMode.GENERIC_TRIGGER; 425 android.hardware.soundtrigger.V2_0.ConfidenceLevel halLevel = 426 new android.hardware.soundtrigger.V2_0.ConfidenceLevel(); 427 halLevel.userId = 31; 428 halLevel.levelPercent = 43; 429 halExtra.levels.add(halLevel); 430 halEvent.phraseExtras.add(halExtra); 431 return halEvent; 432 } 433 createPhraseRecognitionEvent_2_1( int hwHandle, int status)434 static ISoundTriggerHwCallback.PhraseRecognitionEvent createPhraseRecognitionEvent_2_1( 435 int hwHandle, int status) { 436 ISoundTriggerHwCallback.PhraseRecognitionEvent halEvent = 437 new ISoundTriggerHwCallback.PhraseRecognitionEvent(); 438 halEvent.common = createRecognitionEvent_2_1(hwHandle, status); 439 440 android.hardware.soundtrigger.V2_0.PhraseRecognitionExtra halExtra = 441 new android.hardware.soundtrigger.V2_0.PhraseRecognitionExtra(); 442 halExtra.id = 123; 443 halExtra.confidenceLevel = 52; 444 halExtra.recognitionModes = android.hardware.soundtrigger.V2_0.RecognitionMode.VOICE_TRIGGER 445 | android.hardware.soundtrigger.V2_0.RecognitionMode.GENERIC_TRIGGER; 446 android.hardware.soundtrigger.V2_0.ConfidenceLevel halLevel = 447 new android.hardware.soundtrigger.V2_0.ConfidenceLevel(); 448 halLevel.userId = 31; 449 halLevel.levelPercent = 43; 450 halExtra.levels.add(halLevel); 451 halEvent.phraseExtras.add(halExtra); 452 return halEvent; 453 } 454 validatePhraseRecognitionEvent(PhraseRecognitionEvent event, @RecognitionStatus int status, boolean recognitionStillActive)455 static void validatePhraseRecognitionEvent(PhraseRecognitionEvent event, 456 @RecognitionStatus int status, boolean recognitionStillActive) { 457 validateRecognitionEvent(event.common, status, recognitionStillActive); 458 459 assertEquals(1, event.phraseExtras.length); 460 assertEquals(123, event.phraseExtras[0].id); 461 assertEquals(52, event.phraseExtras[0].confidenceLevel); 462 assertEquals(RecognitionMode.VOICE_TRIGGER | RecognitionMode.GENERIC_TRIGGER, 463 event.phraseExtras[0].recognitionModes); 464 assertEquals(1, event.phraseExtras[0].levels.length); 465 assertEquals(31, event.phraseExtras[0].levels[0].userId); 466 assertEquals(43, event.phraseExtras[0].levels[0].levelPercent); 467 } 468 byteArrayToParcelFileDescriptor(byte[] data)469 static ParcelFileDescriptor byteArrayToParcelFileDescriptor(byte[] data) { 470 try (SharedMemory shmem = SharedMemory.create("", data.length)) { 471 ByteBuffer buffer = shmem.mapReadWrite(); 472 buffer.put(data); 473 return shmem.getFdDup(); 474 } catch (Exception e) { 475 throw new RuntimeException(e); 476 } 477 } 478 } 479