Commit e1fd5037 authored by sheckylin's avatar sheckylin Committed by Commit bot

Dump touchpad event logs for touch log source

The CL dumps event logs for devices that run with the CrOS
gesture library. It is designed to be backward-compatible
with the X11 behaviour.

Contributed by sheckylin@chromium.org

BUG=450159
TEST=samus ChromeOS build

Review URL: https://codereview.chromium.org/893753002

Cr-Commit-Position: refs/heads/master@{#318182}
parent 26017a7a
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
#include "base/callback.h" #include "base/callback.h"
#include "base/command_line.h" #include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/json/json_string_value_serializer.h" #include "base/json/json_string_value_serializer.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
...@@ -28,18 +30,123 @@ const char kHUDLogDataKey[] = "hud_log"; ...@@ -28,18 +30,123 @@ const char kHUDLogDataKey[] = "hud_log";
// We continue to go with it in order to be compatible with the existing touch // We continue to go with it in order to be compatible with the existing touch
// log processing toolchain. // log processing toolchain.
const char kDeviceStatusLogDataKey[] = "hack-33025-touchpad"; const char kDeviceStatusLogDataKey[] = "hack-33025-touchpad";
const char kTouchpadEventLogDataKey[] = "hack-33025-touchpad_activity";
// Callback for handing the outcome of GetTouchDeviceStatus(). Appends the // Directory for temp touch event logs.
// collected log to the SystemLogsResponse map. const char kTouchEventLogDir[] = "/home/chronos/user/log";
// Prefixes of touch event logs.
const char kTouchpadGestureLogPrefix[] = "touchpad_activity_";
const char kTouchpadEvdevLogPrefix[] = "cmt_input_events_";
// Binary paths.
const char kShellCommand[] = "/bin/sh";
const char kTarCommand[] = "/bin/tar cf -";
const char kUuencodeCommand[] = "/usr/bin/uuencode";
const int kMaxDeviceTouchEventLogs = 7;
// Clean up intermediate log files dumped during feedback creation.
void CleanupEventLog(scoped_ptr<std::vector<base::FilePath>> log_paths) {
for (size_t i = 0; i < log_paths->size(); ++i)
base::DeleteFile((*log_paths)[i], false);
}
// Check for all known log paths and find the ones whose filenames match a
// prefix. Concatenate their filenames into one string. |max_log_count| is
// the maximum number of logs that we will collect.
//
// This is used to distinguish touchpad/mice logs from touchscreen logs.
std::string GetEventLogListOfOnePrefix(
const std::vector<base::FilePath>& log_paths,
const std::string& prefix,
const int max_log_count) {
int collected = 0;
std::string log_list;
for (size_t i = 0; i < log_paths.size(); ++i) {
const std::string basename = log_paths[i].BaseName().value();
if (StartsWithASCII(basename, prefix, true)) {
log_list.append(" " + log_paths[i].value());
// Limit the max number of collected logs to shorten the log collection
// process.
if (++collected >= max_log_count)
break;
}
}
return log_list;
}
// Pack the collected event logs in a way that is compatible with the log
// analysis tools.
void PackEventLog(system_logs::SystemLogsResponse* response,
scoped_ptr<std::vector<base::FilePath>> log_paths) {
DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
// Combine logs with a command line call that tars them up and uuencode the
// result in one string. This is to be compatible with the X11 behavior.
std::vector<std::pair<std::string, base::CommandLine>> commands;
base::CommandLine command = base::CommandLine(base::FilePath(kShellCommand));
command.AppendArg("-c");
// Make a list that contains touchpad (and mouse) event logs only.
const std::string touchpad_log_list =
GetEventLogListOfOnePrefix(*log_paths, kTouchpadGestureLogPrefix,
kMaxDeviceTouchEventLogs) +
GetEventLogListOfOnePrefix(*log_paths, kTouchpadEvdevLogPrefix,
kMaxDeviceTouchEventLogs);
command.AppendArg(std::string(kTarCommand) + touchpad_log_list +
" 2>/dev/null | " + kUuencodeCommand +
" -m touchpad_activity_log.tar");
commands.push_back(std::make_pair(kTouchpadEventLogDataKey, command));
// For now only touchpad (and mouse) logs are actually collected.
for (size_t i = 0; i < commands.size(); ++i) {
std::string output;
base::GetAppOutput(commands[i].second, &output);
(*response)[commands[i].first] = output;
}
// Cleanup these temporary log files.
BrowserThread::PostBlockingPoolTask(
FROM_HERE, base::Bind(CleanupEventLog, base::Passed(&log_paths)));
}
// Callback for handing the outcome of GetTouchEventLog().
//
// This is the end of the whole touch log collection process.
void OnEventLogCollected(scoped_ptr<system_logs::SystemLogsResponse> response,
const system_logs::SysLogsSourceCallback& callback,
scoped_ptr<std::vector<base::FilePath>> log_paths) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// We cannot eliminate these temporaries and inline these closures because the
// compiler may call release() before get().
const base::Closure pack_closure =
base::Bind(&PackEventLog, base::Unretained(response.get()),
base::Passed(&log_paths));
const base::Closure callback_closure =
base::Bind(callback, base::Owned(response.release()));
BrowserThread::PostBlockingPoolTaskAndReply(FROM_HERE, pack_closure,
callback_closure);
}
// Callback for handing the outcome of GetTouchDeviceStatus().
//
// Appends the collected log to the SystemLogsResponse map. Also goes on to
// collect touch event logs.
void OnStatusLogCollected(scoped_ptr<system_logs::SystemLogsResponse> response, void OnStatusLogCollected(scoped_ptr<system_logs::SystemLogsResponse> response,
const system_logs::SysLogsSourceCallback& callback, const system_logs::SysLogsSourceCallback& callback,
scoped_ptr<std::string> log) { scoped_ptr<std::string> log) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
(*response)[kDeviceStatusLogDataKey] = *log; (*response)[kDeviceStatusLogDataKey] = *log;
BrowserThread::PostTask( // Collect touch event logs.
BrowserThread::UI, FROM_HERE, const base::FilePath kBaseLogPath(kTouchEventLogDir);
base::Bind(callback, base::Owned(response.release()))); ui::OzonePlatform::GetInstance()->GetInputController()->GetTouchEventLog(
kBaseLogPath,
base::Bind(&OnEventLogCollected, base::Passed(&response), callback));
} }
// Collect touch HUD debug logs. This needs to be done on the UI thread. // Collect touch HUD debug logs. This needs to be done on the UI thread.
......
...@@ -121,6 +121,8 @@ component("events_ozone_evdev") { ...@@ -121,6 +121,8 @@ component("events_ozone_evdev") {
sources += [ sources += [
"evdev/libgestures_glue/event_reader_libevdev_cros.cc", "evdev/libgestures_glue/event_reader_libevdev_cros.cc",
"evdev/libgestures_glue/event_reader_libevdev_cros.h", "evdev/libgestures_glue/event_reader_libevdev_cros.h",
"evdev/libgestures_glue/gesture_feedback.cc",
"evdev/libgestures_glue/gesture_feedback.h",
"evdev/libgestures_glue/gesture_interpreter_libevdev_cros.cc", "evdev/libgestures_glue/gesture_interpreter_libevdev_cros.cc",
"evdev/libgestures_glue/gesture_interpreter_libevdev_cros.h", "evdev/libgestures_glue/gesture_interpreter_libevdev_cros.h",
"evdev/libgestures_glue/gesture_logging.cc", "evdev/libgestures_glue/gesture_logging.cc",
......
...@@ -152,6 +152,15 @@ void InputControllerEvdev::GetTouchDeviceStatus( ...@@ -152,6 +152,15 @@ void InputControllerEvdev::GetTouchDeviceStatus(
reply.Run(make_scoped_ptr(new std::string)); reply.Run(make_scoped_ptr(new std::string));
} }
void InputControllerEvdev::GetTouchEventLog(
const base::FilePath& out_dir,
const GetTouchEventLogReply& reply) {
if (input_device_factory_)
input_device_factory_->GetTouchEventLog(out_dir, reply);
else
reply.Run(make_scoped_ptr(new std::vector<base::FilePath>));
}
void InputControllerEvdev::ScheduleUpdateDeviceSettings() { void InputControllerEvdev::ScheduleUpdateDeviceSettings() {
if (!input_device_factory_ || settings_update_pending_) if (!input_device_factory_ || settings_update_pending_)
return; return;
......
...@@ -55,6 +55,8 @@ class EVENTS_OZONE_EVDEV_EXPORT InputControllerEvdev : public InputController { ...@@ -55,6 +55,8 @@ class EVENTS_OZONE_EVDEV_EXPORT InputControllerEvdev : public InputController {
void SetPrimaryButtonRight(bool right) override; void SetPrimaryButtonRight(bool right) override;
void SetTapToClickPaused(bool state) override; void SetTapToClickPaused(bool state) override;
void GetTouchDeviceStatus(const GetTouchDeviceStatusReply& reply) override; void GetTouchDeviceStatus(const GetTouchDeviceStatusReply& reply) override;
void GetTouchEventLog(const base::FilePath& out_dir,
const GetTouchEventLogReply& reply) override;
void DisableInternalTouchpad() override; void DisableInternalTouchpad() override;
void EnableInternalTouchpad() override; void EnableInternalTouchpad() override;
void DisableInternalKeyboardExceptKeys( void DisableInternalKeyboardExceptKeys(
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
#include <linux/input.h> #include <linux/input.h>
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/thread_task_runner_handle.h" #include "base/thread_task_runner_handle.h"
#include "base/threading/worker_pool.h" #include "base/threading/worker_pool.h"
#include "base/time/time.h" #include "base/time/time.h"
...@@ -23,6 +22,7 @@ ...@@ -23,6 +22,7 @@
#if defined(USE_EVDEV_GESTURES) #if defined(USE_EVDEV_GESTURES)
#include "ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.h" #include "ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.h"
#include "ui/events/ozone/evdev/libgestures_glue/gesture_feedback.h"
#include "ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.h" #include "ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.h"
#include "ui/events/ozone/evdev/libgestures_glue/gesture_property_provider.h" #include "ui/events/ozone/evdev/libgestures_glue/gesture_property_provider.h"
#endif #endif
...@@ -88,71 +88,6 @@ void SetGestureBoolProperty(GesturePropertyProvider* provider, ...@@ -88,71 +88,6 @@ void SetGestureBoolProperty(GesturePropertyProvider* provider,
} }
} }
// Return the values in an array in one string. Used for touch logging.
template <typename T>
std::string DumpArrayProperty(const std::vector<T>& value, const char* format) {
std::string ret;
for (size_t i = 0; i < value.size(); ++i) {
if (i > 0)
ret.append(", ");
ret.append(base::StringPrintf(format, value[i]));
}
return ret;
}
// Return the values in a gesture property in one string. Used for touch
// logging.
std::string DumpGesturePropertyValue(GesturesProp* property) {
switch (property->type()) {
case GesturePropertyProvider::PT_INT:
return DumpArrayProperty(property->GetIntValue(), "%d");
break;
case GesturePropertyProvider::PT_SHORT:
return DumpArrayProperty(property->GetShortValue(), "%d");
break;
case GesturePropertyProvider::PT_BOOL:
return DumpArrayProperty(property->GetBoolValue(), "%d");
break;
case GesturePropertyProvider::PT_STRING:
return "\"" + property->GetStringValue() + "\"";
break;
case GesturePropertyProvider::PT_REAL:
return DumpArrayProperty(property->GetDoubleValue(), "%lf");
break;
default:
NOTREACHED();
break;
}
return std::string();
}
// Dump touch device property values to a string.
void DumpTouchDeviceStatus(GesturePropertyProvider* provider,
std::string* status) {
// We use DT_ALL since we want gesture property values for all devices that
// run with the gesture library, not just mice or touchpads.
std::vector<int> ids;
provider->GetDeviceIdsByType(DT_ALL, &ids);
// Dump the property names and values for each device.
for (size_t i = 0; i < ids.size(); ++i) {
std::vector<std::string> names = provider->GetPropertyNamesById(ids[i]);
status->append("\n");
status->append(base::StringPrintf("ID %d:\n", ids[i]));
status->append(base::StringPrintf(
"Device \'%s\':\n", provider->GetDeviceNameById(ids[i]).c_str()));
// Note that, unlike X11, we don't maintain the "atom" concept here.
// Therefore, the property name indices we output here shouldn't be treated
// as unique identifiers of the properties.
std::sort(names.begin(), names.end());
for (size_t j = 0; j < names.size(); ++j) {
status->append(base::StringPrintf("\t%s (%zu):", names[j].c_str(), j));
GesturesProp* property = provider->GetProperty(ids[i], names[j]);
status->append("\t" + DumpGesturePropertyValue(property) + '\n');
}
}
}
#endif #endif
scoped_ptr<EventConverterEvdev> CreateConverter( scoped_ptr<EventConverterEvdev> CreateConverter(
...@@ -408,6 +343,19 @@ void InputDeviceFactoryEvdev::GetTouchDeviceStatus( ...@@ -408,6 +343,19 @@ void InputDeviceFactoryEvdev::GetTouchDeviceStatus(
reply.Run(status.Pass()); 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() { base::WeakPtr<InputDeviceFactoryEvdev> InputDeviceFactoryEvdev::GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr(); return weak_ptr_factory_.GetWeakPtr();
} }
......
...@@ -34,6 +34,8 @@ class GesturePropertyProvider; ...@@ -34,6 +34,8 @@ class GesturePropertyProvider;
#endif #endif
typedef base::Callback<void(scoped_ptr<std::string>)> GetTouchDeviceStatusReply; typedef base::Callback<void(scoped_ptr<std::string>)> GetTouchDeviceStatusReply;
typedef base::Callback<void(scoped_ptr<std::vector<base::FilePath>>)>
GetTouchEventLogReply;
// Manager for event device objects. All device I/O starts here. // Manager for event device objects. All device I/O starts here.
class EVENTS_OZONE_EVDEV_EXPORT InputDeviceFactoryEvdev { class EVENTS_OZONE_EVDEV_EXPORT InputDeviceFactoryEvdev {
...@@ -64,6 +66,8 @@ class EVENTS_OZONE_EVDEV_EXPORT InputDeviceFactoryEvdev { ...@@ -64,6 +66,8 @@ class EVENTS_OZONE_EVDEV_EXPORT InputDeviceFactoryEvdev {
// Bits from InputController that have to be answered on IO. // Bits from InputController that have to be answered on IO.
void UpdateInputDeviceSettings(const InputDeviceSettingsEvdev& settings); void UpdateInputDeviceSettings(const InputDeviceSettingsEvdev& settings);
void GetTouchDeviceStatus(const GetTouchDeviceStatusReply& reply); void GetTouchDeviceStatus(const GetTouchDeviceStatusReply& reply);
void GetTouchEventLog(const base::FilePath& out_dir,
const GetTouchEventLogReply& reply);
base::WeakPtr<InputDeviceFactoryEvdev> GetWeakPtr(); base::WeakPtr<InputDeviceFactoryEvdev> GetWeakPtr();
......
...@@ -20,6 +20,15 @@ void ForwardGetTouchDeviceStatusReply( ...@@ -20,6 +20,15 @@ void ForwardGetTouchDeviceStatusReply(
reply_runner->PostTask(FROM_HERE, base::Bind(reply, base::Passed(&status))); reply_runner->PostTask(FROM_HERE, base::Bind(reply, base::Passed(&status)));
} }
void ForwardGetTouchEventLogReply(
scoped_refptr<base::SingleThreadTaskRunner> reply_runner,
const GetTouchEventLogReply& reply,
scoped_ptr<std::vector<base::FilePath>> log_paths) {
// Thread hop back to UI for reply.
reply_runner->PostTask(FROM_HERE,
base::Bind(reply, base::Passed(&log_paths)));
}
} // namespace } // namespace
InputDeviceFactoryEvdevProxy::InputDeviceFactoryEvdevProxy( InputDeviceFactoryEvdevProxy::InputDeviceFactoryEvdevProxy(
...@@ -88,4 +97,15 @@ void InputDeviceFactoryEvdevProxy::GetTouchDeviceStatus( ...@@ -88,4 +97,15 @@ void InputDeviceFactoryEvdevProxy::GetTouchDeviceStatus(
base::ThreadTaskRunnerHandle::Get(), reply))); base::ThreadTaskRunnerHandle::Get(), reply)));
} }
void InputDeviceFactoryEvdevProxy::GetTouchEventLog(
const base::FilePath& out_dir,
const GetTouchEventLogReply& reply) {
task_runner_->PostTask(
FROM_HERE,
base::Bind(&InputDeviceFactoryEvdev::GetTouchEventLog,
input_device_factory_, out_dir,
base::Bind(&ForwardGetTouchEventLogReply,
base::ThreadTaskRunnerHandle::Get(), reply)));
}
} // namespace ui } // namespace ui
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define UI_EVENTS_OZONE_EVDEV_INPUT_DEVICE_FACTORY_PROXY_EVDEV_H_ #define UI_EVENTS_OZONE_EVDEV_INPUT_DEVICE_FACTORY_PROXY_EVDEV_H_
#include <set> #include <set>
#include <vector>
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
...@@ -21,6 +22,8 @@ class InputDeviceFactoryEvdev; ...@@ -21,6 +22,8 @@ class InputDeviceFactoryEvdev;
struct InputDeviceSettingsEvdev; struct InputDeviceSettingsEvdev;
typedef base::Callback<void(scoped_ptr<std::string>)> GetTouchDeviceStatusReply; typedef base::Callback<void(scoped_ptr<std::string>)> GetTouchDeviceStatusReply;
typedef base::Callback<void(scoped_ptr<std::vector<base::FilePath>>)>
GetTouchEventLogReply;
// Thread safe proxy for InputDeviceFactoryEvdev. // Thread safe proxy for InputDeviceFactoryEvdev.
// //
...@@ -44,6 +47,8 @@ class EVENTS_OZONE_EVDEV_EXPORT InputDeviceFactoryEvdevProxy { ...@@ -44,6 +47,8 @@ class EVENTS_OZONE_EVDEV_EXPORT InputDeviceFactoryEvdevProxy {
void EnableInternalKeyboard(); void EnableInternalKeyboard();
void UpdateInputDeviceSettings(const InputDeviceSettingsEvdev& settings); void UpdateInputDeviceSettings(const InputDeviceSettingsEvdev& settings);
void GetTouchDeviceStatus(const GetTouchDeviceStatusReply& reply); void GetTouchDeviceStatus(const GetTouchDeviceStatusReply& reply);
void GetTouchEventLog(const base::FilePath& out_dir,
const GetTouchEventLogReply& reply);
private: private:
scoped_refptr<base::SingleThreadTaskRunner> task_runner_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/events/ozone/evdev/libgestures_glue/gesture_feedback.h"
#include <time.h>
#include "base/bind.h"
#include "base/command_line.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/process/launch.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/threading/worker_pool.h"
#include "ui/events/ozone/evdev/libgestures_glue/gesture_property_provider.h"
namespace ui {
namespace {
// Binary paths.
const char kGzipCommand[] = "/bin/gzip";
const char kDateCommand[] = "/bin/date";
const size_t kTouchLogTimestampMaxSize = 80;
// Return the values in an array in one string. Used for touch logging.
template <typename T>
std::string DumpArrayProperty(const std::vector<T>& value, const char* format) {
std::string ret;
for (size_t i = 0; i < value.size(); ++i) {
if (i > 0)
ret.append(", ");
ret.append(base::StringPrintf(format, value[i]));
}
return ret;
}
// Return the values in a gesture property in one string. Used for touch
// logging.
std::string DumpGesturePropertyValue(GesturesProp* property) {
switch (property->type()) {
case GesturePropertyProvider::PT_INT:
return DumpArrayProperty(property->GetIntValue(), "%d");
break;
case GesturePropertyProvider::PT_SHORT:
return DumpArrayProperty(property->GetShortValue(), "%d");
break;
case GesturePropertyProvider::PT_BOOL:
return DumpArrayProperty(property->GetBoolValue(), "%d");
break;
case GesturePropertyProvider::PT_STRING:
return "\"" + property->GetStringValue() + "\"";
break;
case GesturePropertyProvider::PT_REAL:
return DumpArrayProperty(property->GetDoubleValue(), "%lf");
break;
default:
NOTREACHED();
break;
}
return std::string();
}
// 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.
std::string GetCurrentTimeForLogging() {
time_t rawtime;
struct tm timeinfo;
char buffer[kTouchLogTimestampMaxSize];
time(&rawtime);
if (!localtime_r(&rawtime, &timeinfo)) {
PLOG(ERROR) << "localtime_r failed";
return "";
}
if (!strftime(buffer, kTouchLogTimestampMaxSize, "%Y%m%d-%H%M%S", &timeinfo))
return "";
return std::string(buffer);
}
// Canonize the device name for logging.
std::string GetCanonicalDeviceName(const std::string& name) {
std::string ret(name);
for (size_t i = 0; i < ret.size(); ++i)
if (!IsAsciiAlpha(ret[i]))
ret[i] = '_';
return ret;
}
// Name event logs in a way that is compatible with existing toolchain.
std::string GenerateEventLogName(GesturePropertyProvider* provider,
const base::FilePath& out_dir,
const std::string& prefix,
const std::string& now,
int id) {
return out_dir.value() + "/" + prefix + now + "." + base::IntToString(id) +
"." + GetCanonicalDeviceName(provider->GetDeviceNameById(id));
}
// Set the logging properties to dump event logs.
void StartToDumpEventLog(GesturePropertyProvider* provider,
const int device_id) {
// Dump gesture log.
GesturesProp* property = provider->GetProperty(device_id, "Log Path");
property->SetStringValue(kTouchpadGestureLogPath);
property = provider->GetProperty(device_id, "Logging Notify");
property->SetIntValue(std::vector<int>(1, 1));
// Dump evdev log.
property = provider->GetProperty(device_id, "Dump Debug Log");
property->SetBoolValue(std::vector<bool>(1, true));
}
} // namespace
// Dump touch device property values to a string.
void DumpTouchDeviceStatus(GesturePropertyProvider* provider,
std::string* status) {
// We use DT_ALL since we want gesture property values for all devices that
// run with the gesture library, not just mice or touchpads.
std::vector<int> ids;
provider->GetDeviceIdsByType(DT_ALL, &ids);
// Dump the property names and values for each device.
for (size_t i = 0; i < ids.size(); ++i) {
std::vector<std::string> names = provider->GetPropertyNamesById(ids[i]);
status->append("\n");
status->append(base::StringPrintf("ID %d:\n", ids[i]));
status->append(base::StringPrintf(
"Device \'%s\':\n", provider->GetDeviceNameById(ids[i]).c_str()));
// Note that, unlike X11, we don't maintain the "atom" concept here.
// Therefore, the property name indices we output here shouldn't be treated
// as unique identifiers of the properties.
std::sort(names.begin(), names.end());
for (size_t j = 0; j < names.size(); ++j) {
status->append(base::StringPrintf("\t%s (%zu):", names[j].c_str(), j));
GesturesProp* property = provider->GetProperty(ids[i], names[j]);
status->append("\t" + DumpGesturePropertyValue(property) + '\n');
}
}
}
// Dump touch event logs.
void DumpTouchEventLog(GesturePropertyProvider* provider,
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(
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.
StartToDumpEventLog(provider, ids[i]);
// 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 */);
}
} // namespace ui
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_EVENTS_OZONE_EVDEV_LIBGESTURES_GLUE_GESTURE_FEEDBACK_H_
#define UI_EVENTS_OZONE_EVDEV_LIBGESTURES_GLUE_GESTURE_FEEDBACK_H_
#include <string>
#include <vector>
#include "base/callback.h"
#include "base/files/file_util.h"
#include "base/memory/scoped_vector.h"
namespace ui {
// Touch event log paths.
const char kTouchpadGestureLogPath[] =
"/home/chronos/user/log/touchpad_activity.txt";
const char kTouchpadEvdevLogPath[] =
"/home/chronos/user/log/cmt_input_events.dat";
class GesturePropertyProvider;
typedef base::Callback<void(scoped_ptr<std::vector<base::FilePath>>)>
GetTouchEventLogReply;
// Utility functions for generating gesture related logs. These logs will be
// included in user feedback reports.
void DumpTouchDeviceStatus(GesturePropertyProvider* provider,
std::string* status);
void DumpTouchEventLog(GesturePropertyProvider* provider,
const base::FilePath& out_dir,
scoped_ptr<std::vector<base::FilePath>> log_paths,
const GetTouchEventLogReply& reply);
} // namespace ui
#endif // UI_EVENTS_OZONE_EVDEV_LIBGESTURES_GLUE_GESTURE_FEEDBACK_H_
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/strings/stringize_macros.h" #include "base/strings/stringize_macros.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "ui/events/ozone/evdev/libgestures_glue/gesture_feedback.h"
#include "ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.h" #include "ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.h"
// Severity level for general info logging purpose. // Severity level for general info logging purpose.
...@@ -556,6 +557,12 @@ std::ostream& operator<<(std::ostream& out, ...@@ -556,6 +557,12 @@ std::ostream& operator<<(std::ostream& out,
return out << s; return out << s;
} }
// A relay function that dumps evdev log to a place that we have access to
// (the default directory is inaccessible without X11).
void DumpTouchEvdevDebugLog(void* data) {
Event_Dump_Debug_Log_To(data, ui::kTouchpadEvdevLogPath);
}
} // namespace } // namespace
// GesturesProp logging function. // GesturesProp logging function.
...@@ -1426,8 +1433,8 @@ bool GesturesPropFunctionsWrapper::InitializeDeviceProperties( ...@@ -1426,8 +1433,8 @@ bool GesturesPropFunctionsWrapper::InitializeDeviceProperties(
// set. // set.
GesturesProp* dump_debug_log_prop = CreateBoolSingle( GesturesProp* dump_debug_log_prop = CreateBoolSingle(
device_data, "Dump Debug Log", &properties->dump_debug_log, false); device_data, "Dump Debug Log", &properties->dump_debug_log, false);
RegisterHandlers( RegisterHandlers(device_data, dump_debug_log_prop, device, NULL,
device_data, dump_debug_log_prop, device, NULL, Event_Dump_Debug_Log); DumpTouchEvdevDebugLog);
// Whether to do the gesture recognition or just passing the multi-touch data // Whether to do the gesture recognition or just passing the multi-touch data
// to upper layers. // to upper layers.
......
...@@ -100,6 +100,8 @@ ...@@ -100,6 +100,8 @@
'evdev/libgestures_glue/event_reader_libevdev_cros.h', 'evdev/libgestures_glue/event_reader_libevdev_cros.h',
'evdev/libgestures_glue/gesture_interpreter_libevdev_cros.cc', 'evdev/libgestures_glue/gesture_interpreter_libevdev_cros.cc',
'evdev/libgestures_glue/gesture_interpreter_libevdev_cros.h', 'evdev/libgestures_glue/gesture_interpreter_libevdev_cros.h',
'evdev/libgestures_glue/gesture_feedback.cc',
'evdev/libgestures_glue/gesture_feedback.h',
'evdev/libgestures_glue/gesture_logging.cc', 'evdev/libgestures_glue/gesture_logging.cc',
'evdev/libgestures_glue/gesture_logging.h', 'evdev/libgestures_glue/gesture_logging.h',
'evdev/libgestures_glue/gesture_property_provider.cc', 'evdev/libgestures_glue/gesture_property_provider.cc',
......
...@@ -37,6 +37,8 @@ class StubInputController : public InputController { ...@@ -37,6 +37,8 @@ class StubInputController : public InputController {
void SetPrimaryButtonRight(bool right) override; void SetPrimaryButtonRight(bool right) override;
void SetTapToClickPaused(bool state) override; void SetTapToClickPaused(bool state) override;
void GetTouchDeviceStatus(const GetTouchDeviceStatusReply& reply) override; void GetTouchDeviceStatus(const GetTouchDeviceStatusReply& reply) override;
void GetTouchEventLog(const base::FilePath& out_dir,
const GetTouchEventLogReply& reply) override;
void DisableInternalTouchpad() override; void DisableInternalTouchpad() override;
void EnableInternalTouchpad() override; void EnableInternalTouchpad() override;
void DisableInternalKeyboardExceptKeys( void DisableInternalKeyboardExceptKeys(
...@@ -130,6 +132,12 @@ void StubInputController::GetTouchDeviceStatus( ...@@ -130,6 +132,12 @@ void StubInputController::GetTouchDeviceStatus(
reply.Run(scoped_ptr<std::string>(new std::string)); reply.Run(scoped_ptr<std::string>(new std::string));
} }
void StubInputController::GetTouchEventLog(const base::FilePath& out_dir,
const GetTouchEventLogReply& reply) {
reply.Run(
scoped_ptr<std::vector<base::FilePath>>(new std::vector<base::FilePath>));
}
void StubInputController::DisableInternalTouchpad() { void StubInputController::DisableInternalTouchpad() {
NOTIMPLEMENTED(); NOTIMPLEMENTED();
} }
......
...@@ -7,8 +7,10 @@ ...@@ -7,8 +7,10 @@
#include <set> #include <set>
#include <string> #include <string>
#include <vector>
#include "base/callback.h" #include "base/callback.h"
#include "base/files/file_path.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "ui/ozone/ozone_export.h" #include "ui/ozone/ozone_export.h"
...@@ -30,6 +32,8 @@ class OZONE_EXPORT InputController { ...@@ -30,6 +32,8 @@ class OZONE_EXPORT InputController {
public: public:
typedef base::Callback<void(scoped_ptr<std::string>)> typedef base::Callback<void(scoped_ptr<std::string>)>
GetTouchDeviceStatusReply; GetTouchDeviceStatusReply;
typedef base::Callback<void(scoped_ptr<std::vector<base::FilePath>>)>
GetTouchEventLogReply;
InputController() {} InputController() {}
virtual ~InputController() {} virtual ~InputController() {}
...@@ -62,6 +66,8 @@ class OZONE_EXPORT InputController { ...@@ -62,6 +66,8 @@ class OZONE_EXPORT InputController {
// Touch log collection. // Touch log collection.
virtual void GetTouchDeviceStatus(const GetTouchDeviceStatusReply& reply) = 0; virtual void GetTouchDeviceStatus(const GetTouchDeviceStatusReply& reply) = 0;
virtual void GetTouchEventLog(const base::FilePath& out_dir,
const GetTouchEventLogReply& reply) = 0;
// Temporarily enable/disable Tap-to-click. Used to enhance the user // Temporarily enable/disable Tap-to-click. Used to enhance the user
// experience in some use cases (e.g., typing, watching video). // experience in some use cases (e.g., typing, watching video).
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment