// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/gpu/android/android_video_decode_accelerator.h"

#include <stdint.h>

#include <memory>

#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "gpu/command_buffer/client/client_test_helper.h"
#include "gpu/command_buffer/service/context_group.h"
#include "gpu/command_buffer/service/gpu_tracer.h"
#include "gpu/command_buffer/service/image_manager.h"
#include "gpu/command_buffer/service/mailbox_manager_impl.h"
#include "gpu/command_buffer/service/service_discardable_manager.h"
#include "gpu/command_buffer/service/shared_image_manager.h"
#include "media/base/android/media_codec_util.h"
#include "media/base/android/mock_android_overlay.h"
#include "media/base/android/mock_media_codec_bridge.h"
#include "media/gpu/android/android_video_decode_accelerator.h"
#include "media/gpu/android/android_video_surface_chooser.h"
#include "media/gpu/android/codec_allocator.h"
#include "media/gpu/android/fake_codec_allocator.h"
#include "media/gpu/android/mock_abstract_texture.h"
#include "media/gpu/android/mock_android_video_surface_chooser.h"
#include "media/gpu/android/mock_device_info.h"
#include "media/media_buildflags.h"
#include "media/video/picture.h"
#include "media/video/video_decode_accelerator.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gl/android/surface_texture.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/init/gl_factory.h"

using ::testing::NiceMock;
using ::testing::NotNull;
using ::testing::Return;
using ::testing::_;

namespace media {
namespace {

#define SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE()     \
  do {                                            \
    if (!MediaCodecUtil::IsMediaCodecAvailable()) \
      return;                                     \
  } while (false)

bool MakeContextCurrent() {
  return true;
}

gpu::gles2::ContextGroup* GetContextGroup(
    scoped_refptr<gpu::gles2::ContextGroup> context_group) {
  return context_group.get();
}

class MockVDAClient : public VideoDecodeAccelerator::Client {
 public:
  MockVDAClient() {}

  MOCK_METHOD1(NotifyInitializationComplete, void(bool));
  MOCK_METHOD5(
      ProvidePictureBuffers,
      void(uint32_t, VideoPixelFormat, uint32_t, const gfx::Size&, uint32_t));
  MOCK_METHOD1(DismissPictureBuffer, void(int32_t));
  MOCK_METHOD1(PictureReady, void(const Picture&));
  MOCK_METHOD1(NotifyEndOfBitstreamBuffer, void(int32_t));
  MOCK_METHOD0(NotifyFlushDone, void());
  MOCK_METHOD0(NotifyResetDone, void());
  MOCK_METHOD1(NotifyError, void(VideoDecodeAccelerator::Error));

 private:
  DISALLOW_COPY_AND_ASSIGN(MockVDAClient);
};

}  // namespace

class AndroidVideoDecodeAcceleratorTest
    : public testing::TestWithParam<VideoCodecProfile> {
 public:
  // Default to baseline H264 because it's always supported.
  AndroidVideoDecodeAcceleratorTest() : config_(GetParam()) {}

  void SetUp() override {
    ASSERT_TRUE(gl::init::InitializeGLOneOff());
    surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size(16, 16));
    context_ = gl::init::CreateGLContext(nullptr, surface_.get(),
                                         gl::GLContextAttribs());
    context_->MakeCurrent(surface_.get());

    codec_allocator_ = std::make_unique<FakeCodecAllocator>(
        base::SequencedTaskRunnerHandle::Get());
    device_info_ = std::make_unique<NiceMock<MockDeviceInfo>>();

    chooser_that_is_usually_null_ =
        std::make_unique<NiceMock<MockAndroidVideoSurfaceChooser>>();
    chooser_ = chooser_that_is_usually_null_.get();

    feature_info_ = new gpu::gles2::FeatureInfo();
    context_group_ = new gpu::gles2::ContextGroup(
        gpu_preferences_, false, &mailbox_manager_, nullptr, nullptr, nullptr,
        feature_info_, false, &image_manager_, nullptr, nullptr,
        gpu::GpuFeatureInfo(), &discardable_manager_, nullptr,
        &shared_image_manager_);

    // By default, allow deferred init.
    config_.is_deferred_initialization_allowed = true;
  }

