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 #ifndef CHRE_UTIL_PIGWEED_RPC_CLIENT_H_
18 #define CHRE_UTIL_PIGWEED_RPC_CLIENT_H_
19
20 #include <cstdint>
21
22 #include "chre/util/non_copyable.h"
23 #include "chre/util/optional.h"
24 #include "chre/util/pigweed/chre_channel_output.h"
25 #include "chre/util/unique_ptr.h"
26 #include "chre_api/chre.h"
27 #include "pw_rpc/client.h"
28 #include "pw_span/span.h"
29 #include "rpc_helper.h"
30
31 namespace chre {
32
33 /**
34 * RPC Client wrapping a Pigweed RPC client.
35 *
36 * This helper class handles Pigweed RPC calls on the client side.
37 *
38 * The `handleEvent` method must be called at the beginning of the
39 * `nanoappHandleEvent` function to handle RPC responses from the server.
40 */
41 class RpcClient : public NonCopyable {
42 public:
43 /**
44 * @param serverNanoappId Nanoapp ID of the server.
45 */
RpcClient(uint64_t serverNanoappId)46 explicit RpcClient(uint64_t serverNanoappId)
47 : mServerNanoappId((serverNanoappId)) {}
48
49 /**
50 * Handles events related to RPC services.
51 *
52 * Handles the following events:
53 * - CHRE_EVENT_RPC_RESPONSE: handle the server responses,
54 * - CHRE_EVENT_NANOAPP_STOPPED: close the channel when the server nanoapp
55 * terminates.
56 *
57 * @param senderInstanceId The Instance ID for the source of this event.
58 * @param eventType The event type.
59 * @param eventData The associated data, if any, for this specific type of
60 * event.
61 * @return whether any event was handled successfully.
62 */
63 bool handleEvent(uint32_t senderInstanceId, uint16_t eventType,
64 const void *eventData);
65
66 /**
67 * Returns a service client.
68 *
69 * NOTE: The template parameter must be set to the Pigweed client type,
70 * i.e. pw::rpc::pw_rpc::nanopb::<ServiceName>::Client
71
72 * @return The service client. It has no value on errors.
73 */
74 template <typename T>
75 Optional<T> get();
76
77 /**
78 * Returns whether the server nanoapp supports the service.
79 *
80 * Also returns false when the nanoapp is not loaded.
81 *
82 * @return whether the service is published by the server.
83 */
84 bool hasService(uint64_t id, uint32_t version);
85
86 /**
87 * Must be called from nanoapp end.
88 */
89 void close();
90
91 private:
92 /**
93 * Handles responses from the server.
94 *
95 * This method must be called when nanoapps receive a CHRE_EVENT_RPC_RESPONSE
96 * event.
97 *
98 * @param senderInstanceId The Instance ID for the source of this event.
99 * @param eventData The associated data, if any.
100 * @return whether the RPC was handled successfully.
101 */
102 bool handleMessageFromServer(uint32_t senderInstanceId,
103 const void *eventData);
104
105 /**
106 * Closes the Pigweed channel when the server terminates.
107 *
108 * @param notification The eventData associated to a
109 * CHRE_EVENT_NANOAPP_STOPPED event.
110 */
111 void handleNanoappStopped(const void *eventData);
112
113 ChreClientNanoappChannelOutput mChannelOutput;
114 pw::rpc::Client mRpcClient;
115 uint64_t mServerNanoappId;
116 uint32_t mChannelId = 0;
117 };
118
119 template <typename T>
get()120 Optional<T> RpcClient::get() {
121 if (mChannelId == 0) {
122 struct chreNanoappInfo info;
123
124 if (!chreGetNanoappInfoByAppId(mServerNanoappId, &info) ||
125 info.instanceId > kRpcNanoappMaxId) {
126 return Optional<T>();
127 }
128
129 mChannelId = chreGetInstanceId();
130 mChannelOutput.setServer(info.instanceId);
131 mRpcClient.OpenChannel(mChannelId, mChannelOutput);
132 }
133
134 chreConfigureNanoappInfoEvents(true);
135 return T(mRpcClient, mChannelId);
136 }
137
138 } // namespace chre
139
140 #endif // CHRE_UTIL_PIGWEED_RPC_SERVER_H_