File: touch_log_source.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (186 lines) | stat: -rw-r--r-- 7,350 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ash/system_logs/touch_log_source.h"

#include <stddef.h>

#include "base/check_op.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/process/launch.h"
#include "base/strings/string_util.h"
#include "base/task/thread_pool.h"
#include "chromeos/ash/components/login/login_state/login_state.h"
#include "content/public/browser/browser_thread.h"
#include "ui/ozone/public/input_controller.h"
#include "ui/ozone/public/ozone_platform.h"

using content::BrowserThread;

namespace {

// The prefix "hack-33025" was historically chosen in http://crbug.com/139715.
// We continue to go with it in order to be compatible with the existing touch
// log processing toolchain.
const char kDeviceStatusLogDataKey[] = "hack-33025-touchpad";
const char kTouchpadEventLogDataKey[] = "hack-33025-touchpad_activity";
const char kTouchscreenEventLogDataKey[] = "hack-33025-touchscreen_activity";

// Directory for temp touch event logs.
constexpr char kTouchEventLogDir[] = "/home/chronos/user/log";
constexpr char kNotLoggedInTouchEventLogDir[] = "/var/log/chrome";

// Prefixes of touch event logs.
const char kTouchpadGestureLogPrefix[] = "touchpad_activity_";
const char kTouchscreenLogPrefix[] = "evdev_input_events_";
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(const std::vector<base::FilePath>& log_paths) {
  for (const base::FilePath& path : log_paths)
    base::DeleteFile(path);
}

// 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 (base::StartsWith(basename, prefix, base::CompareCase::SENSITIVE)) {
      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,
                  const std::vector<base::FilePath>& log_paths) {
  // Combine logs with a command line call that tars them up and uuencode the
  // result in one string.
  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));

  base::CommandLine ts_command =
      base::CommandLine(base::FilePath(kShellCommand));
  ts_command.AppendArg("-c");

  // Make a list that contains touchscreen event logs only.
  const std::string touchscreen_log_list = GetEventLogListOfOnePrefix(
      log_paths, kTouchscreenLogPrefix, kMaxDeviceTouchEventLogs);
  ts_command.AppendArg(std::string(kTarCommand) + touchscreen_log_list +
                       " 2>/dev/null | " + kUuencodeCommand +
                       " -m touchscreen_activity_log.tar");

  commands.push_back(std::make_pair(kTouchscreenEventLogDataKey, ts_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.
  base::ThreadPool::PostTask(
      FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
      base::BindOnce(CleanupEventLog, log_paths));
}

// Callback for handing the outcome of GetTouchEventLog().
//
// This is the end of the whole touch log collection process.
void OnEventLogCollected(
    std::unique_ptr<system_logs::SystemLogsResponse> response,
    system_logs::SysLogsSourceCallback callback,
    const std::vector<base::FilePath>& log_paths) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  system_logs::SystemLogsResponse* response_ptr = response.get();
  base::ThreadPool::PostTaskAndReply(
      FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
      base::BindOnce(&PackEventLog, response_ptr, log_paths),
      base::BindOnce(std::move(callback), std::move(response)));
}

// 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(
    std::unique_ptr<system_logs::SystemLogsResponse> response,
    system_logs::SysLogsSourceCallback callback,
    const std::string& log) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  (*response)[kDeviceStatusLogDataKey] = log;

  // Collect touch event logs.
  // The user-specific log directory will not exist if we are not logged in
  // yet, so choose the location based on that.
  base::FilePath base_log_path(ash::LoginState::Get()->IsUserLoggedIn()
                                   ? kTouchEventLogDir
                                   : kNotLoggedInTouchEventLogDir);
  ui::InputController* input_controller =
      ui::OzonePlatform::GetInstance()->GetInputController();
  input_controller->GetTouchEventLog(
      base_log_path, base::BindOnce(&OnEventLogCollected, std::move(response),
                                    std::move(callback)));
}

}  // namespace

namespace system_logs {

void TouchLogSource::Fetch(SysLogsSourceCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(!callback.is_null());

  // Collect touch device status logs.
  auto response = std::make_unique<SystemLogsResponse>();
  ui::InputController* input_controller =
      ui::OzonePlatform::GetInstance()->GetInputController();
  input_controller->GetTouchDeviceStatus(base::BindOnce(
      &OnStatusLogCollected, std::move(response), std::move(callback)));
}

}  // namespace system_logs