  ~AndroidVideoDecodeAcceleratorTest() override {
    // ~AVDASurfaceBundle() might rely on GL being available, so we have to
    // explicitly drop references to them before tearing down GL.
    vda_ = nullptr;
    codec_allocator_ = nullptr;
    context_ = nullptr;
    surface_ = nullptr;
    feature_info_ = nullptr;
    context_group_ = nullptr;

    gl::init::ShutdownGL(false);
  }

  std::unique_ptr<AndroidOverlay> OverlayFactory(const base::UnguessableToken&,
                                                 AndroidOverlayConfig config) {
    // This shouldn't be called by AVDA.  Our mock surface chooser won't use it
    // either, though it'd be nice to check to token.  Note that this isn't the
    // same as an emtpy factory callback; that means "no factory".  This one
    // looks like a working factory, as long as nobody calls it.
    return nullptr;
  }

  // Create and initialize AVDA with |config_|, and return the result.
  bool InitializeAVDA(bool force_defer_surface_creation = false) {
    // Because VDA has a custom deleter, we must assign it to |vda_| carefully.
    AndroidVideoDecodeAccelerator* avda = new AndroidVideoDecodeAccelerator(
        codec_allocator_.get(), std::move(chooser_that_is_usually_null_),
        base::BindRepeating(&MakeContextCurrent),
        base::BindRepeating(&GetContextGroup, context_group_),
        base::BindRepeating(&AndroidVideoDecodeAcceleratorTest::OverlayFactory,
                            base::Unretained(this)),
        base::BindRepeating(
            &AndroidVideoDecodeAcceleratorTest::CreateAbstractTexture,
            base::Unretained(this)),
        device_info_.get());
    vda_.reset(avda);
    avda->force_defer_surface_creation_for_testing_ =
        force_defer_surface_creation;
    avda->force_allow_software_decoding_for_testing_ = true;

    bool result = vda_->Initialize(config_, &client_);
    base::RunLoop().RunUntilIdle();
    return result;
  }

  std::unique_ptr<gpu::gles2::AbstractTexture> CreateAbstractTexture(
      GLenum target,
      GLenum internal_format,
      GLsizei width,
      GLsizei height,
      GLsizei depth,
      int border,
      GLenum format,
      GLenum type) {
    return std::make_unique<MockAbstractTexture>(0);
  }

  // Initialize |vda_|, providing a new surface for it.  You may get the surface
  // by asking |codec_allocator_|.
  void InitializeAVDAWithOverlay() {
    config_.overlay_info.routing_token = base::UnguessableToken::Create();
    ASSERT_TRUE(InitializeAVDA());
    base::RunLoop().RunUntilIdle();
    ASSERT_TRUE(chooser_->factory_);

    // Have the factory provide an overlay, and verify that codec creation is
    // provided with that overlay.
    std::unique_ptr<MockAndroidOverlay> overlay =
        std::make_unique<MockAndroidOverlay>();
    overlay_callbacks_ = overlay->GetCallbacks();

    // Set the expectations first, since ProvideOverlay might cause callbacks.
    EXPECT_CALL(*codec_allocator_,
                MockCreateMediaCodecAsync(overlay.get(), nullptr));
    chooser_->ProvideOverlay(std::move(overlay));

    // Provide the codec so that we can check if it's freed properly.
    EXPECT_CALL(client_, NotifyInitializationComplete(true));
    codec_allocator_->ProvideMockCodecAsync();
    base::RunLoop().RunUntilIdle();
  }

  void InitializeAVDAWithTextureOwner() {
    ASSERT_TRUE(InitializeAVDA());
    base::RunLoop().RunUntilIdle();
    // We do not expect a factory, since we are using TextureOwner.
    ASSERT_FALSE(chooser_->factory_);

    // Set the expectations first, since ProvideOverlay might cause callbacks.
    EXPECT_CALL(*codec_allocator_,
                MockCreateMediaCodecAsync(nullptr, NotNull()));
    chooser_->ProvideTextureOwner();

    // Provide the codec so that we can check if it's freed properly.
    EXPECT_CALL(client_, NotifyInitializationComplete(true));
    codec_allocator_->ProvideMockCodecAsync();
    base::RunLoop().RunUntilIdle();
  }

  // Set whether HasUnrendereredPictureBuffers will return true or false.
  // TODO(liberato): We can't actually do this yet.  It turns out to be okay,
  // because AVDA doesn't actually SetSurface before DequeueOutput.  It could do
  // so, though, if there aren't unrendered buffers.  Should AVDA ever start
  // switching surfaces immediately upon receiving them, rather than waiting for
  // DequeueOutput, then we'll want to be able to indicate that it has
  // unrendered pictures to prevent that behavior.
  void SetHasUnrenderedPictureBuffers(bool flag) {}

  // Tell |avda_| to switch surfaces to its incoming surface.  This is a method
  // since we're a friend of AVDA, and the tests are subclasses.  It's also
  // somewhat hacky, but much less hacky than trying to run it via a timer.
  void LetAVDAUpdateSurface() {
    SetHasUnrenderedPictureBuffers(false);
    avda()->DequeueOutput();
  }

  // So that SequencedTaskRunnerHandle::Get() works.
  base::test::ScopedTaskEnvironment scoped_task_environment_;

  scoped_refptr<gl::GLSurface> surface_;
  scoped_refptr<gl::GLContext> context_;
  NiceMock<MockVDAClient> client_;
  std::unique_ptr<FakeCodecAllocator> codec_allocator_;

  scoped_refptr<gpu::gles2::ContextGroup> context_group_;
  scoped_refptr<gpu::gles2::FeatureInfo> feature_info_;
  gpu::GpuPreferences gpu_preferences_;
  gpu::gles2::MailboxManagerImpl mailbox_manager_;
  gpu::gles2::ImageManager image_manager_;
  gpu::ServiceDiscardableManager discardable_manager_;
  gpu::SharedImageManager shared_image_manager_;

  // Only set until InitializeAVDA() is called.
  std::unique_ptr<MockAndroidVideoSurfaceChooser> chooser_that_is_usually_null_;
  MockAndroidVideoSurfaceChooser* chooser_;
  VideoDecodeAccelerator::Config config_;
  std::unique_ptr<MockDeviceInfo> device_info_;

  // Set by InitializeAVDAWithOverlay()
  MockAndroidOverlay::Callbacks overlay_callbacks_;

  // This must be a unique pointer to a VDA, not an AVDA, to ensure the
  // the default_delete specialization that calls Destroy() will be used.
  std::unique_ptr<VideoDecodeAccelerator> vda_;

  AndroidVideoDecodeAccelerator* avda() {
    return reinterpret_cast<AndroidVideoDecodeAccelerator*>(vda_.get());
  }
};

TEST_P(AndroidVideoDecodeAcceleratorTest, ConfigureUnsupportedCodec) {
  SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();

  config_ = VideoDecodeAccelerator::Config(VIDEO_CODEC_PROFILE_UNKNOWN);
  ASSERT_FALSE(InitializeAVDA());
}

TEST_P(AndroidVideoDecodeAcceleratorTest,
       ConfigureSupportedCodecSynchronously) {
  SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();

  config_.is_deferred_initialization_allowed = false;

  EXPECT_CALL(*codec_allocator_, MockCreateMediaCodecSync(_, _));
  // AVDA must set client callbacks even in sync mode, so that the chooser is
  // in a sane state.  https://crbug.com/772899 .
  EXPECT_CALL(*chooser_, MockSetClientCallbacks());
  ASSERT_TRUE(InitializeAVDA());
  testing::Mock::VerifyAndClearExpectations(chooser_);
}

TEST_P(AndroidVideoDecodeAcceleratorTest, FailingToCreateACodecSyncIsAnError) {
  // Failuew to create a codec during sync init should cause Initialize to fail.
  SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();

  config_.is_deferred_initialization_allowed = false;
  codec_allocator_->allow_sync_creation = false;

  EXPECT_CALL(*codec_allocator_, MockCreateMediaCodecSync(nullptr, NotNull()));
  ASSERT_FALSE(InitializeAVDA());
}

