Skip to content
This repository was archived by the owner on Oct 25, 2024. It is now read-only.

Commit 254ad1b

Browse files
timnaCommit Bot
authored andcommitted
Delay VoipCore initialization.
Starting from Android N, mobile app may not be able to access microphone while in background where it fails the call. In order to mitigate the issue, delay the ADM initialization as late as possible. Bug: webrtc:12120 Change-Id: I0fbf0300299b6c53413dfaaf88f748edc0a06bc1 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/191100 Commit-Queue: Tim Na <[email protected]> Reviewed-by: Karl Wiberg <[email protected]> Reviewed-by: Per Åhgren <[email protected]> Cr-Commit-Position: refs/heads/master@{#32598}
1 parent 428432d commit 254ad1b

File tree

5 files changed

+61
-39
lines changed

5 files changed

+61
-39
lines changed

api/voip/voip_engine_factory.cc

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,11 @@ std::unique_ptr<VoipEngine> CreateVoipEngine(VoipEngineConfig config) {
2727
RTC_DLOG(INFO) << "No audio processing functionality provided.";
2828
}
2929

30-
auto voip_core = std::make_unique<VoipCore>();
31-
32-
if (!voip_core->Init(std::move(config.encoder_factory),
33-
std::move(config.decoder_factory),
34-
std::move(config.task_queue_factory),
35-
std::move(config.audio_device_module),
36-
std::move(config.audio_processing))) {
37-
RTC_DLOG(LS_ERROR) << "Failed to initialize VoIP core.";
38-
return nullptr;
39-
}
40-
41-
return voip_core;
30+
return std::make_unique<VoipCore>(std::move(config.encoder_factory),
31+
std::move(config.decoder_factory),
32+
std::move(config.task_queue_factory),
33+
std::move(config.audio_device_module),
34+
std::move(config.audio_processing));
4235
}
4336

4437
} // namespace webrtc

api/voip/voip_engine_factory.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,6 @@ struct VoipEngineConfig {
6161
};
6262

6363
// Creates a VoipEngine instance with provided VoipEngineConfig.
64-
// This could return nullptr if AudioDeviceModule (ADM) initialization fails
65-
// during construction of VoipEngine which would render VoipEngine
66-
// nonfunctional.
6764
std::unique_ptr<VoipEngine> CreateVoipEngine(VoipEngineConfig config);
6865

6966
} // namespace webrtc

audio/voip/test/voip_core_unittest.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ class VoipCoreTest : public ::testing::Test {
4545
// Hold the pointer to use for testing.
4646
process_thread_ = process_thread.get();
4747

48-
voip_core_ = std::make_unique<VoipCore>();
49-
voip_core_->Init(std::move(encoder_factory), std::move(decoder_factory),
50-
CreateDefaultTaskQueueFactory(), audio_device_,
51-
std::move(audio_processing), std::move(process_thread));
48+
voip_core_ = std::make_unique<VoipCore>(
49+
std::move(encoder_factory), std::move(decoder_factory),
50+
CreateDefaultTaskQueueFactory(), audio_device_,
51+
std::move(audio_processing), std::move(process_thread));
5252
}
5353

5454
std::unique_ptr<VoipCore> voip_core_;

audio/voip/voip_core.cc

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,12 @@ static constexpr int kMaxChannelId = 100000;
3737

3838
} // namespace
3939

