| Index: media/audio/audio_output_proxy_unittest.cc
 | 
| ===================================================================
 | 
| --- media/audio/audio_output_proxy_unittest.cc	(revision 129817)
 | 
| +++ media/audio/audio_output_proxy_unittest.cc	(working copy)
 | 
| @@ -2,10 +2,13 @@
 | 
|  // Use of this source code is governed by a BSD-style license that can be
 | 
|  // found in the LICENSE file.
 | 
|  
 | 
| +#include <string>
 | 
| +
 | 
|  #include "base/message_loop.h"
 | 
|  #include "base/message_loop_proxy.h"
 | 
|  #include "base/threading/platform_thread.h"
 | 
| -#include "media/audio/audio_output_dispatcher.h"
 | 
| +#include "media/audio/audio_output_dispatcher_impl.h"
 | 
| +#include "media/audio/audio_output_mixer.h"
 | 
|  #include "media/audio/audio_output_proxy.h"
 | 
|  #include "media/audio/audio_manager.h"
 | 
|  #include "testing/gmock/include/gmock/gmock.h"
 | 
| @@ -75,7 +78,7 @@
 | 
|  
 | 
|    virtual void TearDown() {
 | 
|      // All paused proxies should have been closed at this point.
 | 
| -    EXPECT_EQ(0u, dispatcher_->paused_proxies_);
 | 
| +    EXPECT_EQ(0u, dispatcher_impl_->paused_proxies_);
 | 
|  
 | 
|      // This is necessary to free all proxy objects that have been
 | 
|      // closed by the test.
 | 
| @@ -85,42 +88,179 @@
 | 
|    void InitDispatcher(base::TimeDelta close_delay) {
 | 
|      AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
 | 
|                             CHANNEL_LAYOUT_STEREO, 44100, 16, 1024);
 | 
| -    dispatcher_ = new AudioOutputDispatcher(&manager(), params, close_delay);
 | 
| +    dispatcher_impl_ = new AudioOutputDispatcherImpl(&manager(),
 | 
| +                                                     params,
 | 
| +                                                     close_delay);
 | 
| +    mixer_ = new AudioOutputMixer(&manager(), params, close_delay);
 | 
|  
 | 
|      // Necessary to know how long the dispatcher will wait before posting
 | 
|      // StopStreamTask.
 | 
| -    pause_delay_ = dispatcher_->pause_delay_;
 | 
| +    pause_delay_ = dispatcher_impl_->pause_delay_;
 | 
|    }
 | 
|  
 | 
|    MockAudioManager& manager() {
 | 
|      return manager_;
 | 
|    }
 | 
|  
 | 
| +  // Methods that do actual tests.
 | 
| +  void OpenAndClose(AudioOutputDispatcher* dispatcher) {
 | 
| +    MockAudioOutputStream stream;
 | 
| +
 | 
| +    EXPECT_CALL(manager(), MakeAudioOutputStream(_))
 | 
| +        .WillOnce(Return(&stream));
 | 
| +    EXPECT_CALL(stream, Open())
 | 
| +        .WillOnce(Return(true));
 | 
| +    EXPECT_CALL(stream, Close())
 | 
| +        .Times(1);
 | 
| +
 | 
| +    AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher);
 | 
| +    EXPECT_TRUE(proxy->Open());
 | 
| +    proxy->Close();
 | 
| +
 | 
| +    // Wait for the close timer to fire.
 | 
| +    base::PlatformThread::Sleep(
 | 
| +        base::TimeDelta::FromMilliseconds(kTestCloseDelayMs) * 2);
 | 
| +    message_loop_.RunAllPending();
 | 
| +  }
 | 
| +
 | 
| +  // Create a stream, and then calls Start() and Stop().
 | 
| +  void StartAndStop(AudioOutputDispatcher* dispatcher) {
 | 
| +    MockAudioOutputStream stream;
 | 
| +
 | 
| +    EXPECT_CALL(manager(), MakeAudioOutputStream(_))
 | 
| +        .WillOnce(Return(&stream));
 | 
| +    EXPECT_CALL(stream, Open())
 | 
| +        .WillOnce(Return(true));
 | 
| +    EXPECT_CALL(stream, Start(_))
 | 
| +        .Times(1);
 | 
| +    EXPECT_CALL(stream, SetVolume(_))
 | 
| +        .Times(1);
 | 
| +    EXPECT_CALL(stream, Stop())
 | 
| +        .Times(1);
 | 
| +    EXPECT_CALL(stream, Close())
 | 
| +        .Times(1);
 | 
| +
 | 
| +    AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher);
 | 
