1 /*
2  * Copyright (C) 2022 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 #include "chre/util/pigweed/rpc_client.h"
18 
19 #include <cinttypes>
20 #include <cstdint>
21 
22 #include "chre/util/macros.h"
23 #include "chre/util/nanoapp/log.h"
24 #include "chre/util/pigweed/rpc_helper.h"
25 #include "chre_api/chre.h"
26 
27 #ifndef LOG_TAG
28 #define LOG_TAG "[RpcClient]"
29 #endif  // LOG_TAG
30 
31 namespace chre {
32 
handleEvent(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)33 bool RpcClient::handleEvent(uint32_t senderInstanceId, uint16_t eventType,
34                             const void *eventData) {
35   switch (eventType) {
36     case CHRE_EVENT_RPC_RESPONSE:
37       return handleMessageFromServer(senderInstanceId, eventData);
38     case CHRE_EVENT_NANOAPP_STOPPED:
39       handleNanoappStopped(eventData);
40       return true;
41   }
42 
43   return true;
44 }
45 
hasService(uint64_t id,uint32_t version)46 bool RpcClient::hasService(uint64_t id, uint32_t version) {
47   struct chreNanoappInfo info;
48   if (!chreGetNanoappInfoByAppId(mServerNanoappId, &info)) {
49     return false;
50   }
51 
52   for (uint32_t i = 0; i < info.rpcServiceCount; i++) {
53     if (info.rpcServices[i].id == id) {
54       return info.rpcServices[i].version == version;
55     }
56   }
57 
58   return false;
59 }
60 
close()61 void RpcClient::close() {
62   chreConfigureNanoappInfoEvents(false);
63 }
64 
handleMessageFromServer(uint32_t senderInstanceId,const void * eventData)65 bool RpcClient::handleMessageFromServer(uint32_t senderInstanceId,
66                                         const void *eventData) {
67   auto data = static_cast<const chre::ChrePigweedNanoappMessage *>(eventData);
68   pw::span packet(reinterpret_cast<const std::byte *>(data->msg),
69                   data->msgSize);
70   struct chreNanoappInfo info;
71 
72   if (!chreGetNanoappInfoByAppId(mServerNanoappId, &info) ||
73       info.instanceId > kRpcNanoappMaxId) {
74     return false;
75   }
76 
77   if (!validateNanoappChannelId(senderInstanceId, info.instanceId)) {
78     return false;
79   }
80 
81   pw::Status status = mRpcClient.ProcessPacket(packet);
82 
83   if (status != pw::OkStatus()) {
84     LOGE("Failed to process the packet");
85     return false;
86   }
87 
88   return true;
89 }
90 
handleNanoappStopped(const void * eventData)91 void RpcClient::handleNanoappStopped(const void *eventData) {
92   auto info = static_cast<const struct chreNanoappInfo *>(eventData);
93 
94   if (info->instanceId > kRpcNanoappMaxId) {
95     LOGE("Invalid nanoapp Id 0x%08" PRIx32, info->instanceId);
96     return;
97   }
98 
99   if (info->instanceId == mChannelId) {
100     mRpcClient.CloseChannel(mChannelId);
101     mChannelId = 0;
102   }
103 }
104 
105 }  // namespace chre