Import Cobalt 6.18971

Change-Id: I0928329c9b9a5825331ab996d05476a6fe2c174f
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id
index 66145f8..9765737 100644
--- a/src/cobalt/build/build.id
+++ b/src/cobalt/build/build.id
@@ -1 +1 @@
-18938
\ No newline at end of file
+18971
\ No newline at end of file
diff --git a/src/starboard/shared/alsa/alsa_audio_sink_type.cc b/src/starboard/shared/alsa/alsa_audio_sink_type.cc
index 1556242..4c91f52 100644
--- a/src/starboard/shared/alsa/alsa_audio_sink_type.cc
+++ b/src/starboard/shared/alsa/alsa_audio_sink_type.cc
@@ -225,6 +225,8 @@
 bool AlsaAudioSink::IdleLoop() {
   SB_DLOG(INFO) << "alsa::AlsaAudioSink enters idle loop";
 
+  bool drain = true;
+
   for (;;) {
     {
       ScopedLock lock(mutex_);
@@ -239,12 +241,12 @@
     if (is_playing && frames_in_buffer > 0) {
       return true;
     }
-    int delayed_frame = AlsaGetBufferedFrames(playback_handle_);
-    if (delayed_frame < kMinimumFramesInALSA) {
+    if (drain) {
+      drain = false;
       AlsaWriteFrames(playback_handle_, silence_frames_, kFramesPerRequest);
-    } else {
-      SbThreadSleep(time_to_wait_);
+      AlsaDrain(playback_handle_);
     }
+    SbThreadSleep(time_to_wait_);
   }
 
   return false;
diff --git a/src/starboard/shared/alsa/alsa_util.cc b/src/starboard/shared/alsa/alsa_util.cc
index 0568156..b99c848 100644
--- a/src/starboard/shared/alsa/alsa_util.cc
+++ b/src/starboard/shared/alsa/alsa_util.cc
@@ -172,15 +172,16 @@
     return 0;
   }
 
+  int error;
+  snd_pcm_t* handle = reinterpret_cast<snd_pcm_t*>(playback_handle);
+
   int frames = 0;
   for (;;) {
-    frames = snd_pcm_writei(reinterpret_cast<snd_pcm_t*>(playback_handle),
-                            buffer, frames_to_write);
+    frames = snd_pcm_writei(handle, buffer, frames_to_write);
     if (frames > 0) {
       return frames;
     } else if (frames == -EPIPE) {
-      int error =
-          snd_pcm_prepare(reinterpret_cast<snd_pcm_t*>(playback_handle));
+      error = snd_pcm_prepare(handle);
       ALSA_CHECK(error, snd_pcm_prepare, 0);
     } else {
       ALSA_CHECK(frames, snd_pcm_writei, 0);
@@ -195,13 +196,16 @@
 int AlsaGetBufferedFrames(void* playback_handle) {
   int error;
   snd_pcm_t* handle = reinterpret_cast<snd_pcm_t*>(playback_handle);
-  // snd_pcm_delay() isn't able to catch xrun, so we explicitly check for xrun.
-  if (snd_pcm_state(handle) == SND_PCM_STATE_XRUN) {
+  int state = snd_pcm_state(handle);
+  // snd_pcm_delay() isn't able to catch xrun or setup, so we explicitly check
+  // for them.
+  if (state == SND_PCM_STATE_XRUN || state == SND_PCM_STATE_SETUP) {
     error = snd_pcm_prepare(handle);
     ALSA_CHECK(error, snd_pcm_prepare, -1);
     // The buffer has already been reset, so the delay is 0.
     return 0;
   }
+
   snd_pcm_sframes_t delay;
   error = snd_pcm_delay(handle, &delay);
   if (error == 0) {
@@ -223,6 +227,16 @@
   }
 }
 
+void AlsaDrain(void* playback_handle) {
+  if (playback_handle) {
+    snd_pcm_t* handle = reinterpret_cast<snd_pcm_t*>(playback_handle);
+
+    int error;
+    error = snd_pcm_drain(handle);
+    SB_DCHECK(error >= 0);
+  }
+}
+
 }  // namespace alsa
 }  // namespace shared
 }  // namespace starboard
diff --git a/src/starboard/shared/alsa/alsa_util.h b/src/starboard/shared/alsa/alsa_util.h
index bbbe04f..c0d068f 100644
--- a/src/starboard/shared/alsa/alsa_util.h
+++ b/src/starboard/shared/alsa/alsa_util.h
@@ -36,6 +36,7 @@
                     int frames_to_write);
 int AlsaGetBufferedFrames(void* playback_handle);
 void AlsaCloseDevice(void* playback_handle);
+void AlsaDrain(void* playback_handle);
 
 }  // namespace alsa
 }  // namespace shared