Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "ui/events/ozone/evdev/input_device_factory_evdev.h" | 5 #include "ui/events/ozone/evdev/input_device_factory_evdev.h" |
| 6 | 6 |
| 7 #include <fcntl.h> | 7 #include <fcntl.h> |
| 8 #include <linux/input.h> | 8 #include <linux/input.h> |
| 9 #include <locale> | |
| 9 | 10 |
| 11 #include "base/bind.h" | |
| 12 #include "base/command_line.h" | |
| 13 #include "base/files/file_util.h" | |
| 14 #include "base/process/launch.h" | |
| 10 #include "base/stl_util.h" | 15 #include "base/stl_util.h" |
| 11 #include "base/strings/stringprintf.h" | 16 #include "base/strings/stringprintf.h" |
| 12 #include "base/thread_task_runner_handle.h" | 17 #include "base/thread_task_runner_handle.h" |
| 13 #include "base/threading/worker_pool.h" | 18 #include "base/threading/worker_pool.h" |
| 14 #include "base/time/time.h" | 19 #include "base/time/time.h" |
| 15 #include "base/trace_event/trace_event.h" | 20 #include "base/trace_event/trace_event.h" |
| 16 #include "ui/events/devices/device_data_manager.h" | 21 #include "ui/events/devices/device_data_manager.h" |
| 17 #include "ui/events/devices/device_util_linux.h" | 22 #include "ui/events/devices/device_util_linux.h" |
| 18 #include "ui/events/ozone/evdev/device_event_dispatcher_evdev.h" | 23 #include "ui/events/ozone/evdev/device_event_dispatcher_evdev.h" |
| 19 #include "ui/events/ozone/evdev/event_converter_evdev_impl.h" | 24 #include "ui/events/ozone/evdev/event_converter_evdev_impl.h" |
| 20 #include "ui/events/ozone/evdev/event_device_info.h" | 25 #include "ui/events/ozone/evdev/event_device_info.h" |
| 21 #include "ui/events/ozone/evdev/tablet_event_converter_evdev.h" | 26 #include "ui/events/ozone/evdev/tablet_event_converter_evdev.h" |
| 22 #include "ui/events/ozone/evdev/touch_event_converter_evdev.h" | 27 #include "ui/events/ozone/evdev/touch_event_converter_evdev.h" |
| 23 | 28 |
| 24 #if defined(USE_EVDEV_GESTURES) | 29 #if defined(USE_EVDEV_GESTURES) |
| 25 #include "ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.h" | 30 #include "ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.h" |
| 26 #include "ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cr os.h" | 31 #include "ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cr os.h" |
| 27 #include "ui/events/ozone/evdev/libgestures_glue/gesture_property_provider.h" | 32 #include "ui/events/ozone/evdev/libgestures_glue/gesture_property_provider.h" |
| 28 #endif | 33 #endif |
| 29 | 34 |
| 30 #ifndef EVIOCSCLOCKID | 35 #ifndef EVIOCSCLOCKID |
| 31 #define EVIOCSCLOCKID _IOW('E', 0xa0, int) | 36 #define EVIOCSCLOCKID _IOW('E', 0xa0, int) |
| 32 #endif | 37 #endif |
| 33 | 38 |
| 34 namespace ui { | 39 namespace ui { |
| 35 | 40 |
| 36 namespace { | 41 namespace { |
| 37 | 42 |
| 43 // Binary paths. | |
| 44 const char kGzipCommand[] = "/bin/gzip"; | |
| 45 const char kDateCommand[] = "/bin/date"; | |
| 46 | |
| 47 // Touch event log paths. | |
| 48 const char kTouchpadGestureLogPath[] = | |
| 49 "/var/log/xorg/touchpad_activity_log.txt"; | |
| 50 const char kTouchpadEvdevLogPath[] = "/var/log/xorg/cmt_input_events.dat"; | |
|
spang
2015/02/02 21:43:16
Are you planning to make a ChromeOS change to crea
Shecky Lin
2015/02/03 08:20:14
Yeah, sorry, this is probably the problem I am run
Shecky Lin
2015/02/03 11:29:22
Just got a second thought on this. Could we instea
spang
2015/02/03 16:31:20
Yep, /tmp would work. If you want to use /var/log
Shecky Lin
2015/02/10 08:21:22
I decided to use /home/chronos/user/log/ directly.
| |
| 51 | |
| 38 typedef base::Callback<void(scoped_ptr<EventConverterEvdev>)> | 52 typedef base::Callback<void(scoped_ptr<EventConverterEvdev>)> |
| 39 OpenInputDeviceReplyCallback; | 53 OpenInputDeviceReplyCallback; |
| 40 | 54 |
| 41 struct OpenInputDeviceParams { | 55 struct OpenInputDeviceParams { |
| 42 // Unique identifier for the new device. | 56 // Unique identifier for the new device. |
| 43 int id; | 57 int id; |
| 44 | 58 |
| 45 // Device path to open. | 59 // Device path to open. |
| 46 base::FilePath path; | 60 base::FilePath path; |
| 47 | 61 |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 146 // Therefore, the property name indices we output here shouldn't be treated | 160 // Therefore, the property name indices we output here shouldn't be treated |
| 147 // as unique identifiers of the properties. | 161 // as unique identifiers of the properties. |
| 148 std::sort(names.begin(), names.end()); | 162 std::sort(names.begin(), names.end()); |
| 149 for (size_t j = 0; j < names.size(); ++j) { | 163 for (size_t j = 0; j < names.size(); ++j) { |
| 150 status->append(base::StringPrintf("\t%s (%zu):", names[j].c_str(), j)); | 164 status->append(base::StringPrintf("\t%s (%zu):", names[j].c_str(), j)); |
| 151 GesturesProp* property = provider->GetProperty(ids[i], names[j]); | 165 GesturesProp* property = provider->GetProperty(ids[i], names[j]); |
| 152 status->append("\t" + DumpGesturePropertyValue(property) + '\n'); | 166 status->append("\t" + DumpGesturePropertyValue(property) + '\n'); |
| 153 } | 167 } |
| 154 } | 168 } |
| 155 } | 169 } |
| 170 | |
| 171 // Compress dumped event logs in place. | |
| 172 void CompressDumpedLog(scoped_ptr<std::vector<std::string>> log_paths) { | |
| 173 for (size_t i = 0; i < log_paths->size(); ++i) { | |
| 174 // Zip the file. | |
| 175 base::CommandLine command = base::CommandLine(base::FilePath(kGzipCommand)); | |
| 176 command.AppendArg("-f"); | |
| 177 command.AppendArg((*log_paths)[i]); | |
| 178 std::string output; | |
| 179 base::GetAppOutput(command, &output); | |
| 180 | |
| 181 // Replace the original file with the zipped one. | |
| 182 base::Move(base::FilePath((*log_paths)[i] + ".gz"), | |
| 183 base::FilePath((*log_paths)[i])); | |
| 184 } | |
| 185 } | |
| 186 | |
| 187 // Get the current time in a string. | |
| 188 // | |
| 189 // This is done by calling out to the 'date' binary so that the time format | |
| 190 // can be fully compatible with the X11 behavior. | |
| 191 std::string GetCurrentTimeForLogging() { | |
| 192 base::CommandLine command = base::CommandLine(base::FilePath(kDateCommand)); | |
| 193 command.AppendArg("+%Y%m%d-%H%M%S"); | |
|
spang
2015/02/02 21:43:16
Does it make sense for this to be in local time wi
Shecky Lin
2015/02/03 08:20:14
I was just trying to do exactly the same thing in
spang
2015/02/03 16:31:20
Ok, "we don't actually care about the exact time"
| |
| 194 std::string output; | |
| 195 base::GetAppOutput(command, &output); | |
|
spang
2015/02/02 21:43:16
Can't you use just "strftime" or similar? Should n
Shecky Lin
2015/02/03 08:20:14
Good idea. Will do. Thanks.
Shecky Lin
2015/02/10 08:21:22
Done.
| |
| 196 return output; | |
| 197 } | |
| 198 | |
| 199 // Canonize the device name for logging. | |
| 200 std::string GetCanonicalDeviceName(const std::string& name) { | |
| 201 std::locale loc; | |
| 202 std::string ret(name); | |
| 203 for (size_t i = 0; i < ret.size(); ++i) | |
| 204 if (!std::isalpha(ret[i], loc)) | |
| 205 ret[i] = '_'; | |
| 206 return ret; | |
| 207 } | |
| 208 | |
| 209 std::string GenerateEventLogName(GesturePropertyProvider* provider, | |
| 210 const base::FilePath& out_dir, | |
| 211 const std::string& prefix, | |
| 212 const std::string& now, | |
| 213 int id) { | |
| 214 return out_dir.MaybeAsASCII() + "/" + prefix + now + "." + | |
| 215 std::to_string(id) + "." + | |
| 216 GetCanonicalDeviceName(provider->GetDeviceNameById(id)); | |
| 217 } | |
| 218 | |
| 219 // Dump touch event logs. | |
| 220 void DumpTouchEventLog(GesturePropertyProvider* provider, | |
|
spang
2015/02/02 21:43:17
Can you move this function somewhere inside libges
Shecky Lin
2015/02/03 08:20:14
Yeah, make sense, will do.
Shecky Lin
2015/02/10 08:21:22
Done.
| |
| 221 const base::FilePath& out_dir, | |
| 222 scoped_ptr<std::vector<base::FilePath>> log_paths, | |
| 223 const GetTouchEventLogReply& reply) { | |
| 224 // Get device ids. | |
| 225 std::vector<int> ids; | |
| 226 provider->GetDeviceIdsByType(DT_ALL, &ids); | |
| 227 | |
| 228 // Get current time stamp. | |
| 229 std::string now = GetCurrentTimeForLogging(); | |
| 230 | |
| 231 // Dump event logs for gesture devices. | |
| 232 scoped_ptr<std::vector<std::string>> log_paths_to_be_compressed( | |
|
spang
2015/02/02 21:43:17
I don't think you need a new vector here.
You sho
Shecky Lin
2015/02/03 08:20:14
No, this is not for recording the pointer. As said
spang
2015/02/03 16:31:20
Ah, ok.
| |
| 233 new std::vector<std::string>); | |
| 234 for (size_t i = 0; i < ids.size(); ++i) { | |
| 235 // First, see if the device actually uses the gesture library by checking | |
| 236 // if it has any gesture property. | |
| 237 std::vector<std::string> names = provider->GetPropertyNamesById(ids[i]); | |
| 238 if (names.size() == 0) | |
| 239 continue; | |
| 240 | |
| 241 // Set the logging properties to dump event logs. This needs to be done | |
| 242 // synchronously for now or we might have race conditions on the debug | |
| 243 // buffer. If the performance becomes a concern then, we can fork and | |
| 244 // synchronize it. | |
| 245 // | |
| 246 // TODO(sheckylin): Make sure this has no performance impact for user | |
| 247 // feedbacks. | |
| 248 GesturesProp* property = provider->GetProperty(ids[i], "Logging Notify"); | |
| 249 property->SetIntValue(std::vector<int>(1, 1)); | |
| 250 property = provider->GetProperty(ids[i], "Dump Debug Log"); | |
| 251 property->SetBoolValue(std::vector<bool>(1, true)); | |
| 252 | |
| 253 // Rename/move the file to another place since each device's log is | |
| 254 // always dumped using the same name. | |
| 255 std::string gesture_log_filename = GenerateEventLogName( | |
| 256 provider, out_dir, "touchpad_activity_", now, ids[i]); | |
| 257 base::Move(base::FilePath(kTouchpadGestureLogPath), | |
| 258 base::FilePath(gesture_log_filename)); | |
| 259 std::string evdev_log_filename = GenerateEventLogName( | |
| 260 provider, out_dir, "cmt_input_events_", now, ids[i]); | |
| 261 base::Move(base::FilePath(kTouchpadEvdevLogPath), | |
| 262 base::FilePath(evdev_log_filename)); | |
| 263 | |
| 264 // Historically, we compress touchpad/mouse logs with gzip before tarring | |
| 265 // them up. We DONT compress touchscreen logs though. | |
| 266 log_paths_to_be_compressed->push_back(gesture_log_filename); | |
| 267 log_paths->push_back(base::FilePath(gesture_log_filename)); | |
| 268 log_paths_to_be_compressed->push_back(evdev_log_filename); | |
| 269 log_paths->push_back(base::FilePath(evdev_log_filename)); | |
| 270 } | |
| 271 | |
| 272 // Compress touchpad/mouse logs on another thread and return. | |
| 273 base::WorkerPool::PostTaskAndReply( | |
| 274 FROM_HERE, | |
| 275 base::Bind(&CompressDumpedLog, base::Passed(&log_paths_to_be_compressed)), | |
| 276 base::Bind(reply, base::Passed(&log_paths)), true /* task_is_slow */); | |
| 277 } | |
| 278 | |
| 156 #endif | 279 #endif |
| 157 | 280 |
| 158 scoped_ptr<EventConverterEvdev> CreateConverter( | 281 scoped_ptr<EventConverterEvdev> CreateConverter( |
| 159 const OpenInputDeviceParams& params, | 282 const OpenInputDeviceParams& params, |
| 160 int fd, | 283 int fd, |
| 161 InputDeviceType type, | 284 InputDeviceType type, |
| 162 const EventDeviceInfo& devinfo) { | 285 const EventDeviceInfo& devinfo) { |
| 163 #if defined(USE_EVDEV_GESTURES) | 286 #if defined(USE_EVDEV_GESTURES) |
| 164 // Touchpad or mouse: use gestures library. | 287 // Touchpad or mouse: use gestures library. |
| 165 // EventReaderLibevdevCros -> GestureInterpreterLibevdevCros -> DispatchEvent | 288 // EventReaderLibevdevCros -> GestureInterpreterLibevdevCros -> DispatchEvent |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 407 | 530 |
| 408 void InputDeviceFactoryEvdev::GetTouchDeviceStatus( | 531 void InputDeviceFactoryEvdev::GetTouchDeviceStatus( |
| 409 const GetTouchDeviceStatusReply& reply) { | 532 const GetTouchDeviceStatusReply& reply) { |
| 410 scoped_ptr<std::string> status(new std::string); | 533 scoped_ptr<std::string> status(new std::string); |
| 411 #if defined(USE_EVDEV_GESTURES) | 534 #if defined(USE_EVDEV_GESTURES) |
| 412 DumpTouchDeviceStatus(gesture_property_provider_.get(), status.get()); | 535 DumpTouchDeviceStatus(gesture_property_provider_.get(), status.get()); |
| 413 #endif | 536 #endif |
| 414 reply.Run(status.Pass()); | 537 reply.Run(status.Pass()); |
| 415 } | 538 } |
| 416 | 539 |
| 540 void InputDeviceFactoryEvdev::GetTouchEventLog( | |
| 541 const base::FilePath& out_dir, | |
| 542 const GetTouchEventLogReply& reply) { | |
| 543 scoped_ptr<std::vector<base::FilePath>> log_paths( | |
| 544 new std::vector<base::FilePath>); | |
| 545 #if defined(USE_EVDEV_GESTURES) | |
| 546 DumpTouchEventLog(gesture_property_provider_.get(), out_dir, log_paths.Pass(), | |
| 547 reply); | |
| 548 #else | |
| 549 reply.Run(log_paths.Pass()); | |
| 550 #endif | |
| 551 } | |
| 552 | |
| 417 base::WeakPtr<InputDeviceFactoryEvdev> InputDeviceFactoryEvdev::GetWeakPtr() { | 553 base::WeakPtr<InputDeviceFactoryEvdev> InputDeviceFactoryEvdev::GetWeakPtr() { |
| 418 return weak_ptr_factory_.GetWeakPtr(); | 554 return weak_ptr_factory_.GetWeakPtr(); |
| 419 } | 555 } |
| 420 | 556 |
| 421 void InputDeviceFactoryEvdev::NotifyDeviceChange( | 557 void InputDeviceFactoryEvdev::NotifyDeviceChange( |
| 422 const EventConverterEvdev& converter) { | 558 const EventConverterEvdev& converter) { |
| 423 if (converter.HasTouchscreen()) | 559 if (converter.HasTouchscreen()) |
| 424 NotifyTouchscreensUpdated(); | 560 NotifyTouchscreensUpdated(); |
| 425 | 561 |
| 426 if (converter.HasKeyboard()) | 562 if (converter.HasKeyboard()) |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 510 std::vector<int> ids; | 646 std::vector<int> ids; |
| 511 gesture_property_provider_->GetDeviceIdsByType(type, &ids); | 647 gesture_property_provider_->GetDeviceIdsByType(type, &ids); |
| 512 for (size_t i = 0; i < ids.size(); ++i) { | 648 for (size_t i = 0; i < ids.size(); ++i) { |
| 513 SetGestureBoolProperty(gesture_property_provider_.get(), ids[i], name, | 649 SetGestureBoolProperty(gesture_property_provider_.get(), ids[i], name, |
| 514 value); | 650 value); |
| 515 } | 651 } |
| 516 #endif | 652 #endif |
| 517 } | 653 } |
| 518 | 654 |
| 519 } // namespace ui | 655 } // namespace ui |
| OLD | NEW |