| /* |
| * Copyright (C) 2019 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 android.hardware.soundtrigger; |
| |
| import android.hardware.soundtrigger.ModelParams; |
| import android.media.AudioFormat; |
| import android.media.audio.common.AudioConfig; |
| import android.media.soundtrigger_middleware.ConfidenceLevel; |
| import android.media.soundtrigger_middleware.ModelParameterRange; |
| import android.media.soundtrigger_middleware.Phrase; |
| import android.media.soundtrigger_middleware.PhraseRecognitionEvent; |
| import android.media.soundtrigger_middleware.PhraseRecognitionExtra; |
| import android.media.soundtrigger_middleware.PhraseSoundModel; |
| import android.media.soundtrigger_middleware.RecognitionConfig; |
| import android.media.soundtrigger_middleware.RecognitionEvent; |
| import android.media.soundtrigger_middleware.RecognitionMode; |
| import android.media.soundtrigger_middleware.SoundModel; |
| import android.media.soundtrigger_middleware.SoundTriggerModuleDescriptor; |
| import android.media.soundtrigger_middleware.SoundTriggerModuleProperties; |
| |
| import android.annotation.Nullable; |
| |
| import java.util.Arrays; |
| import java.util.UUID; |
| |
| /** @hide */ |
| class ConversionUtil { |
| public static SoundTrigger.ModuleProperties aidl2apiModuleDescriptor( |
| SoundTriggerModuleDescriptor aidlDesc) { |
| SoundTriggerModuleProperties properties = aidlDesc.properties; |
| return new SoundTrigger.ModuleProperties( |
| aidlDesc.handle, |
| properties.implementor, |
| properties.description, |
| properties.uuid, |
| properties.version, |
| properties.maxSoundModels, |
| properties.maxKeyPhrases, |
| properties.maxUsers, |
| aidl2apiRecognitionModes(properties.recognitionModes), |
| properties.captureTransition, |
| properties.maxBufferMs, |
| properties.concurrentCapture, |
| properties.powerConsumptionMw, |
| properties.triggerInEvent |
| ); |
| } |
| |
| public static int aidl2apiRecognitionModes(int aidlModes) { |
| int result = 0; |
| if ((aidlModes & RecognitionMode.VOICE_TRIGGER) != 0) { |
| result |= SoundTrigger.RECOGNITION_MODE_VOICE_TRIGGER; |
| } |
| if ((aidlModes & RecognitionMode.USER_IDENTIFICATION) != 0) { |
| result |= SoundTrigger.RECOGNITION_MODE_USER_IDENTIFICATION; |
| } |
| if ((aidlModes & RecognitionMode.USER_AUTHENTICATION) != 0) { |
| result |= SoundTrigger.RECOGNITION_MODE_USER_AUTHENTICATION; |
| } |
| if ((aidlModes & RecognitionMode.GENERIC_TRIGGER) != 0) { |
| result |= SoundTrigger.RECOGNITION_MODE_GENERIC; |
| } |
| return result; |
| } |
| |
| public static int api2aidlRecognitionModes(int apiModes) { |
| int result = 0; |
| if ((apiModes & SoundTrigger.RECOGNITION_MODE_VOICE_TRIGGER) != 0) { |
| result |= RecognitionMode.VOICE_TRIGGER; |
| } |
| if ((apiModes & SoundTrigger.RECOGNITION_MODE_USER_IDENTIFICATION) != 0) { |
| result |= RecognitionMode.USER_IDENTIFICATION; |
| } |
| if ((apiModes & SoundTrigger.RECOGNITION_MODE_USER_AUTHENTICATION) != 0) { |
| result |= RecognitionMode.USER_AUTHENTICATION; |
| } |
| if ((apiModes & SoundTrigger.RECOGNITION_MODE_GENERIC) != 0) { |
| result |= RecognitionMode.GENERIC_TRIGGER; |
| } |
| return result; |
| } |
| |
| |
| public static SoundModel api2aidlGenericSoundModel(SoundTrigger.GenericSoundModel apiModel) { |
| return api2aidlSoundModel(apiModel); |
| } |
| |
| public static SoundModel api2aidlSoundModel(SoundTrigger.SoundModel apiModel) { |
| SoundModel aidlModel = new SoundModel(); |
| aidlModel.type = apiModel.type; |
| aidlModel.uuid = api2aidlUuid(apiModel.uuid); |
| aidlModel.vendorUuid = api2aidlUuid(apiModel.vendorUuid); |
| aidlModel.data = Arrays.copyOf(apiModel.data, apiModel.data.length); |
| return aidlModel; |
| } |
| |
| public static String api2aidlUuid(UUID apiUuid) { |
| return apiUuid.toString(); |
| } |
| |
| public static PhraseSoundModel api2aidlPhraseSoundModel( |
| SoundTrigger.KeyphraseSoundModel apiModel) { |
| PhraseSoundModel aidlModel = new PhraseSoundModel(); |
| aidlModel.common = api2aidlSoundModel(apiModel); |
| aidlModel.phrases = new Phrase[apiModel.keyphrases.length]; |
| for (int i = 0; i < apiModel.keyphrases.length; ++i) { |
| aidlModel.phrases[i] = api2aidlPhrase(apiModel.keyphrases[i]); |
| } |
| return aidlModel; |
| } |
| |
| public static Phrase api2aidlPhrase(SoundTrigger.Keyphrase apiPhrase) { |
| Phrase aidlPhrase = new Phrase(); |
| aidlPhrase.id = apiPhrase.id; |
| aidlPhrase.recognitionModes = api2aidlRecognitionModes(apiPhrase.recognitionModes); |
| aidlPhrase.users = Arrays.copyOf(apiPhrase.users, apiPhrase.users.length); |
| aidlPhrase.locale = apiPhrase.locale; |
| aidlPhrase.text = apiPhrase.text; |
| return aidlPhrase; |
| } |
| |
| public static RecognitionConfig api2aidlRecognitionConfig( |
| SoundTrigger.RecognitionConfig apiConfig) { |
| RecognitionConfig aidlConfig = new RecognitionConfig(); |
| aidlConfig.captureRequested = apiConfig.captureRequested; |
| // apiConfig.allowMultipleTriggers is ignored by the lower layers. |
| aidlConfig.phraseRecognitionExtras = |
| new PhraseRecognitionExtra[apiConfig.keyphrases.length]; |
| for (int i = 0; i < apiConfig.keyphrases.length; ++i) { |
| aidlConfig.phraseRecognitionExtras[i] = api2aidlPhraseRecognitionExtra( |
| apiConfig.keyphrases[i]); |
| } |
| aidlConfig.data = Arrays.copyOf(apiConfig.data, apiConfig.data.length); |
| return aidlConfig; |
| } |
| |
| public static PhraseRecognitionExtra api2aidlPhraseRecognitionExtra( |
| SoundTrigger.KeyphraseRecognitionExtra apiExtra) { |
| PhraseRecognitionExtra aidlExtra = new PhraseRecognitionExtra(); |
| aidlExtra.id = apiExtra.id; |
| aidlExtra.recognitionModes = api2aidlRecognitionModes(apiExtra.recognitionModes); |
| aidlExtra.confidenceLevel = apiExtra.coarseConfidenceLevel; |
| aidlExtra.levels = new ConfidenceLevel[apiExtra.confidenceLevels.length]; |
| for (int i = 0; i < apiExtra.confidenceLevels.length; ++i) { |
| aidlExtra.levels[i] = api2aidlConfidenceLevel(apiExtra.confidenceLevels[i]); |
| } |
| return aidlExtra; |
| } |
| |
| public static SoundTrigger.KeyphraseRecognitionExtra aidl2apiPhraseRecognitionExtra( |
| PhraseRecognitionExtra aidlExtra) { |
| SoundTrigger.ConfidenceLevel[] apiLevels = |
| new SoundTrigger.ConfidenceLevel[aidlExtra.levels.length]; |
| for (int i = 0; i < aidlExtra.levels.length; ++i) { |
| apiLevels[i] = aidl2apiConfidenceLevel(aidlExtra.levels[i]); |
| } |
| return new SoundTrigger.KeyphraseRecognitionExtra(aidlExtra.id, |
| aidl2apiRecognitionModes(aidlExtra.recognitionModes), |
| aidlExtra.confidenceLevel, apiLevels); |
| } |
| |
| public static ConfidenceLevel api2aidlConfidenceLevel( |
| SoundTrigger.ConfidenceLevel apiLevel) { |
| ConfidenceLevel aidlLevel = new ConfidenceLevel(); |
| aidlLevel.levelPercent = apiLevel.confidenceLevel; |
| aidlLevel.userId = apiLevel.userId; |
| return aidlLevel; |
| } |
| |
| public static SoundTrigger.ConfidenceLevel aidl2apiConfidenceLevel( |
| ConfidenceLevel apiLevel) { |
| return new SoundTrigger.ConfidenceLevel(apiLevel.userId, apiLevel.levelPercent); |
| } |
| |
| public static SoundTrigger.RecognitionEvent aidl2apiRecognitionEvent( |
| int modelHandle, RecognitionEvent aidlEvent) { |
| return new SoundTrigger.GenericRecognitionEvent( |
| aidlEvent.status, |
| modelHandle, aidlEvent.captureAvailable, aidlEvent.captureSession, |
| aidlEvent.captureDelayMs, aidlEvent.capturePreambleMs, aidlEvent.triggerInData, |
| aidl2apiAudioFormat(aidlEvent.audioConfig), aidlEvent.data); |
| } |
| |
| public static SoundTrigger.RecognitionEvent aidl2apiPhraseRecognitionEvent( |
| int modelHandle, |
| PhraseRecognitionEvent aidlEvent) { |
| SoundTrigger.KeyphraseRecognitionExtra[] apiExtras = |
| new SoundTrigger.KeyphraseRecognitionExtra[aidlEvent.phraseExtras.length]; |
| for (int i = 0; i < aidlEvent.phraseExtras.length; ++i) { |
| apiExtras[i] = aidl2apiPhraseRecognitionExtra(aidlEvent.phraseExtras[i]); |
| } |
| return new SoundTrigger.KeyphraseRecognitionEvent(aidlEvent.common.status, modelHandle, |
| aidlEvent.common.captureAvailable, |
| aidlEvent.common.captureSession, aidlEvent.common.captureDelayMs, |
| aidlEvent.common.capturePreambleMs, aidlEvent.common.triggerInData, |
| aidl2apiAudioFormat(aidlEvent.common.audioConfig), aidlEvent.common.data, |
| apiExtras); |
| } |
| |
| public static AudioFormat aidl2apiAudioFormat(AudioConfig audioConfig) { |
| AudioFormat.Builder apiBuilder = new AudioFormat.Builder(); |
| apiBuilder.setSampleRate(audioConfig.sampleRateHz); |
| apiBuilder.setChannelMask(aidl2apiChannelInMask(audioConfig.channelMask)); |
| apiBuilder.setEncoding(aidl2apiEncoding(audioConfig.format)); |
| return apiBuilder.build(); |
| } |
| |
| public static int aidl2apiEncoding(int aidlFormat) { |
| switch (aidlFormat) { |
| case android.media.audio.common.AudioFormat.PCM |
| | android.media.audio.common.AudioFormat.PCM_SUB_16_BIT: |
| return AudioFormat.ENCODING_PCM_16BIT; |
| |
| case android.media.audio.common.AudioFormat.PCM |
| | android.media.audio.common.AudioFormat.PCM_SUB_8_BIT: |
| return AudioFormat.ENCODING_PCM_8BIT; |
| |
| case android.media.audio.common.AudioFormat.PCM |
| | android.media.audio.common.AudioFormat.PCM_SUB_FLOAT: |
| case android.media.audio.common.AudioFormat.PCM |
| | android.media.audio.common.AudioFormat.PCM_SUB_8_24_BIT: |
| case android.media.audio.common.AudioFormat.PCM |
| | android.media.audio.common.AudioFormat.PCM_SUB_24_BIT_PACKED: |
| case android.media.audio.common.AudioFormat.PCM |
| | android.media.audio.common.AudioFormat.PCM_SUB_32_BIT: |
| return AudioFormat.ENCODING_PCM_FLOAT; |
| |
| case android.media.audio.common.AudioFormat.AC3: |
| return AudioFormat.ENCODING_AC3; |
| |
| case android.media.audio.common.AudioFormat.E_AC3: |
| return AudioFormat.ENCODING_E_AC3; |
| |
| case android.media.audio.common.AudioFormat.DTS: |
| return AudioFormat.ENCODING_DTS; |
| |
| case android.media.audio.common.AudioFormat.DTS_HD: |
| return AudioFormat.ENCODING_DTS_HD; |
| |
| case android.media.audio.common.AudioFormat.MP3: |
| return AudioFormat.ENCODING_MP3; |
| |
| case android.media.audio.common.AudioFormat.AAC |
| | android.media.audio.common.AudioFormat.AAC_SUB_LC: |
| return AudioFormat.ENCODING_AAC_LC; |
| |
| case android.media.audio.common.AudioFormat.AAC |
| | android.media.audio.common.AudioFormat.AAC_SUB_HE_V1: |
| return AudioFormat.ENCODING_AAC_HE_V1; |
| |
| case android.media.audio.common.AudioFormat.AAC |
| | android.media.audio.common.AudioFormat.AAC_SUB_HE_V2: |
| return AudioFormat.ENCODING_AAC_HE_V2; |
| |
| case android.media.audio.common.AudioFormat.IEC61937: |
| return AudioFormat.ENCODING_IEC61937; |
| |
| case android.media.audio.common.AudioFormat.DOLBY_TRUEHD: |
| return AudioFormat.ENCODING_DOLBY_TRUEHD; |
| |
| case android.media.audio.common.AudioFormat.AAC |
| | android.media.audio.common.AudioFormat.AAC_SUB_ELD: |
| return AudioFormat.ENCODING_AAC_ELD; |
| |
| case android.media.audio.common.AudioFormat.AAC |
| | android.media.audio.common.AudioFormat.AAC_SUB_XHE: |
| return AudioFormat.ENCODING_AAC_XHE; |
| |
| case android.media.audio.common.AudioFormat.AC4: |
| return AudioFormat.ENCODING_AC4; |
| |
| case android.media.audio.common.AudioFormat.E_AC3 |
| | android.media.audio.common.AudioFormat.E_AC3_SUB_JOC: |
| return AudioFormat.ENCODING_E_AC3_JOC; |
| |
| case android.media.audio.common.AudioFormat.MAT: |
| case android.media.audio.common.AudioFormat.MAT |
| | android.media.audio.common.AudioFormat.MAT_SUB_1_0: |
| case android.media.audio.common.AudioFormat.MAT |
| | android.media.audio.common.AudioFormat.MAT_SUB_2_0: |
| case android.media.audio.common.AudioFormat.MAT |
| | android.media.audio.common.AudioFormat.MAT_SUB_2_1: |
| return AudioFormat.ENCODING_DOLBY_MAT; |
| |
| case android.media.audio.common.AudioFormat.DEFAULT: |
| return AudioFormat.ENCODING_DEFAULT; |
| |
| default: |
| return AudioFormat.ENCODING_INVALID; |
| } |
| } |
| |
| public static int api2aidlModelParameter(int apiParam) { |
| switch (apiParam) { |
| case ModelParams.THRESHOLD_FACTOR: |
| return android.media.soundtrigger_middleware.ModelParameter.THRESHOLD_FACTOR; |
| default: |
| return android.media.soundtrigger_middleware.ModelParameter.INVALID; |
| } |
| } |
| |
| public static int aidl2apiChannelInMask(int aidlMask) { |
| // We're assuming AudioFormat.CHANNEL_IN_* constants are kept in sync with |
| // android.media.audio.common.AudioChannelMask. |
| return aidlMask; |
| } |
| |
| public static SoundTrigger.ModelParamRange aidl2apiModelParameterRange( |
| @Nullable ModelParameterRange aidlRange) { |
| if (aidlRange == null) { |
| return null; |
| } |
| return new SoundTrigger.ModelParamRange(aidlRange.minInclusive, aidlRange.maxInclusive); |
| } |
| } |