chromium/ash/system/palette/stylus_battery_delegate.cc

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/system/palette/stylus_battery_delegate.h"

#include <string>

#include "ash/resources/vector_icons/vector_icons.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/style/ash_color_id.h"
#include "ash/style/ash_color_provider.h"
#include "ash/system/power/peripheral_battery_listener.h"
#include "ash/system/power/power_status.h"
#include "ash/system/tray/tray_constants.h"
#include "base/time/time.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/color/color_provider.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/paint_vector_icon.h"

namespace ash {
namespace {
// Battery percentage threshold used to label the battery level as Low.
constexpr int kStylusLowBatteryThreshold = 24;
constexpr base::TimeDelta kStylusBatteryStatusStaleThreshold = base::Days(14);
}  // namespace

StylusBatteryDelegate::StylusBatteryDelegate() {
  if (Shell::Get()->peripheral_battery_listener())
    battery_observation_.Observe(Shell::Get()->peripheral_battery_listener());
}

StylusBatteryDelegate::~StylusBatteryDelegate() = default;

SkColor StylusBatteryDelegate::GetColorForBatteryLevel() const {
  if (!battery_level_.has_value()) {
    return AshColorProvider::Get()->GetContentLayerColor(
        AshColorProvider::ContentLayerType::kIconColorWarning);
  }
  if (battery_level_ <= kStylusLowBatteryThreshold && !IsBatteryCharging()) {
    return AshColorProvider::Get()->GetContentLayerColor(
        AshColorProvider::ContentLayerType::kIconColorAlert);
  }
  return AshColorProvider::Get()->GetContentLayerColor(
      AshColorProvider::ContentLayerType::kIconColorPrimary);
}

gfx::ImageSkia StylusBatteryDelegate::GetBatteryImage(
    const ui::ColorProvider* color_provider) const {
  PowerStatus::BatteryImageInfo info(GetColorForBatteryLevel());
  info.charge_percent = battery_level_.value_or(0);

  if (IsBatteryCharging()) {
    info.icon_badge = &kUnifiedMenuBatteryBoltIcon;
    info.badge_outline = &kUnifiedMenuBatteryBoltOutlineMaskIcon;
  }

  return PowerStatus::GetBatteryImage(info, kUnifiedTrayBatteryIconSize,
                                      color_provider);
}

gfx::ImageSkia StylusBatteryDelegate::GetBatteryStatusUnknownImage() const {
  const SkColor icon_color = AshColorProvider::Get()->GetContentLayerColor(
      AshColorProvider::ContentLayerType::kIconColorPrimary);

  return gfx::CreateVectorIcon(kStylusBatteryStatusUnknownIcon, icon_color);
}

void StylusBatteryDelegate::SetBatteryUpdateCallback(
    Callback battery_update_callback) {
  battery_update_callback_ = std::move(battery_update_callback);
}

bool StylusBatteryDelegate::IsBatteryCharging() const {
  return battery_charge_status_ ==
             PeripheralBatteryListener::BatteryInfo::ChargeStatus::kCharging ||
         battery_charge_status_ ==
             PeripheralBatteryListener::BatteryInfo::ChargeStatus::kFull;
}

bool StylusBatteryDelegate::IsBatteryLevelLow() const {
  if (!battery_level_.has_value())
    return false;

  return battery_level_ <= kStylusLowBatteryThreshold;
}

bool StylusBatteryDelegate::ShouldShowBatteryStatus() const {
  return last_update_timestamp_.has_value() && last_update_eligible_;
}

bool StylusBatteryDelegate::IsBatteryStatusStale() const {
  if (!last_update_timestamp_.has_value())
    return false;

  return (base::TimeTicks::Now() - last_update_timestamp_.value()) >
         kStylusBatteryStatusStaleThreshold;
}

bool StylusBatteryDelegate::IsBatteryStatusEligible() const {
  return last_update_eligible_;
}

bool StylusBatteryDelegate::IsBatteryInfoValid(
    const PeripheralBatteryListener::BatteryInfo& battery) const {
  if (battery.type != PeripheralBatteryListener::BatteryInfo::PeripheralType::
                          kStylusViaCharger &&
      battery.type != PeripheralBatteryListener::BatteryInfo::PeripheralType::
                          kStylusViaScreen) {
    return false;
  }

  if (!battery.last_active_update_timestamp.has_value() ||
      !battery.level.has_value()) {
    return false;
  }

  if (last_update_timestamp_.has_value() &&
      battery.last_active_update_timestamp < last_update_timestamp_) {
    return false;
  }

  return true;
}

void StylusBatteryDelegate::OnAddingBattery(
    const PeripheralBatteryListener::BatteryInfo& battery) {}

void StylusBatteryDelegate::OnRemovingBattery(
    const PeripheralBatteryListener::BatteryInfo& battery) {}

void StylusBatteryDelegate::OnUpdatedBatteryLevel(
    const PeripheralBatteryListener::BatteryInfo& battery) {
  if (!IsBatteryInfoValid(battery))
    return;

  battery_level_ = battery.level;
  battery_charge_status_ = battery.charge_status;
  last_update_timestamp_ = battery.last_active_update_timestamp;
  last_update_eligible_ = battery.battery_report_eligible;
  if (battery_update_callback_)
    battery_update_callback_.Run();
}

}  // namespace ash