xref: /aosp_15_r20/external/perfetto/src/trace_processor/importers/android_bugreport/android_log_event.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
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