xref: /aosp_15_r20/system/chre/util/pigweed/rpc_server.cc (revision 84e339476a462649f82315436d70fd732297a399)
1*84e33947SAndroid Build Coastguard Worker /*
2*84e33947SAndroid Build Coastguard Worker  * Copyright (C) 2022 The Android Open Source Project
3*84e33947SAndroid Build Coastguard Worker  *
4*84e33947SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*84e33947SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*84e33947SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*84e33947SAndroid Build Coastguard Worker  *
8*84e33947SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*84e33947SAndroid Build Coastguard Worker  *
10*84e33947SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*84e33947SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*84e33947SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*84e33947SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*84e33947SAndroid Build Coastguard Worker  * limitations under the License.
15*84e33947SAndroid Build Coastguard Worker  */
16*84e33947SAndroid Build Coastguard Worker 
17*84e33947SAndroid Build Coastguard Worker #include "chre/util/pigweed/rpc_server.h"
18*84e33947SAndroid Build Coastguard Worker 
19*84e33947SAndroid Build Coastguard Worker #include <cinttypes>
20*84e33947SAndroid Build Coastguard Worker #include <cstdint>
21*84e33947SAndroid Build Coastguard Worker 
22*84e33947SAndroid Build Coastguard Worker #include "chre/util/nanoapp/log.h"
23*84e33947SAndroid Build Coastguard Worker #include "chre/util/pigweed/rpc_helper.h"
24*84e33947SAndroid Build Coastguard Worker #include "chre_api/chre.h"
25*84e33947SAndroid Build Coastguard Worker #include "pw_status/status.h"
26*84e33947SAndroid Build Coastguard Worker 
27*84e33947SAndroid Build Coastguard Worker #ifndef LOG_TAG
28*84e33947SAndroid Build Coastguard Worker #define LOG_TAG "[RpcServer]"
29*84e33947SAndroid Build Coastguard Worker #endif  // LOG_TAG
30*84e33947SAndroid Build Coastguard Worker 
31*84e33947SAndroid Build Coastguard Worker namespace chre {
32*84e33947SAndroid Build Coastguard Worker 
registerServices(size_t numServices,RpcServer::Service * services)33*84e33947SAndroid Build Coastguard Worker bool RpcServer::registerServices(size_t numServices,
34*84e33947SAndroid Build Coastguard Worker                                  RpcServer::Service *services) {
35*84e33947SAndroid Build Coastguard Worker   // Avoid blowing up the stack with chreServices.
36*84e33947SAndroid Build Coastguard Worker   constexpr size_t kMaxServices = 8;
37*84e33947SAndroid Build Coastguard Worker 
38*84e33947SAndroid Build Coastguard Worker   if (numServices > kMaxServices) {
39*84e33947SAndroid Build Coastguard Worker     LOGE("Can not register more than %zu services at once", kMaxServices);
40*84e33947SAndroid Build Coastguard Worker     return false;
41*84e33947SAndroid Build Coastguard Worker   }
42*84e33947SAndroid Build Coastguard Worker 
43*84e33947SAndroid Build Coastguard Worker   chreNanoappRpcService chreServices[kMaxServices];
44*84e33947SAndroid Build Coastguard Worker 
45*84e33947SAndroid Build Coastguard Worker   for (size_t i = 0; i < numServices; ++i) {
46*84e33947SAndroid Build Coastguard Worker     const Service &service = services[i];
47*84e33947SAndroid Build Coastguard Worker 
48*84e33947SAndroid Build Coastguard Worker     if (mServer.IsServiceRegistered(service.service)) {
49*84e33947SAndroid Build Coastguard Worker       return false;
50*84e33947SAndroid Build Coastguard Worker     }
51*84e33947SAndroid Build Coastguard Worker 
52*84e33947SAndroid Build Coastguard Worker     chreServices[i] = {
53*84e33947SAndroid Build Coastguard Worker         .id = service.id,
54*84e33947SAndroid Build Coastguard Worker         .version = service.version,
55*84e33947SAndroid Build Coastguard Worker     };
56*84e33947SAndroid Build Coastguard Worker 
57*84e33947SAndroid Build Coastguard Worker     mServer.RegisterService(service.service);
58*84e33947SAndroid Build Coastguard Worker   }
59*84e33947SAndroid Build Coastguard Worker 
60*84e33947SAndroid Build Coastguard Worker   return chrePublishRpcServices(chreServices, numServices);
61*84e33947SAndroid Build Coastguard Worker }
62*84e33947SAndroid Build Coastguard Worker 
setPermissionForNextMessage(uint32_t permission)63*84e33947SAndroid Build Coastguard Worker void RpcServer::setPermissionForNextMessage(uint32_t permission) {
64*84e33947SAndroid Build Coastguard Worker   mPermission.set(permission);
65*84e33947SAndroid Build Coastguard Worker }
66*84e33947SAndroid Build Coastguard Worker 
handleEvent(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)67*84e33947SAndroid Build Coastguard Worker bool RpcServer::handleEvent(uint32_t senderInstanceId, uint16_t eventType,
68*84e33947SAndroid Build Coastguard Worker                             const void *eventData) {
69*84e33947SAndroid Build Coastguard Worker   switch (eventType) {
70*84e33947SAndroid Build Coastguard Worker     case CHRE_EVENT_MESSAGE_FROM_HOST:
71*84e33947SAndroid Build Coastguard Worker       return handleMessageFromHost(eventData);
72*84e33947SAndroid Build Coastguard Worker     case CHRE_EVENT_RPC_REQUEST:
73*84e33947SAndroid Build Coastguard Worker       return handleMessageFromNanoapp(senderInstanceId, eventData);
74*84e33947SAndroid Build Coastguard Worker     case CHRE_EVENT_HOST_ENDPOINT_NOTIFICATION:
75*84e33947SAndroid Build Coastguard Worker       handleHostClientNotification(eventData);
76*84e33947SAndroid Build Coastguard Worker       return true;
77*84e33947SAndroid Build Coastguard Worker     case CHRE_EVENT_NANOAPP_STOPPED:
78*84e33947SAndroid Build Coastguard Worker       handleNanoappStopped(eventData);
79*84e33947SAndroid Build Coastguard Worker       return true;
80*84e33947SAndroid Build Coastguard Worker     default:
81*84e33947SAndroid Build Coastguard Worker       return true;
82*84e33947SAndroid Build Coastguard Worker   }
83*84e33947SAndroid Build Coastguard Worker }
84*84e33947SAndroid Build Coastguard Worker 
close()85*84e33947SAndroid Build Coastguard Worker void RpcServer::close() {
86*84e33947SAndroid Build Coastguard Worker   chreConfigureNanoappInfoEvents(false);
87*84e33947SAndroid Build Coastguard Worker   // TODO(b/251257328): Disable all notifications at once.
88*84e33947SAndroid Build Coastguard Worker   while (!mConnectedHosts.empty()) {
89*84e33947SAndroid Build Coastguard Worker     chreConfigureHostEndpointNotifications(mConnectedHosts[0], false);
90*84e33947SAndroid Build Coastguard Worker     mConnectedHosts.erase(0);
91*84e33947SAndroid Build Coastguard Worker   }
92*84e33947SAndroid Build Coastguard Worker }
93*84e33947SAndroid Build Coastguard Worker 
handleMessageFromHost(const void * eventData)94*84e33947SAndroid Build Coastguard Worker bool RpcServer::handleMessageFromHost(const void *eventData) {
95*84e33947SAndroid Build Coastguard Worker   auto *hostMessage = static_cast<const chreMessageFromHostData *>(eventData);
96*84e33947SAndroid Build Coastguard Worker 
97*84e33947SAndroid Build Coastguard Worker   if (hostMessage->messageType != CHRE_MESSAGE_TYPE_RPC) {
98*84e33947SAndroid Build Coastguard Worker     return false;
99*84e33947SAndroid Build Coastguard Worker   }
100*84e33947SAndroid Build Coastguard Worker 
101*84e33947SAndroid Build Coastguard Worker   pw::span packet(static_cast<const std::byte *>(hostMessage->message),
102*84e33947SAndroid Build Coastguard Worker                   hostMessage->messageSize);
103*84e33947SAndroid Build Coastguard Worker 
104*84e33947SAndroid Build Coastguard Worker   pw::Result<uint32_t> result = pw::rpc::ExtractChannelId(packet);
105*84e33947SAndroid Build Coastguard Worker   if (!result.status().ok()) {
106*84e33947SAndroid Build Coastguard Worker     LOGE("Unable to extract channel ID from packet: %" PRIu8,
107*84e33947SAndroid Build Coastguard Worker          static_cast<uint8_t>(result.status().code()));
108*84e33947SAndroid Build Coastguard Worker     return false;
109*84e33947SAndroid Build Coastguard Worker   }
110*84e33947SAndroid Build Coastguard Worker 
111*84e33947SAndroid Build Coastguard Worker   if (!validateHostChannelId(hostMessage, result.value())) {
112*84e33947SAndroid Build Coastguard Worker     return false;
113*84e33947SAndroid Build Coastguard Worker   }
114*84e33947SAndroid Build Coastguard Worker 
115*84e33947SAndroid Build Coastguard Worker   if (!chreConfigureHostEndpointNotifications(hostMessage->hostEndpoint,
116*84e33947SAndroid Build Coastguard Worker                                               true)) {
117*84e33947SAndroid Build Coastguard Worker     LOGW("Fail to register for host client updates");
118*84e33947SAndroid Build Coastguard Worker   }
119*84e33947SAndroid Build Coastguard Worker 
120*84e33947SAndroid Build Coastguard Worker   size_t hostIndex = mConnectedHosts.find(hostMessage->hostEndpoint);
121*84e33947SAndroid Build Coastguard Worker   if (hostIndex == mConnectedHosts.size()) {
122*84e33947SAndroid Build Coastguard Worker     mConnectedHosts.push_back(hostMessage->hostEndpoint);
123*84e33947SAndroid Build Coastguard Worker   }
124*84e33947SAndroid Build Coastguard Worker 
125*84e33947SAndroid Build Coastguard Worker   mHostOutput.setHostEndpoint(hostMessage->hostEndpoint);
126*84e33947SAndroid Build Coastguard Worker   pw::Status status = mServer.OpenChannel(result.value(), mHostOutput);
127*84e33947SAndroid Build Coastguard Worker   if (status != pw::OkStatus() && status != pw::Status::AlreadyExists()) {
128*84e33947SAndroid Build Coastguard Worker     LOGE("Failed to open channel: %" PRIu8, static_cast<uint8_t>(status.code()));
129*84e33947SAndroid Build Coastguard Worker     return false;
130*84e33947SAndroid Build Coastguard Worker   }
131*84e33947SAndroid Build Coastguard Worker 
132*84e33947SAndroid Build Coastguard Worker   status = mServer.ProcessPacket(packet);
133*84e33947SAndroid Build Coastguard Worker   if (!status.ok()) {
134*84e33947SAndroid Build Coastguard Worker     LOGE("Failed to process the packet: %" PRIu8, static_cast<uint8_t>(status.code()));
135*84e33947SAndroid Build Coastguard Worker     return false;
136*84e33947SAndroid Build Coastguard Worker   }
137*84e33947SAndroid Build Coastguard Worker 
138*84e33947SAndroid Build Coastguard Worker   return true;
139*84e33947SAndroid Build Coastguard Worker }
140*84e33947SAndroid Build Coastguard Worker 
141*84e33947SAndroid Build Coastguard Worker // TODO(b/242301032): factor code with handleMessageFromHost
handleMessageFromNanoapp(uint32_t senderInstanceId,const void * eventData)142*84e33947SAndroid Build Coastguard Worker bool RpcServer::handleMessageFromNanoapp(uint32_t senderInstanceId,
143*84e33947SAndroid Build Coastguard Worker                                          const void *eventData) {
144*84e33947SAndroid Build Coastguard Worker   const auto data = static_cast<const ChrePigweedNanoappMessage *>(eventData);
145*84e33947SAndroid Build Coastguard Worker   pw::span packet(reinterpret_cast<const std::byte *>(data->msg),
146*84e33947SAndroid Build Coastguard Worker                   data->msgSize);
147*84e33947SAndroid Build Coastguard Worker 
148*84e33947SAndroid Build Coastguard Worker   pw::Result<uint32_t> result = pw::rpc::ExtractChannelId(packet);
149*84e33947SAndroid Build Coastguard Worker   if (!result.status().ok()) {
150*84e33947SAndroid Build Coastguard Worker     LOGE("Unable to extract channel ID from packet: %" PRIu8,
151*84e33947SAndroid Build Coastguard Worker          static_cast<uint8_t>(result.status().code()));
152*84e33947SAndroid Build Coastguard Worker     return false;
153*84e33947SAndroid Build Coastguard Worker   }
154*84e33947SAndroid Build Coastguard Worker 
155*84e33947SAndroid Build Coastguard Worker   if (!validateNanoappChannelId(senderInstanceId, result.value())) {
156*84e33947SAndroid Build Coastguard Worker     return false;
157*84e33947SAndroid Build Coastguard Worker   }
158*84e33947SAndroid Build Coastguard Worker 
159*84e33947SAndroid Build Coastguard Worker   chreConfigureNanoappInfoEvents(true);
160*84e33947SAndroid Build Coastguard Worker 
161*84e33947SAndroid Build Coastguard Worker   mNanoappOutput.setClient(senderInstanceId);
162*84e33947SAndroid Build Coastguard Worker   pw::Status status = mServer.OpenChannel(result.value(), mNanoappOutput);
163*84e33947SAndroid Build Coastguard Worker   if (status != pw::OkStatus() && status != pw::Status::AlreadyExists()) {
164*84e33947SAndroid Build Coastguard Worker     LOGE("Failed to open channel: %" PRIu8, static_cast<uint8_t>(status.code()));
165*84e33947SAndroid Build Coastguard Worker     return false;
166*84e33947SAndroid Build Coastguard Worker   }
167*84e33947SAndroid Build Coastguard Worker 
168*84e33947SAndroid Build Coastguard Worker   status = mServer.ProcessPacket(packet);
169*84e33947SAndroid Build Coastguard Worker   if (!status.ok()) {
170*84e33947SAndroid Build Coastguard Worker     LOGE("Failed to process the packet: %" PRIu8, static_cast<uint8_t>(status.code()));
171*84e33947SAndroid Build Coastguard Worker     return false;
172*84e33947SAndroid Build Coastguard Worker   }
173*84e33947SAndroid Build Coastguard Worker 
174*84e33947SAndroid Build Coastguard Worker   return true;
175*84e33947SAndroid Build Coastguard Worker }
176*84e33947SAndroid Build Coastguard Worker 
handleHostClientNotification(const void * eventData)177*84e33947SAndroid Build Coastguard Worker void RpcServer::handleHostClientNotification(const void *eventData) {
178*84e33947SAndroid Build Coastguard Worker   if (mConnectedHosts.empty()) {
179*84e33947SAndroid Build Coastguard Worker     return;
180*84e33947SAndroid Build Coastguard Worker   }
181*84e33947SAndroid Build Coastguard Worker 
182*84e33947SAndroid Build Coastguard Worker   auto notif =
183*84e33947SAndroid Build Coastguard Worker       static_cast<const struct chreHostEndpointNotification *>(eventData);
184*84e33947SAndroid Build Coastguard Worker 
185*84e33947SAndroid Build Coastguard Worker   if (notif->notificationType == HOST_ENDPOINT_NOTIFICATION_TYPE_DISCONNECT) {
186*84e33947SAndroid Build Coastguard Worker     size_t hostIndex = mConnectedHosts.find(notif->hostEndpointId);
187*84e33947SAndroid Build Coastguard Worker     if (hostIndex != mConnectedHosts.size()) {
188*84e33947SAndroid Build Coastguard Worker       mServer
189*84e33947SAndroid Build Coastguard Worker           .CloseChannel(kChannelIdHostClient |
190*84e33947SAndroid Build Coastguard Worker                         static_cast<uint32_t>(notif->hostEndpointId))
191*84e33947SAndroid Build Coastguard Worker           .IgnoreError();
192*84e33947SAndroid Build Coastguard Worker       mConnectedHosts.erase(hostIndex);
193*84e33947SAndroid Build Coastguard Worker     }
194*84e33947SAndroid Build Coastguard Worker   }
195*84e33947SAndroid Build Coastguard Worker }
196*84e33947SAndroid Build Coastguard Worker 
handleNanoappStopped(const void * eventData)197*84e33947SAndroid Build Coastguard Worker void RpcServer::handleNanoappStopped(const void *eventData) {
198*84e33947SAndroid Build Coastguard Worker   auto info = static_cast<const struct chreNanoappInfo *>(eventData);
199*84e33947SAndroid Build Coastguard Worker 
200*84e33947SAndroid Build Coastguard Worker   if (info->instanceId > kRpcNanoappMaxId) {
201*84e33947SAndroid Build Coastguard Worker     LOGE("Invalid nanoapp instance ID %" PRIu32, info->instanceId);
202*84e33947SAndroid Build Coastguard Worker   } else if (pw::Status status = mServer.CloseChannel(info->instanceId);
203*84e33947SAndroid Build Coastguard Worker              !status.ok()) {
204*84e33947SAndroid Build Coastguard Worker     LOGE("Failed to close channel for nanoapp with instance ID %"
205*84e33947SAndroid Build Coastguard Worker          PRIu32 ": %" PRIu8, info->instanceId,
206*84e33947SAndroid Build Coastguard Worker          static_cast<uint8_t>(status.code()));
207*84e33947SAndroid Build Coastguard Worker   }
208*84e33947SAndroid Build Coastguard Worker }
209*84e33947SAndroid Build Coastguard Worker 
closeChannel(uint32_t id)210*84e33947SAndroid Build Coastguard Worker pw::Status RpcServer::closeChannel(uint32_t id) {
211*84e33947SAndroid Build Coastguard Worker   return mServer.CloseChannel(id);
212*84e33947SAndroid Build Coastguard Worker }
213*84e33947SAndroid Build Coastguard Worker 
214*84e33947SAndroid Build Coastguard Worker }  // namespace chre
215