Home | History | Annotate | Download | only in alsa
      1 // Copyright 2013 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.
      4 
      5 #include "base/strings/stringprintf.h"
      6 #include "media/audio/alsa/alsa_output.h"
      7 #include "media/audio/alsa/alsa_wrapper.h"
      8 #include "media/audio/alsa/audio_manager_alsa.h"
      9 #include "media/audio/fake_audio_log_factory.h"
     10 #include "media/audio/mock_audio_source_callback.h"
     11 #include "media/base/data_buffer.h"
     12 #include "media/base/seekable_buffer.h"
     13 #include "testing/gmock/include/gmock/gmock.h"
     14 #include "testing/gtest/include/gtest/gtest.h"
     15 
     16 using testing::_;
     17 using testing::AllOf;
     18 using testing::AtLeast;
     19 using testing::DoAll;
     20 using testing::Field;
     21 using testing::InSequence;
     22 using testing::Invoke;
     23 using testing::InvokeWithoutArgs;
     24 using testing::Mock;
     25 using testing::MockFunction;
     26 using testing::Return;
     27 using testing::SetArgumentPointee;
     28 using testing::StrictMock;
     29 using testing::StrEq;
     30 using testing::Unused;
     31 
     32 namespace media {
     33 
     34 class MockAlsaWrapper : public AlsaWrapper {
     35  public:
     36   MOCK_METHOD3(DeviceNameHint, int(int card,
     37                                    const char* iface,
     38                                    void*** hints));
     39   MOCK_METHOD2(DeviceNameGetHint, char*(const void* hint, const char* id));
     40   MOCK_METHOD1(DeviceNameFreeHint, int(void** hints));
     41 
     42   MOCK_METHOD4(PcmOpen, int(snd_pcm_t** handle, const char* name,
     43                             snd_pcm_stream_t stream, int mode));
     44   MOCK_METHOD1(PcmClose, int(snd_pcm_t* handle));
     45   MOCK_METHOD1(PcmPrepare, int(snd_pcm_t* handle));
     46   MOCK_METHOD1(PcmDrop, int(snd_pcm_t* handle));
     47   MOCK_METHOD2(PcmDelay, int(snd_pcm_t* handle, snd_pcm_sframes_t* delay));
     48   MOCK_METHOD3(PcmWritei, snd_pcm_sframes_t(snd_pcm_t* handle,
     49                                             const void* buffer,
     50                                             snd_pcm_uframes_t size));
     51   MOCK_METHOD3(PcmReadi, snd_pcm_sframes_t(snd_pcm_t* handle,
     52                                            void* buffer,
     53                                            snd_pcm_uframes_t size));
     54   MOCK_METHOD3(PcmRecover, int(snd_pcm_t* handle, int err, int silent));
     55   MOCK_METHOD7(PcmSetParams, int(snd_pcm_t* handle, snd_pcm_format_t format,
     56                                  snd_pcm_access_t access, unsigned int channels,
     57                                  unsigned int rate, int soft_resample,
     58                                  unsigned int latency));
     59   MOCK_METHOD3(PcmGetParams, int(snd_pcm_t* handle,
     60                                  snd_pcm_uframes_t* buffer_size,
     61                                  snd_pcm_uframes_t* period_size));
     62   MOCK_METHOD1(PcmName, const char*(snd_pcm_t* handle));
     63   MOCK_METHOD1(PcmAvailUpdate, snd_pcm_sframes_t(snd_pcm_t* handle));
     64   MOCK_METHOD1(PcmState, snd_pcm_state_t(snd_pcm_t* handle));
     65   MOCK_METHOD1(PcmStart, int(snd_pcm_t* handle));
     66 
     67   MOCK_METHOD1(StrError, const char*(int errnum));
     68 };
     69 
     70 class MockAudioManagerAlsa : public AudioManagerAlsa {
     71  public:
     72   MockAudioManagerAlsa() : AudioManagerAlsa(&fake_audio_log_factory_) {}
     73   MOCK_METHOD0(Init, void());
     74   MOCK_METHOD0(HasAudioOutputDevices, bool());
     75   MOCK_METHOD0(HasAudioInputDevices, bool());
     76   MOCK_METHOD1(MakeLinearOutputStream, AudioOutputStream*(
     77       const AudioParameters& params));
     78   MOCK_METHOD2(MakeLowLatencyOutputStream, AudioOutputStream*(
     79       const AudioParameters& params,
     80       const std::string& device_id));
     81   MOCK_METHOD2(MakeLowLatencyInputStream, AudioInputStream*(
     82       const AudioParameters& params, const std::string& device_id));
     83 
     84   // We need to override this function in order to skip the checking the number
     85   // of active output streams. It is because the number of active streams
     86   // is managed inside MakeAudioOutputStream, and we don't use
     87   // MakeAudioOutputStream to create the stream in the tests.
     88   virtual void ReleaseOutputStream(AudioOutputStream* stream) OVERRIDE {
     89     DCHECK(stream);
     90     delete stream;
     91   }
     92 
     93   // We don't mock this method since all tests will do the same thing
     94   // and use the current task runner.
     95   virtual scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() OVERRIDE {
     96     return base::MessageLoop::current()->message_loop_proxy();
     97   }
     98 
     99  private:
    100   FakeAudioLogFactory fake_audio_log_factory_;
    101 };
    102 
    103 class AlsaPcmOutputStreamTest : public testing::Test {
    104  protected:
    105   AlsaPcmOutputStreamTest() {
    106     mock_manager_.reset(new StrictMock<MockAudioManagerAlsa>());
    107   }
    108 
    109   virtual ~AlsaPcmOutputStreamTest() {
    110   }
    111 
    112   AlsaPcmOutputStream* CreateStream(ChannelLayout layout) {
    113     return CreateStream(layout, kTestFramesPerPacket);
    114   }
    115 
    116   AlsaPcmOutputStream* CreateStream(ChannelLayout layout,
    117                                     int32 samples_per_packet) {
    118     AudioParameters params(kTestFormat, layout, kTestSampleRate,
    119                            kTestBitsPerSample, samples_per_packet);
    120     return new AlsaPcmOutputStream(kTestDeviceName,
    121                                    params,
    122                                    &mock_alsa_wrapper_,
    123                                    mock_manager_.get());
    124   }
    125 
    126   // Helper function to malloc the string returned by DeviceNameHint for NAME.
    127   static char* EchoHint(const void* name, Unused) {
    128     return strdup(static_cast<const char*>(name));
    129   }
    130 
    131   // Helper function to malloc the string returned by DeviceNameHint for IOID.
    132   static char* OutputHint(Unused, Unused) {
    133     return strdup("Output");
    134   }
    135 
    136   // Helper function to initialize |test_stream->buffer_|. Must be called
    137   // in all tests that use buffer_ without opening the stream.
    138   void InitBuffer(AlsaPcmOutputStream* test_stream) {
    139     DCHECK(test_stream);
    140     packet_ = new media::DataBuffer(kTestPacketSize);
    141     packet_->set_data_size(kTestPacketSize);
    142     test_stream->buffer_.reset(new media::SeekableBuffer(0, kTestPacketSize));
    143     test_stream->buffer_->Append(packet_.get());
    144   }
    145 
    146   static const ChannelLayout kTestChannelLayout;
    147   static const int kTestSampleRate;
    148   static const int kTestBitsPerSample;
    149   static const int kTestBytesPerFrame;
    150   static const AudioParameters::Format kTestFormat;
    151   static const char kTestDeviceName[];
    152   static const char kDummyMessage[];
    153   static const uint32 kTestFramesPerPacket;
    154   static const int kTestPacketSize;
    155   static const int kTestFailedErrno;
    156   static snd_pcm_t* const kFakeHandle;
    157 
    158   // Used to simulate DeviceNameHint.
    159   static char kSurround40[];
    160   static char kSurround41[];
    161   static char kSurround50[];
    162   static char kSurround51[];
    163   static char kSurround70[];
    164   static char kSurround71[];
    165   static void* kFakeHints[];
    166 
    167   StrictMock<MockAlsaWrapper> mock_alsa_wrapper_;
    168   scoped_ptr<StrictMock<MockAudioManagerAlsa> > mock_manager_;
    169   base::MessageLoop message_loop_;
    170   scoped_refptr<media::DataBuffer> packet_;
    171 
    172  private:
    173   DISALLOW_COPY_AND_ASSIGN(AlsaPcmOutputStreamTest);
    174 };
    175 
    176 const ChannelLayout AlsaPcmOutputStreamTest::kTestChannelLayout =
    177     CHANNEL_LAYOUT_STEREO;
    178 const int AlsaPcmOutputStreamTest::kTestSampleRate =
    179     AudioParameters::kAudioCDSampleRate;
    180 const int AlsaPcmOutputStreamTest::kTestBitsPerSample = 8;
    181 const int AlsaPcmOutputStreamTest::kTestBytesPerFrame =
    182     AlsaPcmOutputStreamTest::kTestBitsPerSample / 8 *
    183     ChannelLayoutToChannelCount(AlsaPcmOutputStreamTest::kTestChannelLayout);
    184 const AudioParameters::Format AlsaPcmOutputStreamTest::kTestFormat =
    185     AudioParameters::AUDIO_PCM_LINEAR;
    186 const char AlsaPcmOutputStreamTest::kTestDeviceName[] = "TestDevice";
    187 const char AlsaPcmOutputStreamTest::kDummyMessage[] = "dummy";
    188 const uint32 AlsaPcmOutputStreamTest::kTestFramesPerPacket = 1000;
    189 const int AlsaPcmOutputStreamTest::kTestPacketSize =
    190     AlsaPcmOutputStreamTest::kTestFramesPerPacket *
    191     AlsaPcmOutputStreamTest::kTestBytesPerFrame;
    192 const int AlsaPcmOutputStreamTest::kTestFailedErrno = -EACCES;
    193 snd_pcm_t* const AlsaPcmOutputStreamTest::kFakeHandle =
    194     reinterpret_cast<snd_pcm_t*>(1);
    195 
    196 char AlsaPcmOutputStreamTest::kSurround40[] = "surround40:CARD=foo,DEV=0";
    197 char AlsaPcmOutputStreamTest::kSurround41[] = "surround41:CARD=foo,DEV=0";
    198 char AlsaPcmOutputStreamTest::kSurround50[] = "surround50:CARD=foo,DEV=0";
    199 char AlsaPcmOutputStreamTest::kSurround51[] = "surround51:CARD=foo,DEV=0";
    200 char AlsaPcmOutputStreamTest::kSurround70[] = "surround70:CARD=foo,DEV=0";
    201 char AlsaPcmOutputStreamTest::kSurround71[] = "surround71:CARD=foo,DEV=0";
    202 void* AlsaPcmOutputStreamTest::kFakeHints[] = {
    203     kSurround40, kSurround41, kSurround50, kSurround51,
    204     kSurround70, kSurround71, NULL };
    205 
    206 // Custom action to clear a memory buffer.
    207 ACTION(ClearBuffer) {
    208   arg0->Zero();
    209 }
    210 
    211 TEST_F(AlsaPcmOutputStreamTest, ConstructedState) {
    212   AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
    213   EXPECT_EQ(AlsaPcmOutputStream::kCreated, test_stream->state());
    214   test_stream->Close();
    215 
    216   // Should support mono.
    217   test_stream = CreateStream(CHANNEL_LAYOUT_MONO);
    218   EXPECT_EQ(AlsaPcmOutputStream::kCreated, test_stream->state());
    219   test_stream->Close();
    220 
    221   // Should support multi-channel.
    222   test_stream = CreateStream(CHANNEL_LAYOUT_SURROUND);
    223   EXPECT_EQ(AlsaPcmOutputStream::kCreated, test_stream->state());
    224   test_stream->Close();
    225 
    226   // Bad bits per sample.
    227   AudioParameters bad_bps_params(kTestFormat, kTestChannelLayout,
    228                                  kTestSampleRate, kTestBitsPerSample - 1,
    229                                  kTestFramesPerPacket);
    230   test_stream = new AlsaPcmOutputStream(kTestDeviceName,
    231                                         bad_bps_params,
    232                                         &mock_alsa_wrapper_,
    233                                         mock_manager_.get());
    234   EXPECT_EQ(AlsaPcmOutputStream::kInError, test_stream->state());
    235   test_stream->Close();
    236 
    237   // Bad format.
    238   AudioParameters bad_format_params(
    239       AudioParameters::AUDIO_LAST_FORMAT, kTestChannelLayout, kTestSampleRate,
    240       kTestBitsPerSample, kTestFramesPerPacket);
    241   test_stream = new AlsaPcmOutputStream(kTestDeviceName,
    242                                         bad_format_params,
    243                                         &mock_alsa_wrapper_,
    244                                         mock_manager_.get());
    245   EXPECT_EQ(AlsaPcmOutputStream::kInError, test_stream->state());
    246   test_stream->Close();
    247 }
    248 
    249 TEST_F(AlsaPcmOutputStreamTest, LatencyFloor) {
    250   const double kMicrosPerFrame =
    251       static_cast<double>(1000000) / kTestSampleRate;
    252   const double kPacketFramesInMinLatency =
    253       AlsaPcmOutputStream::kMinLatencyMicros / kMicrosPerFrame / 2.0;
    254 
    255   // Test that packets which would cause a latency under less than
    256   // AlsaPcmOutputStream::kMinLatencyMicros will get clipped to
    257   // AlsaPcmOutputStream::kMinLatencyMicros,
    258   EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _))
    259       .WillOnce(DoAll(SetArgumentPointee<0>(kFakeHandle),
    260                       Return(0)));
    261   EXPECT_CALL(mock_alsa_wrapper_,
    262               PcmSetParams(_, _, _, _, _, _,
    263                            AlsaPcmOutputStream::kMinLatencyMicros))
    264       .WillOnce(Return(0));
    265   EXPECT_CALL(mock_alsa_wrapper_, PcmGetParams(_, _, _))
    266       .WillOnce(DoAll(SetArgumentPointee<1>(kTestFramesPerPacket),
    267                       SetArgumentPointee<2>(kTestFramesPerPacket / 2),
    268                       Return(0)));
    269 
    270   AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout,
    271                                                   kPacketFramesInMinLatency);
    272   ASSERT_TRUE(test_stream->Open());
    273 
    274   // Now close it and test that everything was released.
    275   EXPECT_CALL(mock_alsa_wrapper_, PcmClose(kFakeHandle)).WillOnce(Return(0));
    276   EXPECT_CALL(mock_alsa_wrapper_, PcmName(kFakeHandle))
    277       .WillOnce(Return(kTestDeviceName));
    278   test_stream->Close();
    279 
    280   Mock::VerifyAndClear(&mock_alsa_wrapper_);
    281   Mock::VerifyAndClear(mock_manager_.get());
    282 
    283   // Test that having more packets ends up with a latency based on packet size.
    284   const int kOverMinLatencyPacketSize = kPacketFramesInMinLatency + 1;
    285   int64 expected_micros = AlsaPcmOutputStream::FramesToTimeDelta(
    286       kOverMinLatencyPacketSize * 2, kTestSampleRate).InMicroseconds();
    287 
    288   EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _))
    289       .WillOnce(DoAll(SetArgumentPointee<0>(kFakeHandle), Return(0)));
    290   EXPECT_CALL(mock_alsa_wrapper_,
    291               PcmSetParams(_, _, _, _, _, _, expected_micros))
    292       .WillOnce(Return(0));
    293   EXPECT_CALL(mock_alsa_wrapper_, PcmGetParams(_, _, _))
    294       .WillOnce(DoAll(SetArgumentPointee<1>(kTestFramesPerPacket),
    295                       SetArgumentPointee<2>(kTestFramesPerPacket / 2),
    296                       Return(0)));
    297 
    298   test_stream = CreateStream(kTestChannelLayout,
    299                              kOverMinLatencyPacketSize);
    300   ASSERT_TRUE(test_stream->Open());
    301 
    302   // Now close it and test that everything was released.
    303   EXPECT_CALL(mock_alsa_wrapper_, PcmClose(kFakeHandle))
    304       .WillOnce(Return(0));
    305   EXPECT_CALL(mock_alsa_wrapper_, PcmName(kFakeHandle))
    306       .WillOnce(Return(kTestDeviceName));
    307   test_stream->Close();
    308 
    309   Mock::VerifyAndClear(&mock_alsa_wrapper_);
    310   Mock::VerifyAndClear(mock_manager_.get());
    311 }
    312 
    313 TEST_F(AlsaPcmOutputStreamTest, OpenClose) {
    314   int64 expected_micros = AlsaPcmOutputStream::FramesToTimeDelta(
    315       2 * kTestFramesPerPacket, kTestSampleRate).InMicroseconds();
    316 
    317   // Open() call opens the playback device, sets the parameters, posts a task
    318   // with the resulting configuration data, and transitions the object state to
    319   // kIsOpened.
    320   EXPECT_CALL(mock_alsa_wrapper_,
    321               PcmOpen(_, StrEq(kTestDeviceName),
    322                       SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK))
    323       .WillOnce(DoAll(SetArgumentPointee<0>(kFakeHandle),
    324                       Return(0)));
    325   EXPECT_CALL(mock_alsa_wrapper_,
    326               PcmSetParams(kFakeHandle,
    327                            SND_PCM_FORMAT_U8,
    328                            SND_PCM_ACCESS_RW_INTERLEAVED,
    329                            ChannelLayoutToChannelCount(kTestChannelLayout),
    330                            kTestSampleRate,
    331                            1,
    332                            expected_micros))
    333       .WillOnce(Return(0));
    334   EXPECT_CALL(mock_alsa_wrapper_, PcmGetParams(kFakeHandle, _, _))
    335       .WillOnce(DoAll(SetArgumentPointee<1>(kTestFramesPerPacket),
    336                       SetArgumentPointee<2>(kTestFramesPerPacket / 2),
    337                       Return(0)));
    338 
    339   // Open the stream.
    340   AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
    341   ASSERT_TRUE(test_stream->Open());
    342 
    343   EXPECT_EQ(AlsaPcmOutputStream::kIsOpened, test_stream->state());
    344   EXPECT_EQ(kFakeHandle, test_stream->playback_handle_);
    345   EXPECT_EQ(kTestFramesPerPacket, test_stream->frames_per_packet_);
    346   EXPECT_TRUE(test_stream->buffer_.get());
    347   EXPECT_FALSE(test_stream->stop_stream_);
    348 
    349   // Now close it and test that everything was released.
    350   EXPECT_CALL(mock_alsa_wrapper_, PcmClose(kFakeHandle))
    351       .WillOnce(Return(0));
    352   EXPECT_CALL(mock_alsa_wrapper_, PcmName(kFakeHandle))
    353       .WillOnce(Return(kTestDeviceName));
    354   test_stream->Close();
    355 }
    356 
    357 TEST_F(AlsaPcmOutputStreamTest, PcmOpenFailed) {
    358   EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _))
    359       .WillOnce(Return(kTestFailedErrno));
    360   EXPECT_CALL(mock_alsa_wrapper_, StrError(kTestFailedErrno))
    361       .WillOnce(Return(kDummyMessage));
    362 
    363   AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
    364   ASSERT_FALSE(test_stream->Open());
    365   ASSERT_EQ(AlsaPcmOutputStream::kInError, test_stream->state());
    366 
    367   // Ensure internal state is set for a no-op stream if PcmOpen() failes.
    368   EXPECT_TRUE(test_stream->stop_stream_);
    369   EXPECT_TRUE(test_stream->playback_handle_ == NULL);
    370   EXPECT_FALSE(test_stream->buffer_.get());
    371 
    372   // Close the stream since we opened it to make destruction happy.
    373   test_stream->Close();
    374 }
    375 
    376 TEST_F(AlsaPcmOutputStreamTest, PcmSetParamsFailed) {
    377   EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _))
    378       .WillOnce(DoAll(SetArgumentPointee<0>(kFakeHandle),
    379                       Return(0)));
    380   EXPECT_CALL(mock_alsa_wrapper_, PcmSetParams(_, _, _, _, _, _, _))
    381       .WillOnce(Return(kTestFailedErrno));
    382   EXPECT_CALL(mock_alsa_wrapper_, PcmClose(kFakeHandle))
    383       .WillOnce(Return(0));
    384   EXPECT_CALL(mock_alsa_wrapper_, PcmName(kFakeHandle))
    385       .WillOnce(Return(kTestDeviceName));
    386   EXPECT_CALL(mock_alsa_wrapper_, StrError(kTestFailedErrno))
    387       .WillOnce(Return(kDummyMessage));
    388 
    389   // If open fails, the stream stays in kCreated because it has effectively had
    390   // no changes.
    391   AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
    392   ASSERT_FALSE(test_stream->Open());
    393   EXPECT_EQ(AlsaPcmOutputStream::kInError, test_stream->state());
    394 
    395   // Ensure internal state is set for a no-op stream if PcmSetParams() failes.
    396   EXPECT_TRUE(test_stream->stop_stream_);
    397   EXPECT_TRUE(test_stream->playback_handle_ == NULL);
    398   EXPECT_FALSE(test_stream->buffer_.get());
    399 
    400   // Close the stream since we opened it to make destruction happy.
    401   test_stream->Close();
    402 }
    403 
    404 TEST_F(AlsaPcmOutputStreamTest, StartStop) {
    405   // Open() call opens the playback device, sets the parameters, posts a task
    406   // with the resulting configuration data, and transitions the object state to
    407   // kIsOpened.
    408   EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _))
    409       .WillOnce(DoAll(SetArgumentPointee<0>(kFakeHandle),
    410                       Return(0)));
    411   EXPECT_CALL(mock_alsa_wrapper_, PcmSetParams(_, _, _, _, _, _, _))
    412       .WillOnce(Return(0));
    413   EXPECT_CALL(mock_alsa_wrapper_, PcmGetParams(_, _, _))
    414       .WillOnce(DoAll(SetArgumentPointee<1>(kTestFramesPerPacket),
    415                       SetArgumentPointee<2>(kTestFramesPerPacket / 2),
    416                       Return(0)));
    417 
    418   // Open the stream.
    419   AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
    420   ASSERT_TRUE(test_stream->Open());
    421 
    422   // Expect Device setup.
    423   EXPECT_CALL(mock_alsa_wrapper_, PcmDrop(kFakeHandle))
    424       .WillOnce(Return(0));
    425   EXPECT_CALL(mock_alsa_wrapper_, PcmPrepare(kFakeHandle))
    426       .WillOnce(Return(0));
    427 
    428   // Expect the pre-roll.
    429   MockAudioSourceCallback mock_callback;
    430   EXPECT_CALL(mock_alsa_wrapper_, PcmState(kFakeHandle))
    431       .WillRepeatedly(Return(SND_PCM_STATE_RUNNING));
    432   EXPECT_CALL(mock_alsa_wrapper_, PcmDelay(kFakeHandle, _))
    433       .WillRepeatedly(DoAll(SetArgumentPointee<1>(0), Return(0)));
    434   EXPECT_CALL(mock_callback, OnMoreData(_, _))
    435       .WillRepeatedly(DoAll(ClearBuffer(), Return(kTestFramesPerPacket)));
    436   EXPECT_CALL(mock_alsa_wrapper_, PcmWritei(kFakeHandle, _, _))
    437       .WillRepeatedly(Return(kTestFramesPerPacket));
    438 
    439   // Expect scheduling.
    440   EXPECT_CALL(mock_alsa_wrapper_, PcmAvailUpdate(kFakeHandle))
    441       .Times(AtLeast(2))
    442       .WillRepeatedly(Return(kTestFramesPerPacket));
    443 
    444   test_stream->Start(&mock_callback);
    445   // Start() will issue a WriteTask() directly and then schedule the next one,
    446   // call Stop() immediately after to ensure we don't run the message loop
    447   // forever.
    448   test_stream->Stop();
    449   message_loop_.RunUntilIdle();
    450 
    451   EXPECT_CALL(mock_alsa_wrapper_, PcmClose(kFakeHandle))
    452       .WillOnce(Return(0));
    453   EXPECT_CALL(mock_alsa_wrapper_, PcmName(kFakeHandle))
    454       .WillOnce(Return(kTestDeviceName));
    455   test_stream->Close();
    456 }
    457 
    458 TEST_F(AlsaPcmOutputStreamTest, WritePacket_FinishedPacket) {
    459   AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
    460   InitBuffer(test_stream);
    461   test_stream->TransitionTo(AlsaPcmOutputStream::kIsOpened);
    462   test_stream->TransitionTo(AlsaPcmOutputStream::kIsPlaying);
    463 
    464   // Nothing should happen.  Don't set any expectations and Our strict mocks
    465   // should verify most of this.
    466 
    467   // Test empty buffer.
    468   test_stream->buffer_->Clear();
    469   test_stream->WritePacket();
    470   test_stream->Close();
    471 }
    472 
    473 TEST_F(AlsaPcmOutputStreamTest, WritePacket_NormalPacket) {
    474   // We need to open the stream before writing data to ALSA.
    475   EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _))
    476       .WillOnce(DoAll(SetArgumentPointee<0>(kFakeHandle),
    477                       Return(0)));
    478   EXPECT_CALL(mock_alsa_wrapper_, PcmSetParams(_, _, _, _, _, _, _))
    479       .WillOnce(Return(0));
    480   EXPECT_CALL(mock_alsa_wrapper_, PcmGetParams(_, _, _))
    481       .WillOnce(DoAll(SetArgumentPointee<1>(kTestFramesPerPacket),
    482                       SetArgumentPointee<2>(kTestFramesPerPacket / 2),
    483                       Return(0)));
    484   AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
    485   ASSERT_TRUE(test_stream->Open());
    486   InitBuffer(test_stream);
    487   test_stream->TransitionTo(AlsaPcmOutputStream::kIsPlaying);
    488 
    489   // Write a little less than half the data.
    490   int written = packet_->data_size() / kTestBytesPerFrame / 2 - 1;
    491   EXPECT_CALL(mock_alsa_wrapper_, PcmAvailUpdate(kFakeHandle))
    492         .WillOnce(Return(written));
    493   EXPECT_CALL(mock_alsa_wrapper_, PcmWritei(kFakeHandle, packet_->data(), _))
    494       .WillOnce(Return(written));
    495 
    496   test_stream->WritePacket();
    497 
    498   ASSERT_EQ(test_stream->buffer_->forward_bytes(),
    499             packet_->data_size() - written * kTestBytesPerFrame);
    500 
    501   // Write the rest.
    502   EXPECT_CALL(mock_alsa_wrapper_, PcmAvailUpdate(kFakeHandle))
    503       .WillOnce(Return(kTestFramesPerPacket - written));
    504   EXPECT_CALL(mock_alsa_wrapper_,
    505               PcmWritei(kFakeHandle,
    506                         packet_->data() + written * kTestBytesPerFrame,
    507                         _))
    508       .WillOnce(Return(packet_->data_size() / kTestBytesPerFrame - written));
    509   test_stream->WritePacket();
    510   EXPECT_EQ(0, test_stream->buffer_->forward_bytes());
    511 
    512   // Now close it and test that everything was released.
    513   EXPECT_CALL(mock_alsa_wrapper_, PcmClose(kFakeHandle))
    514       .WillOnce(Return(0));
    515   EXPECT_CALL(mock_alsa_wrapper_, PcmName(kFakeHandle))
    516       .WillOnce(Return(kTestDeviceName));
    517   test_stream->Close();
    518 }
    519 
    520 TEST_F(AlsaPcmOutputStreamTest, WritePacket_WriteFails) {
    521   // We need to open the stream before writing data to ALSA.
    522   EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _))
    523       .WillOnce(DoAll(SetArgumentPointee<0>(kFakeHandle),
    524                       Return(0)));
    525   EXPECT_CALL(mock_alsa_wrapper_, PcmSetParams(_, _, _, _, _, _, _))
    526       .WillOnce(Return(0));
    527   EXPECT_CALL(mock_alsa_wrapper_, PcmGetParams(_, _, _))
    528       .WillOnce(DoAll(SetArgumentPointee<1>(kTestFramesPerPacket),
    529                       SetArgumentPointee<2>(kTestFramesPerPacket / 2),
    530                       Return(0)));
    531   AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
    532   ASSERT_TRUE(test_stream->Open());
    533   InitBuffer(test_stream);
    534   test_stream->TransitionTo(AlsaPcmOutputStream::kIsPlaying);
    535 
    536   // Fail due to a recoverable error and see that PcmRecover code path
    537   // continues normally.
    538   EXPECT_CALL(mock_alsa_wrapper_, PcmAvailUpdate(kFakeHandle))
    539       .WillOnce(Return(kTestFramesPerPacket));
    540   EXPECT_CALL(mock_alsa_wrapper_, PcmWritei(kFakeHandle, _, _))
    541       .WillOnce(Return(-EINTR));
    542   EXPECT_CALL(mock_alsa_wrapper_, PcmRecover(kFakeHandle, _, _))
    543       .WillOnce(Return(0));
    544 
    545   test_stream->WritePacket();
    546 
    547   ASSERT_EQ(test_stream->buffer_->forward_bytes(), packet_->data_size());
    548 
    549   // Fail the next write, and see that stop_stream_ is set.
    550   EXPECT_CALL(mock_alsa_wrapper_, PcmAvailUpdate(kFakeHandle))
    551         .WillOnce(Return(kTestFramesPerPacket));
    552   EXPECT_CALL(mock_alsa_wrapper_, PcmWritei(kFakeHandle, _, _))
    553       .WillOnce(Return(kTestFailedErrno));
    554   EXPECT_CALL(mock_alsa_wrapper_, PcmRecover(kFakeHandle, _, _))
    555       .WillOnce(Return(kTestFailedErrno));
    556   EXPECT_CALL(mock_alsa_wrapper_, StrError(kTestFailedErrno))
    557       .WillOnce(Return(kDummyMessage));
    558   test_stream->WritePacket();
    559   EXPECT_EQ(test_stream->buffer_->forward_bytes(), packet_->data_size());
    560   EXPECT_TRUE(test_stream->stop_stream_);
    561 
    562   // Now close it and test that everything was released.
    563   EXPECT_CALL(mock_alsa_wrapper_, PcmClose(kFakeHandle))
    564       .WillOnce(Return(0));
    565   EXPECT_CALL(mock_alsa_wrapper_, PcmName(kFakeHandle))
    566       .WillOnce(Return(kTestDeviceName));
    567   test_stream->Close();
    568 }
    569 
    570 TEST_F(AlsaPcmOutputStreamTest, WritePacket_StopStream) {
    571   AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
    572   InitBuffer(test_stream);
    573   test_stream->TransitionTo(AlsaPcmOutputStream::kIsOpened);
    574   test_stream->TransitionTo(AlsaPcmOutputStream::kIsPlaying);
    575 
    576   // No expectations set on the strict mock because nothing should be called.
    577   test_stream->stop_stream_ = true;
    578   test_stream->WritePacket();
    579   EXPECT_EQ(0, test_stream->buffer_->forward_bytes());
    580   test_stream->Close();
    581 }
    582 
    583 TEST_F(AlsaPcmOutputStreamTest, BufferPacket) {
    584   AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
    585   InitBuffer(test_stream);
    586   test_stream->buffer_->Clear();
    587 
    588   MockAudioSourceCallback mock_callback;
    589   EXPECT_CALL(mock_alsa_wrapper_, PcmState(_))
    590       .WillOnce(Return(SND_PCM_STATE_RUNNING));
    591   EXPECT_CALL(mock_alsa_wrapper_, PcmDelay(_, _))
    592       .WillOnce(DoAll(SetArgumentPointee<1>(1), Return(0)));
    593   EXPECT_CALL(mock_alsa_wrapper_, PcmAvailUpdate(_))
    594       .WillRepeatedly(Return(0));  // Buffer is full.
    595 
    596   // Return a partially filled packet.
    597   EXPECT_CALL(mock_callback, OnMoreData(_, _))
    598       .WillOnce(DoAll(ClearBuffer(), Return(kTestFramesPerPacket / 2)));
    599 
    600   bool source_exhausted;
    601   test_stream->set_source_callback(&mock_callback);
    602   test_stream->packet_size_ = kTestPacketSize;
    603   test_stream->BufferPacket(&source_exhausted);
    604 
    605   EXPECT_EQ(kTestPacketSize / 2, test_stream->buffer_->forward_bytes());
    606   EXPECT_FALSE(source_exhausted);
    607   test_stream->Close();
    608 }
    609 
    610 TEST_F(AlsaPcmOutputStreamTest, BufferPacket_Negative) {
    611   AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
    612   InitBuffer(test_stream);
    613   test_stream->buffer_->Clear();
    614 
    615   // Simulate where the underrun has occurred right after checking the delay.
    616   MockAudioSourceCallback mock_callback;
    617   EXPECT_CALL(mock_alsa_wrapper_, PcmState(_))
    618       .WillOnce(Return(SND_PCM_STATE_RUNNING));
    619   EXPECT_CALL(mock_alsa_wrapper_, PcmDelay(_, _))
    620       .WillOnce(DoAll(SetArgumentPointee<1>(-1), Return(0)));
    621   EXPECT_CALL(mock_alsa_wrapper_, PcmAvailUpdate(_))
    622       .WillRepeatedly(Return(0));  // Buffer is full.
    623   EXPECT_CALL(mock_callback, OnMoreData(_, _))
    624       .WillOnce(DoAll(ClearBuffer(), Return(kTestFramesPerPacket / 2)));
    625 
    626   bool source_exhausted;
    627   test_stream->set_source_callback(&mock_callback);
    628   test_stream->packet_size_ = kTestPacketSize;
    629   test_stream->BufferPacket(&source_exhausted);
    630 
    631   EXPECT_EQ(kTestPacketSize / 2, test_stream->buffer_->forward_bytes());
    632   EXPECT_FALSE(source_exhausted);
    633   test_stream->Close();
    634 }
    635 
    636 TEST_F(AlsaPcmOutputStreamTest, BufferPacket_Underrun) {
    637   AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
    638   InitBuffer(test_stream);
    639   test_stream->buffer_->Clear();
    640 
    641   // If ALSA has underrun then we should assume a delay of zero.
    642   MockAudioSourceCallback mock_callback;
    643   EXPECT_CALL(mock_alsa_wrapper_, PcmState(_))
    644       .WillOnce(Return(SND_PCM_STATE_XRUN));
    645   EXPECT_CALL(mock_alsa_wrapper_, PcmAvailUpdate(_))
    646       .WillRepeatedly(Return(0));  // Buffer is full.
    647   EXPECT_CALL(mock_callback,
    648               OnMoreData(_, AllOf(
    649                   Field(&AudioBuffersState::pending_bytes, 0),
    650                   Field(&AudioBuffersState::hardware_delay_bytes, 0))))
    651       .WillOnce(DoAll(ClearBuffer(), Return(kTestFramesPerPacket / 2)));
    652 
    653   bool source_exhausted;
    654   test_stream->set_source_callback(&mock_callback);
    655   test_stream->packet_size_ = kTestPacketSize;
    656   test_stream->BufferPacket(&source_exhausted);
    657 
    658   EXPECT_EQ(kTestPacketSize / 2, test_stream->buffer_->forward_bytes());
    659   EXPECT_FALSE(source_exhausted);
    660   test_stream->Close();
    661 }
    662 
    663 TEST_F(AlsaPcmOutputStreamTest, BufferPacket_FullBuffer) {
    664   AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
    665   InitBuffer(test_stream);
    666   // No expectations set on the strict mock because nothing should be called.
    667   bool source_exhausted;
    668   test_stream->packet_size_ = kTestPacketSize;
    669   test_stream->BufferPacket(&source_exhausted);
    670   EXPECT_EQ(kTestPacketSize, test_stream->buffer_->forward_bytes());
    671   EXPECT_FALSE(source_exhausted);
    672   test_stream->Close();
    673 }
    674 
    675 TEST_F(AlsaPcmOutputStreamTest, AutoSelectDevice_DeviceSelect) {
    676   // Try channels from 1 -> 9. and see that we get the more specific surroundXX
    677   // device opened for channels 4-8.  For all other channels, the device should
    678   // default to |AlsaPcmOutputStream::kDefaultDevice|.  We should also not
    679   // downmix any channel in this case because downmixing is only defined for
    680   // channels 4-8, which we are guaranteeing to work.
    681   //
    682   // Note that the loop starts at "1", so the first parameter is ignored in
    683   // these arrays.
    684   const char* kExpectedDeviceName[] = { NULL,
    685                                         AlsaPcmOutputStream::kDefaultDevice,
    686                                         AlsaPcmOutputStream::kDefaultDevice,
    687                                         AlsaPcmOutputStream::kDefaultDevice,
    688                                         kSurround40, kSurround50, kSurround51,
    689                                         kSurround70, kSurround71,
    690                                         AlsaPcmOutputStream::kDefaultDevice };
    691   bool kExpectedDownmix[] = { false, false, false, false, false, true,
    692                               false, false, false, false };
    693   ChannelLayout kExpectedLayouts[] = { CHANNEL_LAYOUT_NONE,
    694                                        CHANNEL_LAYOUT_MONO,
    695                                        CHANNEL_LAYOUT_STEREO,
    696                                        CHANNEL_LAYOUT_SURROUND,
    697                                        CHANNEL_LAYOUT_4_0,
    698                                        CHANNEL_LAYOUT_5_0,
    699                                        CHANNEL_LAYOUT_5_1,
    700                                        CHANNEL_LAYOUT_7_0,
    701                                        CHANNEL_LAYOUT_7_1 };
    702 
    703 
    704   for (int i = 1; i < 9; ++i) {
    705     if (i == 3 || i == 4 || i == 5)  // invalid number of channels
    706       continue;
    707     SCOPED_TRACE(base::StringPrintf("Attempting %d Channel", i));
    708 
    709     // Hints will only be grabbed for channel numbers that have non-default
    710     // devices associated with them.
    711     if (kExpectedDeviceName[i] != AlsaPcmOutputStream::kDefaultDevice) {
    712       // The DeviceNameHint and DeviceNameFreeHint need to be paired to avoid a
    713       // memory leak.
    714       EXPECT_CALL(mock_alsa_wrapper_, DeviceNameHint(_, _, _))
    715           .WillOnce(DoAll(SetArgumentPointee<2>(&kFakeHints[0]), Return(0)));
    716       EXPECT_CALL(mock_alsa_wrapper_, DeviceNameFreeHint(&kFakeHints[0]))
    717           .Times(1);
    718     }
    719 
    720     EXPECT_CALL(mock_alsa_wrapper_,
    721                 PcmOpen(_, StrEq(kExpectedDeviceName[i]), _, _))
    722         .WillOnce(DoAll(SetArgumentPointee<0>(kFakeHandle), Return(0)));
    723     EXPECT_CALL(mock_alsa_wrapper_,
    724                 PcmSetParams(kFakeHandle, _, _, i, _, _, _))
    725         .WillOnce(Return(0));
    726 
    727     // The parameters are specified by ALSA documentation, and are in constants
    728     // in the implementation files.
    729     EXPECT_CALL(mock_alsa_wrapper_, DeviceNameGetHint(_, StrEq("IOID")))
    730         .WillRepeatedly(Invoke(OutputHint));
    731     EXPECT_CALL(mock_alsa_wrapper_, DeviceNameGetHint(_, StrEq("NAME")))
    732         .WillRepeatedly(Invoke(EchoHint));
    733 
    734     AlsaPcmOutputStream* test_stream = CreateStream(kExpectedLayouts[i]);
    735     EXPECT_TRUE(test_stream->AutoSelectDevice(i));
    736     EXPECT_EQ(kExpectedDownmix[i],
    737               static_cast<bool>(test_stream->channel_mixer_));
    738 
    739     Mock::VerifyAndClearExpectations(&mock_alsa_wrapper_);
    740     Mock::VerifyAndClearExpectations(mock_manager_.get());
    741     test_stream->Close();
    742   }
    743 }
    744 
    745 TEST_F(AlsaPcmOutputStreamTest, AutoSelectDevice_FallbackDevices) {
    746   using std::string;
    747 
    748   // If there are problems opening a multi-channel device, it the fallbacks
    749   // operations should be as follows.  Assume the multi-channel device name is
    750   // surround50:
    751   //
    752   //   1) Try open "surround50"
    753   //   2) Try open "plug:surround50".
    754   //   3) Try open "default".
    755   //   4) Try open "plug:default".
    756   //   5) Give up trying to open.
    757   //
    758   const string first_try = kSurround50;
    759   const string second_try = string(AlsaPcmOutputStream::kPlugPrefix) +
    760                             kSurround50;
    761   const string third_try = AlsaPcmOutputStream::kDefaultDevice;
    762   const string fourth_try = string(AlsaPcmOutputStream::kPlugPrefix) +
    763                             AlsaPcmOutputStream::kDefaultDevice;
    764 
    765   EXPECT_CALL(mock_alsa_wrapper_, DeviceNameHint(_, _, _))
    766       .WillOnce(DoAll(SetArgumentPointee<2>(&kFakeHints[0]), Return(0)));
    767   EXPECT_CALL(mock_alsa_wrapper_, DeviceNameFreeHint(&kFakeHints[0]))
    768       .Times(1);
    769   EXPECT_CALL(mock_alsa_wrapper_, DeviceNameGetHint(_, StrEq("IOID")))
    770       .WillRepeatedly(Invoke(OutputHint));
    771   EXPECT_CALL(mock_alsa_wrapper_, DeviceNameGetHint(_, StrEq("NAME")))
    772       .WillRepeatedly(Invoke(EchoHint));
    773   EXPECT_CALL(mock_alsa_wrapper_, StrError(kTestFailedErrno))
    774       .WillRepeatedly(Return(kDummyMessage));
    775 
    776   InSequence s;
    777   EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, StrEq(first_try.c_str()), _, _))
    778       .WillOnce(Return(kTestFailedErrno));
    779   EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, StrEq(second_try.c_str()), _, _))
    780       .WillOnce(Return(kTestFailedErrno));
    781   EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, StrEq(third_try.c_str()), _, _))
    782       .WillOnce(Return(kTestFailedErrno));
    783   EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, StrEq(fourth_try.c_str()), _, _))
    784       .WillOnce(Return(kTestFailedErrno));
    785 
    786   AlsaPcmOutputStream* test_stream = CreateStream(CHANNEL_LAYOUT_5_0);
    787   EXPECT_FALSE(test_stream->AutoSelectDevice(5));
    788   test_stream->Close();
    789 }
    790 
    791 TEST_F(AlsaPcmOutputStreamTest, AutoSelectDevice_HintFail) {
    792   // Should get |kDefaultDevice|, and force a 2-channel downmix on a failure to
    793   // enumerate devices.
    794   EXPECT_CALL(mock_alsa_wrapper_, DeviceNameHint(_, _, _))
    795       .WillRepeatedly(Return(kTestFailedErrno));
    796   EXPECT_CALL(mock_alsa_wrapper_,
    797               PcmOpen(_, StrEq(AlsaPcmOutputStream::kDefaultDevice), _, _))
    798       .WillOnce(DoAll(SetArgumentPointee<0>(kFakeHandle), Return(0)));
    799   EXPECT_CALL(mock_alsa_wrapper_,
    800               PcmSetParams(kFakeHandle, _, _, 2, _, _, _))
    801       .WillOnce(Return(0));
    802   EXPECT_CALL(mock_alsa_wrapper_, StrError(kTestFailedErrno))
    803       .WillOnce(Return(kDummyMessage));
    804 
    805   AlsaPcmOutputStream* test_stream = CreateStream(CHANNEL_LAYOUT_5_0);
    806   EXPECT_TRUE(test_stream->AutoSelectDevice(5));
    807   EXPECT_TRUE(test_stream->channel_mixer_);
    808   test_stream->Close();
    809 }
    810 
    811 TEST_F(AlsaPcmOutputStreamTest, BufferPacket_StopStream) {
    812   AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
    813   InitBuffer(test_stream);
    814   test_stream->stop_stream_ = true;
    815   bool source_exhausted;
    816   test_stream->BufferPacket(&source_exhausted);
    817   EXPECT_EQ(0, test_stream->buffer_->forward_bytes());
    818   EXPECT_TRUE(source_exhausted);
    819   test_stream->Close();
    820 }
    821 
    822 TEST_F(AlsaPcmOutputStreamTest, ScheduleNextWrite) {
    823   AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
    824   test_stream->TransitionTo(AlsaPcmOutputStream::kIsOpened);
    825   test_stream->TransitionTo(AlsaPcmOutputStream::kIsPlaying);
    826   InitBuffer(test_stream);
    827   DVLOG(1) << test_stream->state();
    828   EXPECT_CALL(mock_alsa_wrapper_, PcmAvailUpdate(_))
    829       .WillOnce(Return(10));
    830   test_stream->ScheduleNextWrite(false);
    831   DVLOG(1) << test_stream->state();
    832   // TODO(sergeyu): Figure out how to check that the task has been added to the
    833   // message loop.
    834 
    835   // Cleanup the message queue. Currently ~MessageQueue() doesn't free pending
    836   // tasks unless running on valgrind. The code below is needed to keep
    837   // heapcheck happy.
    838 
    839   test_stream->stop_stream_ = true;
    840   DVLOG(1) << test_stream->state();
    841   test_stream->TransitionTo(AlsaPcmOutputStream::kIsClosed);
    842   DVLOG(1) << test_stream->state();
    843   test_stream->Close();
    844 }
    845 
    846 TEST_F(AlsaPcmOutputStreamTest, ScheduleNextWrite_StopStream) {
    847   AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
    848   test_stream->TransitionTo(AlsaPcmOutputStream::kIsOpened);
    849   test_stream->TransitionTo(AlsaPcmOutputStream::kIsPlaying);
    850 
    851   InitBuffer(test_stream);
    852 
    853   test_stream->stop_stream_ = true;
    854   test_stream->ScheduleNextWrite(true);
    855 
    856   // TODO(ajwong): Find a way to test whether or not another task has been
    857   // posted so we can verify that the Alsa code will indeed break the task
    858   // posting loop.
    859 
    860   test_stream->TransitionTo(AlsaPcmOutputStream::kIsClosed);
    861   test_stream->Close();
    862 }
    863 
    864 }  // namespace media
    865