• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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_DAEMON_H_
18 #define CHRE_DAEMON_H_
19 
20 /**
21  * @file daemon_base.h
22  * This header defines the CHRE daemon base class, off of which all supported
23  * CHRE daemon variants are expected to derive from. The goal is to provide
24  * common (abstract or implemented) interfaces that all CHRE daemons must
25  * implement.
26  */
27 
28 #include <atomic>
29 #include <csignal>
30 #include <cstdint>
31 #include <map>
32 #include <queue>
33 #include <string>
34 #include <thread>
35 
36 #include "chre_host/host_protocol_host.h"
37 #include "chre_host/log_message_parser.h"
38 #include "chre_host/socket_server.h"
39 
40 #ifdef CHRE_DAEMON_METRIC_ENABLED
41 #include <aidl/android/frameworks/stats/IStats.h>
42 #include <android/binder_manager.h>
43 #endif  // CHRE_DAEMON_METRIC_ENABLED
44 
45 namespace android {
46 namespace chre {
47 
48 class ChreDaemonBase {
49  public:
50   ChreDaemonBase();
~ChreDaemonBase()51   virtual ~ChreDaemonBase() {
52     if (mSignalHandlerThread.joinable()) {
53       std::raise(SIGINT);
54       mSignalHandlerThread.join();
55     }
56   }
57 
58   /**
59    * Initialize the CHRE daemon. We're expected to fail here and not start
60    * the daemon if we don't get all the resources we're hoping to.
61    * Any resources claimed by this function should be released in the
62    * destructor
63    *
64    * @return true on successful initialization
65    */
66   virtual bool init() = 0;
67 
68   /**
69    * Start the CHRE Daemon. This method must be called after @ref init() has
70    * been called.
71    */
72   virtual void run() = 0;
73 
74   /**
75    * Send a message to CHRE
76    *
77    * @param clientId The client ID that this message originates from.
78    * @param data The data to pass down.
79    * @param length The size of the data to send.
80    * @return true if successful, false otherwise.
81    */
82   virtual bool sendMessageToChre(uint16_t clientId, void *data,
83                                  size_t dataLen) = 0;
84 
85   /**
86    * Function to be invoked on a shutdown request (eg: from a signal handler)
87    * to initiate a graceful shutdown of the daemon.
88    */
onShutdown()89   virtual void onShutdown() {
90     setShutdownRequested(true);
91     mServer.shutdownServer();
92   }
93 
94   /**
95    * Function to query if a graceful shutdown of CHRE was requested
96    *
97    * @return true if a graceful shutdown was requested
98    */
wasShutdownRequested()99   bool wasShutdownRequested() const {
100     return mChreShutdownRequested;
101   }
102 
103  protected:
104   //! The host ID to use when preloading nanoapps. This is used before the
105   //! server is started and is sufficiently high enough so as to not collide
106   //! with any clients after the server starts.
107   static constexpr uint16_t kHostClientIdDaemon = UINT16_MAX;
108 
109   //! Contains the transaction ID and app ID used to preload nanoapps.
110   struct Transaction {
111     uint32_t transactionId;
112     uint64_t nanoappId;
113   };
114 
setShutdownRequested(bool request)115   void setShutdownRequested(bool request) {
116     mChreShutdownRequested = request;
117   }
118 
119   /**
120    * Attempts to load all preloaded nanoapps from a config file. The config file
121    * is expected to be valid JSON with the following structure:
122    *
123    * { "nanoapps": [
124    *     "/path/to/nanoapp_1",
125    *     "/path/to/nanoapp_2"
126    * ]}
127    *
128    * The napp_header and so files will both be loaded. All errors are logged.
129    */
130   void loadPreloadedNanoapps();
131 
132   /**
133    * Loads a preloaded nanoapp given a filename to load from. Allows the
134    * transaction to complete before the nanoapp starts so the server can start
135    * serving requests as soon as possible.
136    *
137    * @param directory The directory to load the nanoapp from.
138    * @param name The filename of the nanoapp to load.
139    * @param transactionId The transaction ID to use when loading the app.
140    */
141   virtual void loadPreloadedNanoapp(const std::string &directory,
142                                     const std::string &name,
143                                     uint32_t transactionId);
144 
145   /**
146    * Sends a preloaded nanoapp filename / metadata to CHRE.
147    *
148    * @param header The nanoapp header binary blob.
149    * @param nanoappName The filename of the nanoapp to be loaded.
150    * @param transactionId The transaction ID to use when loading the app.
151    * @return true if successful, false otherwise.
152    */
153   bool loadNanoapp(const std::vector<uint8_t> &header,
154                    const std::string &nanoappName, uint32_t transactionId);
155 
156   /**
157    * Loads a nanoapp by sending the nanoapp filename to the CHRE framework. This
158    * method will return after sending the request so no guarantee is made that
159    * the nanoapp is loaded until after the response is received.
160    *
161    * @param appId The ID of the nanoapp to load.
162    * @param appVersion The version of the nanoapp to load.
163    * @param appTargetApiVersion The version of the CHRE API that the app
164    * targets.
165    * @param appBinaryName The name of the binary as stored in the filesystem.
166    * This will be used to load the nanoapp into CHRE.
167    * @param transactionId The transaction ID to use when loading.
168    * @return true if a request was successfully sent, false otherwise.
169    */
170   virtual bool sendNanoappLoad(uint64_t appId, uint32_t appVersion,
171                                uint32_t appTargetApiVersion,
172                                const std::string &appBinaryName,
173                                uint32_t transactionId) = 0;
174 
175   /**
176    * Send a time sync message to CHRE
177    *
178    * @param logOnError If true, logs an error message on failure.
179    *
180    * @return true if the time sync message was successfully sent to CHRE.
181    */
182   virtual bool sendTimeSync(bool logOnError) = 0;
183 
184   /**
185    * Computes and returns the clock drift between the system clock
186    * and the processor timer registers
187    *
188    * @return offset in nanoseconds
189    */
190   virtual int64_t getTimeOffset(bool *success) = 0;
191 
192   /**
193    * Sends a time sync message to CHRE, retrying a specified time until success.
194    *
195    * @param maxNumRetries The number of times to retry sending the message
196    *
197    * @return true if the time sync message was successfully sent to CHRE.
198    */
199   bool sendTimeSyncWithRetry(size_t numRetries, useconds_t retryDelayUs,
200                              bool logOnError);
201 
202   /**
203    * Interface to a callback that is called when the Daemon receives a message.
204    *
205    * @param message A buffer containing the message
206    * @param messageLen size of the message buffer in bytes
207    */
208   virtual void onMessageReceived(const unsigned char *message,
209                                  size_t messageLen) = 0;
210 
211   /**
212    * Handles a message that is directed towards the daemon.
213    *
214    * @param message The message sent to the daemon.
215    */
216   virtual void handleDaemonMessage(const uint8_t *message) = 0;
217 
218   /**
219    * Enables or disables LPMA (low power microphone access).
220    */
221   virtual void configureLpma(bool enabled) = 0;
222 
223 #ifdef CHRE_DAEMON_METRIC_ENABLED
224   /**
225    * Handles a metric log message sent from CHRE
226    *
227    */
228   virtual void handleMetricLog(const ::chre::fbs::MetricLogT *metric_msg);
229 
230 #ifdef CHRE_LOG_ATOM_EXTENSION_ENABLED
231   /**
232    * Handles additional metrics that aren't logged by the common CHRE code.
233    *
234    */
235   virtual void handleVendorMetricLog(
236       const ::chre::fbs::MetricLogT *metric_msg) = 0;
237 #endif  // CHRE_LOG_ATOM_EXTENSION_ENABLED
238 
239   /**
240    * Create and report CHRE vendor atom and send it to stats_client
241    *
242    * @param atom the vendor atom to be reported
243    */
244   void reportMetric(const aidl::android::frameworks::stats::VendorAtom &atom);
245 #endif  // CHRE_DAEMON_METRIC_ENABLED
246 
247   /**
248    * Handles a NAN configuration request sent from CHRE.
249    *
250    * @param request NAN configuration request.
251    */
252   virtual void handleNanConfigurationRequest(
253       const ::chre::fbs::NanConfigurationRequestT *request);
254 
255   /**
256    * Returns the CHRE log message parser instance.
257    * @return log message parser instance.
258    */
getLogger()259   LogMessageParser &getLogger() {
260     return mLogger;
261   }
262 
263   //! Server used to communicate with daemon clients
264   SocketServer mServer;
265 
266  private:
267   LogMessageParser mLogger;
268 
269   std::thread mSignalHandlerThread;
270 
271   //! Set to true when we request a graceful shutdown of CHRE
272   std::atomic<bool> mChreShutdownRequested;
273 };
274 
275 }  // namespace chre
276 }  // namespace android
277 
278 #endif  // CHRE_DAEMON_H
279