1 /*
2  * Copyright (C) 2023 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 // When receive disconnect event, ignore it and leave the shared stream at OPEN
18 // state. It should be possible to open another shared stream and start it.
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 
24 #include <aaudio/AAudio.h>
25 #include <aaudio/AAudioTesting.h>
26 
27 static constexpr unsigned int ONE_SECOND = 1e6;
28 static constexpr unsigned int WAIT_TIME_MS = 10 * ONE_SECOND;
29 #define MMAP_POLICY              AAUDIO_POLICY_ALWAYS
30 
openStream()31 AAudioStream* openStream() {
32     AAudioStreamBuilder *aaudioBuilder = nullptr;
33     aaudio_result_t result = AAudio_createStreamBuilder(&aaudioBuilder);
34     if (result != AAUDIO_OK) {
35         printf("Failed to create stream builder, result=%d, %s\n",
36                result, AAudio_convertResultToText(result));
37         return nullptr;
38     }
39     AAudioStreamBuilder_setSharingMode(aaudioBuilder, AAUDIO_SHARING_MODE_SHARED);
40     AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
41     AAudioStream* aaudioStream;
42     result = AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream);
43     if (result != AAUDIO_OK) {
44         printf("ERROR could not open AAudio stream, %d %s\n",
45                result, AAudio_convertResultToText(result));
46     }
47     AAudioStreamBuilder_delete(aaudioBuilder);
48     return aaudioStream;
49 }
50 
testNoCloseSharedStreamAfterRoutingChanged(bool stopFirstStream)51 aaudio_result_t testNoCloseSharedStreamAfterRoutingChanged(bool stopFirstStream) {
52     aaudio_result_t result = AAUDIO_OK;
53     printf("Please connect external device that supports MMAP playback, will wait 10 seconds\n");
54     usleep(WAIT_TIME_MS);
55 
56     // Open first shared stream
57     printf("Open first shared stream\n");
58     AAudioStream* firstStream = openStream();
59     if (firstStream == nullptr) {
60         return 1;
61     }
62     result = AAudioStream_requestStart(firstStream);
63     if (result != AAUDIO_OK) {
64         return result;
65     }
66 
67     if (stopFirstStream) {
68         printf("Stop first shared stream\n");
69         result = AAudioStream_requestStop(firstStream);
70         if (result != AAUDIO_OK) {
71             return result;
72         }
73         printf("Wait to make sure the stream is stopped\n");
74         usleep(ONE_SECOND * 3);
75     }
76 
77     printf("Please disconnect and reconnect the external device, will wait 10 second\n");
78     usleep(WAIT_TIME_MS);
79 
80     // Open second stream after the first shared stream was reconnected
81     printf("Open second shared stream\n");
82     AAudioStream* secondStream = openStream();
83     if (secondStream == nullptr) {
84         result = 1;
85         goto exit;
86     }
87 
88     // Starting second stream should be successful
89     printf("Start second shared stream\n");
90     result = AAudioStream_requestStart(secondStream);
91     if (result != AAUDIO_OK) {
92         printf("ERROR could not start second stream, %d %s\n",
93                result, AAudio_convertResultToText(result));
94     }
95 
96 exit:
97     // Close all streams
98     AAudioStream_close(firstStream);
99     AAudioStream_close(secondStream);
100     return result;
101 }
102 
main(int argc,char ** argv)103 int main(int argc, char **argv) {
104     (void) argc; // unused
105     (void) argv; // unused
106 
107     aaudio_policy_t originalPolicy = AAudio_getMMapPolicy();
108     AAudio_setMMapPolicy(MMAP_POLICY);
109 
110     printf("Run first test. The first stream is started when routing changed.\n");
111     aaudio_result_t result = testNoCloseSharedStreamAfterRoutingChanged(false /*stopFirstStream*/);
112 
113     if (result != AAUDIO_OK) {
114         goto exit;
115     }
116 
117     printf("First test passed\n");
118     printf("----------------------------------------------------------------\n");
119     printf("Run second test. The first stream is stopped when routing changed.\n");
120     if (testNoCloseSharedStreamAfterRoutingChanged(true /*stopFirstStream*/) == AAUDIO_OK) {
121         printf("Second test passed\n");
122     }
123 
124 exit:
125     AAudio_setMMapPolicy(originalPolicy);
126 
127     return result != AAUDIO_OK ? EXIT_FAILURE : EXIT_SUCCESS;
128 }