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

Side by Side Diff: chrome/browser/chromeos/power/peripheral_battery_observer.cc

Issue 13638018: Add PeripheralBatteryObserver (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: update Created 7 years, 8 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) 2013 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 <vector>
6
7 #include "chrome/browser/chromeos/power/peripheral_battery_observer.h"
8
9 #include "ash/shell.h"
10 #include "base/bind.h"
11 #include "base/string16.h"
12 #include "base/stringprintf.h"
13 #include "base/strings/string_split.h"
14 #include "base/utf_string_conversions.h"
15 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/notifications/notification.h"
17 #include "chrome/browser/notifications/notification_ui_manager.h"
18 #include "chrome/browser/profiles/profile_manager.h"
19 #include "chromeos/dbus/dbus_thread_manager.h"
20 #include "device/bluetooth/bluetooth_adapter_factory.h"
21 #include "device/bluetooth/bluetooth_device.h"
22 #include "grit/ash_strings.h"
23 #include "grit/theme_resources.h"
24 #include "ui/base/l10n/l10n_util.h"
25 #include "ui/base/resource/resource_bundle.h"
26 #include "ui/gfx/image/image.h"
27
28 namespace chromeos {
29
30 namespace {
31
32 // When a peripheral device's battery level is <= kLowBatteryLevel, consider
33 // it to be in low battery condition.
34 const int kLowBatteryLevel = 15;
Daniel Erat 2013/04/09 02:06:18 nit: add blank line after this
Yufeng Shen (Slow to review) 2013/04/10 05:54:08 Done.
35 // Don't show 2 low battery notification within |kNotificationIntervalSec|
36 // seconds.
37 const int kNotificationIntervalSec = 60;
Daniel Erat 2013/04/09 02:06:18 nit: add blank line after this
Yufeng Shen (Slow to review) 2013/04/10 05:54:08 Done.
38 // HID Bluetooth device's battery sysfs entry path looks like
39 // "/sys/class/power_supply/hid-AA:BB:CC:DD:EE:FF-battery".
40 // Here the bluetooth address is showed in reverse order and its true
41 // address "FF:EE:DD:CC:BB:AA".
42 const char kHIDBatteryPathHeader[] = "/sys/class/power_supply/hid-";
Daniel Erat 2013/04/09 02:06:18 instead of "header" and "end", how about "prefix"
Yufeng Shen (Slow to review) 2013/04/10 05:54:08 Done.
43 const char kHIDBatteryPathEnd[] = "-battery";
44
45 class PeripheralBatteryNotificationDelegate : public NotificationDelegate {
46 public:
47 explicit PeripheralBatteryNotificationDelegate(const std::string& id)
48 : id_(id) {}
49
50 // Overridden from NotificationDelegate:
51 virtual void Display() OVERRIDE {}
52 virtual void Error() OVERRIDE {}
53 virtual void Close(bool by_user) OVERRIDE {}
54 virtual void Click() OVERRIDE {}
55 virtual std::string id() const OVERRIDE { return id_; }
56 // A NULL return value prevents loading image from URL. It is OK since our
57 // implementation loads image from system resource bundle.
58 virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE {
59 return NULL;
60 }
61
62 private:
63 const std::string id_;
64
65 DISALLOW_COPY_AND_ASSIGN(PeripheralBatteryNotificationDelegate);
66 };
67
68 } // namespace
69
70 PeripheralBatteryObserver::PeripheralBatteryObserver()
71 : weakptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(
72 new base::WeakPtrFactory<PeripheralBatteryObserver>(this))) {
73 DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver(this);
74 device::BluetoothAdapterFactory::GetAdapter(
75 base::Bind(&PeripheralBatteryObserver::InitializeOnBluetoothReady,
76 weakptr_factory_->GetWeakPtr()));
77 }
78
79 PeripheralBatteryObserver::~PeripheralBatteryObserver() {
80 if (bluetooth_adapter_.get())
81 bluetooth_adapter_->RemoveObserver(this);
82 DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver(this);
83 }
84
85 void PeripheralBatteryObserver::InitializeOnBluetoothReady(
86 scoped_refptr<device::BluetoothAdapter> adapter) {
87 bluetooth_adapter_ = adapter;
88 CHECK(bluetooth_adapter_);
89 bluetooth_adapter_->AddObserver(this);
90 }
91
92 void PeripheralBatteryObserver::PeripheralBatteryStatusReceived(
93 const std::string& path,
94 const std::string& name,
95 int level) {
96 std::string key;
Daniel Erat 2013/04/09 02:06:18 rename this variable to "address" to make it clear
Yufeng Shen (Slow to review) 2013/04/10 05:54:08 Done.
97 if (IsBluetoothHIDBattery(path)) {
98 // For HID bluetooh device, device address is used as key to index
99 // BatteryInfo.
100 key = ExtractBluetoothAddress(path);
101 } else {
102 LOG(ERROR) << "Unsupported battery path " << path;
103 return;
104 }
105
106 if (level < -1 || level > 100) {
107 LOG(ERROR) << "Invalid battery level " << level
108 << " for device " << name << " at path " << path;
109 return;
110 }
111 // If unknown battery level received, cancel any existing notification.
112 if (level == -1) {
113 CancelNotification(key);
114 return;
115 }
116
117 // Post the notification in 2 cases:
118 // 1. It's the first time the battery level is received, and it is
119 // below kLowBatteryLevel.
120 // 2. The battery level is in record and it drops below kLowBatteryLevel.
121 if (batteries_.find(key) == batteries_.end()) {
122 BatteryInfo battery(name, level, base::TimeTicks(), base::TimeTicks::Now());
123 if (level <= kLowBatteryLevel) {
124 if (PostNotification(key, battery))
125 battery.set_notification_timestamp(base::TimeTicks::Now());
126 }
127 batteries_[key] = battery;
128 } else {
129 BatteryInfo* battery = &batteries_[key];
130 battery->set_name(name);
131 int old_level = battery->level();
132 battery->set_level(level);
133 battery->set_update_timestamp(base::TimeTicks::Now());
134 if (old_level > kLowBatteryLevel && level <= kLowBatteryLevel) {
135 if (PostNotification(key, *battery))
136 battery->set_notification_timestamp(base::TimeTicks::Now());
137 }
138 }
139 }
140
141 void PeripheralBatteryObserver::DeviceChanged(device::BluetoothAdapter* adapter,
142 device::BluetoothDevice* device) {
143 if (!device->IsPaired()) {
Daniel Erat 2013/04/09 02:06:18 nit: remove curly braces since the statement is a
Yufeng Shen (Slow to review) 2013/04/10 05:54:08 Done.
144 RemoveBattery(device->GetAddress());
145 }
146 }
147
148 void PeripheralBatteryObserver::DeviceRemoved(device::BluetoothAdapter* adapter,
149 device::BluetoothDevice* device) {
150 RemoveBattery(device->GetAddress());
151 }
152
153 bool PeripheralBatteryObserver::IsBluetoothHIDBattery(const std::string& path) {
154 return StartsWithASCII(path, kHIDBatteryPathHeader, false) &&
155 EndsWith(path, kHIDBatteryPathEnd, false);
156 }
157
158 std::string PeripheralBatteryObserver::ExtractBluetoothAddress(
159 const std::string& path) {
160 int header_size = sizeof(kHIDBatteryPathHeader);
Daniel Erat 2013/04/09 02:06:18 indent this line and the following ones two spaces
Yufeng Shen (Slow to review) 2013/04/10 05:54:08 Done.
161 int end_size = sizeof(kHIDBatteryPathEnd);
Daniel Erat 2013/04/09 02:06:18 this makes me nervous. will it break if someone c
Yufeng Shen (Slow to review) 2013/04/10 05:54:08 Done.
162 int key_len = path.size() - (header_size - 1) - (end_size - 1);
Daniel Erat 2013/04/09 02:06:18 this makes me nervous. return early if key_len <=
Yufeng Shen (Slow to review) 2013/04/10 05:54:08 Done.
163 std::string reverse_address = path.substr(header_size - 1, key_len);
164 StringToLowerASCII(&reverse_address);
165 std::vector<std::string> result;
166 base::SplitString(reverse_address, ':', &result);
167 std::reverse(result.begin(), result.end());
168 std::string address = JoinString(result, ':');
169 return address;
170 }
171
172 void PeripheralBatteryObserver::RemoveBattery(const std::string& key) {
173 std::string key_lowercase = key;
174 StringToLowerASCII(&key_lowercase);
175 if (batteries_.find(key_lowercase) != batteries_.end()) {
Daniel Erat 2013/04/09 02:06:18 if you aren't going to save the iterator to make t
Yufeng Shen (Slow to review) 2013/04/10 05:54:08 Done.
176 batteries_.erase(key_lowercase);
177 CancelNotification(key_lowercase);
178 }
179 }
180
181 bool PeripheralBatteryObserver::PostNotification(const std::string& id,
182 const BatteryInfo& battery) {
183 // Only post notification if kNotificationInterval seconds have passed since
184 // last notification showed, avoiding the case where the battery level
185 // oscillates around the threshold level.
186 if (base::TimeTicks::Now() - battery.last_notification_timestamp() <
187 base::TimeDelta::FromSeconds(kNotificationIntervalSec))
188 return false;
189
190 NotificationUIManager* notification_manager =
191 g_browser_process->notification_ui_manager();
192
193 base::string16 string_text = l10n_util::GetStringFUTF16Int(
194 IDS_ASH_LOW_PERIPHERAL_BATTERY_NOTIFICATION_TEXT,
195 battery.level());
196
197 Notification notification(
198 // TODO(mukai): add SYSTEM priority and use here.
199 GURL(),
200 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
201 IDR_NOTIFICATION_PERIPHERAL_BATTERY_LOW),
202 UTF8ToUTF16(battery.name()),
203 string_text,
204 WebKit::WebTextDirectionDefault,
205 string16(),
206 UTF8ToUTF16(id),
207 new PeripheralBatteryNotificationDelegate(id));
208
209 notification_manager->Add(notification,
210 ProfileManager::GetDefaultProfileOrOffTheRecord());
211
212 return true;
213 }
214
215 void PeripheralBatteryObserver::CancelNotification(const std::string& id) {
216 g_browser_process->notification_ui_manager()->CancelById(id);
217 }
218
219
220 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698