1 /*
2  * Copyright (C) 2017 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_SHARED_HOST_PROTOCOL_CHRE_H_
18 #define CHRE_PLATFORM_SHARED_HOST_PROTOCOL_CHRE_H_
19 
20 #include <stdint.h>
21 
22 #include "chre/core/event_loop_common.h"
23 #include "chre/core/nanoapp.h"
24 #include "chre/core/settings.h"
25 #include "chre/platform/shared/generated/host_messages_generated.h"
26 #include "chre/platform/shared/host_protocol_common.h"
27 #include "chre/util/dynamic_vector.h"
28 #include "chre/util/flatbuffers/helpers.h"
29 #include "chre_api/chre/event.h"
30 #include "flatbuffers/flatbuffers.h"
31 
32 namespace chre {
33 
34 typedef flatbuffers::Offset<fbs::NanoappListEntry> NanoappListEntryOffset;
35 
36 /**
37  * Checks that a string encapsulated as a byte vector is null-terminated, and
38  * if it is, returns a pointer to the vector's data. Otherwise returns null.
39  *
40  * This is similar to getStringFromByteVector in host_protocol_host.h. Ensure
41  * that method's implementation is kept in sync with this.
42  *
43  * @param vec Target vector, can be null
44  *
45  * @return Pointer to the vector's data, or null
46  */
47 const char *getStringFromByteVector(const flatbuffers::Vector<int8_t> *vec);
48 
49 /**
50  * These methods are called from decodeMessageFromHost() and must be implemented
51  * by the code that calls it to handle parsed messages.
52  */
53 class HostMessageHandlers {
54  public:
55   struct LoadNanoappCallbackData {
56     uint64_t appId;
57     uint32_t transactionId;
58     uint16_t hostClientId;
59     UniquePtr<Nanoapp> nanoapp;
60     uint32_t fragmentId;
61     bool sendFragmentResponse;
62   };
63 
64   static void handleNanoappMessage(uint64_t appId, uint32_t messageType,
65                                    uint16_t hostEndpoint,
66                                    const void *messageData,
67                                    size_t messageDataLen, bool isReliable,
68                                    uint32_t messageSequenceNumber);
69 
70   static void handleMessageDeliveryStatus(uint32_t messageSequenceNumber,
71                                           uint8_t errorCode);
72 
73   static void handleHubInfoRequest(uint16_t hostClientId);
74 
75   static void handleNanoappListRequest(uint16_t hostClientId);
76 
77   static void handlePulseRequest();
78 
79   static void handleDebugConfiguration(
80       const fbs::DebugConfiguration *debugConfiguration);
81 
82   static void handleLoadNanoappRequest(
83       uint16_t hostClientId, uint32_t transactionId, uint64_t appId,
84       uint32_t appVersion, uint32_t appFlags, uint32_t targetApiVersion,
85       const void *buffer, size_t bufferLen, const char *appFileName,
86       uint32_t fragmentId, size_t appBinaryLen, bool respondBeforeStart);
87 
88   static void handleUnloadNanoappRequest(uint16_t hostClientId,
89                                          uint32_t transactionId, uint64_t appId,
90                                          bool allowSystemNanoappUnload);
91 
92   static void handleTimeSyncMessage(int64_t offset);
93 
94   static void handleDebugDumpRequest(uint16_t hostClientId);
95 
96   static void handleSettingChangeMessage(fbs::Setting setting,
97                                          fbs::SettingState state);
98 
99   static void handleSelfTestRequest(uint16_t hostClientId);
100 
101   static void handleNanConfigurationUpdate(bool enabled);
102 
103  private:
104   static void sendFragmentResponse(uint16_t hostClientId,
105                                    uint32_t transactionId, uint32_t fragmentId,
106                                    bool success);
107 
108   static void finishLoadingNanoappCallback(
109       SystemCallbackType type, UniquePtr<LoadNanoappCallbackData> &&cbData);
110 
111   /**
112    * Helper function that loads a nanoapp into the system
113    * from a buffer sent over in 1 or more fragments.
114    *
115    * @param hostClientId the ID of client that originated this transaction
116    * @param transactionId the ID of the transaction
117    * @param appId the ID of the app to load
118    * @param appVersion the version of the app to load
119    * @param appFlags The flags provided by the app being loaded
120    * @param targetApiVersion the API version this nanoapp is targeted for
121    * @param buffer the nanoapp binary data. May be only part of the nanoapp's
122    *     binary if it's being sent over multiple fragments
123    * @param bufferLen the size of buffer in bytes
124    * @param fragmentId the identifier indicating which fragment is being loaded
125    * @param appBinaryLen the full size of the nanoapp binary to be loaded
126    *
127    * @return void
128    */
129   static void loadNanoappData(uint16_t hostClientId, uint32_t transactionId,
130                               uint64_t appId, uint32_t appVersion,
131                               uint32_t appFlags, uint32_t targetApiVersion,
132                               const void *buffer, size_t bufferLen,
133                               uint32_t fragmentId, size_t appBinaryLen,
134                               bool respondBeforeStart);
135 };
136 
137 /**
138  * A set of helper methods that simplify the encode/decode of FlatBuffers
139  * messages used in communications with the host from CHRE.
140  */
141 class HostProtocolChre : public HostProtocolCommon {
142  public:
143   /**
144    * Verifies and decodes a FlatBuffers-encoded CHRE message.
145    *
146    * @param message Buffer containing message
147    * @param messageLen Size of the message, in bytes
148    * @param handlers Contains callbacks to process a decoded message
149    *
150    * @return bool true if the message was successfully decoded, false if it was
151    *         corrupted/invalid/unrecognized
152    */
153   static bool decodeMessageFromHost(const void *message, size_t messageLen);
154 
155   /**
156    * Refer to the context hub HAL definition for a details of these parameters.
157    *
158    * @param builder A newly constructed ChreFlatBufferBuilder that will be used
159    * to encode the message
160    */
161   static void encodeHubInfoResponse(
162       ChreFlatBufferBuilder &builder, const char *name, const char *vendor,
163       const char *toolchain, uint32_t legacyPlatformVersion,
164       uint32_t legacyToolchainVersion, float peakMips, float stoppedPower,
165       float sleepPower, float peakPower, uint32_t maxMessageLen,
166       uint64_t platformId, uint32_t version, uint16_t hostClientId,
167       bool supportsReliableMessages);
168 
169   /**
170    * Supports construction of a NanoappListResponse by adding a single
171    * NanoappListEntry to the response. The offset for the newly added entry is
172    * maintained in the given vector until finishNanoappListResponse() is called.
173    * Example usage:
174    *
175    *   ChreFlatBufferBuilder builder;
176    *   DynamicVector<NanoappListEntryOffset> vector;
177    *   for (auto app : appList) {
178    *     HostProtocolChre::addNanoppListEntry(builder, vector, ...);
179    *   }
180    *   HostProtocolChre::finishNanoappListResponse(builder, vector);
181    *
182    * @param builder A ChreFlatBufferBuilder to use for encoding the message
183    * @param offsetVector A vector to track the offset to the newly added
184    *        NanoappListEntry, which be passed to finishNanoappListResponse()
185    *        once all entries are added
186    */
187   static void addNanoappListEntry(
188       ChreFlatBufferBuilder &builder,
189       DynamicVector<NanoappListEntryOffset> &offsetVector, uint64_t appId,
190       uint32_t appVersion, bool enabled, bool isSystemNanoapp,
191       uint32_t appPermissions,
192       const DynamicVector<struct chreNanoappRpcService> &rpcServices);
193 
194   /**
195    * Finishes encoding a NanoappListResponse message after all NanoappListEntry
196    * elements have already been added to the builder.
197    *
198    * @param builder The ChreFlatBufferBuilder used with addNanoappListEntry()
199    * @param offsetVector The vector used with addNanoappListEntry()
200    * @param hostClientId
201    *
202    * @see addNanoappListEntry()
203    */
204   static void finishNanoappListResponse(
205       ChreFlatBufferBuilder &builder,
206       DynamicVector<NanoappListEntryOffset> &offsetVector,
207       uint16_t hostClientId);
208 
209   /**
210    * Encodes a response to the host indicating CHRE is up running.
211    */
212   static void encodePulseResponse(ChreFlatBufferBuilder &builder);
213 
214   /**
215    * Encodes a response to the host communicating the result of dynamically
216    * loading a nanoapp.
217    */
218   static void encodeLoadNanoappResponse(ChreFlatBufferBuilder &builder,
219                                         uint16_t hostClientId,
220                                         uint32_t transactionId, bool success,
221                                         uint32_t fragmentId);
222 
223   /**
224    * Encodes a response to the host communicating the result of dynamically
225    * unloading a nanoapp.
226    */
227   static void encodeUnloadNanoappResponse(ChreFlatBufferBuilder &builder,
228                                           uint16_t hostClientId,
229                                           uint32_t transactionId, bool success);
230 
231   /**
232    * Encodes a nanoapp's instance ID and app ID to the host.
233    */
234   static void encodeNanoappTokenDatabaseInfo(ChreFlatBufferBuilder &builder,
235                                              uint16_t instanceId,
236                                              uint64_t appId,
237                                              uint32_t tokenDatabaseOffset,
238                                              size_t tokenDatabaseSize);
239 
240   /**
241    * Encodes a buffer of log messages to the host.
242    */
243   static void encodeLogMessages(ChreFlatBufferBuilder &builder,
244                                 const uint8_t *logBuffer, size_t bufferSize);
245 
246   /**
247    * Encodes a buffer of V2 log messages to the host.
248    */
249   static void encodeLogMessagesV2(ChreFlatBufferBuilder &builder,
250                                   const uint8_t *logBuffer, size_t bufferSize,
251                                   uint32_t numLogsDropped);
252 
253   /**
254    * Encodes a string into a DebugDumpData message.
255    *
256    * @param debugStr Null-terminated ASCII string containing debug information
257    * @param debugStrSize Size of the debugStr buffer, including null termination
258    */
259   static void encodeDebugDumpData(ChreFlatBufferBuilder &builder,
260                                   uint16_t hostClientId, const char *debugStr,
261                                   size_t debugStrSize);
262 
263   /**
264    * Encodes the final response to a debug dump request.
265    */
266   static void encodeDebugDumpResponse(ChreFlatBufferBuilder &builder,
267                                       uint16_t hostClientId, bool success,
268                                       uint32_t dataCount);
269 
270   /**
271    * Encodes a message requesting time sync from host.
272    */
273   static void encodeTimeSyncRequest(ChreFlatBufferBuilder &builder);
274 
275   /**
276    * Encodes a message notifying the host that audio has been requested by a
277    * nanoapp, so the low-power microphone needs to be powered on.
278    */
279   static void encodeLowPowerMicAccessRequest(ChreFlatBufferBuilder &builder);
280 
281   /**
282    * Encodes a message notifying the host that no nanoapps are requesting audio
283    * anymore, so the low-power microphone may be powered off.
284    */
285   static void encodeLowPowerMicAccessRelease(ChreFlatBufferBuilder &builder);
286 
287   /**
288    * @param state The fbs::Setting value.
289    * @param chreSetting If success, stores the corresponding
290    * chre::Setting value.
291    *
292    * @return true if state was a valid fbs::Setting value.
293    */
294   static bool getSettingFromFbs(fbs::Setting setting, Setting *chreSetting);
295 
296   /**
297    * @param state The fbs::SettingState value.
298    * @param chreSettingEnabled If success, stores the value indicating whether
299    *     the setting is enabled or not.
300    *
301    * @return true if state was a valid fbs::SettingState value.
302    */
303   static bool getSettingEnabledFromFbs(fbs::SettingState state,
304                                        bool *chreSettingEnabled);
305 
306   /**
307    * Encodes a message notifying the result of a self test.
308    */
309   static void encodeSelfTestResponse(ChreFlatBufferBuilder &builder,
310                                      uint16_t hostClientId, bool success);
311 
312   /**
313    * Encodes a metric message using custon-defined protocol
314    */
315   static void encodeMetricLog(ChreFlatBufferBuilder &builder, uint32_t metricId,
316                               const uint8_t *encodedMsg, size_t metricSize);
317 
318   /**
319    * Encodes a NAN configuration request.
320    *
321    * @param builder An instance of the CHRE Flatbuffer builder.
322    * @param enable Boolean to indicate the enable/disable operation being
323    *        requested.
324    */
325   static void encodeNanConfigurationRequest(ChreFlatBufferBuilder &builder,
326                                             bool enable);
327 };
328 
329 }  // namespace chre
330 
331 #endif  // CHRE_PLATFORM_SHARED_HOST_PROTOCOL_CHRE_H_
332