Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(141)

Side by Side Diff: ash/system/chromeos/power/tray_power.cc

Issue 2072013002: mash: Move tray settings and deps to common. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Undo 'git cl format' and nullptr changes. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ash/system/chromeos/power/tray_power.h"
6
7 #include <utility>
8
9 #include "ash/ash_switches.h"
10 #include "ash/common/accessibility_delegate.h"
11 #include "ash/common/system/date/date_view.h"
12 #include "ash/common/system/tray/system_tray_delegate.h"
13 #include "ash/common/system/tray/tray_constants.h"
14 #include "ash/common/system/tray/tray_utils.h"
15 #include "ash/shell.h"
16 #include "ash/system/chromeos/devicetype_utils.h"
17 #include "ash/system/chromeos/power/battery_notification.h"
18 #include "ash/system/chromeos/power/dual_role_notification.h"
19 #include "ash/system/system_notifier.h"
20 #include "base/command_line.h"
21 #include "base/logging.h"
22 #include "base/metrics/histogram.h"
23 #include "base/time/time.h"
24 #include "grit/ash_resources.h"
25 #include "grit/ash_strings.h"
26 #include "ui/accessibility/ax_view_state.h"
27 #include "ui/base/resource/resource_bundle.h"
28 #include "ui/message_center/message_center.h"
29 #include "ui/message_center/notification.h"
30 #include "ui/message_center/notification_delegate.h"
31 #include "ui/views/controls/image_view.h"
32 #include "ui/views/view.h"
33
34 using message_center::MessageCenter;
35 using message_center::Notification;
36
37 namespace ash {
38
39 // Informs the TrayPower instance when a USB notification is closed.
40 class UsbNotificationDelegate : public message_center::NotificationDelegate {
41 public:
42 explicit UsbNotificationDelegate(TrayPower* tray_power)
43 : tray_power_(tray_power) {}
44
45 // Overridden from message_center::NotificationDelegate.
46 void Close(bool by_user) override {
47 if (by_user)
48 tray_power_->NotifyUsbNotificationClosedByUser();
49 }
50
51 private:
52 ~UsbNotificationDelegate() override {}
53
54 TrayPower* tray_power_;
55
56 DISALLOW_COPY_AND_ASSIGN(UsbNotificationDelegate);
57 };
58
59 namespace {
60
61 std::string GetNotificationStateString(
62 TrayPower::NotificationState notification_state) {
63 switch (notification_state) {
64 case TrayPower::NOTIFICATION_NONE:
65 return "none";
66 case TrayPower::NOTIFICATION_LOW_POWER:
67 return "low power";
68 case TrayPower::NOTIFICATION_CRITICAL:
69 return "critical power";
70 }
71 NOTREACHED() << "Unknown state " << notification_state;
72 return "Unknown state";
73 }
74
75 void LogBatteryForUsbCharger(TrayPower::NotificationState state,
76 int battery_percent) {
77 LOG(WARNING) << "Showing " << GetNotificationStateString(state)
78 << " notification. USB charger is connected. "
79 << "Battery percentage: " << battery_percent << "%.";
80 }
81
82 void LogBatteryForNoCharger(TrayPower::NotificationState state,
83 int remaining_minutes) {
84 LOG(WARNING) << "Showing " << GetNotificationStateString(state)
85 << " notification. No charger connected."
86 << " Remaining time: " << remaining_minutes << " minutes.";
87 }
88
89 } // namespace
90
91 namespace tray {
92
93 // This view is used only for the tray.
94 class PowerTrayView : public views::ImageView {
95 public:
96 PowerTrayView() {
97 UpdateImage();
98 }
99
100 ~PowerTrayView() override {}
101
102 // Overriden from views::View.
103 void GetAccessibleState(ui::AXViewState* state) override {
104 state->name = accessible_name_;
105 state->role = ui::AX_ROLE_BUTTON;
106 }
107
108 void UpdateStatus(bool battery_alert) {
109 UpdateImage();
110 SetVisible(PowerStatus::Get()->IsBatteryPresent());
111
112 if (battery_alert) {
113 accessible_name_ = PowerStatus::Get()->GetAccessibleNameString(true);
114 NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, true);
115 }
116 }
117
118 private:
119 void UpdateImage() {
120 const PowerStatus::BatteryImageInfo info =
121 PowerStatus::Get()->GetBatteryImageInfo(PowerStatus::ICON_LIGHT);
122 if (info != previous_image_info_) {
123 SetImage(PowerStatus::Get()->GetBatteryImage(PowerStatus::ICON_LIGHT));
124 previous_image_info_ = info;
125 }
126 }
127
128 base::string16 accessible_name_;
129
130 // Information about the last-used image. Cached to avoid unnecessary updates
131 // (http://crbug.com/589348).
132 PowerStatus::BatteryImageInfo previous_image_info_;
133
134 DISALLOW_COPY_AND_ASSIGN(PowerTrayView);
135 };
136
137 } // namespace tray
138
139 const int TrayPower::kCriticalMinutes = 5;
140 const int TrayPower::kLowPowerMinutes = 15;
141 const int TrayPower::kNoWarningMinutes = 30;
142 const int TrayPower::kCriticalPercentage = 5;
143 const int TrayPower::kLowPowerPercentage = 10;
144 const int TrayPower::kNoWarningPercentage = 15;
145
146 const char TrayPower::kUsbNotificationId[] = "usb-charger";
147
148 TrayPower::TrayPower(SystemTray* system_tray, MessageCenter* message_center)
149 : SystemTrayItem(system_tray),
150 message_center_(message_center),
151 power_tray_(NULL),
152 notification_state_(NOTIFICATION_NONE),
153 usb_charger_was_connected_(false),
154 line_power_was_connected_(false),
155 usb_notification_dismissed_(false) {
156 PowerStatus::Get()->AddObserver(this);
157 }
158
159 TrayPower::~TrayPower() {
160 PowerStatus::Get()->RemoveObserver(this);
161 message_center_->RemoveNotification(kUsbNotificationId, false);
162 }
163
164 views::View* TrayPower::CreateTrayView(LoginStatus status) {
165 // There may not be enough information when this is created about whether
166 // there is a battery or not. So always create this, and adjust visibility as
167 // necessary.
168 CHECK(power_tray_ == NULL);
169 power_tray_ = new tray::PowerTrayView();
170 power_tray_->UpdateStatus(false);
171 return power_tray_;
172 }
173
174 views::View* TrayPower::CreateDefaultView(LoginStatus status) {
175 // Make sure icon status is up to date. (Also triggers stub activation).
176 PowerStatus::Get()->RequestStatusUpdate();
177 return NULL;
178 }
179
180 void TrayPower::DestroyTrayView() {
181 power_tray_ = NULL;
182 }
183
184 void TrayPower::DestroyDefaultView() {
185 }
186
187 void TrayPower::UpdateAfterLoginStatusChange(LoginStatus status) {}
188
189 void TrayPower::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) {
190 SetTrayImageItemBorder(power_tray_, alignment);
191 }
192
193 void TrayPower::OnPowerStatusChanged() {
194 bool battery_alert = UpdateNotificationState();
195 if (power_tray_)
196 power_tray_->UpdateStatus(battery_alert);
197
198 // Factory testing may place the battery into unusual states.
199 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
200 ash::switches::kAshHideNotificationsForFactory))
201 return;
202
203 MaybeShowUsbChargerNotification();
204 MaybeShowDualRoleNotification();
205
206 if (battery_alert) {
207 // Remove any existing notification so it's dismissed before adding a new
208 // one. Otherwise we might update a "low battery" notification to "critical"
209 // without it being shown again.
210 battery_notification_.reset();
211 battery_notification_.reset(
212 new BatteryNotification(message_center_, notification_state_));
213 } else if (notification_state_ == NOTIFICATION_NONE) {
214 battery_notification_.reset();
215 } else if (battery_notification_.get()) {
216 battery_notification_->Update(notification_state_);
217 }
218
219 usb_charger_was_connected_ = PowerStatus::Get()->IsUsbChargerConnected();
220 line_power_was_connected_ = PowerStatus::Get()->IsLinePowerConnected();
221 }
222
223 bool TrayPower::MaybeShowUsbChargerNotification() {
224 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
225 const PowerStatus& status = *PowerStatus::Get();
226
227 bool usb_charger_is_connected = status.IsUsbChargerConnected();
228
229 // Check for a USB charger being connected.
230 if (usb_charger_is_connected && !usb_charger_was_connected_ &&
231 !usb_notification_dismissed_) {
232 std::unique_ptr<Notification> notification(new Notification(
233 message_center::NOTIFICATION_TYPE_SIMPLE, kUsbNotificationId,
234 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_LOW_POWER_CHARGER_TITLE),
235 ash::SubstituteChromeOSDeviceType(
236 IDS_ASH_STATUS_TRAY_LOW_POWER_CHARGER_MESSAGE_SHORT),
237 rb.GetImageNamed(IDR_AURA_NOTIFICATION_LOW_POWER_CHARGER),
238 base::string16(), GURL(),
239 message_center::NotifierId(message_center::NotifierId::SYSTEM_COMPONENT,
240 system_notifier::kNotifierPower),
241 message_center::RichNotificationData(),
242 new UsbNotificationDelegate(this)));
243 message_center_->AddNotification(std::move(notification));
244 return true;
245 } else if (!usb_charger_is_connected && usb_charger_was_connected_) {
246 // USB charger was unplugged or was identified as a different type while
247 // the USB charger notification was showing.
248 message_center_->RemoveNotification(kUsbNotificationId, false);
249 if (!status.IsLinePowerConnected())
250 usb_notification_dismissed_ = false;
251 return true;
252 }
253 return false;
254 }
255
256 void TrayPower::MaybeShowDualRoleNotification() {
257 const PowerStatus& status = *PowerStatus::Get();
258 if (!status.HasDualRoleDevices()) {
259 dual_role_notification_.reset();
260 return;
261 }
262
263 if (!dual_role_notification_)
264 dual_role_notification_.reset(new DualRoleNotification(message_center_));
265 dual_role_notification_->Update();
266 }
267
268 bool TrayPower::UpdateNotificationState() {
269 const PowerStatus& status = *PowerStatus::Get();
270 if (!status.IsBatteryPresent() ||
271 status.IsBatteryTimeBeingCalculated() ||
272 status.IsMainsChargerConnected()) {
273 notification_state_ = NOTIFICATION_NONE;
274 return false;
275 }
276
277 return status.IsUsbChargerConnected() ?
278 UpdateNotificationStateForRemainingPercentage() :
279 UpdateNotificationStateForRemainingTime();
280 }
281
282 bool TrayPower::UpdateNotificationStateForRemainingTime() {
283 // The notification includes a rounded minutes value, so round the estimate
284 // received from the power manager to match.
285 const int remaining_minutes = static_cast<int>(
286 PowerStatus::Get()->GetBatteryTimeToEmpty().InSecondsF() / 60.0 + 0.5);
287
288 if (remaining_minutes >= kNoWarningMinutes ||
289 PowerStatus::Get()->IsBatteryFull()) {
290 notification_state_ = NOTIFICATION_NONE;
291 return false;
292 }
293
294 switch (notification_state_) {
295 case NOTIFICATION_NONE:
296 if (remaining_minutes <= kCriticalMinutes) {
297 notification_state_ = NOTIFICATION_CRITICAL;
298 LogBatteryForNoCharger(notification_state_, remaining_minutes);
299 return true;
300 }
301 if (remaining_minutes <= kLowPowerMinutes) {
302 notification_state_ = NOTIFICATION_LOW_POWER;
303 LogBatteryForNoCharger(notification_state_, remaining_minutes);
304 return true;
305 }
306 return false;
307 case NOTIFICATION_LOW_POWER:
308 if (remaining_minutes <= kCriticalMinutes) {
309 notification_state_ = NOTIFICATION_CRITICAL;
310 LogBatteryForNoCharger(notification_state_, remaining_minutes);
311 return true;
312 }
313 return false;
314 case NOTIFICATION_CRITICAL:
315 return false;
316 }
317 NOTREACHED();
318 return false;
319 }
320
321 bool TrayPower::UpdateNotificationStateForRemainingPercentage() {
322 // The notification includes a rounded percentage, so round the value received
323 // from the power manager to match.
324 const int remaining_percentage =
325 PowerStatus::Get()->GetRoundedBatteryPercent();
326
327 if (remaining_percentage >= kNoWarningPercentage ||
328 PowerStatus::Get()->IsBatteryFull()) {
329 notification_state_ = NOTIFICATION_NONE;
330 return false;
331 }
332
333 switch (notification_state_) {
334 case NOTIFICATION_NONE:
335 if (remaining_percentage <= kCriticalPercentage) {
336 notification_state_ = NOTIFICATION_CRITICAL;
337 LogBatteryForUsbCharger(notification_state_, remaining_percentage);
338 return true;
339 }
340 if (remaining_percentage <= kLowPowerPercentage) {
341 notification_state_ = NOTIFICATION_LOW_POWER;
342 LogBatteryForUsbCharger(notification_state_, remaining_percentage);
343 return true;
344 }
345 return false;
346 case NOTIFICATION_LOW_POWER:
347 if (remaining_percentage <= kCriticalPercentage) {
348 notification_state_ = NOTIFICATION_CRITICAL;
349 LogBatteryForUsbCharger(notification_state_, remaining_percentage);
350 return true;
351 }
352 return false;
353 case NOTIFICATION_CRITICAL:
354 return false;
355 }
356 NOTREACHED();
357 return false;
358 }
359
360 void TrayPower::NotifyUsbNotificationClosedByUser() {
361 usb_notification_dismissed_ = true;
362 }
363
364 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698