| +    EXPECT_TRUE(proxy->Open());
 | 
| +
 | 
| +    proxy->Start(&callback_);
 | 
| +    proxy->Stop();
 | 
| +
 | 
| +    proxy->Close();
 | 
| +
 | 
| +    // Wait for the close timer to fire.
 | 
| +    base::PlatformThread::Sleep(
 | 
| +        base::TimeDelta::FromMilliseconds(kTestCloseDelayMs) * 2);
 | 
| +    message_loop_.RunAllPending();
 | 
| +  }
 | 
| +
 | 
| +  // Verify that the stream is closed after Stop is called.
 | 
| +  void CloseAfterStop(AudioOutputDispatcher* dispatcher) {
 | 
| +    MockAudioOutputStream stream;
 | 
| +
 | 
| +    EXPECT_CALL(manager(), MakeAudioOutputStream(_))
 | 
| +        .WillOnce(Return(&stream));
 | 
| +    EXPECT_CALL(stream, Open())
 | 
| +        .WillOnce(Return(true));
 | 
| +    EXPECT_CALL(stream, Start(_))
 | 
| +        .Times(1);
 | 
| +    EXPECT_CALL(stream, SetVolume(_))
 | 
| +        .Times(1);
 | 
| +    EXPECT_CALL(stream, Stop())
 | 
| +        .Times(1);
 | 
| +    EXPECT_CALL(stream, Close())
 | 
| +        .Times(1);
 | 
| +
 | 
| +    AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher);
 | 
| +    EXPECT_TRUE(proxy->Open());
 | 
| +
 | 
| +    proxy->Start(&callback_);
 | 
| +    proxy->Stop();
 | 
| +
 | 
| +    // Wait for StreamStopped() to post StopStreamTask().
 | 
| +    base::PlatformThread::Sleep(pause_delay_ * 2);
 | 
| +    message_loop_.RunAllPending();
 | 
| +
 | 
| +    // Wait for the close timer to fire.
 | 
| +    base::PlatformThread::Sleep(
 | 
| +        base::TimeDelta::FromMilliseconds(kTestCloseDelayMs) * 2);
 | 
| +    message_loop_.RunAllPending();
 | 
| +
 | 
| +    // Verify expectation before calling Close().
 | 
| +    Mock::VerifyAndClear(&stream);
 | 
| +
 | 
| +    proxy->Close();
 | 
| +  }
 | 
| +
 | 
| +  // Create two streams, but don't start them. Only one device must be open.
 | 
| +  void TwoStreams(AudioOutputDispatcher* dispatcher) {
 | 
| +    MockAudioOutputStream stream;
 | 
| +
 | 
| +    EXPECT_CALL(manager(), MakeAudioOutputStream(_))
 | 
| +        .WillOnce(Return(&stream));
 | 
| +    EXPECT_CALL(stream, Open())
 | 
| +        .WillOnce(Return(true));
 | 
| +    EXPECT_CALL(stream, Close())
 | 
| +        .Times(1);
 | 
| +
 | 
| +    AudioOutputProxy* proxy1 = new AudioOutputProxy(dispatcher);
 | 
| +    AudioOutputProxy* proxy2 = new AudioOutputProxy(dispatcher);
 | 
| +    EXPECT_TRUE(proxy1->Open());
 | 
| +    EXPECT_TRUE(proxy2->Open());
 | 
| +    proxy1->Close();
 | 
| +    proxy2->Close();
 | 
| +
 | 
| +    // Wait for the close timer to fire.
 | 
| +    base::PlatformThread::Sleep(
 | 
| +        base::TimeDelta::FromMilliseconds(kTestCloseDelayMs) * 2);
 | 
| +    message_loop_.RunAllPending();
 | 
| +  }
 | 
| +
 | 
| +  // Open() method failed.
 | 
| +  void OpenFailed(AudioOutputDispatcher* dispatcher) {
 | 
| +    MockAudioOutputStream stream;
 | 
| +
 | 
| +    EXPECT_CALL(manager(), MakeAudioOutputStream(_))
 | 
| +        .WillOnce(Return(&stream));
 | 
| +    EXPECT_CALL(stream, Open())
 | 
| +        .WillOnce(Return(false));
 | 
| +    EXPECT_CALL(stream, Close())
 | 
| +        .Times(1);
 | 
| +
 | 
| +    AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher);
 | 
