xref: /aosp_15_r20/frameworks/av/media/libmediahelper/AudioValidator.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker  * Copyright (C) 2020 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker  *
4*ec779b8eSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker  *
8*ec779b8eSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker  *
10*ec779b8eSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker  * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker  */
16*ec779b8eSAndroid Build Coastguard Worker 
17*ec779b8eSAndroid Build Coastguard Worker #include <media/AudioValidator.h>
18*ec779b8eSAndroid Build Coastguard Worker #include <cmath>
19*ec779b8eSAndroid Build Coastguard Worker 
20*ec779b8eSAndroid Build Coastguard Worker namespace android {
21*ec779b8eSAndroid Build Coastguard Worker 
22*ec779b8eSAndroid Build Coastguard Worker /** returns true if string is overflow */
23*ec779b8eSAndroid Build Coastguard Worker template <size_t size>
checkStringOverflow(const char (& s)[size])24*ec779b8eSAndroid Build Coastguard Worker bool checkStringOverflow(const char (&s)[size]) {
25*ec779b8eSAndroid Build Coastguard Worker     return strnlen(s, size) >= size;
26*ec779b8eSAndroid Build Coastguard Worker }
27*ec779b8eSAndroid Build Coastguard Worker 
safetyNetLog(status_t status,std::string_view bugNumber)28*ec779b8eSAndroid Build Coastguard Worker status_t safetyNetLog(status_t status, std::string_view bugNumber) {
29*ec779b8eSAndroid Build Coastguard Worker     if (status != NO_ERROR && !bugNumber.empty()) {
30*ec779b8eSAndroid Build Coastguard Worker         android_errorWriteLog(0x534e4554, bugNumber.data()); // SafetyNet logging
31*ec779b8eSAndroid Build Coastguard Worker     }
32*ec779b8eSAndroid Build Coastguard Worker     return status;
33*ec779b8eSAndroid Build Coastguard Worker }
34*ec779b8eSAndroid Build Coastguard Worker 
validateAudioAttributes(const audio_attributes_t & attr,std::string_view bugNumber)35*ec779b8eSAndroid Build Coastguard Worker status_t AudioValidator::validateAudioAttributes(
36*ec779b8eSAndroid Build Coastguard Worker         const audio_attributes_t& attr, std::string_view bugNumber)
37*ec779b8eSAndroid Build Coastguard Worker {
38*ec779b8eSAndroid Build Coastguard Worker     status_t status = NO_ERROR;
39*ec779b8eSAndroid Build Coastguard Worker     const size_t tagsMaxSize = AUDIO_ATTRIBUTES_TAGS_MAX_SIZE;
40*ec779b8eSAndroid Build Coastguard Worker     if (strnlen(attr.tags, tagsMaxSize) >= tagsMaxSize) {
41*ec779b8eSAndroid Build Coastguard Worker         status = BAD_VALUE;
42*ec779b8eSAndroid Build Coastguard Worker     }
43*ec779b8eSAndroid Build Coastguard Worker     return safetyNetLog(status, bugNumber);
44*ec779b8eSAndroid Build Coastguard Worker }
45*ec779b8eSAndroid Build Coastguard Worker 
validateEffectDescriptor(const effect_descriptor_t & desc,std::string_view bugNumber)46*ec779b8eSAndroid Build Coastguard Worker status_t AudioValidator::validateEffectDescriptor(
47*ec779b8eSAndroid Build Coastguard Worker         const effect_descriptor_t& desc, std::string_view bugNumber)
48*ec779b8eSAndroid Build Coastguard Worker {
49*ec779b8eSAndroid Build Coastguard Worker     status_t status = NO_ERROR;
50*ec779b8eSAndroid Build Coastguard Worker     if (checkStringOverflow(desc.name) || checkStringOverflow(desc.implementor)) {
51*ec779b8eSAndroid Build Coastguard Worker         status = BAD_VALUE;
52*ec779b8eSAndroid Build Coastguard Worker     }
53*ec779b8eSAndroid Build Coastguard Worker     return safetyNetLog(status, bugNumber);
54*ec779b8eSAndroid Build Coastguard Worker }
55*ec779b8eSAndroid Build Coastguard Worker 
validateAudioPortConfig(const struct audio_port_config & config,std::string_view bugNumber)56*ec779b8eSAndroid Build Coastguard Worker status_t AudioValidator::validateAudioPortConfig(
57*ec779b8eSAndroid Build Coastguard Worker         const struct audio_port_config& config, std::string_view bugNumber)
58*ec779b8eSAndroid Build Coastguard Worker {
59*ec779b8eSAndroid Build Coastguard Worker     status_t status = NO_ERROR;
60*ec779b8eSAndroid Build Coastguard Worker     if (config.type == AUDIO_PORT_TYPE_DEVICE &&
61*ec779b8eSAndroid Build Coastguard Worker         checkStringOverflow(config.ext.device.address)) {
62*ec779b8eSAndroid Build Coastguard Worker         status = BAD_VALUE;
63*ec779b8eSAndroid Build Coastguard Worker     }
64*ec779b8eSAndroid Build Coastguard Worker     return safetyNetLog(status, bugNumber);
65*ec779b8eSAndroid Build Coastguard Worker }
66*ec779b8eSAndroid Build Coastguard Worker 
67*ec779b8eSAndroid Build Coastguard Worker namespace {
68*ec779b8eSAndroid Build Coastguard Worker 
69*ec779b8eSAndroid Build Coastguard Worker template <typename T, std::enable_if_t<std::is_same<T, struct audio_port>::value
70*ec779b8eSAndroid Build Coastguard Worker                                     || std::is_same<T, struct audio_port_v7>::value, int> = 0>
validateAudioPortInternal(const T & port,std::string_view bugNumber={})71*ec779b8eSAndroid Build Coastguard Worker static status_t validateAudioPortInternal(const T& port, std::string_view bugNumber = {}) {
72*ec779b8eSAndroid Build Coastguard Worker     status_t status = NO_ERROR;
73*ec779b8eSAndroid Build Coastguard Worker     if (checkStringOverflow(port.name)) {
74*ec779b8eSAndroid Build Coastguard Worker         status = BAD_VALUE;
75*ec779b8eSAndroid Build Coastguard Worker     }
76*ec779b8eSAndroid Build Coastguard Worker     if (AudioValidator::validateAudioPortConfig(port.active_config) != NO_ERROR) {
77*ec779b8eSAndroid Build Coastguard Worker         status = BAD_VALUE;
78*ec779b8eSAndroid Build Coastguard Worker     }
79*ec779b8eSAndroid Build Coastguard Worker     if (port.type == AUDIO_PORT_TYPE_DEVICE &&
80*ec779b8eSAndroid Build Coastguard Worker         checkStringOverflow(port.ext.device.address)) {
81*ec779b8eSAndroid Build Coastguard Worker         status = BAD_VALUE;
82*ec779b8eSAndroid Build Coastguard Worker     }
83*ec779b8eSAndroid Build Coastguard Worker     return safetyNetLog(status, bugNumber);
84*ec779b8eSAndroid Build Coastguard Worker }
85*ec779b8eSAndroid Build Coastguard Worker 
86*ec779b8eSAndroid Build Coastguard Worker } // namespace
87*ec779b8eSAndroid Build Coastguard Worker 
validateAudioPort(const struct audio_port & port,std::string_view bugNumber)88*ec779b8eSAndroid Build Coastguard Worker status_t AudioValidator::validateAudioPort(
89*ec779b8eSAndroid Build Coastguard Worker         const struct audio_port& port, std::string_view bugNumber)
90*ec779b8eSAndroid Build Coastguard Worker {
91*ec779b8eSAndroid Build Coastguard Worker     return validateAudioPortInternal(port, bugNumber);
92*ec779b8eSAndroid Build Coastguard Worker }
93*ec779b8eSAndroid Build Coastguard Worker 
validateAudioPort(const struct audio_port_v7 & port,std::string_view bugNumber)94*ec779b8eSAndroid Build Coastguard Worker status_t AudioValidator::validateAudioPort(
95*ec779b8eSAndroid Build Coastguard Worker         const struct audio_port_v7& port, std::string_view bugNumber)
96*ec779b8eSAndroid Build Coastguard Worker {
97*ec779b8eSAndroid Build Coastguard Worker     return validateAudioPortInternal(port, bugNumber);
98*ec779b8eSAndroid Build Coastguard Worker }
99*ec779b8eSAndroid Build Coastguard Worker 
100*ec779b8eSAndroid Build Coastguard Worker /** returns BAD_VALUE if sanitization was required. */
validateAudioPatch(const struct audio_patch & patch,std::string_view bugNumber)101*ec779b8eSAndroid Build Coastguard Worker status_t AudioValidator::validateAudioPatch(
102*ec779b8eSAndroid Build Coastguard Worker         const struct audio_patch& patch, std::string_view bugNumber)
103*ec779b8eSAndroid Build Coastguard Worker {
104*ec779b8eSAndroid Build Coastguard Worker     status_t status = NO_ERROR;
105*ec779b8eSAndroid Build Coastguard Worker     if (patch.num_sources > AUDIO_PATCH_PORTS_MAX) {
106*ec779b8eSAndroid Build Coastguard Worker         status = BAD_VALUE;
107*ec779b8eSAndroid Build Coastguard Worker     }
108*ec779b8eSAndroid Build Coastguard Worker     if (patch.num_sinks > AUDIO_PATCH_PORTS_MAX) {
109*ec779b8eSAndroid Build Coastguard Worker         status = BAD_VALUE;
110*ec779b8eSAndroid Build Coastguard Worker     }
111*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < patch.num_sources; i++) {
112*ec779b8eSAndroid Build Coastguard Worker         if (validateAudioPortConfig(patch.sources[i]) != NO_ERROR) {
113*ec779b8eSAndroid Build Coastguard Worker             status = BAD_VALUE;
114*ec779b8eSAndroid Build Coastguard Worker         }
115*ec779b8eSAndroid Build Coastguard Worker     }
116*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < patch.num_sinks; i++) {
117*ec779b8eSAndroid Build Coastguard Worker         if (validateAudioPortConfig(patch.sinks[i]) != NO_ERROR) {
118*ec779b8eSAndroid Build Coastguard Worker             status = BAD_VALUE;
119*ec779b8eSAndroid Build Coastguard Worker         }
120*ec779b8eSAndroid Build Coastguard Worker     }
121*ec779b8eSAndroid Build Coastguard Worker     return safetyNetLog(status, bugNumber);
122*ec779b8eSAndroid Build Coastguard Worker }
123*ec779b8eSAndroid Build Coastguard Worker 
124*ec779b8eSAndroid Build Coastguard Worker /* static */
validateAudioDescriptionMixLevel(float leveldB)125*ec779b8eSAndroid Build Coastguard Worker status_t AudioValidator::validateAudioDescriptionMixLevel(float leveldB)
126*ec779b8eSAndroid Build Coastguard Worker {
127*ec779b8eSAndroid Build Coastguard Worker     constexpr float MAX_AUDIO_DESCRIPTION_MIX_LEVEL = 48.f;
128*ec779b8eSAndroid Build Coastguard Worker     return std::isnan(leveldB) || leveldB > MAX_AUDIO_DESCRIPTION_MIX_LEVEL ? BAD_VALUE : OK;
129*ec779b8eSAndroid Build Coastguard Worker }
130*ec779b8eSAndroid Build Coastguard Worker 
131*ec779b8eSAndroid Build Coastguard Worker /* static */
validateDualMonoMode(audio_dual_mono_mode_t dualMonoMode)132*ec779b8eSAndroid Build Coastguard Worker status_t AudioValidator::validateDualMonoMode(audio_dual_mono_mode_t dualMonoMode)
133*ec779b8eSAndroid Build Coastguard Worker {
134*ec779b8eSAndroid Build Coastguard Worker     switch (dualMonoMode) {
135*ec779b8eSAndroid Build Coastguard Worker         case AUDIO_DUAL_MONO_MODE_OFF:
136*ec779b8eSAndroid Build Coastguard Worker         case AUDIO_DUAL_MONO_MODE_LR:
137*ec779b8eSAndroid Build Coastguard Worker         case AUDIO_DUAL_MONO_MODE_LL:
138*ec779b8eSAndroid Build Coastguard Worker         case AUDIO_DUAL_MONO_MODE_RR:
139*ec779b8eSAndroid Build Coastguard Worker         return OK;
140*ec779b8eSAndroid Build Coastguard Worker     }
141*ec779b8eSAndroid Build Coastguard Worker     return BAD_VALUE;
142*ec779b8eSAndroid Build Coastguard Worker }
143*ec779b8eSAndroid Build Coastguard Worker 
144*ec779b8eSAndroid Build Coastguard Worker /* static */
validatePlaybackRateFallbackMode(audio_timestretch_fallback_mode_t fallbackMode)145*ec779b8eSAndroid Build Coastguard Worker status_t AudioValidator::validatePlaybackRateFallbackMode(
146*ec779b8eSAndroid Build Coastguard Worker         audio_timestretch_fallback_mode_t fallbackMode)
147*ec779b8eSAndroid Build Coastguard Worker {
148*ec779b8eSAndroid Build Coastguard Worker     switch (fallbackMode) {
149*ec779b8eSAndroid Build Coastguard Worker         case AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT:
150*ec779b8eSAndroid Build Coastguard Worker             // This is coarse sounding timestretching used for internal debugging,
151*ec779b8eSAndroid Build Coastguard Worker             // not intended for general use.
152*ec779b8eSAndroid Build Coastguard Worker             break; // warning if not listed.
153*ec779b8eSAndroid Build Coastguard Worker         case AUDIO_TIMESTRETCH_FALLBACK_DEFAULT:
154*ec779b8eSAndroid Build Coastguard Worker         case AUDIO_TIMESTRETCH_FALLBACK_MUTE:
155*ec779b8eSAndroid Build Coastguard Worker         case AUDIO_TIMESTRETCH_FALLBACK_FAIL:
156*ec779b8eSAndroid Build Coastguard Worker             return OK;
157*ec779b8eSAndroid Build Coastguard Worker     }
158*ec779b8eSAndroid Build Coastguard Worker     return BAD_VALUE;
159*ec779b8eSAndroid Build Coastguard Worker }
160*ec779b8eSAndroid Build Coastguard Worker 
161*ec779b8eSAndroid Build Coastguard Worker /* static */
validatePlaybackRateStretchMode(audio_timestretch_stretch_mode_t stretchMode)162*ec779b8eSAndroid Build Coastguard Worker status_t AudioValidator::validatePlaybackRateStretchMode(
163*ec779b8eSAndroid Build Coastguard Worker         audio_timestretch_stretch_mode_t stretchMode)
164*ec779b8eSAndroid Build Coastguard Worker {
165*ec779b8eSAndroid Build Coastguard Worker     switch (stretchMode) {
166*ec779b8eSAndroid Build Coastguard Worker         case AUDIO_TIMESTRETCH_STRETCH_DEFAULT:
167*ec779b8eSAndroid Build Coastguard Worker         case AUDIO_TIMESTRETCH_STRETCH_VOICE:
168*ec779b8eSAndroid Build Coastguard Worker             return OK;
169*ec779b8eSAndroid Build Coastguard Worker     }
170*ec779b8eSAndroid Build Coastguard Worker     return BAD_VALUE;
171*ec779b8eSAndroid Build Coastguard Worker }
172*ec779b8eSAndroid Build Coastguard Worker 
173*ec779b8eSAndroid Build Coastguard Worker /* static */
validatePlaybackRate(const audio_playback_rate_t & playbackRate)174*ec779b8eSAndroid Build Coastguard Worker status_t AudioValidator::validatePlaybackRate(
175*ec779b8eSAndroid Build Coastguard Worker         const audio_playback_rate_t& playbackRate)
176*ec779b8eSAndroid Build Coastguard Worker {
177*ec779b8eSAndroid Build Coastguard Worker     if (playbackRate.mSpeed < 0.f || playbackRate.mPitch < 0.f) return BAD_VALUE;
178*ec779b8eSAndroid Build Coastguard Worker     return validatePlaybackRateFallbackMode(playbackRate.mFallbackMode) ?:
179*ec779b8eSAndroid Build Coastguard Worker             validatePlaybackRateStretchMode(playbackRate.mStretchMode);
180*ec779b8eSAndroid Build Coastguard Worker }
181*ec779b8eSAndroid Build Coastguard Worker 
182*ec779b8eSAndroid Build Coastguard Worker }; // namespace android
183