40-
bool VoipCore::Init(rtc::scoped_refptr<AudioEncoderFactory> encoder_factory,
41-
rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
42-
std::unique_ptr<TaskQueueFactory> task_queue_factory,
43-
rtc::scoped_refptr<AudioDeviceModule> audio_device_module,
44-
rtc::scoped_refptr<AudioProcessing> audio_processing,
45-
std::unique_ptr<ProcessThread> process_thread) {
40+
VoipCore::VoipCore(rtc::scoped_refptr<AudioEncoderFactory> encoder_factory,
41+
rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
42+
std::unique_ptr<TaskQueueFactory> task_queue_factory,
43+
rtc::scoped_refptr<AudioDeviceModule> audio_device_module,
44+
rtc::scoped_refptr<AudioProcessing> audio_processing,
45+
std::unique_ptr<ProcessThread> process_thread) {
4646
encoder_factory_ = std::move(encoder_factory);
4747
decoder_factory_ = std::move(decoder_factory);
4848
task_queue_factory_ = std::move(task_queue_factory);
@@ -58,6 +58,18 @@ bool VoipCore::Init(rtc::scoped_refptr<AudioEncoderFactory> encoder_factory,
5858
// AudioTransportImpl depends on audio mixer and audio processing instances.
5959
audio_transport_ = std::make_unique<AudioTransportImpl>(
6060
audio_mixer_.get(), audio_processing_.get(), nullptr);
61+
}
62+
63+
bool VoipCore::InitializeIfNeeded() {
64+
// |audio_device_module_| internally owns a lock and the whole logic here
65+
// needs to be executed atomically once using another lock in VoipCore.
66+
// Further changes in this method will need to make sure that no deadlock is
67+
// introduced in the future.
68+
MutexLock lock(&lock_);
69+
70+
if (initialized_) {
71+
return true;
72+
}
6173

6274
// Initialize ADM.
6375
if (audio_device_module_->Init() != 0) {
@@ -70,7 +82,6 @@ bool VoipCore::Init(rtc::scoped_refptr<AudioEncoderFactory> encoder_factory,
7082
// recording device functioning (e.g webinar where only speaker is available).
7183
// It's also possible that there are other audio devices available that may
7284
// work.
73-
// TODO([email protected]): consider moving this part out of initialization.
7485

7586
// Initialize default speaker device.
7687
if (audio_device_module_->SetPlayoutDevice(kAudioDeviceId) != 0) {
@@ -111,6 +122,8 @@ bool VoipCore::Init(rtc::scoped_refptr<AudioEncoderFactory> encoder_factory,
111122
RTC_LOG(LS_WARNING) << "Unable to register audio callback.";
112123
}
113124

125+
initialized_ = true;
126+
114127
return true;
115128
}
116129

@@ -243,6 +256,11 @@ bool VoipCore::UpdateAudioTransportWithSenders() {
243256

244257
// Depending on availability of senders, turn on or off ADM recording.
245258
if (!audio_senders.empty()) {
259+
// Initialize audio device module and default device if needed.
260+
if (!InitializeIfNeeded()) {
261+
return false;
262+
}
263+
246264
if (!audio_device_module_->Recording()) {
247265
if (audio_device_module_->InitRecording() != 0) {
248266
RTC_LOG(LS_ERROR) << "InitRecording failed";
@@ -300,6 +318,11 @@ bool VoipCore::StartPlayout(ChannelId channel_id) {
300318
return false;
301319
}
302320

321+
// Initialize audio device module and default device if needed.
322+
if (!InitializeIfNeeded()) {
323+
return false;
324+
}
325+
303326
if (!audio_device_module_->Playing()) {
304327
if (audio_device_module_->InitPlayout() != 0) {
305328
RTC_LOG(LS_ERROR) << "InitPlayout failed";

audio/voip/voip_core.h

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -51,21 +51,17 @@ class VoipCore : public VoipEngine,
5151
public VoipDtmf,
5252
public VoipStatistics {
5353
public:
54-
~VoipCore() override = default;
55-
56-
// Initialize VoipCore components with provided arguments.
57-
// Returns false only when |audio_device_module| fails to initialize which
58-
// would presumably render further processing useless.
54+
// Construct VoipCore with provided arguments.
5955
// ProcessThread implementation can be injected by |process_thread|
6056
// (mainly for testing purpose) and when set to nullptr, default
6157
// implementation will be used.
62-
// TODO([email protected]): Need to report audio device errors to user layer.
63-
bool Init(rtc::scoped_refptr<AudioEncoderFactory> encoder_factory,
64-
rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
65-
std::unique_ptr<TaskQueueFactory> task_queue_factory,
66-
rtc::scoped_refptr<AudioDeviceModule> audio_device_module,
67-
rtc::scoped_refptr<AudioProcessing> audio_processing,
68-
std::unique_ptr<ProcessThread> process_thread = nullptr);
58+
VoipCore(rtc::scoped_refptr<AudioEncoderFactory> encoder_factory,
59+
rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
60+
std::unique_ptr<TaskQueueFactory> task_queue_factory,
61+
rtc::scoped_refptr<AudioDeviceModule> audio_device_module,
62+
rtc::scoped_refptr<AudioProcessing> audio_processing,
63+
std::unique_ptr<ProcessThread> process_thread = nullptr);
64+
~VoipCore() override = default;
6965

7066
// Implements VoipEngine interfaces.
7167
VoipBase& Base() override { return *this; }
@@ -111,6 +107,16 @@ class VoipCore : public VoipEngine,
111107
ChannelId channel_id) override;
112108

113109
private:
110+
// Initialize ADM and default audio device if needed.
111+
// Returns true if ADM is successfully initialized or already in such state
112+
// (e.g called more than once). Returns false when ADM fails to initialize
113+
// which would presumably render further processing useless. Note that such
114+
// failure won't necessarily succeed in next initialization attempt as it
115+
// would mean changing the ADM implementation. From Android N and onwards, the
116+
// mobile app may not be able to gain microphone access when in background
117+
// mode. Therefore it would be better to delay the logic as late as possible.
118+
bool InitializeIfNeeded();
119+
114120
// Fetches the corresponding AudioChannel assigned with given |channel|.
115121
// Returns nullptr if not found.
116122
rtc::scoped_refptr<AudioChannel> GetChannel(ChannelId channel_id);
@@ -126,7 +132,7 @@ class VoipCore : public VoipEngine,
126132
rtc::scoped_refptr<AudioDecoderFactory> decoder_factory_;
127133
std::unique_ptr<TaskQueueFactory> task_queue_factory_;
128134

129-
// Synchronization is handled internally by AudioProessing.
135+
// Synchronization is handled internally by AudioProcessing.
130136
// Must be placed before |audio_device_module_| for proper destruction.
131137
rtc::scoped_refptr<AudioProcessing> audio_processing_;
132138

@@ -154,6 +160,9 @@ class VoipCore : public VoipEngine,
154160
// ChannelId.
155161
std::unordered_map<ChannelId, rtc::scoped_refptr<AudioChannel>> channels_
156162
RTC_GUARDED_BY(lock_);
163+
164+
// Boolean flag to ensure initialization only occurs once.
165+
bool initialized_ RTC_GUARDED_BY(lock_) = false;
157166
};
158167

159168
} // namespace webrtc

0 commit comments

Comments
 (0)