1 /*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "src/trace_processor/importers/android_bugreport/android_log_event.h"
18
19 #include <algorithm>
20 #include <cstddef>
21 #include <cstdint>
22 #include <optional>
23 #include <vector>
24
25 #include "perfetto/ext/base/string_utils.h"
26 #include "perfetto/ext/base/string_view.h"
27
28 namespace perfetto::trace_processor {
29
30 namespace {
FindLines(const uint8_t * data,size_t size)31 std::vector<base::StringView> FindLines(const uint8_t* data, size_t size) {
32 std::vector<base::StringView> lines;
33 const char* line_start = reinterpret_cast<const char*>(data);
34 const char* ptr = line_start;
35 const char* const end = ptr + size;
36
37 for (; ptr != end; ++ptr) {
38 if (*ptr == '\n') {
39 lines.emplace_back(line_start, static_cast<size_t>(ptr - line_start));
40 line_start = ptr + 1;
41 }
42 }
43 return lines;
44 }
45 } // namespace
46
47 // static
DetectFormat(base::StringView line)48 std::optional<AndroidLogEvent::Format> AndroidLogEvent::DetectFormat(
49 base::StringView line) {
50 auto p = base::SplitString(line.ToStdString(), " ");
51 if (p.size() < 5)
52 return std::nullopt;
53
54 if (p[0].size() != 5 || p[0][2] != '-')
55 return std::nullopt;
56
57 if (p[1].size() < 10 || p[1][2] != ':' || p[1][5] != ':' || p[1][8] != '.')
58 return std::nullopt;
59
60 if (p[4].size() == 1 && p[4][0] >= 'A' && p[4][0] <= 'Z')
61 return Format::kPersistentLog;
62
63 if (p[5].size() == 1 && p[5][0] >= 'A' && p[5][0] <= 'Z')
64 return Format::kBugreport;
65
66 return std::nullopt;
67 }
68
69 // static
IsAndroidLogcat(const uint8_t * data,size_t size)70 bool AndroidLogEvent::IsAndroidLogcat(const uint8_t* data, size_t size) {
71 // Make sure we don't split an entire file into lines.
72 constexpr size_t kMaxGuessAndroidLogEventLookAhead = 4096;
73 std::vector<base::StringView> lines =
74 FindLines(data, std::min(size, kMaxGuessAndroidLogEventLookAhead));
75
76 auto is_marker = [](base::StringView line) {
77 return line.StartsWith("--------");
78 };
79 auto it = std::find_if_not(lines.begin(), lines.end(), is_marker);
80
81 return it != lines.end() && DetectFormat(*it).has_value();
82 }
83
84 } // namespace perfetto::trace_processor
85