| +    EXPECT_FALSE(proxy->Open());
 | 
| +    proxy->Close();
 | 
| +
 | 
| +    // Wait for the close timer to fire.
 | 
| +    base::PlatformThread::Sleep(
 | 
| +        base::TimeDelta::FromMilliseconds(kTestCloseDelayMs) * 2);
 | 
| +    message_loop_.RunAllPending();
 | 
| +  }
 | 
| +
 | 
|    MessageLoop message_loop_;
 | 
| -  scoped_refptr<AudioOutputDispatcher> dispatcher_;
 | 
| +  scoped_refptr<AudioOutputDispatcherImpl> dispatcher_impl_;
 | 
| +  scoped_refptr<AudioOutputMixer> mixer_;
 | 
|    base::TimeDelta pause_delay_;
 | 
|    MockAudioManager manager_;
 | 
|    MockAudioSourceCallback callback_;
 | 
|  };
 | 
|  
 | 
|  TEST_F(AudioOutputProxyTest, CreateAndClose) {
 | 
| -  AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher_);
 | 
| +  AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher_impl_);
 | 
|    proxy->Close();
 | 
|  }
 | 
|  
 | 
| +TEST_F(AudioOutputProxyTest, CreateAndClose_Mixer) {
 | 
| +  AudioOutputProxy* proxy = new AudioOutputProxy(mixer_);
 | 
| +  proxy->Close();
 | 
| +}
 | 
| +
 | 
|  TEST_F(AudioOutputProxyTest, OpenAndClose) {
 | 
| -  MockAudioOutputStream stream;
 | 
| +  OpenAndClose(dispatcher_impl_);
 | 
| +}
 | 
|  
 | 
| -  EXPECT_CALL(manager(), MakeAudioOutputStream(_))
 | 
| -      .WillOnce(Return(&stream));
 | 
| -  EXPECT_CALL(stream, Open())
 | 
| -      .WillOnce(Return(true));
 | 
| -  EXPECT_CALL(stream, Close())
 | 
| -      .Times(1);
 | 
| -
 | 
| -  AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher_);
 | 
| -  EXPECT_TRUE(proxy->Open());
 | 
| -  proxy->Close();
 | 
| +TEST_F(AudioOutputProxyTest, OpenAndClose_Mixer) {
 | 
| +  OpenAndClose(mixer_);
 | 
|  }
 | 
|  
 | 
|  // Create a stream, and verify that it is closed after kTestCloseDelayMs.
 | 
| @@ -135,7 +275,7 @@
 | 
|    EXPECT_CALL(stream, Close())
 | 
|        .Times(1);
 | 
|  
 | 
| -  AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher_);
 | 
| +  AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher_impl_);
 | 
|    EXPECT_TRUE(proxy->Open());
 | 
|  
 | 
|    // Simulate a delay.
 | 
| @@ -149,87 +289,28 @@
 | 
|    proxy->Close();
 | 
|  }
 | 
|  
 | 
| -// Create a stream, and then calls Start() and Stop().
 | 
|  TEST_F(AudioOutputProxyTest, StartAndStop) {
 | 
| -  MockAudioOutputStream stream;
 | 
| +  StartAndStop(dispatcher_impl_);
 | 
| +}
 | 
|  
 | 
| -  EXPECT_CALL(manager(), MakeAudioOutputStream(_))
 | 
| -      .WillOnce(Return(&stream));
 | 
| -  EXPECT_CALL(stream, Open())
 | 
| -      .WillOnce(Return(true));
 | 
| -  EXPECT_CALL(stream, Start(_))
 | 
| -      .Times(1);
 | 
| -  EXPECT_CALL(stream, SetVolume(_))
 | 
| -      .Times(1);
 | 
| -  EXPECT_CALL(stream, Stop())
 | 
| -      .Times(1);
 | 
| -  EXPECT_CALL(stream, Close())
 | 
| -      .Times(1);
 | 
| -
 | 
| -  AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher_);
 | 
| -  EXPECT_TRUE(proxy->Open());
 | 
| -
 | 
| -  proxy->Start(&callback_);
 | 
| -  proxy->Stop();
 | 
| -
 | 
| -  proxy->Close();
 | 
| +TEST_F(AudioOutputProxyTest, StartAndStop_Mixer) {
 | 
| +  StartAndStop(mixer_);
 | 
|  }
 | 
|  
 | 
| -// Verify that the stream is closed after Stop is called.
 | 
