// Copyright 2015 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 "ash/rotator/screen_rotation_animator.h"

#include <memory>

#include "ash/public/cpp/ash_switches.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/rotator/screen_rotation_animation.h"
#include "ash/rotator/screen_rotation_animator_observer.h"
#include "ash/shell.h"
#include "ash/utility/transformer_util.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/metrics/histogram_macros.h"
#include "base/time/time.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/common/frame_sinks/copy_output_result.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "ui/aura/window.h"
#include "ui/base/class_property.h"
#include "ui/compositor/callback_layer_animation_observer.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_element.h"
#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/layer_animator.h"
#include "ui/compositor/layer_owner.h"
#include "ui/compositor/layer_tree_owner.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/display/display.h"
#include "ui/display/manager/display_manager.h"
#include "ui/display/manager/managed_display_info.h"
#include "ui/display/screen.h"
#include "ui/gfx/animation/tween.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size_f.h"
#include "ui/gfx/transform.h"
#include "ui/gfx/transform_util.h"
#include "ui/wm/core/window_util.h"

DEFINE_UI_CLASS_PROPERTY_TYPE(ash::ScreenRotationAnimator*)

namespace ash {

namespace {

// The number of degrees that the rotation animations animate through.
const int kRotationDegrees = 20;

// The time it takes for the rotation animations to run.
const int kRotationDurationInMs = 250;

// The rotation factors.
const int kCounterClockWiseRotationFactor = 1;
const int kClockWiseRotationFactor = -1;

// A property key to store the ScreenRotationAnimator of the window; Used for
// screen rotation.
DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(ScreenRotationAnimator,
                                   kScreenRotationAnimatorKey,
                                   nullptr)

display::Display::Rotation GetCurrentScreenRotation(int64_t display_id) {
  return Shell::Get()
      ->display_manager()
      ->GetDisplayInfo(display_id)
      .GetActiveRotation();
}

// 180 degree rotations should animate clock-wise.
int GetRotationFactor(display::Display::Rotation initial_rotation,
                      display::Display::Rotation new_rotation) {
  return (initial_rotation + 3) % 4 == new_rotation
             ? kCounterClockWiseRotationFactor
             : kClockWiseRotationFactor;
}

aura::Window* GetScreenRotationContainer(aura::Window* root_window) {
  return root_window->GetChildById(kShellWindowId_ScreenRotationContainer);
}

// Returns true if the rotation between |initial_rotation| and |new_rotation| is
// 180 degrees.
bool Is180DegreeFlip(display::Display::Rotation initial_rotation,
                     display::Display::Rotation new_rotation) {
  return (initial_rotation + 2) % 4 == new_rotation;
}

// Returns the initial degrees the old layer animation to begin with.
int GetInitialDegrees(display::Display::Rotation initial_rotation,
                      display::Display::Rotation new_rotation) {
  return (Is180DegreeFlip(initial_rotation, new_rotation) ? 180 : 90);
}

void AddLayerAtTopOfWindowLayers(aura::Window* root_window, ui::Layer* layer) {
  // Add the cloned/copied layer tree into the root, so it will be rendered.
  root_window->layer()->Add(layer);
  root_window->layer()->StackAtTop(layer);
}

void AddLayerBelowWindowLayer(aura::Window* root_window,
                              ui::Layer* top_layer,
                              ui::Layer* layer) {
  // Add the cloned/copied layer tree into the root, so it will be rendered.
  root_window->layer()->Add(layer);
  root_window->layer()->StackBelow(layer, top_layer);
}

// The Callback will be invoked when all animation sequences have
// finished. |observer| will be destroyed after invoking the Callback if it
// returns true.
bool AnimationEndedCallback(
    base::WeakPtr<ScreenRotationAnimator> animator,
    const ui::CallbackLayerAnimationObserver& observer) {
  if (animator)
    animator->ProcessAnimationQueue();
  return true;
}

// Creates a Transform for the old layer in screen rotation animation.
gfx::Transform CreateScreenRotationOldLayerTransformForDisplay(
    display::Display::Rotation old_rotation,
    display::Display::Rotation new_rotation,
    const display::Display& display) {
  gfx::Transform inverse;
  CHECK(CreateRotationTransform(old_rotation, new_rotation,
                                gfx::SizeF(display.size()))
            .GetInverse(&inverse));
  return inverse;
}

// The |request_id| changed since last copy request, which means a
// new rotation stated, we need to ignore this copy result.
bool IgnoreCopyResult(int64_t request_id, int64_t current_request_id) {
  DCHECK(request_id <= current_request_id);
  return request_id < current_request_id;
}

bool RootWindowChangedForDisplayId(aura::Window* root_window,
                                   int64_t display_id) {
  return root_window != Shell::GetRootWindowForDisplayId(display_id);
}

// Creates a mask layer and returns the |mask_layer_tree_owner|.
std::unique_ptr<ui::LayerTreeOwner> CreateMaskLayerTreeOwner(
    const gfx::Rect& rect) {
  std::unique_ptr<ui::Layer> mask_layer =
      std::make_unique<ui::Layer>(ui::LAYER_SOLID_COLOR);
  mask_layer->SetBounds(rect);
  mask_layer->SetColor(SK_ColorBLACK);
  return std::make_unique<ui::LayerTreeOwner>(std::move(mask_layer));
}

class ScreenRotationAnimationMetricsReporter
    : public ui::AnimationMetricsReporter {
 public:
  ScreenRotationAnimationMetricsReporter() = default;
  ~ScreenRotationAnimationMetricsReporter() override = default;

  void Report(int value) override {
    UMA_HISTOGRAM_PERCENTAGE("Ash.Rotation.AnimationSmoothness", value);
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimationMetricsReporter);
};

}  // namespace

// static
ScreenRotationAnimator* ScreenRotationAnimator::GetForRootWindow(
    aura::Window* root_window) {
  auto* animator = root_window->GetProperty(kScreenRotationAnimatorKey);
  if (!animator) {
    animator = new ScreenRotationAnimator(root_window);
    root_window->SetProperty(kScreenRotationAnimatorKey, animator);
  }
  return animator;
}

// static
void ScreenRotationAnimator::SetScreenRotationAnimatorForTest(
    aura::Window* root_window,
    std::unique_ptr<ScreenRotationAnimator> animator) {
  root_window->SetProperty(kScreenRotationAnimatorKey, animator.release());
}

ScreenRotationAnimator::ScreenRotationAnimator(aura::Window* root_window)
    : root_window_(root_window),
      screen_rotation_state_(IDLE),
      rotation_request_id_(0),
      metrics_reporter_(
          std::make_unique<ScreenRotationAnimationMetricsReporter>()),
      disable_animation_timers_for_test_(false),
      weak_factory_(this) {}

ScreenRotationAnimator::~ScreenRotationAnimator() {
  // To prevent a call to |AnimationEndedCallback()| from calling a method on
  // the |animator_|.
  weak_factory_.InvalidateWeakPtrs();

  // Explicitly reset the |old_layer_tree_owner_| and |metrics_reporter_| in
  // order to make sure |metrics_reporter_| outlives the attached animation
  // sequence.
  old_layer_tree_owner_.reset();
  metrics_reporter_.reset();
}

void ScreenRotationAnimator::StartRotationAnimation(
    std::unique_ptr<ScreenRotationRequest> rotation_request) {
  const display::Display::Rotation current_rotation =
      GetCurrentScreenRotation(rotation_request->display_id);
  if (current_rotation == rotation_request->new_rotation) {
    // We need to call |ProcessAnimationQueue()| to prepare for next rotation
    // request.
    ProcessAnimationQueue();
    return;
  }

  rotation_request->old_rotation = current_rotation;
  if (DisplayConfigurationController::ANIMATION_SYNC ==
      rotation_request->mode) {
    StartSlowAnimation(std::move(rotation_request));
  } else {
    current_async_rotation_request_ = ScreenRotationRequest(*rotation_request);
    RequestCopyScreenRotationContainerLayer(
        std::make_unique<viz::CopyOutputRequest>(
            viz::CopyOutputRequest::ResultFormat::RGBA_TEXTURE,
            CreateAfterCopyCallbackBeforeRotation(
                std::move(rotation_request))));
    screen_rotation_state_ = COPY_REQUESTED;
  }
}

void ScreenRotationAnimator::StartSlowAnimation(
    std::unique_ptr<ScreenRotationRequest> rotation_request) {
  CreateOldLayerTreeForSlowAnimation();
  SetRotation(rotation_request->display_id, rotation_request->old_rotation,
              rotation_request->new_rotation, rotation_request->source);
  AnimateRotation(std::move(rotation_request));
}

void ScreenRotationAnimator::SetRotation(
    int64_t display_id,
    display::Display::Rotation old_rotation,
    display::Display::Rotation new_rotation,
    display::Display::RotationSource source) {
  // Reset the current request because its rotation must be applied if any.
  current_async_rotation_request_.reset();

  // Allow compositor locks to extend timeout, so that screen rotation only
  // takes output copy after contents are properlly resized, such as wallpaper
  // and ARC apps.
  ui::Compositor* compositor = root_window_->layer()->GetCompositor();
  compositor->SetAllowLocksToExtendTimeout(true);
  Shell::Get()->display_manager()->SetDisplayRotation(display_id, new_rotation,
                                                      source);
  compositor->SetAllowLocksToExtendTimeout(false);
  const display::Display display =
      Shell::Get()->display_manager()->GetDisplayForId(display_id);
  old_layer_tree_owner_->root()->SetTransform(
      CreateScreenRotationOldLayerTransformForDisplay(old_rotation,
                                                      new_rotation, display));
}

void ScreenRotationAnimator::RequestCopyScreenRotationContainerLayer(
    std::unique_ptr<viz::CopyOutputRequest> copy_output_request) {
  ui::Layer* screen_rotation_container_layer =
      GetScreenRotationContainer(root_window_)->layer();
  copy_output_request->set_area(
      gfx::Rect(screen_rotation_container_layer->size()));
  screen_rotation_container_layer->RequestCopyOfOutput(
      std::move(copy_output_request));
}

ScreenRotationAnimator::CopyCallback
ScreenRotationAnimator::CreateAfterCopyCallbackBeforeRotation(
    std::unique_ptr<ScreenRotationRequest> rotation_request) {
  return base::BindOnce(&ScreenRotationAnimator::
                            OnScreenRotationContainerLayerCopiedBeforeRotation,
                        weak_factory_.GetWeakPtr(),
                        base::Passed(&rotation_request));
}

ScreenRotationAnimator::CopyCallback
ScreenRotationAnimator::CreateAfterCopyCallbackAfterRotation(
    std::unique_ptr<ScreenRotationRequest> rotation_request) {
  return base::BindOnce(&ScreenRotationAnimator::
                            OnScreenRotationContainerLayerCopiedAfterRotation,
                        weak_factory_.GetWeakPtr(),
                        base::Passed(&rotation_request));
}

void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedBeforeRotation(
    std::unique_ptr<ScreenRotationRequest> rotation_request,
    std::unique_ptr<viz::CopyOutputResult> result) {
  if (IgnoreCopyResult(rotation_request->id, rotation_request_id_))
    return;
  // Abort rotation and animation if the display was removed or the
  // |root_window| was changed for |display_id|.
  if (RootWindowChangedForDisplayId(root_window_,
                                    rotation_request->display_id)) {
    ProcessAnimationQueue();
    return;
  }
  // Abort animation and set the rotation to target rotation when the copy
  // request has been canceled or failed. It would fail if, for examples: a) The
  // layer is removed from the compositor and destroyed before committing the
  // request to the compositor. b) The compositor is shutdown.
  if (result->IsEmpty()) {
    Shell::Get()->display_manager()->SetDisplayRotation(
        rotation_request->display_id, rotation_request->new_rotation,
        rotation_request->source);
    ProcessAnimationQueue();
    return;
  }

  old_layer_tree_owner_ = CopyLayerTree(std::move(result));
  AddLayerAtTopOfWindowLayers(root_window_, old_layer_tree_owner_->root());

  // TODO(oshima): We need a better way to control animation and other
  // activities during system wide animation.
  animation_scale_mode_ =
      std::make_unique<ui::ScopedAnimationDurationScaleMode>(
          ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);

  for (auto& observer : screen_rotation_animator_observers_)
    observer.OnScreenCopiedBeforeRotation();

  SetRotation(rotation_request->display_id, rotation_request->old_rotation,
              rotation_request->new_rotation, rotation_request->source);

  RequestCopyScreenRotationContainerLayer(
      std::make_unique<viz::CopyOutputRequest>(
          viz::CopyOutputRequest::ResultFormat::RGBA_TEXTURE,
          CreateAfterCopyCallbackAfterRotation(std::move(rotation_request))));
}

void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedAfterRotation(
    std::unique_ptr<ScreenRotationRequest> rotation_request,
    std::unique_ptr<viz::CopyOutputResult> result) {
  animation_scale_mode_.reset();
  if (IgnoreCopyResult(rotation_request->id, rotation_request_id_)) {
    NotifyAnimationFinished(/*canceled=*/true);
    return;
  }
  // In the following cases, abort animation:
  // 1) if the display was removed,
  // 2) if the |root_window| was changed for |display_id|,
  // 3) the copy request has been canceled or failed. It would fail if,
  // for examples: a) The layer is removed from the compositor and destroyed
  // before committing the request to the compositor. b) The compositor is
  // shutdown.
  if (RootWindowChangedForDisplayId(root_window_,
                                    rotation_request->display_id) ||
      result->IsEmpty()) {
    ProcessAnimationQueue();
    return;
  }

  new_layer_tree_owner_ = CopyLayerTree(std::move(result));
  AddLayerBelowWindowLayer(root_window_, old_layer_tree_owner_->root(),
                           new_layer_tree_owner_->root());
  AnimateRotation(std::move(rotation_request));
}

void ScreenRotationAnimator::CreateOldLayerTreeForSlowAnimation() {
  old_layer_tree_owner_ = ::wm::RecreateLayers(root_window_);
  AddLayerAtTopOfWindowLayers(root_window_, old_layer_tree_owner_->root());
}

std::unique_ptr<ui::LayerTreeOwner> ScreenRotationAnimator::CopyLayerTree(
    std::unique_ptr<viz::CopyOutputResult> result) {
  DCHECK(!result->IsEmpty());
  DCHECK_EQ(result->format(), viz::CopyOutputResult::Format::RGBA_TEXTURE);
  auto transfer_resource = viz::TransferableResource::MakeGL(
      result->GetTextureResult()->mailbox, GL_LINEAR, GL_TEXTURE_2D,
      result->GetTextureResult()->sync_token);
  std::unique_ptr<viz::SingleReleaseCallback> release_callback =
      result->TakeTextureOwnership();
  const gfx::Rect rect(
      GetScreenRotationContainer(root_window_)->layer()->size());
  std::unique_ptr<ui::Layer> copy_layer = std::make_unique<ui::Layer>();
  copy_layer->SetBounds(rect);
  copy_layer->SetTransferableResource(transfer_resource,
                                      std::move(release_callback), rect.size());
  return std::make_unique<ui::LayerTreeOwner>(std::move(copy_layer));
}

void ScreenRotationAnimator::AnimateRotation(
    std::unique_ptr<ScreenRotationRequest> rotation_request) {
  screen_rotation_state_ = ROTATING;
  const int rotation_factor = GetRotationFactor(rotation_request->old_rotation,
                                                rotation_request->new_rotation);
  const int old_layer_initial_rotation_degrees = GetInitialDegrees(
      rotation_request->old_rotation, rotation_request->new_rotation);
  const base::TimeDelta duration =
      base::TimeDelta::FromMilliseconds(kRotationDurationInMs);
  const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN;
  const gfx::Rect rotated_screen_bounds = root_window_->GetTargetBounds();
  const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2,
                                      rotated_screen_bounds.height() / 2);

