/* * 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 com.android.server.soundtrigger_middleware; import android.annotation.Nullable; import android.media.soundtrigger.ConfidenceLevel; import android.media.soundtrigger.ModelParameter; import android.media.soundtrigger.Phrase; import android.media.soundtrigger.PhraseRecognitionExtra; import android.media.soundtrigger.PhraseSoundModel; import android.media.soundtrigger.RecognitionConfig; import android.media.soundtrigger.RecognitionMode; import android.media.soundtrigger.SoundModel; import android.media.soundtrigger.SoundModelType; import java.util.Objects; import java.util.regex.Matcher; /** * Utilities for asserting the validity of various data types used by this module. * Each of the methods below would throw an {@link IllegalArgumentException} if its input is * invalid. The input's validity is determined irrespective of any context. In cases where the valid * value space is further limited by state, it is the caller's responsibility to assert. * * @hide */ public class ValidationUtil { static void validateUuid(@Nullable String uuid) { Objects.requireNonNull(uuid); Matcher matcher = UuidUtil.PATTERN.matcher(uuid); if (!matcher.matches()) { throw new IllegalArgumentException( "Illegal format for UUID: " + uuid); } } static void validateGenericModel(@Nullable SoundModel model) { validateModel(model, SoundModelType.GENERIC); } static void validateModel(@Nullable SoundModel model, int expectedType) { Objects.requireNonNull(model); if (model.type != expectedType) { throw new IllegalArgumentException("Invalid type"); } validateUuid(model.uuid); validateUuid(model.vendorUuid); if (model.dataSize > 0) { Objects.requireNonNull(model.data); } } static void validatePhraseModel(@Nullable PhraseSoundModel model) { Objects.requireNonNull(model); validateModel(model.common, SoundModelType.KEYPHRASE); Objects.requireNonNull(model.phrases); for (Phrase phrase : model.phrases) { Objects.requireNonNull(phrase); if ((phrase.recognitionModes & ~(RecognitionMode.VOICE_TRIGGER | RecognitionMode.USER_IDENTIFICATION | RecognitionMode.USER_AUTHENTICATION | RecognitionMode.GENERIC_TRIGGER)) != 0) { throw new IllegalArgumentException("Invalid recognitionModes"); } Objects.requireNonNull(phrase.users); Objects.requireNonNull(phrase.locale); Objects.requireNonNull(phrase.text); } } static void validateRecognitionConfig(@Nullable RecognitionConfig config) { Objects.requireNonNull(config); Objects.requireNonNull(config.phraseRecognitionExtras); for (PhraseRecognitionExtra extra : config.phraseRecognitionExtras) { Objects.requireNonNull(extra); if ((extra.recognitionModes & ~(RecognitionMode.VOICE_TRIGGER | RecognitionMode.USER_IDENTIFICATION | RecognitionMode.USER_AUTHENTICATION | RecognitionMode.GENERIC_TRIGGER)) != 0) { throw new IllegalArgumentException("Invalid recognitionModes"); } if (extra.confidenceLevel < 0 || extra.confidenceLevel > 100) { throw new IllegalArgumentException("Invalid confidenceLevel"); } Objects.requireNonNull(extra.levels); for (ConfidenceLevel level : extra.levels) { Objects.requireNonNull(level); if (level.levelPercent < 0 || level.levelPercent > 100) { throw new IllegalArgumentException("Invalid confidenceLevel"); } } } Objects.requireNonNull(config.data); } static void validateModelParameter(int modelParam) { switch (modelParam) { case ModelParameter.THRESHOLD_FACTOR: return; default: throw new IllegalArgumentException("Invalid model parameter"); } } }