|  TEST_F(AudioOutputProxyTest, CloseAfterStop) {
 | 
| -  MockAudioOutputStream stream;
 | 
| +  CloseAfterStop(dispatcher_impl_);
 | 
| +}
 | 
|  
 | 
| -  EXPECT_CALL(manager(), MakeAudioOutputStream(_))
 | 
| -      .WillOnce(Return(&stream));
 | 
| -  EXPECT_CALL(stream, Open())
 | 
| -      .WillOnce(Return(true));
 | 
| -  EXPECT_CALL(stream, Start(_))
 | 
| -      .Times(1);
 | 
| -  EXPECT_CALL(stream, SetVolume(_))
 | 
| -      .Times(1);
 | 
| -  EXPECT_CALL(stream, Stop())
 | 
| -      .Times(1);
 | 
| -  EXPECT_CALL(stream, Close())
 | 
| -      .Times(1);
 | 
| -
 | 
| -  AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher_);
 | 
| -  EXPECT_TRUE(proxy->Open());
 | 
| -
 | 
| -  proxy->Start(&callback_);
 | 
| -  proxy->Stop();
 | 
| -
 | 
| -  // Wait for StreamStopped() to post StopStreamTask().
 | 
| -  base::PlatformThread::Sleep(pause_delay_ * 2);
 | 
| -  message_loop_.RunAllPending();
 | 
| -
 | 
| -  // Wait for the close timer to fire.
 | 
| -  base::PlatformThread::Sleep(
 | 
| -      base::TimeDelta::FromMilliseconds(kTestCloseDelayMs) * 2);
 | 
| -  message_loop_.RunAllPending();
 | 
| -
 | 
| -  // Verify expectation before calling Close().
 | 
| -  Mock::VerifyAndClear(&stream);
 | 
| -
 | 
| -  proxy->Close();
 | 
| +TEST_F(AudioOutputProxyTest, CloseAfterStop_Mixer) {
 | 
| +  CloseAfterStop(mixer_);
 | 
|  }
 | 
|  
 | 
| -// Create two streams, but don't start them. Only one device must be open.
 | 
|  TEST_F(AudioOutputProxyTest, TwoStreams) {
 | 
| -  MockAudioOutputStream stream;
 | 
| +  TwoStreams(dispatcher_impl_);
 | 
| +}
 | 
|  
 | 
| -  EXPECT_CALL(manager(), MakeAudioOutputStream(_))
 | 
| -      .WillOnce(Return(&stream));
 | 
| -  EXPECT_CALL(stream, Open())
 | 
| -      .WillOnce(Return(true));
 | 
| -  EXPECT_CALL(stream, Close())
 | 
| -      .Times(1);
 | 
| -
 | 
| -  AudioOutputProxy* proxy1 = new AudioOutputProxy(dispatcher_);
 | 
| -  AudioOutputProxy* proxy2 = new AudioOutputProxy(dispatcher_);
 | 
| -  EXPECT_TRUE(proxy1->Open());
 | 
| -  EXPECT_TRUE(proxy2->Open());
 | 
| -  proxy1->Close();
 | 
| -  proxy2->Close();
 | 
| +TEST_F(AudioOutputProxyTest, TwoStreams_Mixer) {
 | 
| +  TwoStreams(mixer_);
 | 
|  }
 | 
|  
 | 
|  // Two streams: verify that second stream is allocated when the first
 | 
| @@ -260,8 +341,8 @@
 | 
|    EXPECT_CALL(stream2, Close())
 | 
|        .Times(1);
 | 
|  
 | 
| -  AudioOutputProxy* proxy1 = new AudioOutputProxy(dispatcher_);
 | 
| -  AudioOutputProxy* proxy2 = new AudioOutputProxy(dispatcher_);
 | 
| +  AudioOutputProxy* proxy1 = new AudioOutputProxy(dispatcher_impl_);
 | 
| +  AudioOutputProxy* proxy2 = new AudioOutputProxy(dispatcher_impl_);
 | 
|    EXPECT_TRUE(proxy1->Open());
 | 
|    EXPECT_TRUE(proxy2->Open());
 | 
|  
 | 
| @@ -273,6 +354,43 @@
 | 
|    proxy2->Close();
 | 
|  }
 | 
|  
 | 
| +// Two streams: verify that only one device will be created.
 | 
