• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 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 #ifndef NATIVEOBOE_NATIVEAUDIOCONTEXT_H
18 #define NATIVEOBOE_NATIVEAUDIOCONTEXT_H
19 
20 #include <jni.h>
21 #include <sys/system_properties.h>
22 #include <thread>
23 #include <unordered_map>
24 #include <vector>
25 
26 #include "common/OboeDebug.h"
27 #include "oboe/Oboe.h"
28 
29 #include "aaudio/AAudioExtensions.h"
30 #include "AudioStreamGateway.h"
31 
32 #include "flowunits/ImpulseOscillator.h"
33 #include "flowgraph/ManyToMultiConverter.h"
34 #include "flowgraph/MonoToMultiConverter.h"
35 #include "flowgraph/SinkFloat.h"
36 #include "flowgraph/SinkI16.h"
37 #include "flowunits/ExponentialShape.h"
38 #include "flowunits/LinearShape.h"
39 #include "flowunits/SineOscillator.h"
40 #include "flowunits/SawtoothOscillator.h"
41 #include "flowunits/TriangleOscillator.h"
42 
43 #include "FullDuplexAnalyzer.h"
44 #include "FullDuplexEcho.h"
45 #include "FullDuplexStream.h"
46 #include "analyzer/GlitchAnalyzer.h"
47 #include "analyzer/DataPathAnalyzer.h"
48 #include "InputStreamCallbackAnalyzer.h"
49 #include "MultiChannelRecording.h"
50 #include "OboeStreamCallbackProxy.h"
51 #include "PlayRecordingCallback.h"
52 #include "SawPingGenerator.h"
53 
54 // These must match order in strings.xml and in StreamConfiguration.java
55 #define NATIVE_MODE_UNSPECIFIED  0
56 #define NATIVE_MODE_OPENSLES     1
57 #define NATIVE_MODE_AAUDIO       2
58 
59 #define MAX_SINE_OSCILLATORS     8
60 #define AMPLITUDE_SINE           1.0
61 #define AMPLITUDE_SAWTOOTH       0.5
62 #define FREQUENCY_SAW_PING       800.0
63 #define AMPLITUDE_SAW_PING       0.8
64 #define AMPLITUDE_IMPULSE        0.7
65 
66 #define NANOS_PER_MICROSECOND    ((int64_t) 1000)
67 #define NANOS_PER_MILLISECOND    (1000 * NANOS_PER_MICROSECOND)
68 #define NANOS_PER_SECOND         (1000 * NANOS_PER_MILLISECOND)
69 
70 #define SECONDS_TO_RECORD        10
71 
72 /**
73  * Abstract base class that corresponds to a test at the Java level.
74  */
75 class ActivityContext {
76 public:
77 
ActivityContext()78     ActivityContext() {}
79 
80     virtual ~ActivityContext() = default;
81 
getStream(int32_t streamIndex)82     std::shared_ptr<oboe::AudioStream> getStream(int32_t streamIndex) {
83         auto it = mOboeStreams.find(streamIndex);
84         if (it != mOboeStreams.end()) {
85             return it->second;
86         } else {
87             return nullptr;
88         }
89     }
90 
91     virtual void configureBuilder(bool isInput, oboe::AudioStreamBuilder &builder);
92 
93     /**
94      * Open a stream with the given parameters.
95      * @param nativeApi
96      * @param sampleRate
97      * @param channelCount
98      * @param format
99      * @param sharingMode
100      * @param performanceMode
101      * @param inputPreset
102      * @param deviceId
103      * @param sessionId
104      * @param framesPerBurst
105      * @param channelConversionAllowed
106      * @param formatConversionAllowed
107      * @param rateConversionQuality
108      * @param isMMap
109      * @param isInput
110      * @return stream ID
111      */
112     int open(jint nativeApi,
113              jint sampleRate,
114              jint channelCount,
115              jint format,
116              jint sharingMode,
117              jint performanceMode,
118              jint inputPreset,
119              jint deviceId,
120              jint sessionId,
121              jint framesPerBurst,
122              jboolean channelConversionAllowed,
123              jboolean formatConversionAllowed,
124              jint rateConversionQuality,
125              jboolean isMMap,
126              jboolean isInput);
127 
128     virtual void close(int32_t streamIndex);
129 
configureForStart()130     virtual void configureForStart() {}
131 
132     oboe::Result start();
133 
134     oboe::Result pause();
135 
136     oboe::Result stopAllStreams();
137 
stop()138     virtual oboe::Result stop() {
139         return stopAllStreams();
140     }
141 
getCpuLoad()142     double getCpuLoad() {
143         return oboeCallbackProxy.getCpuLoad();
144     }
145 
setWorkload(double workload)146     void setWorkload(double workload) {
147         oboeCallbackProxy.setWorkload(workload);
148     }
149 
startPlayback()150     virtual oboe::Result startPlayback() {
151         return oboe::Result::OK;
152     }
153 
stopPlayback()154     virtual oboe::Result stopPlayback() {
155         return oboe::Result::OK;
156     }
157 
runBlockingIO()158     virtual void runBlockingIO() {};
159 
threadCallback(ActivityContext * context)160     static void threadCallback(ActivityContext *context) {
161         context->runBlockingIO();
162     }
163 
stopBlockingIOThread()164     void stopBlockingIOThread() {
165         if (dataThread != nullptr) {
166             // stop a thread that runs in place of the callback
167             threadEnabled.store(false); // ask thread to exit its loop
168             dataThread->join();
169             dataThread = nullptr;
170         }
171     }
172 
getPeakLevel(int index)173     virtual double getPeakLevel(int index) {
174         return 0.0;
175     }
176 
177     static int64_t getNanoseconds(clockid_t clockId = CLOCK_MONOTONIC) {
178         struct timespec time;
179         int result = clock_gettime(clockId, &time);
180         if (result < 0) {
181             return result;
182         }
183         return (time.tv_sec * NANOS_PER_SECOND) + time.tv_nsec;
184     }
185 
186     // Calculate time between beginning and when frame[0] occurred.
calculateColdStartLatencyMillis(int32_t sampleRate,int64_t beginTimeNanos,int64_t timeStampPosition,int64_t timestampNanos)187     int32_t calculateColdStartLatencyMillis(int32_t sampleRate,
188                                             int64_t beginTimeNanos,
189                                             int64_t timeStampPosition,
190                                             int64_t timestampNanos) const {
191         int64_t elapsedNanos = NANOS_PER_SECOND * (timeStampPosition / (double) sampleRate);
192         int64_t timeOfFrameZero = timestampNanos - elapsedNanos;
193         int64_t coldStartLatencyNanos = timeOfFrameZero - beginTimeNanos;
194         return coldStartLatencyNanos / NANOS_PER_MILLISECOND;
195     }
196 
getColdStartInputMillis()197     int32_t getColdStartInputMillis() {
198         std::shared_ptr<oboe::AudioStream> oboeStream = getInputStream();
199         if (oboeStream != nullptr) {
200             int64_t framesRead = oboeStream->getFramesRead();
201             if (framesRead > 0) {
202                 // Base latency on the time that frame[0] would have been received by the app.
203                 int64_t nowNanos = getNanoseconds();
204                 return calculateColdStartLatencyMillis(oboeStream->getSampleRate(),
205                                                        mInputOpenedAt,
206                                                        framesRead,
207                                                        nowNanos);
208             }
209         }
210         return -1;
211     }
212 
getColdStartOutputMillis()213     int32_t getColdStartOutputMillis() {
214         std::shared_ptr<oboe::AudioStream> oboeStream = getOutputStream();
215         if (oboeStream != nullptr) {
216             auto result = oboeStream->getTimestamp(CLOCK_MONOTONIC);
217             if (result) {
218                 auto frameTimestamp = result.value();
219                 // Calculate the time that frame[0] would have been played by the speaker.
220                 int64_t position = frameTimestamp.position;
221                 int64_t timestampNanos = frameTimestamp.timestamp;
222                 return calculateColdStartLatencyMillis(oboeStream->getSampleRate(),
223                                                        mOutputOpenedAt,
224                                                        position,
225                                                        timestampNanos);
226             }
227         }
228         return -1;
229     }
230 
231     /**
232      * Trigger a sound or impulse.
233      * @param enabled
234      */
trigger()235     virtual void trigger() {}
236 
237     bool isMMapUsed(int32_t streamIndex);
238 
getFramesPerBlock()239     int32_t getFramesPerBlock() {
240         return (callbackSize == 0) ? mFramesPerBurst : callbackSize;
241     }
242 
getCallbackCount()243     int64_t getCallbackCount() {
244         return oboeCallbackProxy.getCallbackCount();
245     }
246 
getLastErrorCallbackResult()247     oboe::Result getLastErrorCallbackResult() {
248         std::shared_ptr<oboe::AudioStream> stream = getOutputStream();
249         if (stream == nullptr) {
250             stream = getInputStream();
251         }
252         return stream ? oboe::Result::ErrorNull : stream->getLastErrorCallbackResult();
253     }
254 
getFramesPerCallback()255     int32_t getFramesPerCallback() {
256         return oboeCallbackProxy.getFramesPerCallback();
257     }
258 
setChannelEnabled(int channelIndex,bool enabled)259     virtual void setChannelEnabled(int channelIndex, bool enabled) {}
260 
setSignalType(int signalType)261     virtual void setSignalType(int signalType) {}
262 
263     virtual int32_t saveWaveFile(const char *filename);
264 
setMinimumFramesBeforeRead(int32_t numFrames)265     virtual void setMinimumFramesBeforeRead(int32_t numFrames) {}
266 
267     static bool   mUseCallback;
268     static int    callbackSize;
269 
270     double getTimestampLatency(int32_t streamIndex);
271 
272 protected:
273     std::shared_ptr<oboe::AudioStream> getInputStream();
274     std::shared_ptr<oboe::AudioStream> getOutputStream();
275     int32_t allocateStreamIndex();
276     void freeStreamIndex(int32_t streamIndex);
277 
createRecording()278     virtual void createRecording() {
279         mRecording = std::make_unique<MultiChannelRecording>(mChannelCount,
280                                                              SECONDS_TO_RECORD * mSampleRate);
281     }
282 
finishOpen(bool isInput,oboe::AudioStream * oboeStream)283     virtual void finishOpen(bool isInput, oboe::AudioStream *oboeStream) {}
284 
285     virtual oboe::Result startStreams() = 0;
286 
287     std::unique_ptr<float []>    dataBuffer{};
288 
289     AudioStreamGateway           audioStreamGateway;
290     OboeStreamCallbackProxy      oboeCallbackProxy;
291 
292     std::unique_ptr<MultiChannelRecording>  mRecording{};
293 
294     int32_t                      mNextStreamHandle = 0;
295     std::unordered_map<int32_t, std::shared_ptr<oboe::AudioStream>>  mOboeStreams;
296     int32_t                      mFramesPerBurst = 0; // TODO per stream
297     int32_t                      mChannelCount = 0; // TODO per stream
298     int32_t                      mSampleRate = 0; // TODO per stream
299 
300     std::atomic<bool>            threadEnabled{false};
301     std::thread                 *dataThread = nullptr;
302 
303 private:
304     int64_t mInputOpenedAt = 0;
305     int64_t mOutputOpenedAt = 0;
306 };
307 
308 /**
309  * Test a single input stream.
310  */
311 class ActivityTestInput : public ActivityContext {
312 public:
313 
ActivityTestInput()314     ActivityTestInput() {}
315     virtual ~ActivityTestInput() = default;
316 
317     void configureForStart() override;
318 
getPeakLevel(int index)319     double getPeakLevel(int index) override {
320         return mInputAnalyzer.getPeakLevel(index);
321     }
322 
323     void runBlockingIO() override;
324 
325     InputStreamCallbackAnalyzer  mInputAnalyzer;
326 
setMinimumFramesBeforeRead(int32_t numFrames)327     void setMinimumFramesBeforeRead(int32_t numFrames) override {
328         mInputAnalyzer.setMinimumFramesBeforeRead(numFrames);
329         mMinimumFramesBeforeRead = numFrames;
330     }
331 
getMinimumFramesBeforeRead()332     int32_t getMinimumFramesBeforeRead() const {
333         return mMinimumFramesBeforeRead;
334     }
335 
336 protected:
337 
startStreams()338     oboe::Result startStreams() override {
339         mInputAnalyzer.reset();
340         return getInputStream()->requestStart();
341     }
342 
343     int32_t mMinimumFramesBeforeRead = 0;
344 };
345 
346 /**
347  * Record a configured input stream and play it back some simple way.
348  */
349 class ActivityRecording : public ActivityTestInput {
350 public:
351 
ActivityRecording()352     ActivityRecording() {}
353     virtual ~ActivityRecording() = default;
354 
stop()355     oboe::Result stop() override {
356 
357         oboe::Result resultStopPlayback = stopPlayback();
358         oboe::Result resultStopAudio = ActivityContext::stop();
359 
360         return (resultStopPlayback != oboe::Result::OK) ? resultStopPlayback : resultStopAudio;
361     }
362 
363     oboe::Result startPlayback() override;
364 
365     oboe::Result stopPlayback() override;
366 
367     PlayRecordingCallback        mPlayRecordingCallback;
368     oboe::AudioStream           *playbackStream = nullptr;
369 
370 };
371 
372 /**
373  * Test a single output stream.
374  */
375 class ActivityTestOutput : public ActivityContext {
376 public:
ActivityTestOutput()377     ActivityTestOutput()
378             : sineOscillators(MAX_SINE_OSCILLATORS)
379             , sawtoothOscillators(MAX_SINE_OSCILLATORS) {}
380 
381     virtual ~ActivityTestOutput() = default;
382 
383     void close(int32_t streamIndex) override;
384 
startStreams()385     oboe::Result startStreams() override {
386         return getOutputStream()->start();
387     }
388 
389     void configureForStart() override;
390 
391     virtual void configureStreamGateway();
392 
393     void runBlockingIO() override;
394 
395     void setChannelEnabled(int channelIndex, bool enabled) override;
396 
397     // WARNING - must match order in strings.xml and OboeAudioOutputStream.java
398     enum SignalType {
399         Sine = 0,
400         Sawtooth = 1,
401         FreqSweep = 2,
402         PitchSweep = 3,
403         WhiteNoise = 4
404     };
405 
setSignalType(int signalType)406     void setSignalType(int signalType) override {
407         mSignalType = (SignalType) signalType;
408     }
409 
410 protected:
411     SignalType                       mSignalType = SignalType::Sine;
412 
413     std::vector<SineOscillator>      sineOscillators;
414     std::vector<SawtoothOscillator>  sawtoothOscillators;
415     static constexpr float           kSweepPeriod = 10.0; // for triangle up and down
416 
417     // A triangle LFO is shaped into either a linear or an exponential range.
418     TriangleOscillator               mTriangleOscillator;
419     LinearShape                      mLinearShape;
420     ExponentialShape                 mExponentialShape;
421 
422     std::unique_ptr<ManyToMultiConverter>   manyToMulti;
423     std::unique_ptr<MonoToMultiConverter>   monoToMulti;
424     std::shared_ptr<oboe::flowgraph::SinkFloat>   mSinkFloat;
425     std::shared_ptr<oboe::flowgraph::SinkI16>     mSinkI16;
426 };
427 
428 /**
429  * Generate a short beep with a very short attack.
430  * This is used by Java to measure output latency.
431  */
432 class ActivityTapToTone : public ActivityTestOutput {
433 public:
ActivityTapToTone()434     ActivityTapToTone() {}
435     virtual ~ActivityTapToTone() = default;
436 
437     void configureForStart() override;
438 
trigger()439     virtual void trigger() override {
440         sawPingGenerator.trigger();
441     }
442 
443     SawPingGenerator             sawPingGenerator;
444 };
445 
446 /**
447  * Activity that uses synchronized input/output streams.
448  */
449 class ActivityFullDuplex : public ActivityContext {
450 public:
451 
452     void configureBuilder(bool isInput, oboe::AudioStreamBuilder &builder) override;
453 
getState()454     virtual int32_t getState() { return -1; }
getResult()455     virtual int32_t getResult() { return -1; }
isAnalyzerDone()456     virtual bool isAnalyzerDone() { return false; }
457 
setMinimumFramesBeforeRead(int32_t numFrames)458     void setMinimumFramesBeforeRead(int32_t numFrames) override {
459         getFullDuplexAnalyzer()->setMinimumFramesBeforeRead(numFrames);
460     }
461 
462     virtual FullDuplexAnalyzer *getFullDuplexAnalyzer() = 0;
463 
getResetCount()464     int32_t getResetCount() {
465         return getFullDuplexAnalyzer()->getLoopbackProcessor()->getResetCount();
466     }
467 
468 protected:
createRecording()469     void createRecording() override {
470         mRecording = std::make_unique<MultiChannelRecording>(2, // output and input
471                                                              SECONDS_TO_RECORD * mSampleRate);
472     }
473 };
474 
475 /**
476  * Echo input to output through a delay line.
477  */
478 class ActivityEcho : public ActivityFullDuplex {
479 public:
480 
startStreams()481     oboe::Result startStreams() override {
482         return mFullDuplexEcho->start();
483     }
484 
485     void configureBuilder(bool isInput, oboe::AudioStreamBuilder &builder) override;
486 
setDelayTime(double delayTimeSeconds)487     void setDelayTime(double delayTimeSeconds) {
488         if (mFullDuplexEcho) {
489             mFullDuplexEcho->setDelayTime(delayTimeSeconds);
490         }
491     }
492 
getFullDuplexAnalyzer()493     FullDuplexAnalyzer *getFullDuplexAnalyzer() override {
494         return (FullDuplexAnalyzer *) mFullDuplexEcho.get();
495     }
496 
497 protected:
498     void finishOpen(bool isInput, oboe::AudioStream *oboeStream) override;
499 
500 private:
501     std::unique_ptr<FullDuplexEcho>   mFullDuplexEcho{};
502 };
503 
504 /**
505  * Measure Round Trip Latency
506  */
507 class ActivityRoundTripLatency : public ActivityFullDuplex {
508 public:
509 
startStreams()510     oboe::Result startStreams() override {
511         mAnalyzerLaunched = false;
512         return mFullDuplexLatency->start();
513     }
514 
515     void configureBuilder(bool isInput, oboe::AudioStreamBuilder &builder) override;
516 
getLatencyAnalyzer()517     LatencyAnalyzer *getLatencyAnalyzer() {
518         return &mEchoAnalyzer;
519     }
520 
getState()521     int32_t getState() override {
522         return getLatencyAnalyzer()->getState();
523     }
524 
getResult()525     int32_t getResult() override {
526         return getLatencyAnalyzer()->getState(); // TODO This does not look right.
527     }
528 
isAnalyzerDone()529     bool isAnalyzerDone() override {
530         if (!mAnalyzerLaunched) {
531             mAnalyzerLaunched = launchAnalysisIfReady();
532         }
533         return mEchoAnalyzer.isDone();
534     }
535 
getFullDuplexAnalyzer()536     FullDuplexAnalyzer *getFullDuplexAnalyzer() override {
537         return (FullDuplexAnalyzer *) mFullDuplexLatency.get();
538     }
539 
analyzeData(PulseLatencyAnalyzer * analyzer)540     static void analyzeData(PulseLatencyAnalyzer *analyzer) {
541         analyzer->analyze();
542     }
543 
launchAnalysisIfReady()544     bool launchAnalysisIfReady() {
545         // Are we ready to do the analysis?
546         if (mEchoAnalyzer.hasEnoughData()) {
547             // Crunch the numbers on a separate thread.
548             std::thread t(analyzeData, &mEchoAnalyzer);
549             t.detach();
550             return true;
551         }
552         return false;
553     }
554 
555 protected:
556     void finishOpen(bool isInput, oboe::AudioStream *oboeStream) override;
557 
558 private:
559     std::unique_ptr<FullDuplexAnalyzer>   mFullDuplexLatency{};
560 
561     PulseLatencyAnalyzer  mEchoAnalyzer;
562     bool                  mAnalyzerLaunched = false;
563 };
564 
565 /**
566  * Measure Glitches
567  */
568 class ActivityGlitches : public ActivityFullDuplex {
569 public:
570 
startStreams()571     oboe::Result startStreams() override {
572         return mFullDuplexGlitches->start();
573     }
574 
575     void configureBuilder(bool isInput, oboe::AudioStreamBuilder &builder) override;
576 
getGlitchAnalyzer()577     GlitchAnalyzer *getGlitchAnalyzer() {
578         return &mGlitchAnalyzer;
579     }
580 
getState()581     int32_t getState() override {
582         return getGlitchAnalyzer()->getState();
583     }
584 
getResult()585     int32_t getResult() override {
586         return getGlitchAnalyzer()->getResult();
587     }
588 
isAnalyzerDone()589     bool isAnalyzerDone() override {
590         return mGlitchAnalyzer.isDone();
591     }
592 
getFullDuplexAnalyzer()593     FullDuplexAnalyzer *getFullDuplexAnalyzer() override {
594         return (FullDuplexAnalyzer *) mFullDuplexGlitches.get();
595     }
596 
597 protected:
598     void finishOpen(bool isInput, oboe::AudioStream *oboeStream) override;
599 
600 private:
601     std::unique_ptr<FullDuplexAnalyzer>   mFullDuplexGlitches{};
602     GlitchAnalyzer  mGlitchAnalyzer;
603 };
604 
605 /**
606  * Measure Data Path
607  */
608 class ActivityDataPath : public ActivityFullDuplex {
609 public:
610 
startStreams()611     oboe::Result startStreams() override {
612         return mFullDuplexDataPath->start();
613     }
614 
615     void configureBuilder(bool isInput, oboe::AudioStreamBuilder &builder) override;
616 
configureForStart()617     void configureForStart() override {
618         std::shared_ptr<oboe::AudioStream> outputStream = getOutputStream();
619         int32_t capacityInFrames = outputStream->getBufferCapacityInFrames();
620         int32_t burstInFrames = outputStream->getFramesPerBurst();
621         int32_t capacityInBursts = capacityInFrames / burstInFrames;
622         int32_t sizeInBursts = std::max(2, capacityInBursts / 2);
623         // Set size of buffer to minimize underruns.
624         auto result = outputStream->setBufferSizeInFrames(sizeInBursts * burstInFrames);
625         static_cast<void>(result);  // Avoid unused variable.
626         LOGD("ActivityDataPath: %s() capacity = %d, burst = %d, size = %d",
627              __func__, capacityInFrames, burstInFrames, result.value());
628     }
629 
getDataPathAnalyzer()630     DataPathAnalyzer *getDataPathAnalyzer() {
631         return &mDataPathAnalyzer;
632     }
633 
getFullDuplexAnalyzer()634     FullDuplexAnalyzer *getFullDuplexAnalyzer() override {
635         return (FullDuplexAnalyzer *) mFullDuplexDataPath.get();
636     }
637 
638 protected:
639     void finishOpen(bool isInput, oboe::AudioStream *oboeStream) override;
640 
641 private:
642     std::unique_ptr<FullDuplexAnalyzer>   mFullDuplexDataPath{};
643 
644     DataPathAnalyzer  mDataPathAnalyzer;
645 };
646 
647 /**
648  * Test a single output stream.
649  */
650 class ActivityTestDisconnect : public ActivityContext {
651 public:
ActivityTestDisconnect()652     ActivityTestDisconnect() {}
653 
654     virtual ~ActivityTestDisconnect() = default;
655 
656     void close(int32_t streamIndex) override;
657 
startStreams()658     oboe::Result startStreams() override {
659         std::shared_ptr<oboe::AudioStream> outputStream = getOutputStream();
660         if (outputStream) {
661             return outputStream->start();
662         }
663 
664         std::shared_ptr<oboe::AudioStream> inputStream = getInputStream();
665         if (inputStream) {
666             return inputStream->start();
667         }
668         return oboe::Result::ErrorNull;
669     }
670 
671     void configureForStart() override;
672 
673 private:
674     std::unique_ptr<SineOscillator>         sineOscillator;
675     std::unique_ptr<MonoToMultiConverter>   monoToMulti;
676     std::shared_ptr<oboe::flowgraph::SinkFloat>   mSinkFloat;
677 };
678 
679 /**
680  * Switch between various
681  */
682 class NativeAudioContext {
683 public:
684 
getCurrentActivity()685     ActivityContext *getCurrentActivity() {
686         return currentActivity;
687     };
688 
setActivityType(int activityType)689     void setActivityType(int activityType) {
690         mActivityType = (ActivityType) activityType;
691         switch(mActivityType) {
692             default:
693             case ActivityType::Undefined:
694             case ActivityType::TestOutput:
695                 currentActivity = &mActivityTestOutput;
696                 break;
697             case ActivityType::TestInput:
698                 currentActivity = &mActivityTestInput;
699                 break;
700             case ActivityType::TapToTone:
701                 currentActivity = &mActivityTapToTone;
702                 break;
703             case ActivityType::RecordPlay:
704                 currentActivity = &mActivityRecording;
705                 break;
706             case ActivityType::Echo:
707                 currentActivity = &mActivityEcho;
708                 break;
709             case ActivityType::RoundTripLatency:
710                 currentActivity = &mActivityRoundTripLatency;
711                 break;
712             case ActivityType::Glitches:
713                 currentActivity = &mActivityGlitches;
714                 break;
715             case ActivityType::TestDisconnect:
716                 currentActivity = &mActivityTestDisconnect;
717                 break;
718             case ActivityType::DataPath:
719                 currentActivity = &mActivityDataPath;
720                 break;
721         }
722     }
723 
setDelayTime(double delayTimeMillis)724     void setDelayTime(double delayTimeMillis) {
725         mActivityEcho.setDelayTime(delayTimeMillis);
726     }
727 
728     ActivityTestOutput           mActivityTestOutput;
729     ActivityTestInput            mActivityTestInput;
730     ActivityTapToTone            mActivityTapToTone;
731     ActivityRecording            mActivityRecording;
732     ActivityEcho                 mActivityEcho;
733     ActivityRoundTripLatency     mActivityRoundTripLatency;
734     ActivityGlitches             mActivityGlitches;
735     ActivityDataPath             mActivityDataPath;
736     ActivityTestDisconnect       mActivityTestDisconnect;
737 
738 
739 private:
740 
741     // WARNING - must match definitions in TestAudioActivity.java
742     enum ActivityType {
743         Undefined = -1,
744         TestOutput = 0,
745         TestInput = 1,
746         TapToTone = 2,
747         RecordPlay = 3,
748         Echo = 4,
749         RoundTripLatency = 5,
750         Glitches = 6,
751         TestDisconnect = 7,
752         DataPath = 8,
753     };
754 
755     ActivityType                 mActivityType = ActivityType::Undefined;
756     ActivityContext             *currentActivity = &mActivityTestOutput;
757 
758 };
759 
760 #endif //NATIVEOBOE_NATIVEAUDIOCONTEXT_H
761