TEST_P(AndroidVideoDecodeAcceleratorTest, FailingToCreateACodecAsyncIsAnError) {
  // Verify that a null codec signals error for async init when it doesn't get a
  // mediacodec instance.
  //
  // Also assert that there's only one call to CreateMediaCodecAsync. And since
  // it replies with a null codec, AVDA will be in an error state when it shuts
  // down.  Since we know that it's constructed before we destroy the VDA, we
  // verify that AVDA doens't create codecs during destruction.
  SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();

  // Note that if we somehow end up deferring surface creation, then this would
  // no longer be expected to fail.  It would signal success before asking for a
  // surface or codec.
  EXPECT_CALL(*codec_allocator_, MockCreateMediaCodecAsync(_, NotNull()));
  EXPECT_CALL(client_, NotifyInitializationComplete(false));

  ASSERT_TRUE(InitializeAVDA());
  chooser_->ProvideTextureOwner();
  codec_allocator_->ProvideNullCodecAsync();

  // Make sure that codec allocation has happened before destroying the VDA.
  testing::Mock::VerifyAndClearExpectations(codec_allocator_.get());
}

TEST_P(AndroidVideoDecodeAcceleratorTest,
       LowEndDevicesSucceedInitWithoutASurface) {
  // If AVDA decides that we should defer surface creation, then it should
  // signal success before we provide a surface.  It should still ask for a
  // surface, though.
  SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();

  EXPECT_CALL(*chooser_, MockUpdateState()).Times(0);
  EXPECT_CALL(client_, NotifyInitializationComplete(true));

  // It would be nicer if we didn't just force this on, since we might do so
  // in a state that AVDA isn't supposed to handle (e.g., if we give it a
  // surface, then it would never decide to defer surface creation).
  bool force_defer_surface_creation = true;
  InitializeAVDA(force_defer_surface_creation);
}

TEST_P(AndroidVideoDecodeAcceleratorTest, AsyncInitWithTextureOwnerAndDelete) {
  // When configuring with a TextureOwner and deferred init, we should be
  // asked for a codec, and be notified of init success if we provide one. When
  // AVDA is destroyed, it should release the codec and texture owner.
  SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();

  InitializeAVDAWithTextureOwner();

  // Delete the VDA, and make sure that it tries to free the codec and the right
  // texture owner.
  EXPECT_CALL(
      *codec_allocator_,
      MockReleaseMediaCodec(codec_allocator_->most_recent_codec,
                            codec_allocator_->most_recent_overlay,
                            codec_allocator_->most_recent_texture_owner));
  codec_allocator_->most_recent_codec_destruction_observer->ExpectDestruction();
  vda_ = nullptr;
  base::RunLoop().RunUntilIdle();
}

TEST_P(AndroidVideoDecodeAcceleratorTest, AsyncInitWithSurfaceAndDelete) {
  // When |config_| specifies a surface, we should be given a factory during
  // startup for it.  When |chooser_| provides an overlay, the codec should be
  // allocated using it.  Shutdown should provide the overlay when releasing the
  // media codec.
  SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();

  InitializeAVDAWithOverlay();

  // Delete the VDA, and make sure that it tries to free the codec and the
  // overlay that it provided to us.
  EXPECT_CALL(
      *codec_allocator_,
      MockReleaseMediaCodec(codec_allocator_->most_recent_codec,
                            codec_allocator_->most_recent_overlay,
                            codec_allocator_->most_recent_texture_owner));
  codec_allocator_->most_recent_codec_destruction_observer->ExpectDestruction();
  vda_ = nullptr;
  base::RunLoop().RunUntilIdle();
}

TEST_P(AndroidVideoDecodeAcceleratorTest,
       SwitchesToTextureOwnerWhenSurfaceDestroyed) {
  // Provide a surface, and a codec, then destroy the surface.  AVDA should use
  // SetSurface to switch to TextureOwner.
  SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();

  InitializeAVDAWithOverlay();

  // It would be nice if we knew that this was a texture owner.  As it is, we
  // just destroy the VDA and expect that we're provided with one.  Hopefully,
  // AVDA is actually calling SetSurface properly.
  EXPECT_CALL(*codec_allocator_->most_recent_codec, SetSurface(_))
      .WillOnce(Return(true));
  codec_allocator_->most_recent_codec_destruction_observer
      ->VerifyAndClearExpectations();
  overlay_callbacks_.SurfaceDestroyed.Run();
  base::RunLoop().RunUntilIdle();

  EXPECT_CALL(*codec_allocator_,
              MockReleaseMediaCodec(codec_allocator_->most_recent_codec,
                                    nullptr, NotNull()));
  vda_ = nullptr;
  base::RunLoop().RunUntilIdle();
}

