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_PLATFORM_LOG_BUFFER_MANAGER_BUFFER_H_
18 #define CHRE_PLATFORM_LOG_BUFFER_MANAGER_BUFFER_H_
19 
20 #include "chre/platform/assert.h"
21 #include "chre/platform/condition_variable.h"
22 #include "chre/platform/mutex.h"
23 #include "chre/platform/shared/log_buffer.h"
24 #include "chre/util/singleton.h"
25 #include "chre_api/chre/re.h"
26 
27 #ifndef CHRE_LOG_BUFFER_DATA_SIZE
28 #define CHRE_LOG_BUFFER_DATA_SIZE CHRE_MESSAGE_TO_HOST_MAX_SIZE
29 #endif
30 
31 namespace chre {
32 
33 /**
34  * A log buffer manager that platform code can use to buffer logs when the host
35  * is not available and then send them off when the host becomes available. Uses
36  * the LogBuffer API to buffer the logs in memory.
37  *
38  * The manager uses two LogBuffer objects to handle flushing logs to the host at
39  * the same time as handling more incoming logs. Incoming logs are always put
40  * into the primary buffer first. The secondary buffer takes all the logs
41  * currently in the primary buffer before the logs are sent off to the host
42  * because the secondary buffer is the memory location passed to the
43  * HostLink::sendLogs API. Logs are also flushed to the secondary buffer from
44  * the primary buffer when the primary buffer fills up.
45  *
46  * When implementing this class in platform code. Use the singleton defined
47  * after this class and pass logs to the log or logVa methods. Initialize the
48  * singleton before using it. Call the onLogsSentToHost callback immediately
49  * after sending logs to the host.
50  */
51 class LogBufferManager : public LogBufferCallbackInterface {
52  public:
LogBufferManager(uint8_t * primaryBufferData,uint8_t * secondaryBufferData,size_t bufferSize)53   LogBufferManager(uint8_t *primaryBufferData, uint8_t *secondaryBufferData,
54                    size_t bufferSize)
55       : mPrimaryLogBuffer(this, primaryBufferData, bufferSize),
56         mSecondaryLogBuffer(nullptr /* callback */, secondaryBufferData,
57                             bufferSize) {}
58 
59   ~LogBufferManager() = default;
60 
61   /**
62    * Logs message with printf-style arguments. No trailing newline is required
63    * for this method.
64    */
65   void log(chreLogLevel logLevel, const char *formatStr, ...);
66 
67   /**
68    * Logs message with printf-style arguments. No trailing newline is required
69    * for this method. Uses va_list parameter instead of ...
70    */
71   void logVa(chreLogLevel logLevel, const char *formatStr, va_list args);
72 
73   /**
74    * Overrides required method from LogBufferCallbackInterface.
75    */
76   void onLogsReady() final;
77 
78   /**
79    * Flush any logs that might be in the default log buffer.
80    */
81   void flushLogs();
82 
83   /**
84    * The platform code should call this method after the logs have been sent to
85    * the host to signal that more logs can be sent to the host when ready. The
86    * caller must indicate whether the platform could successfully deliver the
87    * logs as well.
88    *
89    * @param success true if the logs were sent through to host successfully.
90    */
91   void onLogsSentToHost(bool success);
92 
93   /**
94    * Loop that waits on the conditions for sending logs to host to be met and
95    * sends the logs to the host if so. This method never exits. Should be called
96    * by a platform thread.
97    */
98   void startSendLogsToHostLoop();
99 
100  private:
101   /*
102    * @return The LogBuffer log level for the given CHRE log level.
103    */
104   LogBufferLogLevel chreToLogBufferLogLevel(chreLogLevel chreLogLevel);
105 
106   /**
107    * Perform any setup needed by the plaform before the secondary buffer is
108    * used.
109    *
110    * Implemented by the platform.
111    */
112   void preSecondaryBufferUse() const;
113 
114   /**
115    * Same as onLogsSentToHost, but without locking. The calling code should have
116    * the flush logs mutex locked before calling this method.
117    *
118    * @param success true if the logs were successfully delivered to the host.
119    */
120   void onLogsSentToHostLocked(bool success);
121 
122   LogBuffer mPrimaryLogBuffer;
123   LogBuffer mSecondaryLogBuffer;
124 
125   size_t mNumLogsDroppedTotal = 0;
126 
127   ConditionVariable mSendLogsToHostCondition;
128   bool mLogFlushToHostPending = false;
129   bool mLogsBecameReadyWhileFlushPending = false;
130   Mutex mFlushLogsMutex;
131 };
132 
133 //! Provides an alias to the LogBufferManager singleton.
134 typedef Singleton<LogBufferManager> LogBufferManagerSingleton;
135 
136 //! Extern the explicit LogBufferManagerSingleton to force non-inline calls.
137 //! This reduces codesize considerably.
138 extern template class Singleton<LogBufferManager>;
139 
140 }  // namespace chre
141 
142 #endif  // CHRE_PLATFORM_LOG_BUFFER_MANAGER_H_
143