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