  ui::Layer* screen_rotation_container_layer =
      GetScreenRotationContainer(root_window_)->layer();
  ui::Layer* new_root_layer;
  if (!new_layer_tree_owner_) {
    new_root_layer = screen_rotation_container_layer;
  } else {
    new_root_layer = new_layer_tree_owner_->root();
    // Add a black mask layer on top of |screen_rotation_container_layer|.
    mask_layer_tree_owner_ = CreateMaskLayerTreeOwner(
        gfx::Rect(screen_rotation_container_layer->size()));
    AddLayerBelowWindowLayer(root_window_, new_root_layer,
                             mask_layer_tree_owner_->root());
  }

  std::unique_ptr<ScreenRotationAnimation> new_layer_screen_rotation =
      std::make_unique<ScreenRotationAnimation>(
          new_root_layer, kRotationDegrees * rotation_factor,
          0 /* end_degrees */, new_root_layer->opacity(),
          new_root_layer->opacity() /* target_opacity */, pivot, duration,
          tween_type);

  ui::LayerAnimator* new_layer_animator = new_root_layer->GetAnimator();
  new_layer_animator->set_preemption_strategy(
      ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
  std::unique_ptr<ui::LayerAnimationSequence> new_layer_animation_sequence =
      std::make_unique<ui::LayerAnimationSequence>(
          std::move(new_layer_screen_rotation));

  ui::Layer* old_root_layer = old_layer_tree_owner_->root();
  const gfx::Rect original_screen_bounds = old_root_layer->GetTargetBounds();
  // The old layer will also be transformed into the new orientation. We will
  // translate it so that the old layer's center point aligns with the new
  // orientation's center point and use that center point as the pivot for the
  // rotation animation.
  gfx::Transform translate_transform;
  translate_transform.Translate(
      (rotated_screen_bounds.width() - original_screen_bounds.width()) / 2,
      (rotated_screen_bounds.height() - original_screen_bounds.height()) / 2);
  old_root_layer->SetTransform(translate_transform);

  std::unique_ptr<ScreenRotationAnimation> old_layer_screen_rotation =
      std::make_unique<ScreenRotationAnimation>(
          old_root_layer, old_layer_initial_rotation_degrees * rotation_factor,
          (old_layer_initial_rotation_degrees - kRotationDegrees) *
              rotation_factor,
          old_root_layer->opacity(), 0.0f /* target_opacity */, pivot, duration,
          tween_type);

  ui::LayerAnimator* old_layer_animator = old_root_layer->GetAnimator();
  old_layer_animator->set_preemption_strategy(
      ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
  std::unique_ptr<ui::LayerAnimationSequence> old_layer_animation_sequence =
      std::make_unique<ui::LayerAnimationSequence>(
          std::move(old_layer_screen_rotation));

  // In unit tests, we can use ash::ScreenRotationAnimatorTestApi to control the
  // animation.
  if (disable_animation_timers_for_test_) {
    if (new_layer_tree_owner_)
      new_layer_animator->set_disable_timer_for_test(true);
    old_layer_animator->set_disable_timer_for_test(true);
  }
  old_layer_animation_sequence->SetAnimationMetricsReporter(
      metrics_reporter_.get());

  // Add an observer so that the cloned/copied layers can be cleaned up with the
  // animation completes/aborts.
  ui::CallbackLayerAnimationObserver* observer =
      new ui::CallbackLayerAnimationObserver(
          base::Bind(&AnimationEndedCallback, weak_factory_.GetWeakPtr()));
  if (new_layer_tree_owner_)
    new_layer_animation_sequence->AddObserver(observer);
  new_layer_animator->StartAnimation(new_layer_animation_sequence.release());
  old_layer_animation_sequence->AddObserver(observer);
  old_layer_animator->StartAnimation(old_layer_animation_sequence.release());
  observer->SetActive();
}

void ScreenRotationAnimator::Rotate(
    display::Display::Rotation new_rotation,
    display::Display::RotationSource source,
    DisplayConfigurationController::RotationAnimation mode) {
  // |rotation_request_id_| is used to skip stale requests. Before the layer
  // CopyOutputResult callback called, there could have new rotation request.
  // Increases |rotation_request_id_| for each new request and in the callback,
  // we compare the |rotation_request.id| and |rotation_request_id_| to
  // determine the stale status.
  rotation_request_id_++;
  const int64_t display_id =
      display::Screen::GetScreen()->GetDisplayNearestWindow(root_window_).id();
  std::unique_ptr<ScreenRotationRequest> rotation_request =
      std::make_unique<ScreenRotationRequest>(rotation_request_id_, display_id,
                                              new_rotation, source, mode);
  target_rotation_ = new_rotation;

  if (mode == DisplayConfigurationController::ANIMATION_SYNC)
    current_async_rotation_request_.reset();

  switch (screen_rotation_state_) {
    case IDLE:
      DCHECK(!current_async_rotation_request_);
      FALLTHROUGH;
    case COPY_REQUESTED:
      if (current_async_rotation_request_ &&
          !RootWindowChangedForDisplayId(
              root_window_, current_async_rotation_request_->display_id)) {
        Shell::Get()->display_manager()->SetDisplayRotation(
            current_async_rotation_request_->display_id,
            current_async_rotation_request_->new_rotation,
            current_async_rotation_request_->source);
        current_async_rotation_request_.reset();
      }

      StartRotationAnimation(std::move(rotation_request));
      break;
    case ROTATING:
      last_pending_request_ = std::move(rotation_request);
      // The pending request will be processed when the
      // |AnimationEndedCallback()| should be called after |StopAnimating()|.
      StopAnimating();
      break;
  }
}

void ScreenRotationAnimator::AddObserver(
    ScreenRotationAnimatorObserver* observer) {
  screen_rotation_animator_observers_.AddObserver(observer);
}

void ScreenRotationAnimator::RemoveObserver(
    ScreenRotationAnimatorObserver* observer) {
  screen_rotation_animator_observers_.RemoveObserver(observer);
}

void ScreenRotationAnimator::ProcessAnimationQueue() {
  screen_rotation_state_ = IDLE;
  old_layer_tree_owner_.reset();
  new_layer_tree_owner_.reset();
  mask_layer_tree_owner_.reset();
  current_async_rotation_request_.reset();
  if (last_pending_request_ &&
      !RootWindowChangedForDisplayId(root_window_,
                                     last_pending_request_->display_id)) {
    StartRotationAnimation(std::move(last_pending_request_));
    return;
  }

  NotifyAnimationFinished(/*canceled=*/false);
}

bool ScreenRotationAnimator::IsRotating() const {
  return screen_rotation_state_ != IDLE;
}

display::Display::Rotation ScreenRotationAnimator::GetTargetRotation() const {
  return target_rotation_;
}

void ScreenRotationAnimator::StopAnimating() {
  // |old_layer_tree_owner_| new_layer_tree_owner_| could be nullptr if another
  // the rotation request comes before the copy request finished.
  if (old_layer_tree_owner_)
    old_layer_tree_owner_->root()->GetAnimator()->StopAnimating();
  if (new_layer_tree_owner_)
    new_layer_tree_owner_->root()->GetAnimator()->StopAnimating();
  mask_layer_tree_owner_.reset();
}

void ScreenRotationAnimator::NotifyAnimationFinished(bool canceled) {
  for (auto& observer : screen_rotation_animator_observers_)
    observer.OnScreenRotationAnimationFinished(this, canceled);
}

}  // namespace ash
