1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 #include "base/message_loop/message_loop.h"
8 #include "base/run_loop.h"
9 #include "media/audio/audio_manager.h"
10 #include "media/audio/audio_manager_base.h"
11 #include "media/audio/audio_output_dispatcher_impl.h"
12 #include "media/audio/audio_output_proxy.h"
13 #include "media/audio/audio_output_resampler.h"
14 #include "media/audio/fake_audio_log_factory.h"
15 #include "media/audio/fake_audio_output_stream.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
20 using ::testing::AllOf
;
21 using ::testing::DoAll
;
22 using ::testing::Field
;
23 using ::testing::Mock
;
24 using ::testing::NotNull
;
25 using ::testing::Return
;
26 using ::testing::SetArrayArgument
;
27 using media::AudioBus
;
28 using media::AudioBuffersState
;
29 using media::AudioInputStream
;
30 using media::AudioManager
;
31 using media::AudioManagerBase
;
32 using media::AudioOutputDispatcher
;
33 using media::AudioOutputProxy
;
34 using media::AudioOutputStream
;
35 using media::AudioParameters
;
36 using media::FakeAudioOutputStream
;
40 static const int kTestCloseDelayMs
= 10;
42 // Delay between callbacks to AudioSourceCallback::OnMoreData.
43 static const int kOnMoreDataCallbackDelayMs
= 10;
45 // Let start run long enough for many OnMoreData callbacks to occur.
46 static const int kStartRunTimeMs
= kOnMoreDataCallbackDelayMs
* 10;
48 class MockAudioOutputStream
: public AudioOutputStream
{
50 MockAudioOutputStream(AudioManagerBase
* manager
,
51 const AudioParameters
& params
)
52 : start_called_(false),
56 FakeAudioOutputStream::MakeFakeStream(manager
, params_
)) {
59 void Start(AudioSourceCallback
* callback
) {
61 fake_output_stream_
->Start(callback
);
66 fake_output_stream_
->Stop();
69 ~MockAudioOutputStream() {}
71 bool start_called() { return start_called_
; }
72 bool stop_called() { return stop_called_
; }
74 MOCK_METHOD0(Open
, bool());
75 MOCK_METHOD1(SetVolume
, void(double volume
));
76 MOCK_METHOD1(GetVolume
, void(double* volume
));
77 MOCK_METHOD0(Close
, void());
82 AudioParameters params_
;
83 scoped_ptr
<AudioOutputStream
> fake_output_stream_
;
86 class MockAudioManager
: public AudioManagerBase
{
88 MockAudioManager() : AudioManagerBase(&fake_audio_log_factory_
) {}
89 virtual ~MockAudioManager() {
93 MOCK_METHOD0(HasAudioOutputDevices
, bool());
94 MOCK_METHOD0(HasAudioInputDevices
, bool());
95 MOCK_METHOD0(GetAudioInputDeviceModel
, base::string16());
96 MOCK_METHOD2(MakeAudioOutputStream
, AudioOutputStream
*(
97 const AudioParameters
& params
,
98 const std::string
& device_id
));
99 MOCK_METHOD2(MakeAudioOutputStreamProxy
, AudioOutputStream
*(
100 const AudioParameters
& params
,
101 const std::string
& device_id
));
102 MOCK_METHOD2(MakeAudioInputStream
, AudioInputStream
*(
103 const AudioParameters
& params
, const std::string
& device_id
));
104 MOCK_METHOD0(ShowAudioInputSettings
, void());
105 MOCK_METHOD0(GetTaskRunner
, scoped_refptr
<base::SingleThreadTaskRunner
>());
106 MOCK_METHOD0(GetWorkerTaskRunner
,
107 scoped_refptr
<base::SingleThreadTaskRunner
>());
108 MOCK_METHOD1(GetAudioInputDeviceNames
, void(
109 media::AudioDeviceNames
* device_name
));
111 MOCK_METHOD1(MakeLinearOutputStream
, AudioOutputStream
*(
112 const AudioParameters
& params
));
113 MOCK_METHOD2(MakeLowLatencyOutputStream
, AudioOutputStream
*(
114 const AudioParameters
& params
, const std::string
& device_id
));
115 MOCK_METHOD2(MakeLinearInputStream
, AudioInputStream
*(
116 const AudioParameters
& params
, const std::string
& device_id
));
117 MOCK_METHOD2(MakeLowLatencyInputStream
, AudioInputStream
*(
118 const AudioParameters
& params
, const std::string
& device_id
));
119 MOCK_METHOD2(GetPreferredOutputStreamParameters
, AudioParameters(
120 const std::string
& device_id
, const AudioParameters
& params
));
123 media::FakeAudioLogFactory fake_audio_log_factory_
;
126 class MockAudioSourceCallback
: public AudioOutputStream::AudioSourceCallback
{
128 int OnMoreData(AudioBus
* audio_bus
, AudioBuffersState buffers_state
) {
130 return audio_bus
->frames();
132 MOCK_METHOD1(OnError
, void(AudioOutputStream
* stream
));
139 class AudioOutputProxyTest
: public testing::Test
{
141 virtual void SetUp() {
142 EXPECT_CALL(manager_
, GetTaskRunner())
143 .WillRepeatedly(Return(message_loop_
.message_loop_proxy()));
144 EXPECT_CALL(manager_
, GetWorkerTaskRunner())
145 .WillRepeatedly(Return(message_loop_
.message_loop_proxy()));
146 // Use a low sample rate and large buffer size when testing otherwise the
147 // FakeAudioOutputStream will keep the message loop busy indefinitely; i.e.,
148 // RunUntilIdle() will never terminate.
149 params_
= AudioParameters(AudioParameters::AUDIO_PCM_LINEAR
,
150 CHANNEL_LAYOUT_STEREO
, 8000, 16, 2048);
151 InitDispatcher(base::TimeDelta::FromMilliseconds(kTestCloseDelayMs
));
154 virtual void TearDown() {
155 // This is necessary to free all proxy objects that have been
156 // closed by the test.
157 message_loop_
.RunUntilIdle();
160 virtual void InitDispatcher(base::TimeDelta close_delay
) {
161 dispatcher_impl_
= new AudioOutputDispatcherImpl(&manager(),
167 virtual void OnStart() {}
169 MockAudioManager
& manager() {
173 void WaitForCloseTimer(MockAudioOutputStream
* stream
) {
174 base::RunLoop run_loop
;
175 EXPECT_CALL(*stream
, Close())
176 .WillOnce(testing::InvokeWithoutArgs(&run_loop
, &base::RunLoop::Quit
));
180 void CloseAndWaitForCloseTimer(AudioOutputProxy
* proxy
,
181 MockAudioOutputStream
* stream
) {
182 // Close the stream and verify it doesn't happen immediately.
184 Mock::VerifyAndClear(stream
);
186 // Wait for the actual close event to come from the close timer.
187 WaitForCloseTimer(stream
);
190 // Basic Open() and Close() test.
191 void OpenAndClose(AudioOutputDispatcher
* dispatcher
) {
192 MockAudioOutputStream
stream(&manager_
, params_
);
194 EXPECT_CALL(manager(), MakeAudioOutputStream(_
, _
))
195 .WillOnce(Return(&stream
));
196 EXPECT_CALL(stream
, Open())
197 .WillOnce(Return(true));
199 AudioOutputProxy
* proxy
= new AudioOutputProxy(dispatcher
);
200 EXPECT_TRUE(proxy
->Open());
201 CloseAndWaitForCloseTimer(proxy
, &stream
);
204 // Creates a stream, and then calls Start() and Stop().
205 void StartAndStop(AudioOutputDispatcher
* dispatcher
) {
206 MockAudioOutputStream
stream(&manager_
, params_
);
208 EXPECT_CALL(manager(), MakeAudioOutputStream(_
, _
))
209 .WillOnce(Return(&stream
));
210 EXPECT_CALL(stream
, Open())
211 .WillOnce(Return(true));
212 EXPECT_CALL(stream
, SetVolume(_
))
215 AudioOutputProxy
* proxy
= new AudioOutputProxy(dispatcher
);
216 EXPECT_TRUE(proxy
->Open());
218 proxy
->Start(&callback_
);
222 CloseAndWaitForCloseTimer(proxy
, &stream
);
223 EXPECT_TRUE(stream
.stop_called());
224 EXPECT_TRUE(stream
.start_called());
227 // Verify that the stream is closed after Stop() is called.
228 void CloseAfterStop(AudioOutputDispatcher
* dispatcher
) {
229 MockAudioOutputStream
stream(&manager_
, params_
);
231 EXPECT_CALL(manager(), MakeAudioOutputStream(_
, _
))
232 .WillOnce(Return(&stream
));
233 EXPECT_CALL(stream
, Open())
234 .WillOnce(Return(true));
235 EXPECT_CALL(stream
, SetVolume(_
))
238 AudioOutputProxy
* proxy
= new AudioOutputProxy(dispatcher
);
239 EXPECT_TRUE(proxy
->Open());
241 proxy
->Start(&callback_
);
245 // Wait for the close timer to fire after StopStream().
246 WaitForCloseTimer(&stream
);
248 EXPECT_TRUE(stream
.stop_called());
249 EXPECT_TRUE(stream
.start_called());
252 // Create two streams, but don't start them. Only one device must be opened.
253 void TwoStreams(AudioOutputDispatcher
* dispatcher
) {
254 MockAudioOutputStream
stream(&manager_
, params_
);
256 EXPECT_CALL(manager(), MakeAudioOutputStream(_
, _
))
257 .WillOnce(Return(&stream
));
258 EXPECT_CALL(stream
, Open())
259 .WillOnce(Return(true));
261 AudioOutputProxy
* proxy1
= new AudioOutputProxy(dispatcher
);
262 AudioOutputProxy
* proxy2
= new AudioOutputProxy(dispatcher
);
263 EXPECT_TRUE(proxy1
->Open());
264 EXPECT_TRUE(proxy2
->Open());
266 CloseAndWaitForCloseTimer(proxy2
, &stream
);
267 EXPECT_FALSE(stream
.stop_called());
268 EXPECT_FALSE(stream
.start_called());
271 // Open() method failed.
272 void OpenFailed(AudioOutputDispatcher
* dispatcher
) {
273 MockAudioOutputStream
stream(&manager_
, params_
);
275 EXPECT_CALL(manager(), MakeAudioOutputStream(_
, _
))
276 .WillOnce(Return(&stream
));
277 EXPECT_CALL(stream
, Open())
278 .WillOnce(Return(false));
279 EXPECT_CALL(stream
, Close())
282 AudioOutputProxy
* proxy
= new AudioOutputProxy(dispatcher
);
283 EXPECT_FALSE(proxy
->Open());
285 EXPECT_FALSE(stream
.stop_called());
286 EXPECT_FALSE(stream
.start_called());
289 void CreateAndWait(AudioOutputDispatcher
* dispatcher
) {
290 MockAudioOutputStream
stream(&manager_
, params_
);
292 EXPECT_CALL(manager(), MakeAudioOutputStream(_
, _
))
293 .WillOnce(Return(&stream
));
294 EXPECT_CALL(stream
, Open())
295 .WillOnce(Return(true));
297 AudioOutputProxy
* proxy
= new AudioOutputProxy(dispatcher
);
298 EXPECT_TRUE(proxy
->Open());
300 WaitForCloseTimer(&stream
);
302 EXPECT_FALSE(stream
.stop_called());
303 EXPECT_FALSE(stream
.start_called());
306 void OneStream_TwoPlays(AudioOutputDispatcher
* dispatcher
) {
307 MockAudioOutputStream
stream(&manager_
, params_
);
309 EXPECT_CALL(manager(), MakeAudioOutputStream(_
, _
))
310 .WillOnce(Return(&stream
));
312 EXPECT_CALL(stream
, Open())
313 .WillOnce(Return(true));
314 EXPECT_CALL(stream
, SetVolume(_
))
317 AudioOutputProxy
* proxy1
= new AudioOutputProxy(dispatcher
);
318 EXPECT_TRUE(proxy1
->Open());
320 proxy1
->Start(&callback_
);
324 // The stream should now be idle and get reused by |proxy2|.
325 AudioOutputProxy
* proxy2
= new AudioOutputProxy(dispatcher
);
326 EXPECT_TRUE(proxy2
->Open());
327 proxy2
->Start(&callback_
);
332 CloseAndWaitForCloseTimer(proxy2
, &stream
);
333 EXPECT_TRUE(stream
.stop_called());
334 EXPECT_TRUE(stream
.start_called());
337 void TwoStreams_BothPlaying(AudioOutputDispatcher
* dispatcher
) {
338 MockAudioOutputStream
stream1(&manager_
, params_
);
339 MockAudioOutputStream
stream2(&manager_
, params_
);
341 EXPECT_CALL(manager(), MakeAudioOutputStream(_
, _
))
342 .WillOnce(Return(&stream1
))
343 .WillOnce(Return(&stream2
));
345 EXPECT_CALL(stream1
, Open())
346 .WillOnce(Return(true));
347 EXPECT_CALL(stream1
, SetVolume(_
))
350 EXPECT_CALL(stream2
, Open())
351 .WillOnce(Return(true));
352 EXPECT_CALL(stream2
, SetVolume(_
))
355 AudioOutputProxy
* proxy1
= new AudioOutputProxy(dispatcher
);
356 AudioOutputProxy
* proxy2
= new AudioOutputProxy(dispatcher
);
357 EXPECT_TRUE(proxy1
->Open());
358 EXPECT_TRUE(proxy2
->Open());
360 proxy1
->Start(&callback_
);
361 proxy2
->Start(&callback_
);
364 CloseAndWaitForCloseTimer(proxy1
, &stream1
);
367 CloseAndWaitForCloseTimer(proxy2
, &stream2
);
369 EXPECT_TRUE(stream1
.stop_called());
370 EXPECT_TRUE(stream1
.start_called());
371 EXPECT_TRUE(stream2
.stop_called());
372 EXPECT_TRUE(stream2
.start_called());
375 void StartFailed(AudioOutputDispatcher
* dispatcher
) {
376 MockAudioOutputStream
stream(&manager_
, params_
);
378 EXPECT_CALL(manager(), MakeAudioOutputStream(_
, _
))
379 .WillOnce(Return(&stream
));
380 EXPECT_CALL(stream
, Open())
381 .WillOnce(Return(true));
383 AudioOutputProxy
* proxy
= new AudioOutputProxy(dispatcher
);
384 EXPECT_TRUE(proxy
->Open());
386 WaitForCloseTimer(&stream
);
388 // |stream| is closed at this point. Start() should reopen it again.
389 EXPECT_CALL(manager(), MakeAudioOutputStream(_
, _
))
391 .WillRepeatedly(Return(reinterpret_cast<AudioOutputStream
*>(NULL
)));
393 EXPECT_CALL(callback_
, OnError(_
))
396 proxy
->Start(&callback_
);
398 // Double Start() in the error case should be allowed since it's possible a
399 // callback may not have had time to process the OnError() in between.
401 proxy
->Start(&callback_
);
403 Mock::VerifyAndClear(&callback_
);
408 base::MessageLoop message_loop_
;
409 scoped_refptr
<AudioOutputDispatcherImpl
> dispatcher_impl_
;
410 MockAudioManager manager_
;
411 MockAudioSourceCallback callback_
;
412 AudioParameters params_
;
415 class AudioOutputResamplerTest
: public AudioOutputProxyTest
{
417 virtual void TearDown() {
418 AudioOutputProxyTest::TearDown();
421 virtual void InitDispatcher(base::TimeDelta close_delay
) OVERRIDE
{
422 // Use a low sample rate and large buffer size when testing otherwise the
423 // FakeAudioOutputStream will keep the message loop busy indefinitely; i.e.,
424 // RunUntilIdle() will never terminate.
425 resampler_params_
= AudioParameters(
426 AudioParameters::AUDIO_PCM_LOW_LATENCY
, CHANNEL_LAYOUT_STEREO
,
428 resampler_
= new AudioOutputResampler(
429 &manager(), params_
, resampler_params_
, std::string(), close_delay
);
432 virtual void OnStart() OVERRIDE
{
433 // Let Start() run for a bit.
434 base::RunLoop run_loop
;
435 message_loop_
.PostDelayedTask(
437 run_loop
.QuitClosure(),
438 base::TimeDelta::FromMilliseconds(kStartRunTimeMs
));
443 AudioParameters resampler_params_
;
444 scoped_refptr
<AudioOutputResampler
> resampler_
;
447 TEST_F(AudioOutputProxyTest
, CreateAndClose
) {
448 AudioOutputProxy
* proxy
= new AudioOutputProxy(dispatcher_impl_
);
452 TEST_F(AudioOutputResamplerTest
, CreateAndClose
) {
453 AudioOutputProxy
* proxy
= new AudioOutputProxy(resampler_
);
457 TEST_F(AudioOutputProxyTest
, OpenAndClose
) {
458 OpenAndClose(dispatcher_impl_
);
461 TEST_F(AudioOutputResamplerTest
, OpenAndClose
) {
462 OpenAndClose(resampler_
);
465 // Create a stream, and verify that it is closed after kTestCloseDelayMs.
466 // if it doesn't start playing.
467 TEST_F(AudioOutputProxyTest
, CreateAndWait
) {
468 CreateAndWait(dispatcher_impl_
);
471 // Create a stream, and verify that it is closed after kTestCloseDelayMs.
472 // if it doesn't start playing.
473 TEST_F(AudioOutputResamplerTest
, CreateAndWait
) {
474 CreateAndWait(resampler_
);
477 TEST_F(AudioOutputProxyTest
, StartAndStop
) {
478 StartAndStop(dispatcher_impl_
);
481 TEST_F(AudioOutputResamplerTest
, StartAndStop
) {
482 StartAndStop(resampler_
);
485 TEST_F(AudioOutputProxyTest
, CloseAfterStop
) {
486 CloseAfterStop(dispatcher_impl_
);
489 TEST_F(AudioOutputResamplerTest
, CloseAfterStop
) {
490 CloseAfterStop(resampler_
);
493 TEST_F(AudioOutputProxyTest
, TwoStreams
) { TwoStreams(dispatcher_impl_
); }
495 TEST_F(AudioOutputResamplerTest
, TwoStreams
) { TwoStreams(resampler_
); }
497 // Two streams: verify that second stream is allocated when the first
499 TEST_F(AudioOutputProxyTest
, OneStream_TwoPlays
) {
500 OneStream_TwoPlays(dispatcher_impl_
);
503 TEST_F(AudioOutputResamplerTest
, OneStream_TwoPlays
) {
504 OneStream_TwoPlays(resampler_
);
507 // Two streams, both are playing. Dispatcher should not open a third stream.
508 TEST_F(AudioOutputProxyTest
, TwoStreams_BothPlaying
) {
509 TwoStreams_BothPlaying(dispatcher_impl_
);
512 TEST_F(AudioOutputResamplerTest
, TwoStreams_BothPlaying
) {
513 TwoStreams_BothPlaying(resampler_
);
516 TEST_F(AudioOutputProxyTest
, OpenFailed
) { OpenFailed(dispatcher_impl_
); }
518 // Start() method failed.
519 TEST_F(AudioOutputProxyTest
, StartFailed
) {
520 StartFailed(dispatcher_impl_
);
523 TEST_F(AudioOutputResamplerTest
, StartFailed
) { StartFailed(resampler_
); }
525 // Simulate AudioOutputStream::Create() failure with a low latency stream and
526 // ensure AudioOutputResampler falls back to the high latency path.
527 TEST_F(AudioOutputResamplerTest
, LowLatencyCreateFailedFallback
) {
528 MockAudioOutputStream
stream(&manager_
, params_
);
529 EXPECT_CALL(manager(), MakeAudioOutputStream(_
, _
))
531 .WillOnce(Return(static_cast<AudioOutputStream
*>(NULL
)))
532 .WillRepeatedly(Return(&stream
));
533 EXPECT_CALL(stream
, Open())
534 .WillOnce(Return(true));
536 AudioOutputProxy
* proxy
= new AudioOutputProxy(resampler_
);
537 EXPECT_TRUE(proxy
->Open());
538 CloseAndWaitForCloseTimer(proxy
, &stream
);
541 // Simulate AudioOutputStream::Open() failure with a low latency stream and
542 // ensure AudioOutputResampler falls back to the high latency path.
543 TEST_F(AudioOutputResamplerTest
, LowLatencyOpenFailedFallback
) {
544 MockAudioOutputStream
failed_stream(&manager_
, params_
);
545 MockAudioOutputStream
okay_stream(&manager_
, params_
);
546 EXPECT_CALL(manager(), MakeAudioOutputStream(_
, _
))
548 .WillOnce(Return(&failed_stream
))
549 .WillRepeatedly(Return(&okay_stream
));
550 EXPECT_CALL(failed_stream
, Open())
551 .WillOnce(Return(false));
552 EXPECT_CALL(failed_stream
, Close())
554 EXPECT_CALL(okay_stream
, Open())
555 .WillOnce(Return(true));
557 AudioOutputProxy
* proxy
= new AudioOutputProxy(resampler_
);
558 EXPECT_TRUE(proxy
->Open());
559 CloseAndWaitForCloseTimer(proxy
, &okay_stream
);
562 // Simulate failures to open both the low latency and the fallback high latency
563 // stream and ensure AudioOutputResampler falls back to a fake stream.
564 TEST_F(AudioOutputResamplerTest
, HighLatencyFallbackFailed
) {
565 MockAudioOutputStream
okay_stream(&manager_
, params_
);
567 // Only Windows has a high latency output driver that is not the same as the low
570 static const int kFallbackCount
= 2;
572 static const int kFallbackCount
= 1;
574 EXPECT_CALL(manager(), MakeAudioOutputStream(_
, _
))
575 .Times(kFallbackCount
)
576 .WillRepeatedly(Return(static_cast<AudioOutputStream
*>(NULL
)));
578 // To prevent shared memory issues the sample rate and buffer size should
579 // match the input stream parameters.
580 EXPECT_CALL(manager(), MakeAudioOutputStream(AllOf(
581 testing::Property(&AudioParameters::format
, AudioParameters::AUDIO_FAKE
),
582 testing::Property(&AudioParameters::sample_rate
, params_
.sample_rate()),
584 &AudioParameters::frames_per_buffer
, params_
.frames_per_buffer())),
587 .WillOnce(Return(&okay_stream
));
588 EXPECT_CALL(okay_stream
, Open())
589 .WillOnce(Return(true));
591 AudioOutputProxy
* proxy
= new AudioOutputProxy(resampler_
);
592 EXPECT_TRUE(proxy
->Open());
593 CloseAndWaitForCloseTimer(proxy
, &okay_stream
);
596 // Simulate failures to open both the low latency, the fallback high latency
597 // stream, and the fake audio output stream and ensure AudioOutputResampler
598 // terminates normally.
599 TEST_F(AudioOutputResamplerTest
, AllFallbackFailed
) {
600 // Only Windows has a high latency output driver that is not the same as the low
603 static const int kFallbackCount
= 3;
605 static const int kFallbackCount
= 2;
607 EXPECT_CALL(manager(), MakeAudioOutputStream(_
, _
))
608 .Times(kFallbackCount
)
609 .WillRepeatedly(Return(static_cast<AudioOutputStream
*>(NULL
)));
611 AudioOutputProxy
* proxy
= new AudioOutputProxy(resampler_
);
612 EXPECT_FALSE(proxy
->Open());
616 // Simulate an eventual OpenStream() failure; i.e. successful OpenStream() calls
617 // eventually followed by one which fails; root cause of http://crbug.com/150619
618 TEST_F(AudioOutputResamplerTest
, LowLatencyOpenEventuallyFails
) {
619 MockAudioOutputStream
stream1(&manager_
, params_
);
620 MockAudioOutputStream
stream2(&manager_
, params_
);
622 // Setup the mock such that all three streams are successfully created.
623 EXPECT_CALL(manager(), MakeAudioOutputStream(_
, _
))
624 .WillOnce(Return(&stream1
))
625 .WillOnce(Return(&stream2
))
626 .WillRepeatedly(Return(static_cast<AudioOutputStream
*>(NULL
)));
628 // Stream1 should be able to successfully open and start.
629 EXPECT_CALL(stream1
, Open())
630 .WillOnce(Return(true));
631 EXPECT_CALL(stream1
, SetVolume(_
))
634 // Stream2 should also be able to successfully open and start.
635 EXPECT_CALL(stream2
, Open())
636 .WillOnce(Return(true));
637 EXPECT_CALL(stream2
, SetVolume(_
))
640 // Open and start the first proxy and stream.
641 AudioOutputProxy
* proxy1
= new AudioOutputProxy(resampler_
);
642 EXPECT_TRUE(proxy1
->Open());
643 proxy1
->Start(&callback_
);
646 // Open and start the second proxy and stream.
647 AudioOutputProxy
* proxy2
= new AudioOutputProxy(resampler_
);
648 EXPECT_TRUE(proxy2
->Open());
649 proxy2
->Start(&callback_
);
652 // Attempt to open the third stream which should fail.
653 AudioOutputProxy
* proxy3
= new AudioOutputProxy(resampler_
);
654 EXPECT_FALSE(proxy3
->Open());
657 // Perform the required Stop()/Close() shutdown dance for each proxy. Under
658 // the hood each proxy should correctly call CloseStream() if OpenStream()
661 CloseAndWaitForCloseTimer(proxy2
, &stream2
);
664 CloseAndWaitForCloseTimer(proxy1
, &stream1
);
666 EXPECT_TRUE(stream1
.stop_called());
667 EXPECT_TRUE(stream1
.start_called());
668 EXPECT_TRUE(stream2
.stop_called());
669 EXPECT_TRUE(stream2
.start_called());