OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ash/system/chromeos/power/tray_power.h" | 5 #include "ash/system/chromeos/power/tray_power.h" |
6 | 6 |
7 #include "ash/ash_switches.h" | 7 #include "ash/ash_switches.h" |
8 #include "ash/shell.h" | 8 #include "ash/shell.h" |
9 #include "ash/shell_delegate.h" | 9 #include "ash/shell_delegate.h" |
10 #include "ash/system/chromeos/power/power_status_view.h" | 10 #include "ash/system/chromeos/power/power_status_view.h" |
(...skipping 11 matching lines...) Expand all Loading... |
22 #include "third_party/icu/public/i18n/unicode/fieldpos.h" | 22 #include "third_party/icu/public/i18n/unicode/fieldpos.h" |
23 #include "third_party/icu/public/i18n/unicode/fmtable.h" | 23 #include "third_party/icu/public/i18n/unicode/fmtable.h" |
24 #include "third_party/skia/include/core/SkRect.h" | 24 #include "third_party/skia/include/core/SkRect.h" |
25 #include "ui/base/accessibility/accessible_view_state.h" | 25 #include "ui/base/accessibility/accessible_view_state.h" |
26 #include "ui/base/l10n/l10n_util.h" | 26 #include "ui/base/l10n/l10n_util.h" |
27 #include "ui/base/resource/resource_bundle.h" | 27 #include "ui/base/resource/resource_bundle.h" |
28 #include "ui/gfx/image/image.h" | 28 #include "ui/gfx/image/image.h" |
29 #include "ui/gfx/image/image_skia.h" | 29 #include "ui/gfx/image/image_skia.h" |
30 #include "ui/gfx/image/image_skia_operations.h" | 30 #include "ui/gfx/image/image_skia_operations.h" |
31 #include "ui/gfx/size.h" | 31 #include "ui/gfx/size.h" |
| 32 #include "ui/message_center/message_center.h" |
| 33 #include "ui/message_center/notification.h" |
32 #include "ui/views/controls/button/button.h" | 34 #include "ui/views/controls/button/button.h" |
33 #include "ui/views/controls/image_view.h" | 35 #include "ui/views/controls/image_view.h" |
34 #include "ui/views/controls/label.h" | 36 #include "ui/views/controls/label.h" |
35 #include "ui/views/layout/box_layout.h" | 37 #include "ui/views/layout/box_layout.h" |
36 #include "ui/views/layout/fill_layout.h" | 38 #include "ui/views/layout/fill_layout.h" |
37 #include "ui/views/layout/grid_layout.h" | 39 #include "ui/views/layout/grid_layout.h" |
38 #include "ui/views/view.h" | 40 #include "ui/views/view.h" |
39 #include "ui/views/widget/widget.h" | 41 #include "ui/views/widget/widget.h" |
40 | 42 |
41 using chromeos::PowerManagerHandler; | 43 using chromeos::PowerManagerHandler; |
42 using chromeos::PowerSupplyStatus; | 44 using chromeos::PowerSupplyStatus; |
| 45 using message_center::MessageCenter; |
| 46 using message_center::Notification; |
43 | 47 |
44 namespace ash { | 48 namespace ash { |
45 namespace internal { | 49 namespace internal { |
46 | 50 |
47 namespace { | 51 namespace { |
48 // Width and height of battery images. | 52 // Width and height of battery images. |
49 const int kBatteryImageHeight = 25; | 53 const int kBatteryImageHeight = 25; |
50 const int kBatteryImageWidth = 25; | 54 const int kBatteryImageWidth = 25; |
51 // Number of different power states. | 55 // Number of different power states. |
52 const int kNumPowerImages = 15; | 56 const int kNumPowerImages = 15; |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 int battery_icon_offset_; | 198 int battery_icon_offset_; |
195 bool battery_charging_unreliable_; | 199 bool battery_charging_unreliable_; |
196 | 200 |
197 DISALLOW_COPY_AND_ASSIGN(PowerNotificationView); | 201 DISALLOW_COPY_AND_ASSIGN(PowerNotificationView); |
198 }; | 202 }; |
199 | 203 |
200 } // namespace tray | 204 } // namespace tray |
201 | 205 |
202 using tray::PowerNotificationView; | 206 using tray::PowerNotificationView; |
203 | 207 |
204 TrayPower::TrayPower(SystemTray* system_tray) | 208 TrayPower::TrayPower(SystemTray* system_tray, MessageCenter* message_center) |
205 : SystemTrayItem(system_tray), | 209 : SystemTrayItem(system_tray), |
| 210 message_center_(message_center), |
206 power_tray_(NULL), | 211 power_tray_(NULL), |
207 notification_view_(NULL), | 212 notification_view_(NULL), |
208 notification_state_(NOTIFICATION_NONE) { | 213 notification_state_(NOTIFICATION_NONE) { |
209 PowerManagerHandler::Get()->AddObserver(this); | 214 // Tests may not have a PowerManagerHandler. |
| 215 if (PowerManagerHandler::IsInitialized()) |
| 216 PowerManagerHandler::Get()->AddObserver(this); |
210 } | 217 } |
211 | 218 |
212 TrayPower::~TrayPower() { | 219 TrayPower::~TrayPower() { |
213 if (PowerManagerHandler::IsInitialized()) | 220 if (PowerManagerHandler::IsInitialized()) |
214 PowerManagerHandler::Get()->RemoveObserver(this); | 221 PowerManagerHandler::Get()->RemoveObserver(this); |
215 } | 222 } |
216 | 223 |
217 // static | 224 // static |
218 bool TrayPower::IsBatteryChargingUnreliable( | 225 bool TrayPower::IsBatteryChargingUnreliable( |
219 const chromeos::PowerSupplyStatus& supply_status) { | 226 const chromeos::PowerSupplyStatus& supply_status) { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 IDR_AURA_UBER_TRAY_POWER_SMALL_DARK : IDR_AURA_UBER_TRAY_POWER_SMALL); | 274 IDR_AURA_UBER_TRAY_POWER_SMALL_DARK : IDR_AURA_UBER_TRAY_POWER_SMALL); |
268 } | 275 } |
269 gfx::Rect region( | 276 gfx::Rect region( |
270 image_offset * kBatteryImageWidth, | 277 image_offset * kBatteryImageWidth, |
271 image_index * kBatteryImageHeight, | 278 image_index * kBatteryImageHeight, |
272 kBatteryImageWidth, kBatteryImageHeight); | 279 kBatteryImageWidth, kBatteryImageHeight); |
273 return gfx::ImageSkiaOperations::ExtractSubset(*all.ToImageSkia(), region); | 280 return gfx::ImageSkiaOperations::ExtractSubset(*all.ToImageSkia(), region); |
274 } | 281 } |
275 | 282 |
276 // static | 283 // static |
| 284 gfx::Image TrayPower::GetUsbChargerNotificationImage() { |
| 285 // TODO(jamescook): Use a specialized art asset here. |
| 286 gfx::ImageSkia icon = |
| 287 GetBatteryImage(kNumPowerImages - 1, 0, true, ICON_LIGHT); |
| 288 return gfx::Image(icon); |
| 289 } |
| 290 |
| 291 // static |
277 base::string16 TrayPower::GetAccessibleNameString( | 292 base::string16 TrayPower::GetAccessibleNameString( |
278 const chromeos::PowerSupplyStatus& supply_status) { | 293 const chromeos::PowerSupplyStatus& supply_status) { |
279 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 294 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
280 if (supply_status.line_power_on && supply_status.battery_is_full) { | 295 if (supply_status.line_power_on && supply_status.battery_is_full) { |
281 return rb.GetLocalizedString( | 296 return rb.GetLocalizedString( |
282 IDS_ASH_STATUS_TRAY_BATTERY_FULL_CHARGE_ACCESSIBLE); | 297 IDS_ASH_STATUS_TRAY_BATTERY_FULL_CHARGE_ACCESSIBLE); |
283 } | 298 } |
284 bool charging_unreliable = | 299 bool charging_unreliable = |
285 IsBatteryChargingUnreliable(supply_status); | 300 IsBatteryChargingUnreliable(supply_status); |
286 if (supply_status.battery_percentage < 0.0f) { | 301 if (supply_status.battery_percentage < 0.0f) { |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
393 if (power_tray_) | 408 if (power_tray_) |
394 power_tray_->UpdatePowerStatus(status, battery_alert); | 409 power_tray_->UpdatePowerStatus(status, battery_alert); |
395 if (notification_view_) | 410 if (notification_view_) |
396 notification_view_->UpdatePowerStatus(status); | 411 notification_view_->UpdatePowerStatus(status); |
397 | 412 |
398 // Factory testing may place the battery into unusual states. | 413 // Factory testing may place the battery into unusual states. |
399 if (CommandLine::ForCurrentProcess()->HasSwitch( | 414 if (CommandLine::ForCurrentProcess()->HasSwitch( |
400 ash::switches::kAshHideNotificationsForFactory)) | 415 ash::switches::kAshHideNotificationsForFactory)) |
401 return; | 416 return; |
402 | 417 |
| 418 if (ash::switches::UseUsbChargerNotification()) |
| 419 MaybeShowUsbChargerNotification(last_power_supply_status_, status); |
| 420 |
403 if (battery_alert) | 421 if (battery_alert) |
404 ShowNotificationView(); | 422 ShowNotificationView(); |
405 else if (notification_state_ == NOTIFICATION_NONE) | 423 else if (notification_state_ == NOTIFICATION_NONE) |
406 HideNotificationView(); | 424 HideNotificationView(); |
| 425 |
| 426 last_power_supply_status_ = status; |
407 } | 427 } |
408 | 428 |
409 void TrayPower::RequestStatusUpdate() const { | 429 void TrayPower::RequestStatusUpdate() const { |
410 PowerManagerHandler::Get()->RequestStatusUpdate(); | 430 PowerManagerHandler::Get()->RequestStatusUpdate(); |
411 } | 431 } |
412 | 432 |
| 433 bool TrayPower::MaybeShowUsbChargerNotification( |
| 434 const PowerSupplyStatus& old_status, |
| 435 const PowerSupplyStatus& new_status) { |
| 436 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
| 437 const char kNotificationId[] = "usb-charger"; |
| 438 // Check for a USB charger being connected. |
| 439 if (new_status.battery_state == PowerSupplyStatus::CONNECTED_TO_USB && |
| 440 old_status.battery_state != PowerSupplyStatus::CONNECTED_TO_USB) { |
| 441 scoped_ptr<Notification> notification(new Notification( |
| 442 message_center::NOTIFICATION_TYPE_SIMPLE, |
| 443 kNotificationId, |
| 444 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_LOW_POWER_CHARGER_TITLE), |
| 445 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_LOW_POWER_CHARGER_MESSAGE), |
| 446 GetUsbChargerNotificationImage(), |
| 447 base::string16(), |
| 448 std::string(), |
| 449 message_center::RichNotificationData(), |
| 450 NULL)); |
| 451 message_center_->AddNotification(notification.Pass()); |
| 452 return true; |
| 453 } |
| 454 |
| 455 // Check for unplug of a USB charger while the USB charger notification is |
| 456 // showing. |
| 457 if (new_status.battery_state != PowerSupplyStatus::CONNECTED_TO_USB && |
| 458 old_status.battery_state == PowerSupplyStatus::CONNECTED_TO_USB) { |
| 459 message_center_->RemoveNotification(kNotificationId, false); |
| 460 return true; |
| 461 } |
| 462 return false; |
| 463 } |
| 464 |
413 bool TrayPower::UpdateNotificationState( | 465 bool TrayPower::UpdateNotificationState( |
414 const chromeos::PowerSupplyStatus& status) { | 466 const chromeos::PowerSupplyStatus& status) { |
415 if (!status.battery_is_present || | 467 if (!status.battery_is_present || |
416 status.is_calculating_battery_time || | 468 status.is_calculating_battery_time || |
417 status.battery_state == PowerSupplyStatus::CHARGING) { | 469 status.battery_state == PowerSupplyStatus::CHARGING) { |
418 notification_state_ = NOTIFICATION_NONE; | 470 notification_state_ = NOTIFICATION_NONE; |
419 return false; | 471 return false; |
420 } | 472 } |
421 | 473 |
422 if (TrayPower::IsBatteryChargingUnreliable(status)) { | 474 if (TrayPower::IsBatteryChargingUnreliable(status)) { |
423 return UpdateNotificationStateForRemainingPercentage( | 475 return UpdateNotificationStateForRemainingPercentage( |
424 status.battery_percentage); | 476 status.battery_percentage); |
425 } else { | 477 } else { |
426 return UpdateNotificationStateForRemainingTime( | 478 return UpdateNotificationStateForRemainingTime( |
427 status.battery_seconds_to_empty); | 479 status.battery_seconds_to_empty); |
428 } | 480 } |
429 } | 481 } |
430 | 482 |
431 bool TrayPower::UpdateNotificationStateForRemainingTime(int remaining_seconds) { | 483 bool TrayPower::UpdateNotificationStateForRemainingTime(int remaining_seconds) { |
432 if (remaining_seconds >= kNoWarningSeconds) { | 484 if (remaining_seconds >= kNoWarningSeconds) { |
433 notification_state_ = NOTIFICATION_NONE; | 485 notification_state_ = NOTIFICATION_NONE; |
434 return false; | 486 return false; |
435 } | 487 } |
436 | 488 |
437 switch (notification_state_) { | 489 switch (notification_state_) { |
438 case NOTIFICATION_NONE: | 490 case NOTIFICATION_NONE: |
439 if (remaining_seconds <= kCriticalSeconds) { | 491 if (remaining_seconds <= kCriticalSeconds) { |
440 notification_state_ = NOTIFICATION_CRITICAL; | 492 notification_state_ = NOTIFICATION_CRITICAL; |
441 return true; | 493 return true; |
442 } else if (remaining_seconds <= kLowPowerSeconds) { | 494 } |
| 495 if (remaining_seconds <= kLowPowerSeconds) { |
443 notification_state_ = NOTIFICATION_LOW_POWER; | 496 notification_state_ = NOTIFICATION_LOW_POWER; |
444 return true; | 497 return true; |
445 } | 498 } |
446 return false; | 499 return false; |
447 case NOTIFICATION_LOW_POWER: | 500 case NOTIFICATION_LOW_POWER: |
448 if (remaining_seconds <= kCriticalSeconds) { | 501 if (remaining_seconds <= kCriticalSeconds) { |
449 notification_state_ = NOTIFICATION_CRITICAL; | 502 notification_state_ = NOTIFICATION_CRITICAL; |
450 return true; | 503 return true; |
451 } | 504 } |
452 return false; | 505 return false; |
(...skipping 30 matching lines...) Expand all Loading... |
483 return false; | 536 return false; |
484 case NOTIFICATION_CRITICAL: | 537 case NOTIFICATION_CRITICAL: |
485 return false; | 538 return false; |
486 } | 539 } |
487 NOTREACHED(); | 540 NOTREACHED(); |
488 return false; | 541 return false; |
489 } | 542 } |
490 | 543 |
491 } // namespace internal | 544 } // namespace internal |
492 } // namespace ash | 545 } // namespace ash |
OLD | NEW |