1 /*
2  * Copyright (C) 2018 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 // Test AAudio SessionId, which is used to associate Effects with a stream
18 
19 #include <stdio.h>
20 #include <unistd.h>
21 
22 #include <aaudio/AAudio.h>
23 #include <gtest/gtest.h>
24 
25 #include "test_aaudio.h"
26 
27 constexpr int kNumFrames = 256;
28 constexpr int kChannelCount = 2;
29 
30 // Test AAUDIO_SESSION_ID_NONE default
checkSessionIdNone(aaudio_performance_mode_t perfMode)31 static void checkSessionIdNone(aaudio_performance_mode_t perfMode) {
32 
33     float *buffer = new float[kNumFrames * kChannelCount];
34 
35     AAudioStreamBuilder *aaudioBuilder = nullptr;
36 
37     AAudioStream *aaudioStream1 = nullptr;
38     int32_t       sessionId1 = 0;
39 
40     // Use an AAudioStreamBuilder to contain requested parameters.
41     ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
42 
43     // Request stream properties.
44     AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
45 
46     // Create an AAudioStream using the Builder.
47     ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream1));
48 
49     // Since we did not request or specify a SessionID, we should get NONE
50     sessionId1 = AAudioStream_getSessionId(aaudioStream1);
51     ASSERT_EQ(AAUDIO_SESSION_ID_NONE, sessionId1);
52 
53     ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream1));
54 
55     ASSERT_EQ(kNumFrames, AAudioStream_write(aaudioStream1, buffer, kNumFrames, NANOS_PER_SECOND));
56 
57     EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream1));
58 
59     EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream1));
60     delete[] buffer;
61     AAudioStreamBuilder_delete(aaudioBuilder);
62 }
63 
TEST(test_session_id,aaudio_session_id_none_perfnone)64 TEST(test_session_id, aaudio_session_id_none_perfnone) {
65     checkSessionIdNone(AAUDIO_PERFORMANCE_MODE_NONE);
66 }
67 
TEST(test_session_id,aaudio_session_id_none_lowlat)68 TEST(test_session_id, aaudio_session_id_none_lowlat) {
69     checkSessionIdNone(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
70 }
71 
72 // Test AAUDIO_SESSION_ID_ALLOCATE
checkSessionIdAllocate(aaudio_performance_mode_t perfMode,aaudio_direction_t direction)73 static void checkSessionIdAllocate(aaudio_performance_mode_t perfMode,
74                                    aaudio_direction_t direction) {
75 
76     float *buffer = new float[kNumFrames * kChannelCount];
77 
78     AAudioStreamBuilder *aaudioBuilder = nullptr;
79 
80     AAudioStream *aaudioStream1 = nullptr;
81     int32_t       sessionId1 = 0;
82     AAudioStream *aaudioStream2 = nullptr;
83     int32_t       sessionId2 = 0;
84 
85     // Use an AAudioStreamBuilder to contain requested parameters.
86     ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
87 
88     // Request stream properties.
89     AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
90     // This stream could be input or output.
91     AAudioStreamBuilder_setDirection(aaudioBuilder, direction);
92 
93     // Ask AAudio to allocate a Session ID.
94     AAudioStreamBuilder_setSessionId(aaudioBuilder, AAUDIO_SESSION_ID_ALLOCATE);
95 
96     // Create an AAudioStream using the Builder.
97     ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream1));
98 
99     // Get the allocated ID from the stream.
100     sessionId1 = AAudioStream_getSessionId(aaudioStream1);
101 
102     // Check for invalid session IDs.
103     ASSERT_NE(AAUDIO_SESSION_ID_NONE, sessionId1);
104     ASSERT_NE(AAUDIO_SESSION_ID_ALLOCATE, sessionId1);
105 
106     ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream1));
107 
108     if (direction == AAUDIO_DIRECTION_INPUT) {
109         ASSERT_EQ(kNumFrames, AAudioStream_read(aaudioStream1,
110                                                 buffer, kNumFrames, NANOS_PER_SECOND));
111     } else {
112         ASSERT_EQ(kNumFrames, AAudioStream_write(aaudioStream1,
113                                          buffer, kNumFrames, NANOS_PER_SECOND));
114     }
115 
116     EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream1));
117 
118     // Now open a second stream using the same session ID. ==================
119     AAudioStreamBuilder_setSessionId(aaudioBuilder, sessionId1);
120 
121     // Reverse direction for second stream.
122     aaudio_direction_t otherDirection = (direction == AAUDIO_DIRECTION_OUTPUT)
123                                         ? AAUDIO_DIRECTION_INPUT
124                                         : AAUDIO_DIRECTION_OUTPUT;
125     AAudioStreamBuilder_setDirection(aaudioBuilder, otherDirection);
126 
127     // Create an AAudioStream using the Builder.
128     ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream2));
129 
130     // Get the allocated ID from the stream.
131     // It should match the ID that we set it to in the builder.
132     sessionId2 = AAudioStream_getSessionId(aaudioStream2);
133     ASSERT_EQ(sessionId1, sessionId2);
134 
135     ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream2));
136 
137     if (otherDirection == AAUDIO_DIRECTION_INPUT) {
138         ASSERT_EQ(kNumFrames, AAudioStream_read(aaudioStream2,
139                                                  buffer, kNumFrames, NANOS_PER_SECOND));
140     } else {
141         ASSERT_EQ(kNumFrames, AAudioStream_write(aaudioStream2,
142                                                  buffer, kNumFrames, NANOS_PER_SECOND));
143     }
144 
145     EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream2));
146 
147     EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream2));
148 
149 
150     EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream1));
151     delete[] buffer;
152     AAudioStreamBuilder_delete(aaudioBuilder);
153 }
154 
TEST(test_session_id,aaudio_session_id_alloc_perfnone_in)155 TEST(test_session_id, aaudio_session_id_alloc_perfnone_in) {
156     checkSessionIdAllocate(AAUDIO_PERFORMANCE_MODE_NONE, AAUDIO_DIRECTION_INPUT);
157 }
TEST(test_session_id,aaudio_session_id_alloc_perfnone_out)158 TEST(test_session_id, aaudio_session_id_alloc_perfnone_out) {
159     checkSessionIdAllocate(AAUDIO_PERFORMANCE_MODE_NONE, AAUDIO_DIRECTION_OUTPUT);
160 }
161 
TEST(test_session_id,aaudio_session_id_alloc_lowlat_in)162 TEST(test_session_id, aaudio_session_id_alloc_lowlat_in) {
163     checkSessionIdAllocate(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, AAUDIO_DIRECTION_INPUT);
164 }
TEST(test_session_id,aaudio_session_id_alloc_lowlat_out)165 TEST(test_session_id, aaudio_session_id_alloc_lowlat_out) {
166     checkSessionIdAllocate(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, AAUDIO_DIRECTION_OUTPUT);
167 }
168