1 /*
2 * Copyright 2017 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
18 #define LOG_TAG "AAudioStreamParameters"
19 #include <utils/Log.h>
20 #include <system/audio.h>
21
22 #include "AAudioStreamParameters.h"
23
24 using namespace aaudio;
25
26 // TODO These defines should be moved to a central place in audio.
27 #define SAMPLES_PER_FRAME_MIN 1
28 #define SAMPLES_PER_FRAME_MAX FCC_LIMIT
29 #define SAMPLE_RATE_HZ_MIN 8000
30 // HDMI supports up to 32 channels at 1536000 Hz.
31 #define SAMPLE_RATE_HZ_MAX 1600000
32
copyFrom(const AAudioStreamParameters & other)33 void AAudioStreamParameters::copyFrom(const AAudioStreamParameters &other) {
34 mSamplesPerFrame = other.mSamplesPerFrame;
35 mSampleRate = other.mSampleRate;
36 mDeviceId = other.mDeviceId;
37 mSessionId = other.mSessionId;
38 mSharingMode = other.mSharingMode;
39 mAudioFormat = other.mAudioFormat;
40 mDirection = other.mDirection;
41 mBufferCapacity = other.mBufferCapacity;
42 mUsage = other.mUsage;
43 mContentType = other.mContentType;
44 mSpatializationBehavior = other.mSpatializationBehavior;
45 mIsContentSpatialized = other.mIsContentSpatialized;
46 mInputPreset = other.mInputPreset;
47 mAllowedCapturePolicy = other.mAllowedCapturePolicy;
48 mIsPrivacySensitive = other.mIsPrivacySensitive;
49 mOpPackageName = other.mOpPackageName;
50 mAttributionTag = other.mAttributionTag;
51 mChannelMask = other.mChannelMask;
52 }
53
isFormatValid(audio_format_t format)54 static aaudio_result_t isFormatValid(audio_format_t format) {
55 switch (format) {
56 case AUDIO_FORMAT_DEFAULT:
57 case AUDIO_FORMAT_PCM_16_BIT:
58 case AUDIO_FORMAT_PCM_32_BIT:
59 case AUDIO_FORMAT_PCM_FLOAT:
60 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
61 break; // valid
62 default:
63 ALOGD("audioFormat not valid, audio_format_t = 0x%08x", format);
64 return AAUDIO_ERROR_INVALID_FORMAT;
65 // break;
66 }
67 return AAUDIO_OK;
68 }
69
validate() const70 aaudio_result_t AAudioStreamParameters::validate() const {
71 if (mSamplesPerFrame != AAUDIO_UNSPECIFIED
72 && (mSamplesPerFrame < SAMPLES_PER_FRAME_MIN || mSamplesPerFrame > SAMPLES_PER_FRAME_MAX)) {
73 ALOGD("channelCount out of range = %d", mSamplesPerFrame);
74 return AAUDIO_ERROR_OUT_OF_RANGE;
75 }
76
77 if (mDeviceId < 0) {
78 ALOGD("deviceId out of range = %d", mDeviceId);
79 return AAUDIO_ERROR_OUT_OF_RANGE;
80 }
81
82 // All Session ID values are legal.
83 switch (mSessionId) {
84 case AAUDIO_SESSION_ID_NONE:
85 case AAUDIO_SESSION_ID_ALLOCATE:
86 break;
87 default:
88 break;
89 }
90
91 switch (mSharingMode) {
92 case AAUDIO_SHARING_MODE_EXCLUSIVE:
93 case AAUDIO_SHARING_MODE_SHARED:
94 break;
95 default:
96 ALOGD("illegal sharingMode = %d", mSharingMode);
97 return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
98 // break;
99 }
100
101 aaudio_result_t result = isFormatValid (mAudioFormat);
102 if (result != AAUDIO_OK) return result;
103
104 if (mSampleRate != AAUDIO_UNSPECIFIED
105 && (mSampleRate < SAMPLE_RATE_HZ_MIN || mSampleRate > SAMPLE_RATE_HZ_MAX)) {
106 ALOGD("sampleRate out of range = %d", mSampleRate);
107 return AAUDIO_ERROR_INVALID_RATE;
108 }
109
110 if (mBufferCapacity < 0) {
111 ALOGD("bufferCapacity out of range = %d", mBufferCapacity);
112 return AAUDIO_ERROR_OUT_OF_RANGE;
113 }
114
115 switch (mDirection) {
116 case AAUDIO_DIRECTION_INPUT:
117 case AAUDIO_DIRECTION_OUTPUT:
118 break; // valid
119 default:
120 ALOGD("direction not valid = %d", mDirection);
121 return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
122 // break;
123 }
124
125 switch (mUsage) {
126 case AAUDIO_UNSPECIFIED:
127 case AAUDIO_USAGE_MEDIA:
128 case AAUDIO_USAGE_VOICE_COMMUNICATION:
129 case AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
130 case AAUDIO_USAGE_ALARM:
131 case AAUDIO_USAGE_NOTIFICATION:
132 case AAUDIO_USAGE_NOTIFICATION_RINGTONE:
133 case AAUDIO_USAGE_NOTIFICATION_EVENT:
134 case AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
135 case AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
136 case AAUDIO_USAGE_ASSISTANCE_SONIFICATION:
137 case AAUDIO_USAGE_GAME:
138 case AAUDIO_USAGE_ASSISTANT:
139 case AAUDIO_SYSTEM_USAGE_EMERGENCY:
140 case AAUDIO_SYSTEM_USAGE_SAFETY:
141 case AAUDIO_SYSTEM_USAGE_VEHICLE_STATUS:
142 case AAUDIO_SYSTEM_USAGE_ANNOUNCEMENT:
143 break; // valid
144 default:
145 ALOGD("usage not valid = %d", mUsage);
146 return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
147 // break;
148 }
149
150 switch (mContentType) {
151 case AAUDIO_UNSPECIFIED:
152 case AAUDIO_CONTENT_TYPE_MUSIC:
153 case AAUDIO_CONTENT_TYPE_MOVIE:
154 case AAUDIO_CONTENT_TYPE_SONIFICATION:
155 case AAUDIO_CONTENT_TYPE_SPEECH:
156 break; // valid
157 default:
158 ALOGD("content type not valid = %d", mContentType);
159 return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
160 // break;
161 }
162
163 switch (mSpatializationBehavior) {
164 case AAUDIO_UNSPECIFIED:
165 case AAUDIO_SPATIALIZATION_BEHAVIOR_AUTO:
166 case AAUDIO_SPATIALIZATION_BEHAVIOR_NEVER:
167 break; // valid
168 default:
169 ALOGD("spatialization behavior not valid = %d", mSpatializationBehavior);
170 return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
171 // break;
172 }
173
174 // no validation required for mIsContentSpatialized
175
176 switch (mInputPreset) {
177 case AAUDIO_UNSPECIFIED:
178 case AAUDIO_INPUT_PRESET_GENERIC:
179 case AAUDIO_INPUT_PRESET_CAMCORDER:
180 case AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION:
181 case AAUDIO_INPUT_PRESET_VOICE_RECOGNITION:
182 case AAUDIO_INPUT_PRESET_UNPROCESSED:
183 case AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE:
184 break; // valid
185 default:
186 ALOGD("input preset not valid = %d", mInputPreset);
187 return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
188 // break;
189 }
190
191 switch (mAllowedCapturePolicy) {
192 case AAUDIO_UNSPECIFIED:
193 case AAUDIO_ALLOW_CAPTURE_BY_ALL:
194 case AAUDIO_ALLOW_CAPTURE_BY_SYSTEM:
195 case AAUDIO_ALLOW_CAPTURE_BY_NONE:
196 break; // valid
197 default:
198 ALOGD("allowed capture policy not valid = %d", mAllowedCapturePolicy);
199 return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
200 // break;
201 }
202
203 return validateChannelMask();
204 }
205
validateChannelMask() const206 bool AAudioStreamParameters::validateChannelMask() const {
207 if (mChannelMask == AAUDIO_UNSPECIFIED) {
208 return AAUDIO_OK;
209 }
210
211 if (mChannelMask & AAUDIO_CHANNEL_BIT_INDEX) {
212 switch (mChannelMask) {
213 case AAUDIO_CHANNEL_INDEX_MASK_1:
214 case AAUDIO_CHANNEL_INDEX_MASK_2:
215 case AAUDIO_CHANNEL_INDEX_MASK_3:
216 case AAUDIO_CHANNEL_INDEX_MASK_4:
217 case AAUDIO_CHANNEL_INDEX_MASK_5:
218 case AAUDIO_CHANNEL_INDEX_MASK_6:
219 case AAUDIO_CHANNEL_INDEX_MASK_7:
220 case AAUDIO_CHANNEL_INDEX_MASK_8:
221 case AAUDIO_CHANNEL_INDEX_MASK_9:
222 case AAUDIO_CHANNEL_INDEX_MASK_10:
223 case AAUDIO_CHANNEL_INDEX_MASK_11:
224 case AAUDIO_CHANNEL_INDEX_MASK_12:
225 case AAUDIO_CHANNEL_INDEX_MASK_13:
226 case AAUDIO_CHANNEL_INDEX_MASK_14:
227 case AAUDIO_CHANNEL_INDEX_MASK_15:
228 case AAUDIO_CHANNEL_INDEX_MASK_16:
229 case AAUDIO_CHANNEL_INDEX_MASK_17:
230 case AAUDIO_CHANNEL_INDEX_MASK_18:
231 case AAUDIO_CHANNEL_INDEX_MASK_19:
232 case AAUDIO_CHANNEL_INDEX_MASK_20:
233 case AAUDIO_CHANNEL_INDEX_MASK_21:
234 case AAUDIO_CHANNEL_INDEX_MASK_22:
235 case AAUDIO_CHANNEL_INDEX_MASK_23:
236 case AAUDIO_CHANNEL_INDEX_MASK_24:
237 return AAUDIO_OK;
238 default:
239 ALOGD("Invalid channel index mask %#x", mChannelMask);
240 return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
241 }
242 }
243
244 if (getDirection() == AAUDIO_DIRECTION_INPUT) {
245 switch (mChannelMask) {
246 case AAUDIO_CHANNEL_MONO:
247 case AAUDIO_CHANNEL_STEREO:
248 case AAUDIO_CHANNEL_FRONT_BACK:
249 case AAUDIO_CHANNEL_2POINT0POINT2:
250 case AAUDIO_CHANNEL_2POINT1POINT2:
251 case AAUDIO_CHANNEL_3POINT0POINT2:
252 case AAUDIO_CHANNEL_3POINT1POINT2:
253 case AAUDIO_CHANNEL_5POINT1:
254 return AAUDIO_OK;
255 default:
256 ALOGD("Invalid channel mask %#x, IN", mChannelMask);
257 return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
258 }
259 } else {
260 switch (mChannelMask) {
261 case AAUDIO_CHANNEL_MONO:
262 case AAUDIO_CHANNEL_STEREO:
263 case AAUDIO_CHANNEL_2POINT1:
264 case AAUDIO_CHANNEL_TRI:
265 case AAUDIO_CHANNEL_TRI_BACK:
266 case AAUDIO_CHANNEL_3POINT1:
267 case AAUDIO_CHANNEL_2POINT0POINT2:
268 case AAUDIO_CHANNEL_2POINT1POINT2:
269 case AAUDIO_CHANNEL_3POINT0POINT2:
270 case AAUDIO_CHANNEL_3POINT1POINT2:
271 case AAUDIO_CHANNEL_QUAD:
272 case AAUDIO_CHANNEL_QUAD_SIDE:
273 case AAUDIO_CHANNEL_SURROUND:
274 case AAUDIO_CHANNEL_PENTA:
275 case AAUDIO_CHANNEL_5POINT1:
276 case AAUDIO_CHANNEL_5POINT1_SIDE:
277 case AAUDIO_CHANNEL_5POINT1POINT2:
278 case AAUDIO_CHANNEL_5POINT1POINT4:
279 case AAUDIO_CHANNEL_6POINT1:
280 case AAUDIO_CHANNEL_7POINT1:
281 case AAUDIO_CHANNEL_7POINT1POINT2:
282 case AAUDIO_CHANNEL_7POINT1POINT4:
283 case AAUDIO_CHANNEL_9POINT1POINT4:
284 case AAUDIO_CHANNEL_9POINT1POINT6:
285 return AAUDIO_OK;
286 default:
287 ALOGD("Invalid channel mask %#x. OUT", mChannelMask);
288 return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
289 }
290 }
291 }
292
dump() const293 void AAudioStreamParameters::dump() const {
294 ALOGD("mDeviceId = %6d", mDeviceId);
295 ALOGD("mSessionId = %6d", mSessionId);
296 ALOGD("mSampleRate = %6d", mSampleRate);
297 ALOGD("mSamplesPerFrame = %6d", mSamplesPerFrame);
298 ALOGD("mChannelMask = %#x", mChannelMask);
299 ALOGD("mSharingMode = %6d", (int)mSharingMode);
300 ALOGD("mAudioFormat = %6d", (int)mAudioFormat);
301 ALOGD("mDirection = %6d", mDirection);
302 ALOGD("mBufferCapacity = %6d", mBufferCapacity);
303 ALOGD("mUsage = %6d", mUsage);
304 ALOGD("mContentType = %6d", mContentType);
305 ALOGD("mSpatializationBehavior = %6d", mSpatializationBehavior);
306 ALOGD("mIsContentSpatialized = %s", mIsContentSpatialized ? "true" : "false");
307 ALOGD("mInputPreset = %6d", mInputPreset);
308 ALOGD("mAllowedCapturePolicy = %6d", mAllowedCapturePolicy);
309 ALOGD("mIsPrivacySensitive = %s", mIsPrivacySensitive ? "true" : "false");
310 ALOGD("mOpPackageName = %s", !mOpPackageName.has_value() ?
311 "(null)" : mOpPackageName.value().c_str());
312 ALOGD("mAttributionTag = %s", !mAttributionTag.has_value() ?
313 "(null)" : mAttributionTag.value().c_str());
314 }
315