1 /*
2  * Copyright (C) 2018 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 #ifndef SRC_TRACED_PROBES_ANDROID_LOG_ANDROID_LOG_DATA_SOURCE_H_
18 #define SRC_TRACED_PROBES_ANDROID_LOG_ANDROID_LOG_DATA_SOURCE_H_
19 
20 #include <unordered_map>
21 #include <unordered_set>
22 #include <vector>
23 
24 #include "perfetto/ext/base/paged_memory.h"
25 #include "perfetto/ext/base/scoped_file.h"
26 #include "perfetto/ext/base/string_view.h"
27 #include "perfetto/ext/base/unix_socket.h"
28 #include "perfetto/ext/base/weak_ptr.h"
29 #include "perfetto/tracing/core/forward_decls.h"
30 #include "src/traced/probes/probes_data_source.h"
31 
32 namespace perfetto {
33 
34 class TraceWriter;
35 namespace base {
36 class TaskRunner;
37 }
38 
39 namespace protos {
40 namespace pbzero {
41 class AndroidLogPacket;
42 class AndroidLogPacket_LogEvent;
43 }  // namespace pbzero
44 }  // namespace protos
45 
46 class AndroidLogDataSource : public ProbesDataSource {
47  public:
48   static const ProbesDataSource::Descriptor descriptor;
49 
50   struct Stats {
51     uint64_t num_total = 0;    // Total number of log entries received.
52     uint64_t num_failed = 0;   // Parser failures.
53     uint64_t num_skipped = 0;  // Messages skipped due to filters.
54   };
55 
56   // One EventFormat == one line of /system/etc/event-log-tags.
57   struct EventFormat {
58     std::string name;
59     std::vector<std::string> fields;
60   };
61 
62   AndroidLogDataSource(DataSourceConfig,
63                        base::TaskRunner*,
64                        TracingSessionID,
65                        std::unique_ptr<TraceWriter> writer);
66 
67   ~AndroidLogDataSource() override;
68 
69   // ProbesDataSource implementation.
70   void Start() override;
71   void Flush(FlushRequestID, std::function<void()> callback) override;
72 
73   // Reads the contents of /system/etc/event-log-tags. Virtual for testing.
74   virtual std::string ReadEventLogDefinitions();
75 
76   // Connects to the /dev/socket/logdr socket. Virtual for testing.
77   virtual base::UnixSocketRaw ConnectLogdrSocket();
78 
79   // Parses the contents of ReadEventLogDefinitions().
80   void ParseEventLogDefinitions();
81 
82   const EventFormat* GetEventFormat(int id) const;
stats()83   const Stats& stats() const { return stats_; }
84   base::WeakPtr<AndroidLogDataSource> GetWeakPtr() const;
85 
86  private:
87   void EnableSocketWatchTask(bool);
88   void OnSocketDataAvailable();
89   void ReadLogSocket();
90 
91   // Parses one line of /system/etc/event-log-tags.
92   bool ParseEventLogDefinitionLine(char* line, size_t len);
93 
94   // Parses a textual (i.e. tag + message) event, which is the majority of
95   // log events. All buffers but the LID_EVENTS contain text events.
96   // If parsing fails returns false and leaves the |out_evt| field unset.
97   // If parsing succeeds returns true and:
98   // - If the event is skipped due to filters, |out_evt| is left unset.
99   // - If a new event is aded to the packet, |out_evt| is set to that.
100   bool ParseTextEvent(const char* start,
101                       const char* end,
102                       protos::pbzero::AndroidLogPacket* packet,
103                       protos::pbzero::AndroidLogPacket_LogEvent** out_evt);
104 
105   // Parses a binary event from the "events" buffer.
106   // If parsing fails returns false and leaves the |out_evt| field unset.
107   // If parsing succeeds returns true and:
108   // - If the event is skipped due to filters, |out_evt| is left unset.
109   // - If a new event is aded to the packet, |out_evt| is set to that.
110   bool ParseBinaryEvent(const char* start,
111                         const char* end,
112                         protos::pbzero::AndroidLogPacket* packet,
113                         protos::pbzero::AndroidLogPacket_LogEvent** out_evt);
114 
115   base::TaskRunner* const task_runner_;
116   std::unique_ptr<TraceWriter> writer_;
117   base::UnixSocketRaw logdr_sock_;
118 
119   // Config parameters coming from the data source section in the trace config.
120   int min_prio_ = 0;
121   std::string mode_;
122 
123   // For filtering events based on tags.
124   std::unordered_set<base::StringView> filter_tags_;
125   std::vector<char> filter_tags_strbuf_;
126 
127   // Lookup map for binary events (log_id=EVENTS). Translates a numeric id into
128   // a corresponding field descriptor. This is generated by parsing
129   // /system/etc/event-log-tags when starting.
130   std::unordered_map<int, EventFormat> event_formats_;
131 
132   // Buffer used for parsing. It's safer (read: fails sooner) than using the
133   // stack, due to red zones around the boundaries.
134   base::PagedMemory buf_;
135   Stats stats_;
136   bool fd_watch_task_enabled_ = false;
137 
138   base::WeakPtrFactory<AndroidLogDataSource> weak_factory_;  // Keep last.
139 };
140 
141 }  // namespace perfetto
142 
143 #endif  // SRC_TRACED_PROBES_ANDROID_LOG_ANDROID_LOG_DATA_SOURCE_H_
144