tray_power.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ash/system/chromeos/power/tray_power.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/ash_switches.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell.h"
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ash/shell_delegate.h"
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ash/system/chromeos/power/power_status_view.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/system/date/date_view.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/system/tray/tray_constants.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/system/tray/tray_notification_view.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ash/system/tray/tray_utils.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stringprintf.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/utf_string_conversions.h"
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chromeos/dbus/power_supply_status.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/ash_resources.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/ash_strings.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/icu/public/i18n/unicode/fieldpos.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/icu/public/i18n/unicode/fmtable.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkRect.h"
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/accessibility/accessible_view_state.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_skia.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_skia_operations.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/size.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/button/button.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/image_view.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/label.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/layout/box_layout.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/layout/fill_layout.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/layout/grid_layout.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/view.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using chromeos::PowerManagerHandler;
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using chromeos::PowerSupplyStatus;
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ash {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace internal {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Width and height of battery images.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kBatteryImageHeight = 25;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kBatteryImageWidth = 25;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Number of different power states.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kNumPowerImages = 15;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Top/bottom padding of the text items.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kPaddingVertical = 10;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Specify min width of status label for layout.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kLabelMinWidth = 120;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Notification times.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kCriticalSeconds = 5 * 60;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kLowPowerSeconds = 15 * 60;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kNoWarningSeconds = 30 * 60;
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Minimum battery percentage rendered in UI.
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int kMinBatteryPercent = 1;
63a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// Notification in battery percentage.
64a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)const double kCriticalPercentage = 5.0;
65a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)const double kLowPowerPercentage = 10.0;
66a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)const double kNoWarningPercentage = 15.0;
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::string16 GetBatteryTimeAccessibilityString(int hour, int min) {
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(hour || min);
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (hour && !min) {
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return Shell::GetInstance()->delegate()->GetTimeDurationLongString(
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::TimeDelta::FromHours(hour));
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (min && !hour) {
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return Shell::GetInstance()->delegate()->GetTimeDurationLongString(
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::TimeDelta::FromMinutes(min));
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return l10n_util::GetStringFUTF16(
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      IDS_ASH_STATUS_TRAY_BATTERY_TIME_ACCESSIBLE,
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Shell::GetInstance()->delegate()->GetTimeDurationLongString(
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          base::TimeDelta::FromHours(hour)),
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Shell::GetInstance()->delegate()->GetTimeDurationLongString(
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          base::TimeDelta::FromMinutes(min)));
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace tray {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This view is used only for the tray.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PowerTrayView : public views::ImageView {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PowerTrayView()
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : battery_icon_index_(-1),
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        battery_icon_offset_(0),
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        battery_charging_unreliable_(false) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateImage();
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~PowerTrayView() {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Overriden from views::View.
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE {
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    state->name = accessible_name_;
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    state->role = ui::AccessibilityTypes::ROLE_PUSHBUTTON;
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void UpdatePowerStatus(const PowerSupplyStatus& status,
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                         bool battery_alert) {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    supply_status_ = status;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Sanitize.
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (supply_status_.battery_is_full)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      supply_status_.battery_percentage = 100.0;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateImage();
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetVisible(status.battery_is_present);
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (battery_alert) {
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      accessible_name_ = TrayPower::GetAccessibleNameString(status);
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_ALERT, true);
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void UpdateImage() {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int index = TrayPower::GetBatteryImageIndex(supply_status_);
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int offset = TrayPower::GetBatteryImageOffset(supply_status_);
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool charging_unreliable =
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        TrayPower::IsBatteryChargingUnreliable(supply_status_);
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (battery_icon_index_ != index ||
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        battery_icon_offset_ != offset ||
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        battery_charging_unreliable_ != charging_unreliable) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      battery_icon_index_ = index;
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      battery_icon_offset_ = offset;
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      battery_charging_unreliable_ = charging_unreliable;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (battery_icon_index_ != -1)
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        SetImage(TrayPower::GetBatteryImage(battery_icon_index_,
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                            battery_icon_offset_,
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                            battery_charging_unreliable_,
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                            ICON_LIGHT));
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PowerSupplyStatus supply_status_;
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::string16 accessible_name_;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Index of the current icon in the icon array image, or -1 if unknown.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int battery_icon_index_;
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int battery_icon_offset_;
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool battery_charging_unreliable_;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(PowerTrayView);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PowerNotificationView : public TrayNotificationView {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit PowerNotificationView(TrayPower* owner)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : TrayNotificationView(owner, 0),
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        battery_icon_index_(-1),
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        battery_icon_offset_(0),
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        battery_charging_unreliable_(false) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_status_view_ =
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new PowerStatusView(PowerStatusView::VIEW_NOTIFICATION, true);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitView(power_status_view_);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void UpdatePowerStatus(const PowerSupplyStatus& status) {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int index = TrayPower::GetBatteryImageIndex(status);
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int offset = TrayPower::GetBatteryImageOffset(status);
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool charging_unreliable = TrayPower::IsBatteryChargingUnreliable(status);
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (battery_icon_index_ != index ||
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        battery_icon_offset_ != offset ||
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        battery_charging_unreliable_ != charging_unreliable) {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      battery_icon_index_ = index;
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      battery_icon_offset_ = offset;
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      battery_charging_unreliable_ = charging_unreliable;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (battery_icon_index_ != -1) {
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        SetIconImage(TrayPower::GetBatteryImage(
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                         battery_icon_index_,
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                         battery_icon_offset_,
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                         battery_charging_unreliable_,
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                         ICON_DARK));
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_status_view_->UpdatePowerStatus(status);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PowerStatusView* power_status_view_;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Index of the current icon in the icon array image, or -1 if unknown.
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int battery_icon_index_;
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int battery_icon_offset_;
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool battery_charging_unreliable_;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(PowerNotificationView);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace tray
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using tray::PowerNotificationView;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TrayPower::TrayPower(SystemTray* system_tray)
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : SystemTrayItem(system_tray),
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      power_tray_(NULL),
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      notification_view_(NULL),
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      notification_state_(NOTIFICATION_NONE) {
20990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  PowerManagerHandler::Get()->AddObserver(this);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TrayPower::~TrayPower() {
21390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (PowerManagerHandler::IsInitialized())
21490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    PowerManagerHandler::Get()->RemoveObserver(this);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool TrayPower::IsBatteryChargingUnreliable(
21990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const chromeos::PowerSupplyStatus& supply_status) {
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      supply_status.battery_state ==
22290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          PowerSupplyStatus::NEITHER_CHARGING_NOR_DISCHARGING ||
22390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      supply_status.battery_state ==
22490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          PowerSupplyStatus::CONNECTED_TO_USB;
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
22890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int TrayPower::GetBatteryImageIndex(
22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const chromeos::PowerSupplyStatus& supply_status) {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int image_index = 0;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (supply_status.battery_percentage >= 100) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image_index = kNumPowerImages - 1;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (!supply_status.battery_is_present) {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image_index = kNumPowerImages;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image_index = static_cast<int>(supply_status.battery_percentage /
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                   100.0 * (kNumPowerImages - 1));
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image_index = std::max(std::min(image_index, kNumPowerImages - 2), 0);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return image_index;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
24490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int TrayPower::GetBatteryImageOffset(
24590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const chromeos::PowerSupplyStatus& supply_status) {
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (IsBatteryChargingUnreliable(supply_status) ||
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      !supply_status.line_power_on)
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return 0;
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return 1;
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)gfx::ImageSkia TrayPower::GetBatteryImage(int image_index,
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          int image_offset,
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          bool charging_unreliable,
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          IconSet icon_set) {
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Image all;
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (charging_unreliable) {
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    all = ui::ResourceBundle::GetSharedInstance().GetImageNamed(
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        icon_set == ICON_DARK ?
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        IDR_AURA_UBER_TRAY_POWER_SMALL_CHARGING_UNRELIABLE_DARK :
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        IDR_AURA_UBER_TRAY_POWER_SMALL_CHARGING_UNRELIABLE);
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    all = ui::ResourceBundle::GetSharedInstance().GetImageNamed(
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        icon_set == ICON_DARK ?
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        IDR_AURA_UBER_TRAY_POWER_SMALL_DARK : IDR_AURA_UBER_TRAY_POWER_SMALL);
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect region(
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      image_offset * kBatteryImageWidth,
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      image_index * kBatteryImageHeight,
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kBatteryImageWidth, kBatteryImageHeight);
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return gfx::ImageSkiaOperations::ExtractSubset(*all.ToImageSkia(), region);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::string16 TrayPower::GetAccessibleNameString(
27790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const chromeos::PowerSupplyStatus& supply_status) {
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (supply_status.line_power_on && supply_status.battery_is_full) {
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return rb.GetLocalizedString(
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        IDS_ASH_STATUS_TRAY_BATTERY_FULL_CHARGE_ACCESSIBLE);
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool charging_unreliable =
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      IsBatteryChargingUnreliable(supply_status);
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (supply_status.battery_percentage < 0.0f) {
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (charging_unreliable) {
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return rb.GetLocalizedString(
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          IDS_ASH_STATUS_TRAY_BATTERY_CHARGING_UNRELIABLE_ACCESSIBLE);
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return rb.GetLocalizedString(
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        IDS_ASH_STATUS_TRAY_BATTERY_CALCULATING_ACCESSIBLE);
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::string16 battery_percentage_accessbile = l10n_util::GetStringFUTF16(
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      supply_status.line_power_on ?
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      IDS_ASH_STATUS_TRAY_BATTERY_PERCENT_CHARGING_ACCESSIBLE:
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      IDS_ASH_STATUS_TRAY_BATTERY_PERCENT_ACCESSIBLE ,
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::IntToString16(GetRoundedBatteryPercentage(
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          supply_status.battery_percentage)));
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::string16 battery_time_accessible = base::string16();
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (charging_unreliable) {
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    battery_time_accessible = rb.GetLocalizedString(
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        IDS_ASH_STATUS_TRAY_BATTERY_CHARGING_UNRELIABLE_ACCESSIBLE);
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (supply_status.is_calculating_battery_time) {
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      battery_time_accessible = rb.GetLocalizedString(
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          IDS_ASH_STATUS_TRAY_BATTERY_CALCULATING_ACCESSIBLE);
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    } else {
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::TimeDelta time = base::TimeDelta::FromSeconds(
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          supply_status.line_power_on ?
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          supply_status.battery_seconds_to_full :
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          supply_status.battery_seconds_to_empty);
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      int hour = time.InHours();
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      int min = (time - base::TimeDelta::FromHours(hour)).InMinutes();
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (hour || min) {
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::string16 minute = min < 10 ?
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            ASCIIToUTF16("0") + base::IntToString16(min) :
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            base::IntToString16(min);
318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        battery_time_accessible =
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            l10n_util::GetStringFUTF16(
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                supply_status.line_power_on ?
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                IDS_ASH_STATUS_TRAY_BATTERY_TIME_UNTIL_FULL_ACCESSIBLE :
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                IDS_ASH_STATUS_TRAY_BATTERY_TIME_LEFT_ACCESSIBLE,
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                GetBatteryTimeAccessibilityString(hour, min));
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return battery_time_accessible.empty() ?
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      battery_percentage_accessbile :
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      battery_percentage_accessbile + ASCIIToUTF16(". ")
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      + battery_time_accessible;
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int TrayPower::GetRoundedBatteryPercentage(double battery_percentage) {
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(battery_percentage >= 0.0);
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return std::max(kMinBatteryPercent,
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      static_cast<int>(battery_percentage + 0.5));
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)views::View* TrayPower::CreateTrayView(user::LoginStatus status) {
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There may not be enough information when this is created about whether
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // there is a battery or not. So always create this, and adjust visibility as
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // necessary.
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PowerSupplyStatus power_status =
34590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      PowerManagerHandler::Get()->GetPowerSupplyStatus();
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(power_tray_ == NULL);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  power_tray_ = new tray::PowerTrayView();
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  power_tray_->UpdatePowerStatus(power_status, false);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return power_tray_;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)views::View* TrayPower::CreateDefaultView(user::LoginStatus status) {
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure icon status is up-to-date. (Also triggers stub activation).
35490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RequestStatusUpdate();
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)views::View* TrayPower::CreateNotificationView(user::LoginStatus status) {
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(notification_view_ == NULL);
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PowerSupplyStatus power_status =
36190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      PowerManagerHandler::Get()->GetPowerSupplyStatus();
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!power_status.battery_is_present)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification_view_ = new PowerNotificationView(this);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification_view_->UpdatePowerStatus(power_status);
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return notification_view_;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TrayPower::DestroyTrayView() {
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  power_tray_ = NULL;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TrayPower::DestroyDefaultView() {
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TrayPower::DestroyNotificationView() {
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification_view_ = NULL;
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TrayPower::UpdateAfterLoginStatusChange(user::LoginStatus status) {
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TrayPower::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) {
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetTrayImageItemBorder(power_tray_, alignment);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void TrayPower::OnPowerStatusChanged(
39090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const chromeos::PowerSupplyStatus& status) {
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool battery_alert = UpdateNotificationState(status);
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (power_tray_)
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    power_tray_->UpdatePowerStatus(status, battery_alert);
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (notification_view_)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    notification_view_->UpdatePowerStatus(status);
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (battery_alert)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ShowNotificationView();
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (notification_state_ == NOTIFICATION_NONE)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HideNotificationView();
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void TrayPower::RequestStatusUpdate() const {
40490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  PowerManagerHandler::Get()->RequestStatusUpdate();
40590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
40690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
40790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool TrayPower::UpdateNotificationState(
40890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const chromeos::PowerSupplyStatus& status) {
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!status.battery_is_present ||
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      status.is_calculating_battery_time ||
411a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      status.battery_state == PowerSupplyStatus::CHARGING) {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    notification_state_ = NOTIFICATION_NONE;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
416a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (TrayPower::IsBatteryChargingUnreliable(status)) {
417a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return UpdateNotificationStateForRemainingPercentage(
418a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        status.battery_percentage);
419a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  } else {
420a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return UpdateNotificationStateForRemainingTime(
421a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        status.battery_seconds_to_empty);
422a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
423a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
424a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
425a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)bool TrayPower::UpdateNotificationStateForRemainingTime(int remaining_seconds) {
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (remaining_seconds >= kNoWarningSeconds) {
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    notification_state_ = NOTIFICATION_NONE;
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (notification_state_) {
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case NOTIFICATION_NONE:
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (remaining_seconds <= kCriticalSeconds) {
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        notification_state_ = NOTIFICATION_CRITICAL;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (remaining_seconds <= kLowPowerSeconds) {
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        notification_state_ = NOTIFICATION_LOW_POWER;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case NOTIFICATION_LOW_POWER:
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (remaining_seconds <= kCriticalSeconds) {
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        notification_state_ = NOTIFICATION_CRITICAL;
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case NOTIFICATION_CRITICAL:
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
454a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)bool TrayPower::UpdateNotificationStateForRemainingPercentage(
455a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    double remaining_percentage) {
456a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (remaining_percentage > kNoWarningPercentage) {
457a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    notification_state_ = NOTIFICATION_NONE;
458a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return false;
459a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
460a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
461a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  switch (notification_state_) {
462a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    case NOTIFICATION_NONE:
463a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      if (remaining_percentage <= kCriticalPercentage) {
464a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        notification_state_ = NOTIFICATION_CRITICAL;
465a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        return true;
466a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      }
467a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      if (remaining_percentage <= kLowPowerPercentage) {
468a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        notification_state_ = NOTIFICATION_LOW_POWER;
469a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        return true;
470a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      }
471a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      return false;
472a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    case NOTIFICATION_LOW_POWER:
473a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      if (remaining_percentage <= kCriticalPercentage) {
474a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        notification_state_ = NOTIFICATION_CRITICAL;
475a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        return true;
476a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      }
477a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      return false;
478a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    case NOTIFICATION_CRITICAL:
479a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      return false;
480a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
481a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  NOTREACHED();
482a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return false;
483a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
484a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace internal
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ash
487