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