• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 CHRE_LOG_MESSAGE_PARSER_H_
18 #define CHRE_LOG_MESSAGE_PARSER_H_
19 
20 #include <endian.h>
21 #include <cinttypes>
22 #include <memory>
23 #include "chre/util/time.h"
24 #include "chre_host/bt_snoop_log_parser.h"
25 
26 #include <android/log.h>
27 
28 #include "pw_tokenizer/detokenize.h"
29 
30 using pw::tokenizer::DetokenizedString;
31 using pw::tokenizer::Detokenizer;
32 
33 namespace android {
34 namespace chre {
35 
36 class LogMessageParser {
37  public:
38   LogMessageParser();
39 
40   /**
41    * Allow the user to enable verbose logging during instantiation.
42    */
LogMessageParser(bool enableVerboseLogging)43   LogMessageParser(bool enableVerboseLogging)
44       : mVerboseLoggingEnabled(enableVerboseLogging) {}
45 
46   /**
47    * Initializes the log message parser by reading the log token database,
48    * and instantiates a detokenizer to handle encoded log messages.
49    */
50   void init();
51 
52   //! Logs from a log buffer containing one or more log messages (version 1)
53   void log(const uint8_t *logBuffer, size_t logBufferSize);
54 
55   //! Logs from a log buffer containing one or more log messages (version 2)
56   void logV2(const uint8_t *logBuffer, size_t logBufferSize,
57              uint32_t numLogsDropped);
58 
59   /**
60    * With verbose logging enabled (either during instantiation via a
61    * constructor argument, or during compilation via N_DEBUG being defined
62    * and set), dump a binary log buffer to a human-readable string.
63    *
64    * @param logBuffer buffer to be output as a string
65    * @param logBufferSize size of the buffer being output
66    */
67   void dump(const uint8_t *logBuffer, size_t logBufferSize);
68 
69  private:
70   static constexpr char kHubLogFormatStr[] = "@ %3" PRIu32 ".%03" PRIu32 ": %s";
71 
72   enum LogLevel : uint8_t {
73     ERROR = 1,
74     WARNING = 2,
75     INFO = 3,
76     DEBUG = 4,
77     VERBOSE = 5,
78   };
79 
80   //! See host_messages.fbs for the definition of this struct.
81   struct LogMessage {
82     enum LogLevel logLevel;
83     uint64_t timestampNanos;
84     char logMessage[];
85   } __attribute__((packed));
86 
87   //! See host_messages.fbs for the definition of this struct.
88   struct LogMessageV2 {
89     uint8_t metadata;
90     uint32_t timestampMillis;
91     char logMessage[];
92   } __attribute__((packed));
93 
94   /**
95    * Helper struct for readable decoding of a tokenized log message payload,
96    * essentially encapsulates the 'logMessage' field in LogMessageV2 for an
97    * encoded log.
98    */
99   struct EncodedLog {
100     uint8_t size;
101     char data[];
102   };
103 
104   bool mVerboseLoggingEnabled;
105 
106   //! The number of logs dropped since CHRE start
107   uint32_t mNumLogsDropped = 0;
108 
109   std::unique_ptr<Detokenizer> mDetokenizer;
110 
111   static android_LogPriority chreLogLevelToAndroidLogPriority(uint8_t level);
112 
113   BtSnoopLogParser mBtLogParser;
114 
115   void updateAndPrintDroppedLogs(uint32_t numLogsDropped);
116 
117   //! Method for parsing unencoded (string) log messages.
118   void parseAndEmitLogMessage(const LogMessageV2 *message);
119 
120   /**
121    * Parses and emits an encoded log message while also returning the size of
122    * the parsed message for buffer index bookkeeping.
123    *
124    * @return Size of the encoded log message payload. Note that the size
125    * includes the 1 byte header that we use for encoded log messages to track
126    * message size.
127    */
128   size_t parseAndEmitTokenizedLogMessageAndGetSize(const LogMessageV2 *message);
129 
130   void emitLogMessage(uint8_t level, uint32_t timestampMillis,
131                       const char *logMessage);
132 
133   /**
134    * Initialize the Log Detokenizer
135    *
136    * The log detokenizer reads a binary database file that contains key value
137    * pairs of hash-keys <--> Decoded log messages, and creates an instance
138    * of the Detokenizer.
139    *
140    * @return an instance of the Detokenizer
141    */
142   std::unique_ptr<Detokenizer> logDetokenizerInit();
143 
144   /**
145    * Helper function to get the logging level from the log message metadata.
146    *
147    * @param metadata A byte from the log message payload containing the
148    *        log level and encoding information.
149    *
150    * @return The log level of the current log message.
151    */
152   uint8_t getLogLevelFromMetadata(uint8_t metadata);
153 
154   /**
155    * Helper function to check the metadata whether the log message was encoded.
156    *
157    * @param metadata A byte from the log message payload containing the
158    *        log level and encoding information.
159    *
160    * @return true if an encoding was used on the log message payload.
161    */
162   bool isLogMessageEncoded(uint8_t metadata);
163 
164   /**
165    * Helper function to check the metadata whether the log message is a BT snoop
166    * log.
167    *
168    * @param metadata A byte from the log message payload containing the
169    *        log level and log type information.
170    *
171    * @return true if the log message type is BT Snoop log.
172    */
173   bool isBtSnoopLogMessage(uint8_t metadata);
174 };
175 
176 }  // namespace chre
177 }  // namespace android
178 
179 #endif  // CHRE_LOG_MESSAGE_PARSER_H_
180