Chromium Code Reviews| Index: ui/events/ozone/evdev/input_device_factory_evdev.cc |
| diff --git a/ui/events/ozone/evdev/input_device_factory_evdev.cc b/ui/events/ozone/evdev/input_device_factory_evdev.cc |
| index f215cd7c67e8dc24e63165ebcad98d103d7e0a7c..7ad1b4a40be0c9f101e278c7b45c2bf1e099206b 100644 |
| --- a/ui/events/ozone/evdev/input_device_factory_evdev.cc |
| +++ b/ui/events/ozone/evdev/input_device_factory_evdev.cc |
| @@ -6,7 +6,12 @@ |
| #include <fcntl.h> |
| #include <linux/input.h> |
| +#include <locale> |
| +#include "base/bind.h" |
| +#include "base/command_line.h" |
| +#include "base/files/file_util.h" |
| +#include "base/process/launch.h" |
| #include "base/stl_util.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/thread_task_runner_handle.h" |
| @@ -35,6 +40,15 @@ namespace ui { |
| namespace { |
| +// Binary paths. |
| +const char kGzipCommand[] = "/bin/gzip"; |
| +const char kDateCommand[] = "/bin/date"; |
| + |
| +// Touch event log paths. |
| +const char kTouchpadGestureLogPath[] = |
| + "/var/log/xorg/touchpad_activity_log.txt"; |
| +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.
|
| + |
| typedef base::Callback<void(scoped_ptr<EventConverterEvdev>)> |
| OpenInputDeviceReplyCallback; |
| @@ -153,6 +167,115 @@ void DumpTouchDeviceStatus(GesturePropertyProvider* provider, |
| } |
| } |
| } |
| + |
| +// Compress dumped event logs in place. |
| +void CompressDumpedLog(scoped_ptr<std::vector<std::string>> log_paths) { |
| + for (size_t i = 0; i < log_paths->size(); ++i) { |
| + // Zip the file. |
| + base::CommandLine command = base::CommandLine(base::FilePath(kGzipCommand)); |
| + command.AppendArg("-f"); |
| + command.AppendArg((*log_paths)[i]); |
| + std::string output; |
| + base::GetAppOutput(command, &output); |
| + |
| + // Replace the original file with the zipped one. |
| + base::Move(base::FilePath((*log_paths)[i] + ".gz"), |
| + base::FilePath((*log_paths)[i])); |
| + } |
| +} |
| + |
| +// Get the current time in a string. |
| +// |
| +// This is done by calling out to the 'date' binary so that the time format |
| +// can be fully compatible with the X11 behavior. |
| +std::string GetCurrentTimeForLogging() { |
| + base::CommandLine command = base::CommandLine(base::FilePath(kDateCommand)); |
| + 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"
|
| + std::string output; |
| + 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.
|
| + return output; |
| +} |
| + |
| +// Canonize the device name for logging. |
| +std::string GetCanonicalDeviceName(const std::string& name) { |
| + std::locale loc; |
| + std::string ret(name); |
| + for (size_t i = 0; i < ret.size(); ++i) |
| + if (!std::isalpha(ret[i], loc)) |
| + ret[i] = '_'; |
| + return ret; |
| +} |
| + |
| +std::string GenerateEventLogName(GesturePropertyProvider* provider, |
| + const base::FilePath& out_dir, |
| + const std::string& prefix, |
| + const std::string& now, |
| + int id) { |
| + return out_dir.MaybeAsASCII() + "/" + prefix + now + "." + |
| + std::to_string(id) + "." + |
| + GetCanonicalDeviceName(provider->GetDeviceNameById(id)); |
| +} |
| + |
| +// Dump touch event logs. |
| +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.
|
| + const base::FilePath& out_dir, |
| + scoped_ptr<std::vector<base::FilePath>> log_paths, |
| + const GetTouchEventLogReply& reply) { |
| + // Get device ids. |
| + std::vector<int> ids; |
| + provider->GetDeviceIdsByType(DT_ALL, &ids); |
| + |
| + // Get current time stamp. |
| + std::string now = GetCurrentTimeForLogging(); |
| + |
| + // Dump event logs for gesture devices. |
| + 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.
|
| + new std::vector<std::string>); |
| + for (size_t i = 0; i < ids.size(); ++i) { |
| + // First, see if the device actually uses the gesture library by checking |
| + // if it has any gesture property. |
| + std::vector<std::string> names = provider->GetPropertyNamesById(ids[i]); |
| + if (names.size() == 0) |
| + continue; |
| + |
| + // Set the logging properties to dump event logs. This needs to be done |
| + // synchronously for now or we might have race conditions on the debug |
| + // buffer. If the performance becomes a concern then, we can fork and |
| + // synchronize it. |
| + // |
| + // TODO(sheckylin): Make sure this has no performance impact for user |
| + // feedbacks. |
| + GesturesProp* property = provider->GetProperty(ids[i], "Logging Notify"); |
| + property->SetIntValue(std::vector<int>(1, 1)); |
| + property = provider->GetProperty(ids[i], "Dump Debug Log"); |
| + property->SetBoolValue(std::vector<bool>(1, true)); |
| + |
| + // Rename/move the file to another place since each device's log is |
| + // always dumped using the same name. |
| + std::string gesture_log_filename = GenerateEventLogName( |
| + provider, out_dir, "touchpad_activity_", now, ids[i]); |
| + base::Move(base::FilePath(kTouchpadGestureLogPath), |
| + base::FilePath(gesture_log_filename)); |
| + std::string evdev_log_filename = GenerateEventLogName( |
| + provider, out_dir, "cmt_input_events_", now, ids[i]); |
| + base::Move(base::FilePath(kTouchpadEvdevLogPath), |
| + base::FilePath(evdev_log_filename)); |
| + |
| + // Historically, we compress touchpad/mouse logs with gzip before tarring |
| + // them up. We DONT compress touchscreen logs though. |
| + log_paths_to_be_compressed->push_back(gesture_log_filename); |
| + log_paths->push_back(base::FilePath(gesture_log_filename)); |
| + log_paths_to_be_compressed->push_back(evdev_log_filename); |
| + log_paths->push_back(base::FilePath(evdev_log_filename)); |
| + } |
| + |
| + // Compress touchpad/mouse logs on another thread and return. |
| + base::WorkerPool::PostTaskAndReply( |
| + FROM_HERE, |
| + base::Bind(&CompressDumpedLog, base::Passed(&log_paths_to_be_compressed)), |
| + base::Bind(reply, base::Passed(&log_paths)), true /* task_is_slow */); |
| +} |
| + |
| #endif |
| scoped_ptr<EventConverterEvdev> CreateConverter( |
| @@ -414,6 +537,19 @@ void InputDeviceFactoryEvdev::GetTouchDeviceStatus( |
| reply.Run(status.Pass()); |
| } |
| +void InputDeviceFactoryEvdev::GetTouchEventLog( |
| + const base::FilePath& out_dir, |
| + const GetTouchEventLogReply& reply) { |
| + scoped_ptr<std::vector<base::FilePath>> log_paths( |
| + new std::vector<base::FilePath>); |
| +#if defined(USE_EVDEV_GESTURES) |
| + DumpTouchEventLog(gesture_property_provider_.get(), out_dir, log_paths.Pass(), |
| + reply); |
| +#else |
| + reply.Run(log_paths.Pass()); |
| +#endif |
| +} |
| + |
| base::WeakPtr<InputDeviceFactoryEvdev> InputDeviceFactoryEvdev::GetWeakPtr() { |
| return weak_ptr_factory_.GetWeakPtr(); |
| } |