xref: /aosp_15_r20/system/chre/core/chre_message_hub_manager.cc (revision 84e339476a462649f82315436d70fd732297a399)
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 #ifdef CHRE_MESSAGE_ROUTER_SUPPORT_ENABLED
18 
19 #include "chre/core/chre_message_hub_manager.h"
20 #include "chre/core/event_loop_common.h"
21 #include "chre/core/event_loop_manager.h"
22 #include "chre/core/nanoapp.h"
23 #include "chre/util/system/message_common.h"
24 #include "chre/util/system/message_router.h"
25 #include "chre/util/unique_ptr.h"
26 
27 #include <cinttypes>
28 #include <optional>
29 
30 using ::chre::message::Endpoint;
31 using ::chre::message::EndpointId;
32 using ::chre::message::EndpointInfo;
33 using ::chre::message::EndpointType;
34 using ::chre::message::Message;
35 using ::chre::message::MessageRouter;
36 using ::chre::message::MessageRouterSingleton;
37 using ::chre::message::Session;
38 
39 namespace chre {
40 
init()41 void ChreMessageHubManager::init() {
42   std::optional<MessageRouter::MessageHub> chreMessageHub =
43       MessageRouterSingleton::get()->registerMessageHub(
44           "CHRE", kChreMessageHubId, *this);
45   if (chreMessageHub.has_value()) {
46     mChreMessageHub = std::move(*chreMessageHub);
47   } else {
48     LOGE("Failed to register the CHRE MessageHub");
49   }
50 }
51 
onMessageToNanoappCallback(SystemCallbackType,UniquePtr<MessageCallbackData> && data)52 void ChreMessageHubManager::onMessageToNanoappCallback(
53     SystemCallbackType /* type */, UniquePtr<MessageCallbackData> &&data) {
54   bool success = false;
55   Nanoapp *nanoapp =
56       EventLoopManagerSingleton::get()->getEventLoop().findNanoappByAppId(
57           data->nanoappId);
58   uint32_t messagePermissions = data->messageToNanoapp.messagePermissions;
59   if (nanoapp == nullptr) {
60     LOGE("Unable to find nanoapp with ID 0x%" PRIx64
61          " to receive message with type %" PRIu32 " and permissions %" PRIu32
62          " with session ID %" PRIu16,
63          data->nanoappId, data->messageToNanoapp.messageType,
64          data->messageToNanoapp.messagePermissions,
65          data->messageToNanoapp.sessionId);
66   } else if (!nanoapp->hasPermissions(messagePermissions)) {
67     LOGE("nanoapp with ID 0x%" PRIx64
68          " does not have permissions to receive "
69          "message with type %" PRIu32 " and permissions 0x%" PRIx32,
70          nanoapp->getAppId(), data->messageToNanoapp.messageType,
71          data->messageToNanoapp.messagePermissions);
72   } else if (!EventLoopManagerSingleton::get()
73                   ->getEventLoop()
74                   .distributeEventSync(CHRE_EVENT_MESSAGE_FROM_ENDPOINT,
75                                        &data->messageToNanoapp,
76                                        nanoapp->getInstanceId())) {
77     LOGE("Unable to distribute message to nanoapp with ID 0x%" PRIx64,
78          nanoapp->getAppId());
79   } else {
80     success = true;
81   }
82 
83   // Close session on failure so sender knows there was an issue
84   if (!success) {
85     EventLoopManagerSingleton::get()
86         ->getChreMessageHubManager()
87         .getMessageHub()
88         .closeSession(data->messageToNanoapp.sessionId);
89   }
90 }
91 
onSessionClosedCallback(SystemCallbackType,UniquePtr<SessionClosedCallbackData> && data)92 void ChreMessageHubManager::onSessionClosedCallback(
93     SystemCallbackType /* type */,
94     UniquePtr<SessionClosedCallbackData> &&data) {
95   Nanoapp *nanoapp =
96       EventLoopManagerSingleton::get()->getEventLoop().findNanoappByAppId(
97           data->nanoappId);
98   if (nanoapp == nullptr) {
99     LOGE("Unable to find nanoapp with ID 0x%" PRIx64
100          " to close the session with ID %" PRIu16,
101          data->nanoappId, data->sessionClosedData.sessionId);
102     return;
103   }
104 
105   bool success =
106       EventLoopManagerSingleton::get()->getEventLoop().distributeEventSync(
107           CHRE_EVENT_ENDPOINT_SESSION_CLOSED, &data->sessionClosedData,
108           nanoapp->getInstanceId());
109   if (!success) {
110     LOGE("Unable to process session closed event to nanoapp with ID 0x%" PRIx64,
111          nanoapp->getAppId());
112   }
113 }
114 
onMessageReceived(pw::UniquePtr<std::byte[]> && data,size_t length,uint32_t messageType,uint32_t messagePermissions,const Session & session,bool sentBySessionInitiator)115 bool ChreMessageHubManager::onMessageReceived(pw::UniquePtr<std::byte[]> &&data,
116                                               size_t length,
117                                               uint32_t messageType,
118                                               uint32_t messagePermissions,
119                                               const Session &session,
120                                               bool sentBySessionInitiator) {
121   Endpoint receiver = sentBySessionInitiator ? session.peer : session.initiator;
122   auto messageCallbackData = MakeUnique<MessageCallbackData>();
123   if (messageCallbackData.isNull()) {
124     LOG_OOM();
125     return false;
126   }
127 
128   messageCallbackData->messageToNanoapp = {
129       .messageType = messageType,
130       .messagePermissions = messagePermissions,
131       .message = data.get(),
132       .messageSize = length,
133       .sessionId = session.sessionId,
134   };
135   messageCallbackData->data = std::move(data);
136   messageCallbackData->nanoappId = receiver.endpointId;
137 
138   EventLoopManagerSingleton::get()->deferCallback(
139       SystemCallbackType::EndpointMessageToNanoappEvent,
140       std::move(messageCallbackData),
141       ChreMessageHubManager::onMessageToNanoappCallback);
142   return true;
143 }
144 
onSessionClosed(const Session & session)145 void ChreMessageHubManager::onSessionClosed(const Session &session) {
146   auto sessionClosedCallbackData = MakeUnique<SessionClosedCallbackData>();
147   if (sessionClosedCallbackData.isNull()) {
148     LOG_OOM();
149     return;
150   }
151 
152   Endpoint otherParty;
153   uint64_t nanoappId;
154   if (session.initiator.messageHubId == kChreMessageHubId) {
155     otherParty = session.peer;
156     nanoappId = session.initiator.endpointId;
157   } else {
158     otherParty = session.initiator;
159     nanoappId = session.peer.endpointId;
160   }
161 
162   sessionClosedCallbackData->sessionClosedData = {
163       .hubId = otherParty.messageHubId,
164       .endpointId = otherParty.endpointId,
165       .sessionId = session.sessionId,
166   };
167   sessionClosedCallbackData->nanoappId = nanoappId;
168 
169   EventLoopManagerSingleton::get()->deferCallback(
170       SystemCallbackType::EndpointSessionClosedEvent,
171       std::move(sessionClosedCallbackData),
172       ChreMessageHubManager::onSessionClosedCallback);
173 }
174 
forEachEndpoint(const pw::Function<bool (const EndpointInfo &)> & function)175 void ChreMessageHubManager::forEachEndpoint(
176     const pw::Function<bool(const EndpointInfo &)> &function) {
177   EventLoopManagerSingleton::get()->getEventLoop().onMatchingNanoappEndpoint(
178       function);
179 }
180 
getEndpointInfo(EndpointId endpointId)181 std::optional<EndpointInfo> ChreMessageHubManager::getEndpointInfo(
182     EndpointId endpointId) {
183   return EventLoopManagerSingleton::get()->getEventLoop().getEndpointInfo(
184       endpointId);
185 }
186 
187 }  // namespace chre
188 
189 #endif  // CHRE_MESSAGE_ROUTER_SUPPORT_ENABLED
190