• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #define LOG_TAG "AAudioTest"
18 
19 #include <sys/types.h>
20 #include <unistd.h>
21 
22 #include <android/log.h>
23 #include <gtest/gtest.h>
24 
25 #include "test_aaudio.h"
26 #include "utils.h"
27 
getNanoseconds(clockid_t clockId)28 int64_t getNanoseconds(clockid_t clockId) {
29     struct timespec time;
30     int result = clock_gettime(clockId, &time);
31     if (result < 0) {
32         return -errno;
33     }
34     return (time.tv_sec * NANOS_PER_SECOND) + time.tv_nsec;
35 }
36 
performanceModeToString(aaudio_performance_mode_t mode)37 const char* performanceModeToString(aaudio_performance_mode_t mode) {
38     switch (mode) {
39         case AAUDIO_PERFORMANCE_MODE_NONE: return "DEFAULT";
40         case AAUDIO_PERFORMANCE_MODE_POWER_SAVING: return "POWER_SAVING";
41         case AAUDIO_PERFORMANCE_MODE_LOW_LATENCY: return "LOW_LATENCY";
42     }
43     return "UNKNOWN";
44 }
45 
sharingModeToString(aaudio_sharing_mode_t mode)46 const char* sharingModeToString(aaudio_sharing_mode_t mode) {
47     switch (mode) {
48         case AAUDIO_SHARING_MODE_SHARED: return "SHARED";
49         case AAUDIO_SHARING_MODE_EXCLUSIVE: return "EXCLUSIVE";
50     }
51     return "UNKNOWN";
52 }
53 
54 
StreamBuilderHelper(aaudio_direction_t direction,int32_t sampleRate,int32_t channelCount,aaudio_format_t dataFormat,aaudio_sharing_mode_t sharingMode,aaudio_performance_mode_t perfMode)55 StreamBuilderHelper::StreamBuilderHelper(
56         aaudio_direction_t direction, int32_t sampleRate,
57         int32_t channelCount, aaudio_format_t dataFormat,
58         aaudio_sharing_mode_t sharingMode, aaudio_performance_mode_t perfMode)
59         : mDirection{direction},
60           mRequested{sampleRate, channelCount, dataFormat, sharingMode, perfMode},
61           mActual{0, 0, AAUDIO_FORMAT_INVALID, -1, -1}, mFramesPerBurst{-1},
62           mBuilder{nullptr}, mStream{nullptr} {}
63 
~StreamBuilderHelper()64 StreamBuilderHelper::~StreamBuilderHelper() {
65     close();
66 }
67 
initBuilder()68 void StreamBuilderHelper::initBuilder() {
69     // Use an AAudioStreamBuilder to define the stream.
70     aaudio_result_t result = AAudio_createStreamBuilder(&mBuilder);
71     ASSERT_EQ(AAUDIO_OK, result);
72     ASSERT_TRUE(mBuilder != nullptr);
73 
74     // Request stream properties.
75     AAudioStreamBuilder_setDeviceId(mBuilder, AAUDIO_UNSPECIFIED);
76     AAudioStreamBuilder_setDirection(mBuilder, mDirection);
77     AAudioStreamBuilder_setSampleRate(mBuilder, mRequested.sampleRate);
78     AAudioStreamBuilder_setChannelCount(mBuilder, mRequested.channelCount);
79     AAudioStreamBuilder_setFormat(mBuilder, mRequested.dataFormat);
80     AAudioStreamBuilder_setSharingMode(mBuilder, mRequested.sharingMode);
81     AAudioStreamBuilder_setPerformanceMode(mBuilder, mRequested.perfMode);
82 }
83 
84 // Needs to be a 'void' function due to ASSERT requirements.
createAndVerifyStream(bool * success)85 void StreamBuilderHelper::createAndVerifyStream(bool *success) {
86     *success = false;
87 
88     aaudio_result_t result = AAudioStreamBuilder_openStream(mBuilder, &mStream);
89     if (mRequested.sharingMode == AAUDIO_SHARING_MODE_EXCLUSIVE && result != AAUDIO_OK) {
90         __android_log_write(ANDROID_LOG_WARN, LOG_TAG, "Could not open a stream in EXCLUSIVE mode");
91         return;
92     }
93     ASSERT_EQ(AAUDIO_OK, result);
94     ASSERT_TRUE(mStream != nullptr);
95     ASSERT_EQ(AAUDIO_STREAM_STATE_OPEN, AAudioStream_getState(mStream));
96     ASSERT_EQ(mDirection, AAudioStream_getDirection(mStream));
97 
98     mActual.sharingMode = AAudioStream_getSharingMode(mStream);
99     if (mActual.sharingMode != mRequested.sharingMode) {
100         // Since we are covering all possible values, the "actual" mode
101         // will also be tested, so no need to run the same test twice.
102         __android_log_print(ANDROID_LOG_WARN, LOG_TAG, "Sharing mode %s is not available",
103                 sharingModeToString(mRequested.sharingMode));
104         return;
105     }
106 
107     // Check to see what kind of stream we actually got.
108     mActual.sampleRate = AAudioStream_getSampleRate(mStream);
109     ASSERT_GE(mActual.sampleRate, 44100);
110     ASSERT_LE(mActual.sampleRate, 96000); // TODO what is min/max?
111 
112     mActual.channelCount = AAudioStream_getChannelCount(mStream);
113     ASSERT_GE(mActual.channelCount, 1);
114     ASSERT_LE(mActual.channelCount, 16); // TODO what is min/max?
115 
116     mActual.dataFormat = AAudioStream_getFormat(mStream);
117     ASSERT_EQ(AAUDIO_FORMAT_PCM_I16, mActual.dataFormat);
118 
119     mActual.perfMode = AAudioStream_getPerformanceMode(mStream);
120     if (mRequested.perfMode != AAUDIO_PERFORMANCE_MODE_NONE
121             && mRequested.perfMode != mActual.perfMode) {
122         // Since we are covering all possible values, the "actual" mode
123         // will also be tested, so no need to run the same test twice.
124         __android_log_print(ANDROID_LOG_WARN, LOG_TAG, "Performance mode %s is not available",
125                 performanceModeToString(mRequested.sharingMode));
126         return;
127     }
128 
129     mFramesPerBurst = AAudioStream_getFramesPerBurst(mStream);
130     ASSERT_GE(mFramesPerBurst, 16);
131     ASSERT_LE(mFramesPerBurst, 3072); // on some devices, it can be 2052
132 
133     int32_t actualBufferSize = AAudioStream_getBufferSizeInFrames(mStream);
134     ASSERT_GT(actualBufferSize, 0);
135     ASSERT_GT(AAudioStream_setBufferSizeInFrames(mStream, actualBufferSize), 0);
136 
137     *success = true;
138 }
139 
close()140 void StreamBuilderHelper::close() {
141     if (mBuilder != nullptr) {
142         ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_delete(mBuilder));
143     }
144     if (mStream != nullptr) {
145         ASSERT_EQ(AAUDIO_OK, AAudioStream_close(mStream));
146     }
147 }
148 
streamCommand(StreamCommand cmd,aaudio_stream_state_t fromState,aaudio_stream_state_t toState)149 void StreamBuilderHelper::streamCommand(
150         StreamCommand cmd, aaudio_stream_state_t fromState, aaudio_stream_state_t toState) {
151     ASSERT_EQ(AAUDIO_OK, cmd(mStream));
152     aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNINITIALIZED;
153     ASSERT_EQ(AAUDIO_OK,
154             AAudioStream_waitForStateChange(mStream, fromState, &state, DEFAULT_STATE_TIMEOUT));
155     ASSERT_EQ(toState, state);
156 }
157 
158 
InputStreamBuilderHelper(aaudio_sharing_mode_t requestedSharingMode,aaudio_performance_mode_t requestedPerfMode)159 InputStreamBuilderHelper::InputStreamBuilderHelper(
160         aaudio_sharing_mode_t requestedSharingMode, aaudio_performance_mode_t requestedPerfMode)
161         : StreamBuilderHelper{AAUDIO_DIRECTION_INPUT,
162             48000, 1, AAUDIO_FORMAT_PCM_I16, requestedSharingMode, requestedPerfMode} {}
163 
164 // Native apps don't have permissions, thus recording can
165 // only be tested when running as root.
canTestRecording()166 static bool canTestRecording() {
167     static const bool runningAsRoot = getuid() == 0;
168     return runningAsRoot;
169 }
170 
createAndVerifyStream(bool * success)171 void InputStreamBuilderHelper::createAndVerifyStream(bool *success) {
172     if (!canTestRecording()) {
173         __android_log_write(ANDROID_LOG_WARN, LOG_TAG, "No permissions to run recording tests");
174         *success = false;
175     } else {
176         StreamBuilderHelper::createAndVerifyStream(success);
177     }
178 }
179 
180 
OutputStreamBuilderHelper(aaudio_sharing_mode_t requestedSharingMode,aaudio_performance_mode_t requestedPerfMode)181 OutputStreamBuilderHelper::OutputStreamBuilderHelper(
182         aaudio_sharing_mode_t requestedSharingMode, aaudio_performance_mode_t requestedPerfMode)
183         : StreamBuilderHelper{AAUDIO_DIRECTION_OUTPUT,
184             48000, 2, AAUDIO_FORMAT_PCM_I16, requestedSharingMode, requestedPerfMode} {}
185 
initBuilder()186 void OutputStreamBuilderHelper::initBuilder() {
187     StreamBuilderHelper::initBuilder();
188     AAudioStreamBuilder_setBufferCapacityInFrames(mBuilder, kBufferCapacityFrames);
189 }
190 
createAndVerifyStream(bool * success)191 void OutputStreamBuilderHelper::createAndVerifyStream(bool *success) {
192     StreamBuilderHelper::createAndVerifyStream(success);
193     if (*success) {
194         ASSERT_GE(AAudioStream_getBufferCapacityInFrames(mStream), kBufferCapacityFrames);
195     }
196 }
197