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