TEST_P(AndroidVideoDecodeAcceleratorTest, SwitchesToTextureOwnerEventually) {
  // Provide a surface, and a codec, then request that AVDA switches to a
  // texture owner.  Verify that it does.
  SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();

  InitializeAVDAWithOverlay();

  EXPECT_CALL(*codec_allocator_->most_recent_codec, SetSurface(_))
      .WillOnce(Return(true));

  // Note that it's okay if |avda_| switches before ProvideTextureOwner
  // returns, since it has no queued output anyway.
  chooser_->ProvideTextureOwner();
  LetAVDAUpdateSurface();

  // Verify that we're now using some texture owner.
  EXPECT_CALL(*codec_allocator_,
              MockReleaseMediaCodec(codec_allocator_->most_recent_codec,
                                    nullptr, NotNull()));
  codec_allocator_->most_recent_codec_destruction_observer->ExpectDestruction();
  vda_ = nullptr;
  base::RunLoop().RunUntilIdle();
}

TEST_P(AndroidVideoDecodeAcceleratorTest,
       SetSurfaceFailureDoesntSwitchSurfaces) {
  // Initialize AVDA with a surface, then request that AVDA switches to a
  // texture owner.  When it tries to UpdateSurface, pretend to fail.  AVDA
  // should notify error, and also release the original surface.
  SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();

  InitializeAVDAWithOverlay();

  EXPECT_CALL(*codec_allocator_->most_recent_codec, SetSurface(_))
      .WillOnce(Return(false));
  EXPECT_CALL(client_,
              NotifyError(AndroidVideoDecodeAccelerator::PLATFORM_FAILURE))
      .Times(1);
  codec_allocator_->most_recent_codec_destruction_observer
      ->VerifyAndClearExpectations();
  chooser_->ProvideTextureOwner();
  LetAVDAUpdateSurface();
}

TEST_P(AndroidVideoDecodeAcceleratorTest,
       SwitchToSurfaceAndBackBeforeSetSurface) {
  // Ask AVDA to switch from ST to overlay, then back to ST before it has a
  // chance to do the first switch.  It should simply drop the overlay.
  SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();

  InitializeAVDAWithTextureOwner();

  // Don't let AVDA switch immediately, else it could choose to SetSurface when
  // it first gets the overlay.
  SetHasUnrenderedPictureBuffers(true);
  EXPECT_CALL(*codec_allocator_->most_recent_codec, SetSurface(_)).Times(0);
  std::unique_ptr<MockAndroidOverlay> overlay =
      std::make_unique<MockAndroidOverlay>();
  // Make sure that the overlay is not destroyed too soon.
  std::unique_ptr<DestructionObserver> observer =
      overlay->CreateDestructionObserver();
  observer->DoNotAllowDestruction();

  chooser_->ProvideOverlay(std::move(overlay));

  // Now it is expected to drop the overlay.
  observer->ExpectDestruction();

  // While the incoming surface is pending, switch back to TextureOwner.
  chooser_->ProvideTextureOwner();
}

TEST_P(AndroidVideoDecodeAcceleratorTest,
       ChangingOutputSurfaceVoluntarilyWithoutSetSurfaceIsIgnored) {
  // If we ask AVDA to change to TextureOwner should be ignored on platforms
  // that don't support SetSurface (pre-M or blacklisted).  It should also
  // ignore TextureOwner => overlay, but we don't check that.
  //
  // Also note that there are other probably reasonable things to do (like
  // signal an error), but we want to be sure that it doesn't try to SetSurface.
  // We also want to be sure that, if it doesn't signal an error, that it also
  // doesn't get confused about which surface is in use.  So, we assume that it
  // doesn't signal an error, and we check that it releases the right surface
  // with the codec.
  SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();
  EXPECT_CALL(client_, NotifyError(_)).Times(0);

  ON_CALL(*device_info_, IsSetOutputSurfaceSupported())
      .WillByDefault(Return(false));
  InitializeAVDAWithOverlay();
  EXPECT_CALL(*codec_allocator_->most_recent_codec, SetSurface(_)).Times(0);

  // This should not switch to TextureOwner.
  chooser_->ProvideTextureOwner();
  LetAVDAUpdateSurface();
}