| +TEST_F(AudioOutputProxyTest, TwoStreams_OnePlaying_Mixer) {
 | 
| +  MockAudioOutputStream stream;
 | 
| +
 | 
| +  InitDispatcher(base::TimeDelta::FromMilliseconds(kTestCloseDelayMs));
 | 
| +
 | 
| +  EXPECT_CALL(manager(), MakeAudioOutputStream(_))
 | 
| +      .WillOnce(Return(&stream));
 | 
| +
 | 
| +  EXPECT_CALL(stream, Open())
 | 
| +      .WillOnce(Return(true));
 | 
| +  EXPECT_CALL(stream, Start(_))
 | 
| +      .Times(1);
 | 
| +  EXPECT_CALL(stream, SetVolume(_))
 | 
| +      .Times(1);
 | 
| +  EXPECT_CALL(stream, Stop())
 | 
| +      .Times(1);
 | 
| +  EXPECT_CALL(stream, Close())
 | 
| +      .Times(1);
 | 
| +
 | 
| +  AudioOutputProxy* proxy1 = new AudioOutputProxy(mixer_);
 | 
| +  AudioOutputProxy* proxy2 = new AudioOutputProxy(mixer_);
 | 
| +  EXPECT_TRUE(proxy1->Open());
 | 
| +  EXPECT_TRUE(proxy2->Open());
 | 
| +
 | 
| +  proxy1->Start(&callback_);
 | 
| +  proxy1->Stop();
 | 
| +
 | 
| +  proxy1->Close();
 | 
| +  proxy2->Close();
 | 
| +
 | 
| +  // Wait for the close timer to fire.
 | 
| +  base::PlatformThread::Sleep(
 | 
| +      base::TimeDelta::FromMilliseconds(kTestCloseDelayMs) * 2);
 | 
| +  message_loop_.RunAllPending();
 | 
| +}
 | 
| +
 | 
|  // Two streams, both are playing. Dispatcher should not open a third stream.
 | 
|  TEST_F(AudioOutputProxyTest, TwoStreams_BothPlaying) {
 | 
|    MockAudioOutputStream stream1;
 | 
| @@ -306,8 +424,8 @@
 | 
|    EXPECT_CALL(stream2, Close())
 | 
|        .Times(1);
 | 
|  
 | 
| -  AudioOutputProxy* proxy1 = new AudioOutputProxy(dispatcher_);
 | 
| -  AudioOutputProxy* proxy2 = new AudioOutputProxy(dispatcher_);
 | 
| +  AudioOutputProxy* proxy1 = new AudioOutputProxy(dispatcher_impl_);
 | 
| +  AudioOutputProxy* proxy2 = new AudioOutputProxy(dispatcher_impl_);
 | 
|    EXPECT_TRUE(proxy1->Open());
 | 
|    EXPECT_TRUE(proxy2->Open());
 | 
|  
 | 
| @@ -320,22 +438,53 @@
 | 
|    proxy2->Close();
 | 
|  }
 | 
|  
 | 
| -// Open() method failed.
 | 
| -TEST_F(AudioOutputProxyTest, OpenFailed) {
 | 
| +// Two streams, both are playing. Still have to use single device.
 | 
| +TEST_F(AudioOutputProxyTest, TwoStreams_BothPlaying_Mixer) {
 | 
|    MockAudioOutputStream stream;
 | 
|  
 | 
| +  InitDispatcher(base::TimeDelta::FromMilliseconds(kTestCloseDelayMs));
 | 
| +
 | 
|    EXPECT_CALL(manager(), MakeAudioOutputStream(_))
 | 
|        .WillOnce(Return(&stream));
 | 
| +
 | 
|    EXPECT_CALL(stream, Open())
 | 
| -      .WillOnce(Return(false));
 | 
| +      .WillOnce(Return(true));
 | 
| +  EXPECT_CALL(stream, Start(_))
 | 
| +      .Times(1);
 | 
| +  EXPECT_CALL(stream, SetVolume(_))
 | 
| +      .Times(1);
 | 
| +  EXPECT_CALL(stream, Stop())
 | 
| +      .Times(1);
 | 
|    EXPECT_CALL(stream, Close())
 | 
|        .Times(1);
 | 
|  
 | 
| -  AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher_);
 | 
| -  EXPECT_FALSE(proxy->Open());
 | 
| -  proxy->Close();
 | 
| +  AudioOutputProxy* proxy1 = new AudioOutputProxy(mixer_);
 | 
| +  AudioOutputProxy* proxy2 = new AudioOutputProxy(mixer_);
 | 
| +  EXPECT_TRUE(proxy1->Open());
 | 
| +  EXPECT_TRUE(proxy2->Open());
 | 
| +
 | 
| +  proxy1->Start(&callback_);
 | 
| +  proxy2->Start(&callback_);
 | 
| +  proxy1->Stop();
 | 
| +  proxy2->Stop();
 | 
| +
 | 
| +  proxy1->Close();
 | 
| +  proxy2->Close();
 | 
| +
 | 
| +  // Wait for the close timer to fire.
 | 
| +  base::PlatformThread::Sleep(
 | 
| +      base::TimeDelta::FromMilliseconds(kTestCloseDelayMs) * 2);
 | 
| +  message_loop_.RunAllPending();
 | 
|  }
 | 
