• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
~RpcClient()49   ~RpcClient() {
50     chreConfigureNanoappInfoEvents(false);
51   }
52 
53   /**
54    * Handles events related to RPC services.
55    *
56    * Handles the following events:
57    * - PW_RPC_CHRE_NAPP_RESPONSE_EVENT_TYPE: handle the server responses,
58    * - CHRE_EVENT_NANOAPP_STOPPED: close the channel when the server nanoapp
59    *   terminates.
60    *
61    * @param senderInstanceId The Instance ID for the source of this event.
62    * @param eventType The event type.
63    * @param eventData The associated data, if any, for this specific type of
64    *                  event.
65    * @return whether any event was handled successfully.
66    */
67   bool handleEvent(uint32_t senderInstanceId, uint16_t eventType,
68                    const void *eventData);
69 
70   /**
71    * Returns a service client.
72    *
73    * NOTE: The template parameter must be set to the Pigweed client type,
74    *       i.e. pw::rpc::pw_rpc::nanopb::<ServiceName>::Client
75 
76    * @return The service client. It has no value on errors.
77    */
78   template <typename T>
79   Optional<T> get();
80 
81   /**
82    * Returns whether the server nanoapp supports the service.
83    *
84    * Also returns false when the nanoapp is not loaded.
85    *
86    * @return whether the service is published by the server.
87    */
88   bool hasService(uint64_t id, uint32_t version);
89 
90  private:
91   /**
92    * Handles responses from the server.
93    *
94    * This method must be called when nanoapps receive a
95    * PW_RPC_CHRE_NAPP_RESPONSE_EVENT_TYPE event.
96    *
97    * @param senderInstanceId The Instance ID for the source of this event.
98    * @param eventData  The associated data, if any.
99    * @return whether the RPC was handled successfully.
100    */
101   bool handleMessageFromServer(uint32_t senderInstanceId,
102                                const void *eventData);
103 
104   /**
105    * Closes the Pigweed channel when the server terminates.
106    *
107    * @param notification The eventData associated to a
108    *    CHRE_EVENT_NANOAPP_STOPPED event.
109    */
110   void handleNanoappStopped(const void *eventData);
111 
112   ChreClientNanoappChannelOutput mChannelOutput;
113   pw::rpc::Client mRpcClient;
114   uint64_t mServerNanoappId;
115   uint32_t mChannelId = 0;
116 };
117 
118 template <typename T>
get()119 Optional<T> RpcClient::get() {
120   if (mChannelId == 0) {
121     struct chreNanoappInfo info;
122 
123     if (!chreGetNanoappInfoByAppId(mServerNanoappId, &info) ||
124         info.instanceId > kRpcNanoappMaxId) {
125       return Optional<T>();
126     }
127 
128     mChannelId = chreGetInstanceId();
129     mChannelOutput.setServer(info.instanceId);
130     mRpcClient.OpenChannel(mChannelId, mChannelOutput);
131   }
132 
133   chreConfigureNanoappInfoEvents(true);
134   return T(mRpcClient, mChannelId);
135 }
136 
137 }  // namespace chre
138 
139 #endif  // CHRE_UTIL_PIGWEED_RPC_SERVER_H_