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