diff --git a/chromecast/media/cma/pipeline/media_pipeline_impl.cc b/chromecast/media/cma/pipeline/media_pipeline_impl.cc index fa6d002234ff5..87e383f838f02 100644 --- a/chromecast/media/cma/pipeline/media_pipeline_impl.cc +++ b/chromecast/media/cma/pipeline/media_pipeline_impl.cc @@ -369,12 +369,18 @@ void MediaPipelineImpl::OnFlushDone(bool is_audio_stream) { if (pending_flush_task_->audio_flushed && pending_flush_task_->video_flushed) { - // Stop the backend, so that the backend won't push their pending buffer, - // which may be invalidated later, to hardware. (b/25342604) - media_pipeline_backend_->Stop(); - backend_state_ = BACKEND_STATE_INITIALIZED; - metrics::CastMetricsHelper::GetInstance()->RecordApplicationEvent( - "Cast.Platform.Ended"); + // Only Stop() and transition to INITIALIZED if the backend was actually + // started. A compromised renderer can call Renderer.Flush() before + // StartPlayingFrom(); without this guard we would call Stop() on a + // never-Initialize()d vendor backend and then permanently bypass the + // lazy Initialize() in StartPlayingFrom(). (b/25342604 still applies for + // the started case.) + if (backend_state_ != BACKEND_STATE_UNINITIALIZED) { + media_pipeline_backend_->Stop(); + backend_state_ = BACKEND_STATE_INITIALIZED; + metrics::CastMetricsHelper::GetInstance()->RecordApplicationEvent( + "Cast.Platform.Ended"); + } base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( FROM_HERE, std::move(pending_flush_task_->done_cb));