1 /*
2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "sdk/android/src/jni/audio_device/audio_device_module.h"
12
13 #include <memory>
14 #include <utility>
15
16 #include "api/make_ref_counted.h"
17 #include "api/sequence_checker.h"
18 #include "api/task_queue/default_task_queue_factory.h"
19 #include "api/task_queue/task_queue_factory.h"
20 #include "modules/audio_device/audio_device_buffer.h"
21 #include "rtc_base/checks.h"
22 #include "rtc_base/logging.h"
23 #include "sdk/android/generated_audio_device_module_base_jni/WebRtcAudioManager_jni.h"
24 #include "system_wrappers/include/metrics.h"
25
26 namespace webrtc {
27 namespace jni {
28
29 namespace {
30
31 // This class combines a generic instance of an AudioInput and a generic
32 // instance of an AudioOutput to create an AudioDeviceModule. This is mostly
33 // done by delegating to the audio input/output with some glue code. This class
34 // also directly implements some of the AudioDeviceModule methods with dummy
35 // implementations.
36 //
37 // An instance can be created on any thread, but must then be used on one and
38 // the same thread. All public methods must also be called on the same thread.
39 // A thread checker will RTC_DCHECK if any method is called on an invalid
40 // thread.
41 // TODO(henrika): it might be useful to also support a scenario where the ADM
42 // is constructed on thread T1, used on thread T2 and destructed on T2 or T3.
43 // If so, care must be taken to ensure that only T2 is a COM thread.
44 class AndroidAudioDeviceModule : public AudioDeviceModule {
45 public:
46 // For use with UMA logging. Must be kept in sync with histograms.xml in
47 // Chrome, located at
48 // https://cs.chromium.org/chromium/src/tools/metrics/histograms/histograms.xml
49 enum class InitStatus {
50 OK = 0,
51 PLAYOUT_ERROR = 1,
52 RECORDING_ERROR = 2,
53 OTHER_ERROR = 3,
54 NUM_STATUSES = 4
55 };
56
AndroidAudioDeviceModule(AudioDeviceModule::AudioLayer audio_layer,bool is_stereo_playout_supported,bool is_stereo_record_supported,uint16_t playout_delay_ms,std::unique_ptr<AudioInput> audio_input,std::unique_ptr<AudioOutput> audio_output)57 AndroidAudioDeviceModule(AudioDeviceModule::AudioLayer audio_layer,
58 bool is_stereo_playout_supported,
59 bool is_stereo_record_supported,
60 uint16_t playout_delay_ms,
61 std::unique_ptr<AudioInput> audio_input,
62 std::unique_ptr<AudioOutput> audio_output)
63 : audio_layer_(audio_layer),
64 is_stereo_playout_supported_(is_stereo_playout_supported),
65 is_stereo_record_supported_(is_stereo_record_supported),
66 playout_delay_ms_(playout_delay_ms),
67 task_queue_factory_(CreateDefaultTaskQueueFactory()),
68 input_(std::move(audio_input)),
69 output_(std::move(audio_output)),
70 initialized_(false) {
71 RTC_CHECK(input_);
72 RTC_CHECK(output_);
73 RTC_DLOG(LS_INFO) << __FUNCTION__;
74 thread_checker_.Detach();
75 }
76
~AndroidAudioDeviceModule()77 ~AndroidAudioDeviceModule() override { RTC_DLOG(LS_INFO) << __FUNCTION__; }
78
ActiveAudioLayer(AudioDeviceModule::AudioLayer * audioLayer) const79 int32_t ActiveAudioLayer(
80 AudioDeviceModule::AudioLayer* audioLayer) const override {
81 RTC_DLOG(LS_INFO) << __FUNCTION__;
82 *audioLayer = audio_layer_;
83 return 0;
84 }
85
RegisterAudioCallback(AudioTransport * audioCallback)86 int32_t RegisterAudioCallback(AudioTransport* audioCallback) override {
87 RTC_DLOG(LS_INFO) << __FUNCTION__;
88 return audio_device_buffer_->RegisterAudioCallback(audioCallback);
89 }
90
Init()91 int32_t Init() override {
92 RTC_DLOG(LS_INFO) << __FUNCTION__;
93 RTC_DCHECK(thread_checker_.IsCurrent());
94 audio_device_buffer_ =
95 std::make_unique<AudioDeviceBuffer>(task_queue_factory_.get());
96 AttachAudioBuffer();
97 if (initialized_) {
98 return 0;
99 }
100 InitStatus status;
101 if (output_->Init() != 0) {
102 status = InitStatus::PLAYOUT_ERROR;
103 } else if (input_->Init() != 0) {
104 output_->Terminate();
105 status = InitStatus::RECORDING_ERROR;
106 } else {
107 initialized_ = true;
108 status = InitStatus::OK;
109 }
110 RTC_HISTOGRAM_ENUMERATION("WebRTC.Audio.InitializationResult",
111 static_cast<int>(status),
112 static_cast<int>(InitStatus::NUM_STATUSES));
113 if (status != InitStatus::OK) {
114 RTC_LOG(LS_ERROR) << "Audio device initialization failed.";
115 return -1;
116 }
117 return 0;
118 }
119
Terminate()120 int32_t Terminate() override {
121 RTC_DLOG(LS_INFO) << __FUNCTION__;
122 if (!initialized_)
123 return 0;
124 RTC_DCHECK(thread_checker_.IsCurrent());
125 int32_t err = input_->Terminate();
126 err |= output_->Terminate();
127 initialized_ = false;
128 thread_checker_.Detach();
129 audio_device_buffer_.reset(nullptr);
130 RTC_DCHECK_EQ(err, 0);
131 return err;
132 }
133
Initialized() const134 bool Initialized() const override {
135 RTC_DLOG(LS_INFO) << __FUNCTION__ << ":" << initialized_;
136 return initialized_;
137 }
138
PlayoutDevices()139 int16_t PlayoutDevices() override {
140 RTC_DLOG(LS_INFO) << __FUNCTION__;
141 RTC_LOG(LS_INFO) << "output: " << 1;
142 return 1;
143 }
144
RecordingDevices()145 int16_t RecordingDevices() override {
146 RTC_DLOG(LS_INFO) << __FUNCTION__;
147 RTC_DLOG(LS_INFO) << "output: " << 1;
148 return 1;
149 }
150
PlayoutDeviceName(uint16_t index,char name[kAdmMaxDeviceNameSize],char guid[kAdmMaxGuidSize])151 int32_t PlayoutDeviceName(uint16_t index,
152 char name[kAdmMaxDeviceNameSize],
153 char guid[kAdmMaxGuidSize]) override {
154 RTC_CHECK_NOTREACHED();
155 }
156
RecordingDeviceName(uint16_t index,char name[kAdmMaxDeviceNameSize],char guid[kAdmMaxGuidSize])157 int32_t RecordingDeviceName(uint16_t index,
158 char name[kAdmMaxDeviceNameSize],
159 char guid[kAdmMaxGuidSize]) override {
160 RTC_CHECK_NOTREACHED();
161 }
162
SetPlayoutDevice(uint16_t index)163 int32_t SetPlayoutDevice(uint16_t index) override {
164 // OK to use but it has no effect currently since device selection is
165 // done using Andoid APIs instead.
166 RTC_DLOG(LS_INFO) << __FUNCTION__ << "(" << index << ")";
167 return 0;
168 }
169
SetPlayoutDevice(AudioDeviceModule::WindowsDeviceType device)170 int32_t SetPlayoutDevice(
171 AudioDeviceModule::WindowsDeviceType device) override {
172 RTC_CHECK_NOTREACHED();
173 }
174
SetRecordingDevice(uint16_t index)175 int32_t SetRecordingDevice(uint16_t index) override {
176 // OK to use but it has no effect currently since device selection is
177 // done using Andoid APIs instead.
178 RTC_DLOG(LS_INFO) << __FUNCTION__ << "(" << index << ")";
179 return 0;
180 }
181
SetRecordingDevice(AudioDeviceModule::WindowsDeviceType device)182 int32_t SetRecordingDevice(
183 AudioDeviceModule::WindowsDeviceType device) override {
184 RTC_CHECK_NOTREACHED();
185 }
186
PlayoutIsAvailable(bool * available)187 int32_t PlayoutIsAvailable(bool* available) override {
188 RTC_DLOG(LS_INFO) << __FUNCTION__;
189 *available = true;
190 RTC_DLOG(LS_INFO) << "output: " << *available;
191 return 0;
192 }
193
InitPlayout()194 int32_t InitPlayout() override {
195 RTC_DLOG(LS_INFO) << __FUNCTION__;
196 if (!initialized_)
197 return -1;
198 if (PlayoutIsInitialized()) {
199 return 0;
200 }
201 int32_t result = output_->InitPlayout();
202 RTC_DLOG(LS_INFO) << "output: " << result;
203 RTC_HISTOGRAM_BOOLEAN("WebRTC.Audio.InitPlayoutSuccess",
204 static_cast<int>(result == 0));
205 return result;
206 }
207
PlayoutIsInitialized() const208 bool PlayoutIsInitialized() const override {
209 RTC_DLOG(LS_INFO) << __FUNCTION__;
210 return output_->PlayoutIsInitialized();
211 }
212
RecordingIsAvailable(bool * available)213 int32_t RecordingIsAvailable(bool* available) override {
214 RTC_DLOG(LS_INFO) << __FUNCTION__;
215 *available = true;
216 RTC_DLOG(LS_INFO) << "output: " << *available;
217 return 0;
218 }
219
InitRecording()220 int32_t InitRecording() override {
221 RTC_DLOG(LS_INFO) << __FUNCTION__;
222 if (!initialized_)
223 return -1;
224 if (RecordingIsInitialized()) {
225 return 0;
226 }
227 int32_t result = input_->InitRecording();
228 RTC_DLOG(LS_INFO) << "output: " << result;
229 RTC_HISTOGRAM_BOOLEAN("WebRTC.Audio.InitRecordingSuccess",
230 static_cast<int>(result == 0));
231 return result;
232 }
233
RecordingIsInitialized() const234 bool RecordingIsInitialized() const override {
235 RTC_DLOG(LS_INFO) << __FUNCTION__;
236 return input_->RecordingIsInitialized();
237 }
238
StartPlayout()239 int32_t StartPlayout() override {
240 RTC_DLOG(LS_INFO) << __FUNCTION__;
241 if (!initialized_)
242 return -1;
243 if (Playing()) {
244 return 0;
245 }
246 int32_t result = output_->StartPlayout();
247 RTC_DLOG(LS_INFO) << "output: " << result;
248 RTC_HISTOGRAM_BOOLEAN("WebRTC.Audio.StartPlayoutSuccess",
249 static_cast<int>(result == 0));
250 if (result == 0) {
251 // Only start playing the audio device buffer if starting the audio
252 // output succeeded.
253 audio_device_buffer_->StartPlayout();
254 }
255 return result;
256 }
257
StopPlayout()258 int32_t StopPlayout() override {
259 RTC_DLOG(LS_INFO) << __FUNCTION__;
260 if (!initialized_)
261 return -1;
262 if (!Playing())
263 return 0;
264 RTC_LOG(LS_INFO) << __FUNCTION__;
265 audio_device_buffer_->StopPlayout();
266 int32_t result = output_->StopPlayout();
267 RTC_DLOG(LS_INFO) << "output: " << result;
268 RTC_HISTOGRAM_BOOLEAN("WebRTC.Audio.StopPlayoutSuccess",
269 static_cast<int>(result == 0));
270 return result;
271 }
272
Playing() const273 bool Playing() const override {
274 RTC_DLOG(LS_INFO) << __FUNCTION__;
275 return output_->Playing();
276 }
277
StartRecording()278 int32_t StartRecording() override {
279 RTC_DLOG(LS_INFO) << __FUNCTION__;
280 if (!initialized_)
281 return -1;
282 if (Recording()) {
283 return 0;
284 }
285 int32_t result = input_->StartRecording();
286 RTC_DLOG(LS_INFO) << "output: " << result;
287 RTC_HISTOGRAM_BOOLEAN("WebRTC.Audio.StartRecordingSuccess",
288 static_cast<int>(result == 0));
289 if (result == 0) {
290 // Only start recording the audio device buffer if starting the audio
291 // input succeeded.
292 audio_device_buffer_->StartRecording();
293 }
294 return result;
295 }
296
StopRecording()297 int32_t StopRecording() override {
298 RTC_DLOG(LS_INFO) << __FUNCTION__;
299 if (!initialized_)
300 return -1;
301 if (!Recording())
302 return 0;
303 audio_device_buffer_->StopRecording();
304 int32_t result = input_->StopRecording();
305 RTC_DLOG(LS_INFO) << "output: " << result;
306 RTC_HISTOGRAM_BOOLEAN("WebRTC.Audio.StopRecordingSuccess",
307 static_cast<int>(result == 0));
308 return result;
309 }
310
Recording() const311 bool Recording() const override {
312 RTC_DLOG(LS_INFO) << __FUNCTION__;
313 return input_->Recording();
314 }
315
InitSpeaker()316 int32_t InitSpeaker() override {
317 RTC_DLOG(LS_INFO) << __FUNCTION__;
318 return initialized_ ? 0 : -1;
319 }
320
SpeakerIsInitialized() const321 bool SpeakerIsInitialized() const override {
322 RTC_DLOG(LS_INFO) << __FUNCTION__;
323 return initialized_;
324 }
325
InitMicrophone()326 int32_t InitMicrophone() override {
327 RTC_DLOG(LS_INFO) << __FUNCTION__;
328 return initialized_ ? 0 : -1;
329 }
330
MicrophoneIsInitialized() const331 bool MicrophoneIsInitialized() const override {
332 RTC_DLOG(LS_INFO) << __FUNCTION__;
333 return initialized_;
334 }
335
SpeakerVolumeIsAvailable(bool * available)336 int32_t SpeakerVolumeIsAvailable(bool* available) override {
337 RTC_DLOG(LS_INFO) << __FUNCTION__;
338 if (!initialized_)
339 return -1;
340 *available = output_->SpeakerVolumeIsAvailable();
341 RTC_DLOG(LS_INFO) << "output: " << *available;
342 return 0;
343 }
344
SetSpeakerVolume(uint32_t volume)345 int32_t SetSpeakerVolume(uint32_t volume) override {
346 RTC_DLOG(LS_INFO) << __FUNCTION__;
347 if (!initialized_)
348 return -1;
349 return output_->SetSpeakerVolume(volume);
350 }
351
SpeakerVolume(uint32_t * output_volume) const352 int32_t SpeakerVolume(uint32_t* output_volume) const override {
353 RTC_DLOG(LS_INFO) << __FUNCTION__;
354 if (!initialized_)
355 return -1;
356 absl::optional<uint32_t> volume = output_->SpeakerVolume();
357 if (!volume)
358 return -1;
359 *output_volume = *volume;
360 RTC_DLOG(LS_INFO) << "output: " << *volume;
361 return 0;
362 }
363
MaxSpeakerVolume(uint32_t * output_max_volume) const364 int32_t MaxSpeakerVolume(uint32_t* output_max_volume) const override {
365 RTC_DLOG(LS_INFO) << __FUNCTION__;
366 if (!initialized_)
367 return -1;
368 absl::optional<uint32_t> max_volume = output_->MaxSpeakerVolume();
369 if (!max_volume)
370 return -1;
371 *output_max_volume = *max_volume;
372 return 0;
373 }
374
MinSpeakerVolume(uint32_t * output_min_volume) const375 int32_t MinSpeakerVolume(uint32_t* output_min_volume) const override {
376 RTC_DLOG(LS_INFO) << __FUNCTION__;
377 if (!initialized_)
378 return -1;
379 absl::optional<uint32_t> min_volume = output_->MinSpeakerVolume();
380 if (!min_volume)
381 return -1;
382 *output_min_volume = *min_volume;
383 return 0;
384 }
385
MicrophoneVolumeIsAvailable(bool * available)386 int32_t MicrophoneVolumeIsAvailable(bool* available) override {
387 RTC_DLOG(LS_INFO) << __FUNCTION__;
388 *available = false;
389 RTC_DLOG(LS_INFO) << "output: " << *available;
390 return -1;
391 }
392
SetMicrophoneVolume(uint32_t volume)393 int32_t SetMicrophoneVolume(uint32_t volume) override {
394 RTC_DLOG(LS_INFO) << __FUNCTION__ << "(" << volume << ")";
395 RTC_CHECK_NOTREACHED();
396 }
397
MicrophoneVolume(uint32_t * volume) const398 int32_t MicrophoneVolume(uint32_t* volume) const override {
399 RTC_DLOG(LS_INFO) << __FUNCTION__;
400 RTC_CHECK_NOTREACHED();
401 }
402
MaxMicrophoneVolume(uint32_t * maxVolume) const403 int32_t MaxMicrophoneVolume(uint32_t* maxVolume) const override {
404 RTC_DLOG(LS_INFO) << __FUNCTION__;
405 RTC_CHECK_NOTREACHED();
406 }
407
MinMicrophoneVolume(uint32_t * minVolume) const408 int32_t MinMicrophoneVolume(uint32_t* minVolume) const override {
409 RTC_DLOG(LS_INFO) << __FUNCTION__;
410 RTC_CHECK_NOTREACHED();
411 }
412
SpeakerMuteIsAvailable(bool * available)413 int32_t SpeakerMuteIsAvailable(bool* available) override {
414 RTC_DLOG(LS_INFO) << __FUNCTION__;
415 RTC_CHECK_NOTREACHED();
416 }
417
SetSpeakerMute(bool enable)418 int32_t SetSpeakerMute(bool enable) override {
419 RTC_DLOG(LS_INFO) << __FUNCTION__ << "(" << enable << ")";
420 RTC_CHECK_NOTREACHED();
421 }
422
SpeakerMute(bool * enabled) const423 int32_t SpeakerMute(bool* enabled) const override {
424 RTC_DLOG(LS_INFO) << __FUNCTION__;
425 RTC_CHECK_NOTREACHED();
426 }
427
MicrophoneMuteIsAvailable(bool * available)428 int32_t MicrophoneMuteIsAvailable(bool* available) override {
429 RTC_DLOG(LS_INFO) << __FUNCTION__;
430 RTC_CHECK_NOTREACHED();
431 }
432
SetMicrophoneMute(bool enable)433 int32_t SetMicrophoneMute(bool enable) override {
434 RTC_DLOG(LS_INFO) << __FUNCTION__ << "(" << enable << ")";
435 RTC_CHECK_NOTREACHED();
436 }
437
MicrophoneMute(bool * enabled) const438 int32_t MicrophoneMute(bool* enabled) const override {
439 RTC_DLOG(LS_INFO) << __FUNCTION__;
440 RTC_CHECK_NOTREACHED();
441 }
442
StereoPlayoutIsAvailable(bool * available) const443 int32_t StereoPlayoutIsAvailable(bool* available) const override {
444 RTC_DLOG(LS_INFO) << __FUNCTION__;
445 *available = is_stereo_playout_supported_;
446 RTC_DLOG(LS_INFO) << "output: " << *available;
447 return 0;
448 }
449
SetStereoPlayout(bool enable)450 int32_t SetStereoPlayout(bool enable) override {
451 RTC_DLOG(LS_INFO) << __FUNCTION__ << "(" << enable << ")";
452 // Android does not support changes between mono and stero on the fly. The
453 // use of stereo or mono is determined by the audio layer. It is allowed
454 // to call this method if that same state is not modified.
455 bool available = is_stereo_playout_supported_;
456 if (enable != available) {
457 RTC_LOG(LS_WARNING) << "changing stereo playout not supported";
458 return -1;
459 }
460 return 0;
461 }
462
StereoPlayout(bool * enabled) const463 int32_t StereoPlayout(bool* enabled) const override {
464 RTC_DLOG(LS_INFO) << __FUNCTION__;
465 *enabled = is_stereo_playout_supported_;
466 RTC_DLOG(LS_INFO) << "output: " << *enabled;
467 return 0;
468 }
469
StereoRecordingIsAvailable(bool * available) const470 int32_t StereoRecordingIsAvailable(bool* available) const override {
471 RTC_DLOG(LS_INFO) << __FUNCTION__;
472 *available = is_stereo_record_supported_;
473 RTC_DLOG(LS_INFO) << "output: " << *available;
474 return 0;
475 }
476
SetStereoRecording(bool enable)477 int32_t SetStereoRecording(bool enable) override {
478 RTC_DLOG(LS_INFO) << __FUNCTION__ << "(" << enable << ")";
479 // Android does not support changes between mono and stero on the fly. The
480 // use of stereo or mono is determined by the audio layer. It is allowed
481 // to call this method if that same state is not modified.
482 bool available = is_stereo_record_supported_;
483 if (enable != available) {
484 RTC_LOG(LS_WARNING) << "changing stereo recording not supported";
485 return -1;
486 }
487 return 0;
488 }
489
StereoRecording(bool * enabled) const490 int32_t StereoRecording(bool* enabled) const override {
491 RTC_DLOG(LS_INFO) << __FUNCTION__;
492 *enabled = is_stereo_record_supported_;
493 RTC_DLOG(LS_INFO) << "output: " << *enabled;
494 return 0;
495 }
496
PlayoutDelay(uint16_t * delay_ms) const497 int32_t PlayoutDelay(uint16_t* delay_ms) const override {
498 // Best guess we can do is to use half of the estimated total delay.
499 *delay_ms = playout_delay_ms_ / 2;
500 RTC_DCHECK_GT(*delay_ms, 0);
501 return 0;
502 }
503
504 // Returns true if the device both supports built in AEC and the device
505 // is not blocklisted.
506 // Currently, if OpenSL ES is used in both directions, this method will still
507 // report the correct value and it has the correct effect. As an example:
508 // a device supports built in AEC and this method returns true. Libjingle
509 // will then disable the WebRTC based AEC and that will work for all devices
510 // (mainly Nexus) even when OpenSL ES is used for input since our current
511 // implementation will enable built-in AEC by default also for OpenSL ES.
512 // The only "bad" thing that happens today is that when Libjingle calls
513 // OpenSLESRecorder::EnableBuiltInAEC() it will not have any real effect and
514 // a "Not Implemented" log will be filed. This non-perfect state will remain
515 // until I have added full support for audio effects based on OpenSL ES APIs.
BuiltInAECIsAvailable() const516 bool BuiltInAECIsAvailable() const override {
517 RTC_DLOG(LS_INFO) << __FUNCTION__;
518 if (!initialized_)
519 return false;
520 bool isAvailable = input_->IsAcousticEchoCancelerSupported();
521 RTC_DLOG(LS_INFO) << "output: " << isAvailable;
522 return isAvailable;
523 }
524
525 // Not implemented for any input device on Android.
BuiltInAGCIsAvailable() const526 bool BuiltInAGCIsAvailable() const override {
527 RTC_DLOG(LS_INFO) << __FUNCTION__;
528 RTC_DLOG(LS_INFO) << "output: " << false;
529 return false;
530 }
531
532 // Returns true if the device both supports built in NS and the device
533 // is not blocklisted.
534 // TODO(henrika): add implementation for OpenSL ES based audio as well.
535 // In addition, see comments for BuiltInAECIsAvailable().
BuiltInNSIsAvailable() const536 bool BuiltInNSIsAvailable() const override {
537 RTC_DLOG(LS_INFO) << __FUNCTION__;
538 if (!initialized_)
539 return false;
540 bool isAvailable = input_->IsNoiseSuppressorSupported();
541 RTC_DLOG(LS_INFO) << "output: " << isAvailable;
542 return isAvailable;
543 }
544
545 // TODO(henrika): add implementation for OpenSL ES based audio as well.
EnableBuiltInAEC(bool enable)546 int32_t EnableBuiltInAEC(bool enable) override {
547 RTC_DLOG(LS_INFO) << __FUNCTION__ << "(" << enable << ")";
548 if (!initialized_)
549 return -1;
550 RTC_CHECK(BuiltInAECIsAvailable()) << "HW AEC is not available";
551 int32_t result = input_->EnableBuiltInAEC(enable);
552 RTC_DLOG(LS_INFO) << "output: " << result;
553 return result;
554 }
555
EnableBuiltInAGC(bool enable)556 int32_t EnableBuiltInAGC(bool enable) override {
557 RTC_DLOG(LS_INFO) << __FUNCTION__ << "(" << enable << ")";
558 RTC_CHECK_NOTREACHED();
559 }
560
561 // TODO(henrika): add implementation for OpenSL ES based audio as well.
EnableBuiltInNS(bool enable)562 int32_t EnableBuiltInNS(bool enable) override {
563 RTC_DLOG(LS_INFO) << __FUNCTION__ << "(" << enable << ")";
564 if (!initialized_)
565 return -1;
566 RTC_CHECK(BuiltInNSIsAvailable()) << "HW NS is not available";
567 int32_t result = input_->EnableBuiltInNS(enable);
568 RTC_DLOG(LS_INFO) << "output: " << result;
569 return result;
570 }
571
GetPlayoutUnderrunCount() const572 int32_t GetPlayoutUnderrunCount() const override {
573 if (!initialized_)
574 return -1;
575 return output_->GetPlayoutUnderrunCount();
576 }
577
AttachAudioBuffer()578 int32_t AttachAudioBuffer() {
579 RTC_DLOG(LS_INFO) << __FUNCTION__;
580 output_->AttachAudioBuffer(audio_device_buffer_.get());
581 input_->AttachAudioBuffer(audio_device_buffer_.get());
582 return 0;
583 }
584
585 private:
586 SequenceChecker thread_checker_;
587
588 const AudioDeviceModule::AudioLayer audio_layer_;
589 const bool is_stereo_playout_supported_;
590 const bool is_stereo_record_supported_;
591 const uint16_t playout_delay_ms_;
592 const std::unique_ptr<TaskQueueFactory> task_queue_factory_;
593 const std::unique_ptr<AudioInput> input_;
594 const std::unique_ptr<AudioOutput> output_;
595 std::unique_ptr<AudioDeviceBuffer> audio_device_buffer_;
596
597 bool initialized_;
598 };
599
600 } // namespace
601
GetAudioManager(JNIEnv * env,const JavaRef<jobject> & j_context)602 ScopedJavaLocalRef<jobject> GetAudioManager(JNIEnv* env,
603 const JavaRef<jobject>& j_context) {
604 return Java_WebRtcAudioManager_getAudioManager(env, j_context);
605 }
606
GetDefaultSampleRate(JNIEnv * env,const JavaRef<jobject> & j_audio_manager)607 int GetDefaultSampleRate(JNIEnv* env, const JavaRef<jobject>& j_audio_manager) {
608 return Java_WebRtcAudioManager_getSampleRate(env, j_audio_manager);
609 }
610
GetAudioParameters(JNIEnv * env,const JavaRef<jobject> & j_context,const JavaRef<jobject> & j_audio_manager,int input_sample_rate,int output_sample_rate,bool use_stereo_input,bool use_stereo_output,AudioParameters * input_parameters,AudioParameters * output_parameters)611 void GetAudioParameters(JNIEnv* env,
612 const JavaRef<jobject>& j_context,
613 const JavaRef<jobject>& j_audio_manager,
614 int input_sample_rate,
615 int output_sample_rate,
616 bool use_stereo_input,
617 bool use_stereo_output,
618 AudioParameters* input_parameters,
619 AudioParameters* output_parameters) {
620 const int output_channels = use_stereo_output ? 2 : 1;
621 const int input_channels = use_stereo_input ? 2 : 1;
622 const size_t output_buffer_size = Java_WebRtcAudioManager_getOutputBufferSize(
623 env, j_context, j_audio_manager, output_sample_rate, output_channels);
624 const size_t input_buffer_size = Java_WebRtcAudioManager_getInputBufferSize(
625 env, j_context, j_audio_manager, input_sample_rate, input_channels);
626 output_parameters->reset(output_sample_rate,
627 static_cast<size_t>(output_channels),
628 static_cast<size_t>(output_buffer_size));
629 input_parameters->reset(input_sample_rate,
630 static_cast<size_t>(input_channels),
631 static_cast<size_t>(input_buffer_size));
632 RTC_CHECK(input_parameters->is_valid());
633 RTC_CHECK(output_parameters->is_valid());
634 }
635
CreateAudioDeviceModuleFromInputAndOutput(AudioDeviceModule::AudioLayer audio_layer,bool is_stereo_playout_supported,bool is_stereo_record_supported,uint16_t playout_delay_ms,std::unique_ptr<AudioInput> audio_input,std::unique_ptr<AudioOutput> audio_output)636 rtc::scoped_refptr<AudioDeviceModule> CreateAudioDeviceModuleFromInputAndOutput(
637 AudioDeviceModule::AudioLayer audio_layer,
638 bool is_stereo_playout_supported,
639 bool is_stereo_record_supported,
640 uint16_t playout_delay_ms,
641 std::unique_ptr<AudioInput> audio_input,
642 std::unique_ptr<AudioOutput> audio_output) {
643 RTC_DLOG(LS_INFO) << __FUNCTION__;
644 return rtc::make_ref_counted<AndroidAudioDeviceModule>(
645 audio_layer, is_stereo_playout_supported, is_stereo_record_supported,
646 playout_delay_ms, std::move(audio_input), std::move(audio_output));
647 }
648
649 } // namespace jni
650 } // namespace webrtc
651