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