|  
 | 
| +TEST_F(AudioOutputProxyTest, OpenFailed) {
 | 
| +  OpenFailed(dispatcher_impl_);
 | 
| +}
 | 
| +
 | 
| +TEST_F(AudioOutputProxyTest, OpenFailed_Mixer) {
 | 
| +  OpenFailed(mixer_);
 | 
| +}
 | 
| +
 | 
|  // Start() method failed.
 | 
|  TEST_F(AudioOutputProxyTest, StartFailed) {
 | 
|    MockAudioOutputStream stream;
 | 
| @@ -347,7 +496,7 @@
 | 
|    EXPECT_CALL(stream, Close())
 | 
|        .Times(1);
 | 
|  
 | 
| -  AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher_);
 | 
| +  AudioOutputProxy* proxy = new AudioOutputProxy(dispatcher_impl_);
 | 
|    EXPECT_TRUE(proxy->Open());
 | 
|  
 | 
|    // Simulate a delay.
 | 
| @@ -371,3 +520,55 @@
 | 
|  
 | 
|    proxy->Close();
 | 
|  }
 | 
| +
 | 
| +// Start() method failed.
 | 
| +TEST_F(AudioOutputProxyTest, StartFailed_Mixer) {
 | 
| +  MockAudioOutputStream stream;
 | 
| +
 | 
| +  EXPECT_CALL(manager(), MakeAudioOutputStream(_))
 | 
| +      .WillOnce(Return(&stream));
 | 
| +  EXPECT_CALL(stream, Open())
 | 
| +      .WillOnce(Return(true));
 | 
| +  EXPECT_CALL(stream, Close())
 | 
| +      .Times(1);
 | 
| +  EXPECT_CALL(stream, Start(_))
 | 
| +      .Times(1);
 | 
| +  EXPECT_CALL(stream, SetVolume(_))
 | 
| +      .Times(1);
 | 
| +  EXPECT_CALL(stream, Stop())
 | 
| +      .Times(1);
 | 
| +
 | 
| +  AudioOutputProxy* proxy1 = new AudioOutputProxy(mixer_);
 | 
| +  AudioOutputProxy* proxy2 = new AudioOutputProxy(mixer_);
 | 
| +  EXPECT_TRUE(proxy1->Open());
 | 
| +  EXPECT_TRUE(proxy2->Open());
 | 
| +  proxy1->Start(&callback_);
 | 
| +  proxy1->Stop();
 | 
| +  proxy1->Close();
 | 
| +
 | 
| +  // Wait for the close timer to fire.
 | 
| +  base::PlatformThread::Sleep(
 | 
| +      base::TimeDelta::FromMilliseconds(kTestCloseDelayMs) * 2);
 | 
| +  message_loop_.RunAllPending();
 | 
| +
 | 
| +  // Verify expectation before continueing.
 | 
| +  Mock::VerifyAndClear(&stream);
 | 
| +
 | 
| +  // |stream| is closed at this point. Start() should reopen it again.
 | 
| +  EXPECT_CALL(manager(), MakeAudioOutputStream(_))
 | 
| +      .WillOnce(Return(reinterpret_cast<AudioOutputStream*>(NULL)));
 | 
| +
 | 
| +  EXPECT_CALL(callback_, OnError(_, _))
 | 
| +      .Times(1);
 | 
| +
 | 
| +  proxy2->Start(&callback_);
 | 
| +
 | 
| +  Mock::VerifyAndClear(&callback_);
 | 
| +
 | 
| +  proxy2->Close();
 | 
| +
 | 
| +  // Wait for the close timer to fire.
 | 
| +  base::PlatformThread::Sleep(
 | 
| +      base::TimeDelta::FromMilliseconds(kTestCloseDelayMs) * 2);
 | 
| +  message_loop_.RunAllPending();
 | 
| +}
 | 
| 
 |