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 #ifndef CTS_MEDIA_TEST_AAUDIO_UTILS_H
17 #define CTS_MEDIA_TEST_AAUDIO_UTILS_H
18 
19 #include <dlfcn.h>
20 #include <atomic>
21 #include <map>
22 #include <unordered_set>
23 #include <gtest/gtest.h>
24 #include <sys/system_properties.h>
25 
26 #include <android/binder_auto_utils.h>
27 #include <android/binder_ibinder.h>
28 
29 #include <aaudio/AAudio.h>
30 #include <system/audio.h> /* FCC_LIMIT */
31 
32 #include "test_aaudio.h"    // NANOS_PER_MILLISECOND
33 
34 int64_t getNanoseconds(clockid_t clockId = CLOCK_MONOTONIC);
35 const char* performanceModeToString(aaudio_performance_mode_t mode);
36 const char* sharingModeToString(aaudio_sharing_mode_t mode);
37 
38 static constexpr const char* FEATURE_PLAYBACK = "android.hardware.audio.output";
39 static constexpr const char* FEATURE_RECORDING = "android.hardware.microphone";
40 static constexpr const char* FEATURE_LOW_LATENCY = "android.hardware.audio.low_latency";
41 bool deviceSupportsFeature(const char* feature);
42 
43 class StreamBuilderHelper {
44   public:
45     struct Parameters {
46         int32_t sampleRate;
47         int32_t channelCount;
48         aaudio_format_t dataFormat;
49         aaudio_sharing_mode_t sharingMode;
50         aaudio_performance_mode_t perfMode;
51     };
52 
53     void initBuilder();
54     void createAndVerifyStream(bool *success);
55     void close();
56 
startStream()57     void startStream() {
58         streamCommand(&AAudioStream_requestStart,
59                 AAUDIO_STREAM_STATE_STARTING, AAUDIO_STREAM_STATE_STARTED);
60     }
pauseStream()61     void pauseStream() {
62         streamCommand(&AAudioStream_requestPause,
63                 AAUDIO_STREAM_STATE_PAUSING, AAUDIO_STREAM_STATE_PAUSED);
64     }
stopStream()65     void stopStream() {
66         streamCommand(&AAudioStream_requestStop,
67                 AAUDIO_STREAM_STATE_STOPPING, AAUDIO_STREAM_STATE_STOPPED);
68     }
69 
waitForState(aaudio_stream_state_t targetState)70     void waitForState(aaudio_stream_state_t targetState) {
71         aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNKNOWN;
72         const int kNumTries = 4; // max number of states we expect to transition through
73         for (int i = 0; ((i < kNumTries) && (state != targetState)); i++) {
74             EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(stream(),
75                                                                  state,
76                                                                  &state,
77                                                                  DEFAULT_STATE_TIMEOUT));
78         }
79     }
80 
flushStream()81     void flushStream() {
82         streamCommand(&AAudioStream_requestFlush,
83                 AAUDIO_STREAM_STATE_FLUSHING, AAUDIO_STREAM_STATE_FLUSHED);
84     }
85 
builder()86     AAudioStreamBuilder* builder() const { return mBuilder; }
stream()87     AAudioStream* stream() const { return mStream; }
actual()88     const Parameters& actual() const { return mActual; }
framesPerBurst()89     int32_t framesPerBurst() const { return mFramesPerBurst; }
90 
91   protected:
92     StreamBuilderHelper(aaudio_direction_t direction, int32_t sampleRate,
93             int32_t channelCount, aaudio_format_t dataFormat,
94             aaudio_sharing_mode_t sharingMode, aaudio_performance_mode_t perfMode);
95     ~StreamBuilderHelper();
96 
97     typedef aaudio_result_t (StreamCommand)(AAudioStream*);
98     void streamCommand(
99             StreamCommand cmd, aaudio_stream_state_t fromState, aaudio_stream_state_t toState);
100 
101     static const std::map<aaudio_performance_mode_t, int64_t> sMaxFramesPerBurstMs;
102     static const std::unordered_set<aaudio_format_t> sValidStreamFormats;
103     const aaudio_direction_t mDirection;
104     const Parameters mRequested;
105     Parameters mActual;
106     int32_t mFramesPerBurst;
107     AAudioStreamBuilder *mBuilder;
108     AAudioStream *mStream;
109 
110   private:
111     const int32_t kMinValidSampleRate = 8000; // 8 kHz
112     const int32_t kMaxValidSampleRate = 2000000; // 2 MHz
113     const int32_t kMinValidChannelCount = 1;
114     const int32_t kMaxValidChannelCount = FCC_LIMIT;
115 };
116 
117 class InputStreamBuilderHelper : public StreamBuilderHelper {
118   public:
119     InputStreamBuilderHelper(
120             aaudio_sharing_mode_t requestedSharingMode,
121             aaudio_performance_mode_t requestedPerfMode,
122             aaudio_format_t requestedFormat = AAUDIO_FORMAT_PCM_FLOAT,
123             int32_t requestedSampleRate = 48000);
124 };
125 
126 class OutputStreamBuilderHelper : public StreamBuilderHelper {
127   public:
128     OutputStreamBuilderHelper(
129             aaudio_sharing_mode_t requestedSharingMode,
130             aaudio_performance_mode_t requestedPerfMode,
131             aaudio_format_t requestedFormat = AAUDIO_FORMAT_PCM_I16,
132             int32_t requestSampleRate = 48000);
133     void initBuilder();
134 
135   private:
136     const int32_t kBufferCapacityFrames = 2000;
137 };
138 
139 
140 #define LIB_AAUDIO_NAME          "libaaudio.so"
141 #define FUNCTION_IS_MMAP         "AAudioStream_isMMapUsed"
142 #define FUNCTION_SET_MMAP_POLICY "AAudio_setMMapPolicy"
143 #define FUNCTION_GET_MMAP_POLICY "AAudio_getMMapPolicy"
144 
145 enum {
146     AAUDIO_POLICY_UNSPECIFIED = 0,
147 /* These definitions are from aaudio/AAudioTesting.h */
148     AAUDIO_POLICY_NEVER = 1,
149     AAUDIO_POLICY_AUTO = 2,
150     AAUDIO_POLICY_ALWAYS = 3
151 };
152 typedef int32_t aaudio_policy_t;
153 
154 /**
155  * Call some AAudio test routines that are not part of the normal API.
156  */
157 class AAudioExtensions {
158 public:
159     AAudioExtensions();
160 
isPolicyEnabled(int32_t policy)161     static bool isPolicyEnabled(int32_t policy) {
162         return (policy == AAUDIO_POLICY_AUTO || policy == AAUDIO_POLICY_ALWAYS);
163     }
164 
getInstance()165     static AAudioExtensions &getInstance() {
166         static AAudioExtensions instance;
167         return instance;
168     }
169 
getMMapPolicyProperty()170     static int getMMapPolicyProperty() {
171         return getIntegerProperty("aaudio.mmap_policy", AAUDIO_POLICY_UNSPECIFIED);
172     }
173 
getMMapPolicy()174     aaudio_policy_t getMMapPolicy() {
175         if (!mFunctionsLoaded) return -1;
176         return mAAudio_getMMapPolicy();
177     }
178 
setMMapPolicy(aaudio_policy_t policy)179     int32_t setMMapPolicy(aaudio_policy_t policy) {
180         if (!mFunctionsLoaded) return -1;
181         return mAAudio_setMMapPolicy(policy);
182     }
183 
isMMapUsed(AAudioStream * aaudioStream)184     bool isMMapUsed(AAudioStream *aaudioStream) {
185         if (!mFunctionsLoaded) return false;
186         return mAAudioStream_isMMap(aaudioStream);
187     }
188 
setMMapEnabled(bool enabled)189     int32_t setMMapEnabled(bool enabled) {
190         return setMMapPolicy(enabled ? AAUDIO_POLICY_AUTO : AAUDIO_POLICY_NEVER);
191     }
192 
isMMapEnabled()193     bool isMMapEnabled() {
194         return isPolicyEnabled(mAAudio_getMMapPolicy());
195     }
196 
isMMapSupported()197     bool isMMapSupported() const {
198         return mMMapSupported;
199     }
200 
isMMapExclusiveSupported()201     bool isMMapExclusiveSupported() const {
202         return mMMapExclusiveSupported;
203     }
204 
205 private:
206 
207     static int getIntegerProperty(const char *name, int defaultValue);
208 
209     /**
210      * Load some AAudio test functions.
211      * This should only be called once from the constructor.
212      * @return true if it succeeds
213      */
214     bool loadLibrary();
215 
216     bool      mFunctionsLoaded = false;
217     void     *mLibHandle = nullptr;
218     bool    (*mAAudioStream_isMMap)(AAudioStream *stream) = nullptr;
219     int32_t (*mAAudio_setMMapPolicy)(aaudio_policy_t policy) = nullptr;
220     aaudio_policy_t (*mAAudio_getMMapPolicy)() = nullptr;
221 
222     const bool   mMMapSupported;
223     const bool   mMMapExclusiveSupported;
224 };
225 
226 class AudioServerCrashMonitor {
227 public:
getInstance()228     static AudioServerCrashMonitor& getInstance() {
229         static AudioServerCrashMonitor instance;
230         return instance;
231     }
232     ~AudioServerCrashMonitor();
233 
234     void linkToDeath();
235 
isDeathRecipientLinked()236     bool isDeathRecipientLinked() const { return mDeathRecipientLinked; }
237     void onAudioServerCrash();
238 
239 private:
240     AudioServerCrashMonitor();
241 
242     ::ndk::SpAIBinder getAudioFlinger();
243 
244     ::ndk::SpAIBinder mAudioFlinger;
245     ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
246     bool mDeathRecipientLinked = false;
247 };
248 
249 class AAudioCtsBase : public ::testing::Test {
250 protected:
251     void SetUp() override;
252     void TearDown() override;
253 
254 private:
255     void checkIfAudioServerCrash();
256 };
257 
258 bool isIEC61937Supported();
259 
260 bool isEchoReferenceSupported();
261 
262 void enableAudioOutputPermission();
263 
264 void enableAudioHotwordPermission();
265 
266 void disablePermissions();
267 
268 #endif  // CTS_MEDIA_TEST_AAUDIO_UTILS_H
269