TEST_P(AndroidVideoDecodeAcceleratorTest,
       OnSurfaceDestroyedWithoutSetSurfaceFreesTheCodec) {
  // If AVDA receives OnSurfaceDestroyed without support for SetSurface, then it
  // should free the codec.
  SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();
  ON_CALL(*device_info_, IsSetOutputSurfaceSupported())
      .WillByDefault(Return(false));
  InitializeAVDAWithOverlay();
  EXPECT_CALL(*codec_allocator_->most_recent_codec, SetSurface(_)).Times(0);

  // This should free the codec.
  EXPECT_CALL(
      *codec_allocator_,
      MockReleaseMediaCodec(codec_allocator_->most_recent_codec,
                            codec_allocator_->most_recent_overlay, nullptr));
  codec_allocator_->most_recent_codec_destruction_observer->ExpectDestruction();
  overlay_callbacks_.SurfaceDestroyed.Run();
  base::RunLoop().RunUntilIdle();

  // Verify that the codec has been released, since |vda_| will be destroyed
  // soon.  The expectations must be met before that.
  testing::Mock::VerifyAndClearExpectations(&codec_allocator_);
  codec_allocator_->most_recent_codec_destruction_observer
      ->VerifyAndClearExpectations();
}

TEST_P(AndroidVideoDecodeAcceleratorTest,
       MultipleTextureOwnerCallbacksAreIgnored) {
  // Ask AVDA to switch to ST when it's already using ST, nothing should happen.
  SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();

  InitializeAVDAWithTextureOwner();

  // This should do nothing.
  EXPECT_CALL(*codec_allocator_->most_recent_codec, SetSurface(_)).Times(0);
  chooser_->ProvideTextureOwner();

  base::RunLoop().RunUntilIdle();
}

TEST_P(AndroidVideoDecodeAcceleratorTest,
       OverlayInfoWithDuplicateSurfaceIDDoesntChangeTheFactory) {
  // Send OverlayInfo with duplicate info, and verify that it doesn't change
  // the factory.
  SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();
  InitializeAVDAWithOverlay();

  EXPECT_CALL(*chooser_, MockUpdateState()).Times(1);
  EXPECT_CALL(*chooser_, MockReplaceOverlayFactory(_)).Times(0);
  OverlayInfo overlay_info = config_.overlay_info;
  avda()->SetOverlayInfo(overlay_info);
}

TEST_P(AndroidVideoDecodeAcceleratorTest,
       OverlayInfoWithNewSurfaceIDDoesChangeTheFactory) {
  // Send OverlayInfo with new surface info, and verify that it does change the
  // overlay factory.
  SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();
  InitializeAVDAWithOverlay();

  EXPECT_CALL(*chooser_, MockUpdateState()).Times(1);
  OverlayInfo overlay_info = config_.overlay_info;
  overlay_info.routing_token = base::UnguessableToken::Create();
  avda()->SetOverlayInfo(overlay_info);
}

TEST_P(AndroidVideoDecodeAcceleratorTest, FullscreenSignalIsSentToChooser) {
  // Send OverlayInfo that has |is_fullscreen| set, and verify that the chooser
  // is notified about it.
  SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();
  InitializeAVDAWithOverlay();
  OverlayInfo overlay_info = config_.overlay_info;
  overlay_info.is_fullscreen = !config_.overlay_info.is_fullscreen;
  avda()->SetOverlayInfo(overlay_info);
  ASSERT_EQ(chooser_->current_state_.is_fullscreen, overlay_info.is_fullscreen);
}

static std::vector<VideoCodecProfile> GetTestList() {
  std::vector<VideoCodecProfile> test_profiles;

#if BUILDFLAG(USE_PROPRIETARY_CODECS)
  if (MediaCodecUtil::IsMediaCodecAvailable())
    test_profiles.push_back(H264PROFILE_BASELINE);
#endif

  if (MediaCodecUtil::IsVp8DecoderAvailable())
    test_profiles.push_back(VP8PROFILE_ANY);
  if (MediaCodecUtil::IsVp9DecoderAvailable())
    test_profiles.push_back(VP9PROFILE_PROFILE0);
  return test_profiles;
}

INSTANTIATE_TEST_SUITE_P(AndroidVideoDecodeAcceleratorTest,
                         AndroidVideoDecodeAcceleratorTest,
                         testing::ValuesIn(GetTestList()));

}  // namespace media
