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

Side by Side Diff: device/usb/usb_service_linux.cc

Issue 2849953003: Use the task scheduler for blocking tasks in the USB service on Linux (Closed)
Patch Set: Remove more passing of the SequencedTaskRunner Created 3 years, 7 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
« no previous file with comments | « device/usb/usb_service_linux.h ('k') | device/usb/usb_service_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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 "device/usb/usb_service_linux.h" 5 #include "device/usb/usb_service_linux.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <utility> 9 #include <utility>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/files/file.h" 12 #include "base/files/file.h"
13 #include "base/files/file_path.h" 13 #include "base/files/file_path.h"
14 #include "base/files/file_util.h" 14 #include "base/files/file_util.h"
15 #include "base/location.h" 15 #include "base/location.h"
16 #include "base/logging.h" 16 #include "base/logging.h"
17 #include "base/memory/ptr_util.h" 17 #include "base/memory/ptr_util.h"
18 #include "base/memory/weak_ptr.h" 18 #include "base/memory/weak_ptr.h"
19 #include "base/scoped_observer.h" 19 #include "base/scoped_observer.h"
20 #include "base/single_thread_task_runner.h"
21 #include "base/stl_util.h" 20 #include "base/stl_util.h"
22 #include "base/strings/string_number_conversions.h" 21 #include "base/strings/string_number_conversions.h"
23 #include "base/strings/utf_string_conversions.h" 22 #include "base/strings/utf_string_conversions.h"
23 #include "base/threading/sequenced_task_runner_handle.h"
24 #include "base/threading/thread_restrictions.h" 24 #include "base/threading/thread_restrictions.h"
25 #include "build/build_config.h" 25 #include "build/build_config.h"
26 #include "components/device_event_log/device_event_log.h" 26 #include "components/device_event_log/device_event_log.h"
27 #include "device/base/device_monitor_linux.h" 27 #include "device/udev_linux/udev_watcher.h"
28 #include "device/usb/usb_device_handle.h" 28 #include "device/usb/usb_device_handle.h"
29 #include "device/usb/usb_device_linux.h" 29 #include "device/usb/usb_device_linux.h"
30 #include "device/usb/webusb_descriptors.h" 30 #include "device/usb/webusb_descriptors.h"
31 31
32 namespace device { 32 namespace device {
33 33
34 namespace { 34 namespace {
35 35
36 // Standard USB requests and descriptor types: 36 // Standard USB requests and descriptor types:
37 const uint16_t kUsbVersion2_1 = 0x0210; 37 const uint16_t kUsbVersion2_1 = 0x0210;
(...skipping 22 matching lines...) Expand all
60 if (device_handle) { 60 if (device_handle) {
61 ReadWebUsbDescriptors( 61 ReadWebUsbDescriptors(
62 device_handle, base::Bind(&OnReadDescriptors, callback, device_handle)); 62 device_handle, base::Bind(&OnReadDescriptors, callback, device_handle));
63 } else { 63 } else {
64 callback.Run(false /* failure */); 64 callback.Run(false /* failure */);
65 } 65 }
66 } 66 }
67 67
68 } // namespace 68 } // namespace
69 69
70 class UsbServiceLinux::FileThreadHelper : public DeviceMonitorLinux::Observer { 70 class UsbServiceLinux::FileThreadHelper : public UdevWatcher::Observer {
71 public: 71 public:
72 FileThreadHelper(base::WeakPtr<UsbServiceLinux> service, 72 FileThreadHelper(base::WeakPtr<UsbServiceLinux> service);
73 scoped_refptr<base::SingleThreadTaskRunner> task_runner);
74 ~FileThreadHelper() override; 73 ~FileThreadHelper() override;
75 74
76 void Start(); 75 void Start();
77 76
78 private: 77 private:
79 // DeviceMonitorLinux::Observer: 78 // UdevWatcher::Observer
80 void OnDeviceAdded(udev_device* udev_device) override; 79 void OnDeviceAdded(ScopedUdevDevicePtr device) override;
81 void OnDeviceRemoved(udev_device* device) override; 80 void OnDeviceRemoved(ScopedUdevDevicePtr device) override;
82 81
83 base::ThreadChecker thread_checker_; 82 std::unique_ptr<UdevWatcher> watcher_;
84 ScopedObserver<DeviceMonitorLinux, DeviceMonitorLinux::Observer> observer_;
85 83
86 // |service_| can only be checked for validity on |task_runner_|'s thread. 84 // |service_| can only be checked for validity on |task_runner_|'s sequence.
87 base::WeakPtr<UsbServiceLinux> service_; 85 base::WeakPtr<UsbServiceLinux> service_;
88 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 86 scoped_refptr<base::SequencedTaskRunner> task_runner_;
87
88 base::SequenceChecker sequence_checker_;
89 89
90 DISALLOW_COPY_AND_ASSIGN(FileThreadHelper); 90 DISALLOW_COPY_AND_ASSIGN(FileThreadHelper);
91 }; 91 };
92 92
93 UsbServiceLinux::FileThreadHelper::FileThreadHelper( 93 UsbServiceLinux::FileThreadHelper::FileThreadHelper(
94 base::WeakPtr<UsbServiceLinux> service, 94 base::WeakPtr<UsbServiceLinux> service)
95 scoped_refptr<base::SingleThreadTaskRunner> task_runner) 95 : service_(service), task_runner_(base::SequencedTaskRunnerHandle::Get()) {
96 : observer_(this), service_(service), task_runner_(std::move(task_runner)) { 96 // Detaches from the sequence on which this object was created. It will be
97 thread_checker_.DetachFromThread(); 97 // bound to its owning sequence when Start() is called.
98 sequence_checker_.DetachFromSequence();
98 } 99 }
99 100
100 UsbServiceLinux::FileThreadHelper::~FileThreadHelper() { 101 UsbServiceLinux::FileThreadHelper::~FileThreadHelper() {
101 DCHECK(thread_checker_.CalledOnValidThread()); 102 DCHECK(sequence_checker_.CalledOnValidSequence());
102 } 103 }
103 104
104 // static 105 // static
105 void UsbServiceLinux::FileThreadHelper::Start() { 106 void UsbServiceLinux::FileThreadHelper::Start() {
107 DCHECK(sequence_checker_.CalledOnValidSequence());
106 base::ThreadRestrictions::AssertIOAllowed(); 108 base::ThreadRestrictions::AssertIOAllowed();
107 DCHECK(thread_checker_.CalledOnValidThread());
108 109
109 DeviceMonitorLinux* monitor = DeviceMonitorLinux::GetInstance(); 110 watcher_ = UdevWatcher::StartWatching(this);
110 observer_.Add(monitor); 111 watcher_->EnumerateExistingDevices();
111 monitor->Enumerate(
112 base::Bind(&FileThreadHelper::OnDeviceAdded, base::Unretained(this)));
113 task_runner_->PostTask(FROM_HERE, 112 task_runner_->PostTask(FROM_HERE,
114 base::Bind(&UsbServiceLinux::HelperStarted, service_)); 113 base::Bind(&UsbServiceLinux::HelperStarted, service_));
115 } 114 }
116 115
117 void UsbServiceLinux::FileThreadHelper::OnDeviceAdded( 116 void UsbServiceLinux::FileThreadHelper::OnDeviceAdded(
118 udev_device* udev_device) { 117 ScopedUdevDevicePtr device) {
119 const char* subsystem = udev_device_get_subsystem(udev_device); 118 DCHECK(sequence_checker_.CalledOnValidSequence());
119 const char* subsystem = udev_device_get_subsystem(device.get());
120 if (!subsystem || strcmp(subsystem, "usb") != 0) 120 if (!subsystem || strcmp(subsystem, "usb") != 0)
121 return; 121 return;
122 122
123 const char* value = udev_device_get_devnode(udev_device); 123 const char* value = udev_device_get_devnode(device.get());
124 if (!value) 124 if (!value)
125 return; 125 return;
126 std::string device_path = value; 126 std::string device_path = value;
127 127
128 const char* sysfs_path = udev_device_get_syspath(udev_device); 128 const char* sysfs_path = udev_device_get_syspath(device.get());
129 if (!sysfs_path) 129 if (!sysfs_path)
130 return; 130 return;
131 131
132 base::FilePath descriptors_path = 132 base::FilePath descriptors_path =
133 base::FilePath(sysfs_path).Append("descriptors"); 133 base::FilePath(sysfs_path).Append("descriptors");
134 std::string descriptors_str; 134 std::string descriptors_str;
135 if (!base::ReadFileToString(descriptors_path, &descriptors_str)) 135 if (!base::ReadFileToString(descriptors_path, &descriptors_str))
136 return; 136 return;
137 137
138 UsbDeviceDescriptor descriptor; 138 UsbDeviceDescriptor descriptor;
139 if (!descriptor.Parse(std::vector<uint8_t>(descriptors_str.begin(), 139 if (!descriptor.Parse(std::vector<uint8_t>(descriptors_str.begin(),
140 descriptors_str.end()))) { 140 descriptors_str.end()))) {
141 return; 141 return;
142 } 142 }
143 143
144 if (descriptor.device_class == kDeviceClassHub) { 144 if (descriptor.device_class == kDeviceClassHub) {
145 // Don't try to enumerate hubs. We never want to connect to a hub. 145 // Don't try to enumerate hubs. We never want to connect to a hub.
146 return; 146 return;
147 } 147 }
148 148
149 std::string manufacturer; 149 std::string manufacturer;
150 value = udev_device_get_sysattr_value(udev_device, "manufacturer"); 150 value = udev_device_get_sysattr_value(device.get(), "manufacturer");
151 if (value) 151 if (value)
152 manufacturer = value; 152 manufacturer = value;
153 153
154 std::string product; 154 std::string product;
155 value = udev_device_get_sysattr_value(udev_device, "product"); 155 value = udev_device_get_sysattr_value(device.get(), "product");
156 if (value) 156 if (value)
157 product = value; 157 product = value;
158 158
159 std::string serial_number; 159 std::string serial_number;
160 value = udev_device_get_sysattr_value(udev_device, "serial"); 160 value = udev_device_get_sysattr_value(device.get(), "serial");
161 if (value) 161 if (value)
162 serial_number = value; 162 serial_number = value;
163 163
164 unsigned active_configuration = 0; 164 unsigned active_configuration = 0;
165 value = udev_device_get_sysattr_value(udev_device, "bConfigurationValue"); 165 value = udev_device_get_sysattr_value(device.get(), "bConfigurationValue");
166 if (value) 166 if (value)
167 base::StringToUint(value, &active_configuration); 167 base::StringToUint(value, &active_configuration);
168 168
169 task_runner_->PostTask( 169 task_runner_->PostTask(
170 FROM_HERE, base::Bind(&UsbServiceLinux::OnDeviceAdded, service_, 170 FROM_HERE, base::Bind(&UsbServiceLinux::OnDeviceAdded, service_,
171 device_path, descriptor, manufacturer, product, 171 device_path, descriptor, manufacturer, product,
172 serial_number, active_configuration)); 172 serial_number, active_configuration));
173 } 173 }
174 174
175 void UsbServiceLinux::FileThreadHelper::OnDeviceRemoved(udev_device* device) { 175 void UsbServiceLinux::FileThreadHelper::OnDeviceRemoved(
176 DCHECK(thread_checker_.CalledOnValidThread()); 176 ScopedUdevDevicePtr device) {
177 const char* device_path = udev_device_get_devnode(device); 177 DCHECK(sequence_checker_.CalledOnValidSequence());
178 const char* device_path = udev_device_get_devnode(device.get());
178 if (device_path) { 179 if (device_path) {
179 task_runner_->PostTask( 180 task_runner_->PostTask(
180 FROM_HERE, base::Bind(&UsbServiceLinux::OnDeviceRemoved, service_, 181 FROM_HERE, base::Bind(&UsbServiceLinux::OnDeviceRemoved, service_,
181 std::string(device_path))); 182 std::string(device_path)));
182 } 183 }
183 } 184 }
184 185
185 UsbServiceLinux::UsbServiceLinux( 186 UsbServiceLinux::UsbServiceLinux()
186 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_in) 187 : UsbService(CreateBlockingTaskRunner()), weak_factory_(this) {
187 : UsbService(std::move(blocking_task_runner_in)), weak_factory_(this) { 188 helper_ = base::MakeUnique<FileThreadHelper>(weak_factory_.GetWeakPtr());
188 helper_ = base::MakeUnique<FileThreadHelper>(weak_factory_.GetWeakPtr(),
189 task_runner());
190 blocking_task_runner()->PostTask( 189 blocking_task_runner()->PostTask(
191 FROM_HERE, 190 FROM_HERE,
192 base::Bind(&FileThreadHelper::Start, base::Unretained(helper_.get()))); 191 base::Bind(&FileThreadHelper::Start, base::Unretained(helper_.get())));
193 } 192 }
194 193
195 UsbServiceLinux::~UsbServiceLinux() { 194 UsbServiceLinux::~UsbServiceLinux() {
196 DCHECK(!helper_); 195 DCHECK(!helper_);
197 } 196 }
198 197
199 void UsbServiceLinux::Shutdown() { 198 void UsbServiceLinux::Shutdown() {
(...skipping 23 matching lines...) Expand all
223 USB_LOG(ERROR) << "Got duplicate add event for path: " << device_path; 222 USB_LOG(ERROR) << "Got duplicate add event for path: " << device_path;
224 return; 223 return;
225 } 224 }
226 225
227 // Devices that appear during initial enumeration are gathered into the first 226 // Devices that appear during initial enumeration are gathered into the first
228 // result returned by GetDevices() and prevent device add/remove notifications 227 // result returned by GetDevices() and prevent device add/remove notifications
229 // from being sent. 228 // from being sent.
230 if (!enumeration_ready()) 229 if (!enumeration_ready())
231 ++first_enumeration_countdown_; 230 ++first_enumeration_countdown_;
232 231
233 scoped_refptr<UsbDeviceLinux> device(new UsbDeviceLinux( 232 scoped_refptr<UsbDeviceLinux> device(
234 device_path, descriptor, manufacturer, product, serial_number, 233 new UsbDeviceLinux(device_path, descriptor, manufacturer, product,
235 active_configuration, blocking_task_runner())); 234 serial_number, active_configuration));
236 devices_by_path_[device->device_path()] = device; 235 devices_by_path_[device->device_path()] = device;
237 if (device->usb_version() >= kUsbVersion2_1) { 236 if (device->usb_version() >= kUsbVersion2_1) {
238 device->Open(base::Bind(&OnDeviceOpenedToReadDescriptors, 237 device->Open(base::Bind(&OnDeviceOpenedToReadDescriptors,
239 base::Bind(&UsbServiceLinux::DeviceReady, 238 base::Bind(&UsbServiceLinux::DeviceReady,
240 weak_factory_.GetWeakPtr(), device))); 239 weak_factory_.GetWeakPtr(), device)));
241 } else { 240 } else {
242 DeviceReady(device, true /* success */); 241 DeviceReady(device, true /* success */);
243 } 242 }
244 } 243 }
245 244
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 result.reserve(devices().size()); 314 result.reserve(devices().size());
316 for (const auto& map_entry : devices()) 315 for (const auto& map_entry : devices())
317 result.push_back(map_entry.second); 316 result.push_back(map_entry.second);
318 for (const auto& callback : enumeration_callbacks_) 317 for (const auto& callback : enumeration_callbacks_)
319 callback.Run(result); 318 callback.Run(result);
320 enumeration_callbacks_.clear(); 319 enumeration_callbacks_.clear();
321 } 320 }
322 } 321 }
323 322
324 } // namespace device 323 } // namespace device
OLDNEW
« no previous file with comments | « device/usb/usb_service_linux.h ('k') | device/usb/usb_service_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698