• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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_CORE_CHRE_MESSAGE_HUB_MANAGER_H_
18 #define CHRE_CORE_CHRE_MESSAGE_HUB_MANAGER_H_
19 
20 #ifdef CHRE_MESSAGE_ROUTER_SUPPORT_ENABLED
21 
22 #include "chre/platform/mutex.h"
23 #include "chre/util/dynamic_vector.h"
24 #include "chre/util/non_copyable.h"
25 #include "chre/util/system/callback_allocator.h"
26 #include "chre/util/system/message_common.h"
27 #include "chre/util/system/message_router.h"
28 #include "chre/util/system/system_callback_type.h"
29 #include "chre/util/unique_ptr.h"
30 #include "chre_api/chre.h"
31 
32 #include "pw_containers/vector.h"
33 #include "pw_intrusive_ptr/recyclable.h"
34 
35 #include <cstdint>
36 #include <optional>
37 
38 namespace chre {
39 
40 //! Manager class for the CHRE Message Hub.
41 class ChreMessageHubManager : public NonCopyable {
42  public:
43   //! The ID of the CHRE MessageHub
44   constexpr static message::MessageHubId kChreMessageHubId = CHRE_PLATFORM_ID;
45 
46   ChreMessageHubManager();
47   ~ChreMessageHubManager();
48 
49   //! Initializes the ChreMessageHubManager
50   void init();
51 
52   //! @return the MessageHub for the CHRE Message Hub
getMessageHub()53   message::MessageRouter::MessageHub &getMessageHub() {
54     return mChreMessageHub;
55   }
56 
57   //! Gets endpoint information for the given hub and endpoint IDs.
58   //! @return whether the endpoint information was successfully populated.
59   bool getEndpointInfo(message::MessageHubId hubId,
60                        message::EndpointId endpointId,
61                        chreMsgEndpointInfo &info);
62 
63   //! Configures ready events for the given endpoint or service.
64   //! This function must be called from the event loop thread.
65   //! @return true if the ready events were configured successfully, false
66   //! otherwise.
67   bool configureReadyEvents(uint16_t nanoappInstanceId,
68                             message::EndpointId fromEndpointId,
69                             message::MessageHubId hubId,
70                             message::EndpointId endpointId,
71                             const char *serviceDescriptor, bool enable);
72 
73   //! Gets session information for the given session ID.
74   //! @return whether the session information was successfully populated.
75   bool getSessionInfo(message::EndpointId fromEndpointId,
76                       message::SessionId sessionId, chreMsgSessionInfo &info);
77 
78   //! Opens a session from the given endpoint to the other endpoint in an
79   //! asynchronous manner.
80   //! @return true if the session was opened successfully, false otherwise
81   bool openSessionAsync(message::EndpointId fromEndpointId,
82                         message::MessageHubId toHubId,
83                         message::EndpointId toEndpointId,
84                         const char *serviceDescriptor);
85 
86   //! Opens a session from the given endpoint to the other endpoint in an
87   //! asynchronous manner. Either toHubId, toEndpointId, or serviceDescriptor
88   //! can be set to CHRE_MSG_HUB_ID_INVALID, ENDPOINT_ID_INVALID, or nullptr,
89   //! respectively. If they are set to invalid values, the default values will
90   //! be used if available. If no default values are available, the session will
91   //! not be opened and this function will return false.
92   //! @return true if the session was opened successfully, false otherwise
93   bool openDefaultSessionAsync(message::EndpointId fromEndpointId,
94                                message::MessageHubId toHubId,
95                                message::EndpointId toEndpointId,
96                                const char *serviceDescriptor);
97 
98   //! Closes the session and verifies the fromEndpointId is a member of the
99   //! session.
100   //! @return true if the session was closed successfully, false otherwise
101   bool closeSession(message::EndpointId fromEndpointId,
102                     message::SessionId sessionId);
103 
104   //! Sends a reliable message on the given session. If this function fails,
105   //! the free callback will be called and it will return false.
106   //! @return whether the message was successfully sent
107   bool sendMessage(void *message, size_t messageSize, uint32_t messageType,
108                    uint16_t sessionId, uint32_t messagePermissions,
109                    chreMessageFreeFunction *freeCallback,
110                    message::EndpointId fromEndpointId);
111 
112   //! Publishes a service from the given nanoapp.
113   //! This function must be called from the event loop thread.
114   //! @return true if the service was published successfully, false otherwise
115   bool publishServices(message::EndpointId fromEndpointId,
116                        const chreMsgServiceInfo *serviceInfos,
117                        size_t numServices);
118 
119   //! Unregisters the given endpoint (nanoapp) from the MessageHub
120   //! This will clean up all pending resources then unregister the endpoint
121   //! from the MessageHub.
122   void unregisterEndpoint(message::EndpointId endpointId);
123 
124   //! Cleans up all pending resources for the given endpoint (nanoapp).
125   //! This should only be called from the event loop thread.
126   void cleanupEndpointResources(message::EndpointId endpointId);
127 
128   //! Converts a message::EndpointType to a CHRE endpoint type
129   //! @return the CHRE endpoint type
130   chreMsgEndpointType toChreEndpointType(message::EndpointType type);
131 
132   //! Converts a message::Reason to a CHRE endpoint reason
133   //! @return the CHRE endpoint reason
134   chreMsgEndpointReason toChreEndpointReason(message::Reason reason);
135 
136  private:
137   //! Data to be passed to the message callback
138   struct MessageCallbackData {
139     chreMsgMessageFromEndpointData messageToNanoapp;
140     pw::UniquePtr<std::byte[]> data;
141     uint64_t nanoappId;
142   };
143 
144   //! Data to be passed to the message free callback
145   struct MessageFreeCallbackData {
146     chreMessageFreeFunction *freeCallback;
147     uint64_t nanoappId;
148   };
149 
150   //! Data to be passed to the session closed callback
151   struct SessionCallbackData {
152     chreMsgSessionInfo sessionData;
153     bool isClosed;
154     uint64_t nanoappId;
155   };
156 
157   //! Data that represents a service published by a nanoapp
158   struct NanoappServiceData {
159     uint64_t nanoappId;
160     chreMsgServiceInfo serviceInfo;
161   };
162 
163   //! Data that represents a ready event configured for an endpoint or service
164   struct EndpointReadyEventData {
165     message::EndpointId fromEndpointId;
166     message::MessageHubId messageHubId;
167     message::EndpointId endpointId;
168     const char *serviceDescriptor;
169   };
170 
171   //! The callback used to register the CHRE MessageHub with the MessageRouter
172   //! @see MessageRouter::MessageHubCallback
173   class ChreMessageHubCallback
174       : public message::MessageRouter::MessageHubCallback,
175         pw::Recyclable<ChreMessageHubCallback> {
176    public:
ChreMessageHubCallback(ChreMessageHubManager & manager)177     explicit ChreMessageHubCallback(ChreMessageHubManager &manager)
178         : mChreMessageHubManager(&manager) {}
179 
~ChreMessageHubCallback()180     ~ChreMessageHubCallback() {
181       clearManager();
182     }
183 
184     //! Clears the manager pointer.
185     void clearManager();
186 
187    private:
188     friend class pw::Recyclable<ChreMessageHubCallback>;
189 
190     //! @see MessageRouter::MessageHubCallback
191     bool onMessageReceived(pw::UniquePtr<std::byte[]> &&data,
192                            uint32_t messageType, uint32_t messagePermissions,
193                            const message::Session &session,
194                            bool sentBySessionInitiator) override;
195     void onSessionOpenRequest(const message::Session &session) override;
196     void onSessionOpened(const message::Session &session) override;
197     void onSessionClosed(const message::Session &session,
198                          message::Reason reason) override;
199     void forEachEndpoint(const pw::Function<bool(const message::EndpointInfo &)>
200                              &function) override;
201     std::optional<message::EndpointInfo> getEndpointInfo(
202         message::EndpointId endpointId) override;
203     std::optional<message::EndpointId> getEndpointForService(
204         const char *serviceDescriptor) override;
205     bool doesEndpointHaveService(message::EndpointId endpointId,
206                                  const char *serviceDescriptor) override;
207     void forEachService(const pw::Function<bool(const message::EndpointInfo &,
208                                                 const message::ServiceInfo &)>
209                             &function) override;
210     void onHubRegistered(const message::MessageHubInfo &info) override;
211     void onHubUnregistered(message::MessageHubId id) override;
212     void onEndpointRegistered(message::MessageHubId messageHubId,
213                               message::EndpointId endpointId) override;
214     void onEndpointUnregistered(message::MessageHubId messageHubId,
215                                 message::EndpointId endpointId) override;
216 
217     //! @see pw::Recyclable
218     void pw_recycle() override;
219 
220     //! The ChreMessageHubManager that owns this callback and its lock.
221     Mutex mManagerLock;
222     ChreMessageHubManager *mChreMessageHubManager;
223   };
224 
225   friend class ChreMessageHubCallback;
226 
227   constexpr static size_t kMaxFreeCallbackRecords = 25;
228 
229   //! Callback to process message sent to a nanoapp - used by the event loop
230   static void onMessageToNanoappCallback(
231       SystemCallbackType type,
232       UniquePtr<ChreMessageHubManager::MessageCallbackData> &&data);
233 
234   //! Callback to process session closed or opened event for a nanoapp - used
235   //! by the event loop
236   static void onSessionStateChangedCallback(
237       SystemCallbackType type,
238       UniquePtr<ChreMessageHubManager::SessionCallbackData> &&data);
239 
240   //! Callback to process session open complete event - used by the event loop
241   static void onSessionOpenCompleteCallback(uint16_t type, void *data,
242                                             void *extraData);
243 
244   //! Callback called when a message is freed
245   static void onMessageFreeCallback(std::byte *message, size_t length,
246                                     MessageFreeCallbackData &&callbackData);
247 
248   //! Callback passed to deferCallback when handling a message free callback
249   static void handleMessageFreeCallback(uint16_t type, void *data,
250                                         void *extraData);
251 
252   //! Called on a state change for a session - open or close. If reason is
253   //! not provided, the state change is open, else it is closed.
254   void onSessionStateChanged(const message::Session &session,
255                              std::optional<message::Reason> reason);
256 
257   //! Called when a session open is requested.
258   void onSessionOpenComplete(message::SessionId sessionId);
259 
260   //! Processes an endpoint ready event from MessageRouter. Can only be called
261   //! from the event loop thread.
262   void onEndpointReadyEvent(message::MessageHubId messageHubId,
263                             message::EndpointId endpointId);
264 
265   //! @return The free callback record from the callback allocator.
266   std::optional<CallbackAllocator<MessageFreeCallbackData>::CallbackRecord>
getAndRemoveFreeCallbackRecord(void * ptr)267   getAndRemoveFreeCallbackRecord(void *ptr) {
268     return mAllocator.GetAndRemoveCallbackRecord(ptr);
269   }
270 
271   //! @return The first MessageHub ID for the given endpoint ID
272   message::MessageHubId findDefaultMessageHubId(message::EndpointId endpointId);
273 
274   //! @return true if the nanoapp has a service with the given service
275   //! descriptor in the legacy service descriptor format.
276   bool doesNanoappHaveLegacyService(uint64_t nanoappId, uint64_t serviceId);
277 
278   //! @return true if the services are valid and can be published, false
279   //! otherwise. Caller must hold mNanoappPublishedServicesMutex.
280   bool validateServicesLocked(uint64_t nanoappId,
281                               const chreMsgServiceInfo *serviceInfos,
282                               size_t numServices);
283 
284   //! Searches for an endpoint with the given hub ID, endpoint ID, and service
285   //! descriptor. The hubId can be MESSAGE_HUB_ID_ANY to search for the
286   //! endpoint on any hub, the endpointId can be ENDPOINT_ID_ANY to search for
287   //! the endpoint on any hub, or the service descriptor can be non-nullptr to
288   //! search for any endpoint that has the service.
289   //! @return the endpoint if found, std::nullopt otherwise.
290   std::optional<message::Endpoint> searchForEndpoint(
291       message::MessageHubId messageHubId, message::EndpointId endpointId,
292       const char *serviceDescriptor);
293 
294   //! Removes the ready event request for the given endpoint or service.
295   void disableReadyEvents(message::EndpointId fromEndpointId,
296                           message::MessageHubId hubId,
297                           message::EndpointId endpointId,
298                           const char *serviceDescriptor);
299 
300   //! Converts from a chreMsgEndpointServiceFormat to a message::RpcFormat.
301   //! @return the RpcFormat
302   message::RpcFormat toMessageRpcFormat(chreMsgEndpointServiceFormat format);
303 
304   //! The MessageHub for the CHRE
305   message::MessageRouter::MessageHub mChreMessageHub;
306 
307   //! The callback for the CHRE MessageHub
308   pw::IntrusivePtr<ChreMessageHubCallback> mChreMessageHubCallback;
309 
310   //! The vector of free callback records - used by the
311   //! CallbackAllocator
312   pw::Vector<CallbackAllocator<MessageFreeCallbackData>::CallbackRecord,
313              kMaxFreeCallbackRecords>
314       mFreeCallbackRecords;
315 
316   //! The allocator for message free callbacks - used when sending a message
317   //! from a nanoapp with a free callback
318   CallbackAllocator<MessageFreeCallbackData> mAllocator;
319 
320   //! Mutex to protect mNanoappPublishedServices
321   Mutex mNanoappPublishedServicesMutex;
322 
323   //! The vector of services published by nanoapps
324   DynamicVector<NanoappServiceData> mNanoappPublishedServices;
325 
326   //! The vector of ready event requests
327   //! This should only be accessed from the event loop thread
328   DynamicVector<EndpointReadyEventData> mEndpointReadyEventRequests;
329 };
330 
331 }  // namespace chre
332 
333 #endif  // CHRE_MESSAGE_ROUTER_SUPPORT_ENABLED
334 
335 #endif  // CHRE_CORE_CHRE_MESSAGE_HUB_MANAGER_H_
336