• 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_TOKENIZED_LOG_MESSAGE_PARSER_H_
18 #define CHRE_TOKENIZED_LOG_MESSAGE_PARSER_H_
19 
20 #include <memory>
21 #include "chre_host/daemon_base.h"
22 #include "chre_host/log_message_parser_base.h"
23 
24 #include "pw_tokenizer/detokenize.h"
25 
26 using pw::tokenizer::DetokenizedString;
27 using pw::tokenizer::Detokenizer;
28 
29 namespace android {
30 namespace chre {
31 
32 class ChreTokenizedLogMessageParser : public ChreLogMessageParserBase {
33  public:
init()34   virtual bool init() override final {
35     mDetokenizer = logDetokenizerInit();
36     return mDetokenizer != nullptr;
37   }
38 
log(const uint8_t * logBuffer,size_t logBufferSize)39   virtual void log(const uint8_t *logBuffer,
40                    size_t logBufferSize) override final {
41     parseAndEmitTokenizedLogMessages(logBuffer, logBufferSize,
42                                      mDetokenizer.get());
43   }
44 
logV2(const uint8_t * logBuffer,size_t logBufferSize)45   void logV2(const uint8_t *logBuffer, size_t logBufferSize) override {
46     // TODO(b/172654554): Modify tokenized logging to only support v2 logs.
47   }
48 
49  private:
50   std::unique_ptr<Detokenizer> mDetokenizer;
51 
52   /**
53    * Initialize the Log Detokenizer
54    *
55    * The log detokenizer reads a binary database file that contains key value
56    * pairs of hash-keys <--> Decoded log messages, and creates an instance
57    * of the Detokenizer.
58    *
59    * @return an instance of the Detokenizer
60    */
logDetokenizerInit()61   std::unique_ptr<Detokenizer> logDetokenizerInit() {
62     constexpr const char kLogDatabaseFilePath[] =
63         "/vendor/etc/chre/libchre_log_database.bin";
64     std::vector<uint8_t> tokenData;
65     if (ChreDaemonBase::readFileContents(kLogDatabaseFilePath, &tokenData)) {
66       pw::tokenizer::TokenDatabase database =
67           pw::tokenizer::TokenDatabase::Create(tokenData);
68       if (database.ok()) {
69         return std::make_unique<Detokenizer>(database);
70       } else {
71         LOGE("CHRE Token database creation not OK");
72       }
73     } else {
74       LOGE("Failed to read CHRE Token database file");
75     }
76     return std::unique_ptr<Detokenizer>(nullptr);
77   }
78 
79   // Log messages are routed through ashLog if tokenized logging
80   // is disabled, so only parse tokenized log messages here.
parseAndEmitTokenizedLogMessages(const uint8_t * message,unsigned int messageLen,const Detokenizer * detokenizer)81   void parseAndEmitTokenizedLogMessages(const uint8_t *message,
82                                         unsigned int messageLen,
83                                         const Detokenizer *detokenizer) {
84     if (detokenizer != nullptr) {
85       // TODO: Pull out common code from the tokenized/standard log
86       // parser functions when we implement batching for tokenized
87       // logs (b/148873804)
88       constexpr size_t kLogMessageHeaderSize =
89           1 /*logLevel*/ + sizeof(uint64_t) /*timestamp*/;
90       uint8_t level = *message;
91       ++message;
92 
93       uint64_t timestampNanos;
94       memcpy(&timestampNanos, message, sizeof(uint64_t));
95       timestampNanos = le64toh(timestampNanos);
96       message += sizeof(uint64_t);
97 
98       DetokenizedString detokenizedLog =
99           detokenizer->Detokenize(message, messageLen - kLogMessageHeaderSize);
100       std::string decodedLog = detokenizedLog.BestStringWithErrors();
101       uint32_t timestampMillis =
102           timestampNanos / chre::kOneMillisecondInNanoseconds;
103       emitLogMessage(level, timestampNanos, decodedLog.c_str());
104     } else {
105       // log an error and risk log spam? fail silently? log once?
106     }
107   }
108 };
109 
110 }  // namespace chre
111 }  // namespace android
112 
113 #endif  // CHRE_TOKENIZED_LOG_MESSAGE_PARSER_H_