xref: /aosp_15_r20/system/chre/host/hal_generic/common/multi_client_context_hub_base.h (revision 84e339476a462649f82315436d70fd732297a399)
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 ANDROID_HARDWARE_CONTEXTHUB_COMMON_MULTICLIENTS_HAL_BASE_H_
18 #define ANDROID_HARDWARE_CONTEXTHUB_COMMON_MULTICLIENTS_HAL_BASE_H_
19 
20 #include <aidl/android/hardware/contexthub/BnContextHub.h>
21 #include <chre_host/generated/host_messages_generated.h>
22 #include <chre_host/log_message_parser.h>
23 #include <chre_host/metrics_reporter.h>
24 
25 #include "chre_connection_callback.h"
26 #include "chre_host/napp_header.h"
27 #include "chre_host/preloaded_nanoapp_loader.h"
28 #include "chre_host/time_syncer.h"
29 #include "context_hub_v4_impl.h"
30 #include "debug_dump_helper.h"
31 #include "event_logger.h"
32 #include "hal_client_id.h"
33 #include "hal_client_manager.h"
34 
35 #include <chrono>
36 #include <deque>
37 #include <memory>
38 #include <mutex>
39 #include <optional>
40 #include <unordered_map>
41 #include <vector>
42 
43 namespace android::hardware::contexthub::common::implementation {
44 
45 using namespace aidl::android::hardware::contexthub;
46 using namespace android::chre;
47 using ::ndk::ScopedAStatus;
48 
49 /**
50  * The base class of multiclient HAL.
51  *
52  * <p>A subclass should initiate mConnection, mHalClientManager and
53  * mPreloadedNanoappLoader in its constructor.
54  */
55 class MultiClientContextHubBase
56     : public BnContextHub,
57       public ::android::hardware::contexthub::common::implementation::
58           ChreConnectionCallback,
59       public ::android::hardware::contexthub::DebugDumpHelper {
60  public:
61   /** The entry point of death recipient for a disconnected client. */
62   static void onClientDied(void *cookie);
63 
64   MultiClientContextHubBase();
65 
66   // Functions implementing IContextHub.
67   ScopedAStatus getContextHubs(
68       std::vector<ContextHubInfo> *contextHubInfos) override;
69   ScopedAStatus loadNanoapp(int32_t contextHubId,
70                             const NanoappBinary &appBinary,
71                             int32_t transactionId) override;
72   ScopedAStatus unloadNanoapp(int32_t contextHubId, int64_t appId,
73                               int32_t transactionId) override;
74   ScopedAStatus disableNanoapp(int32_t contextHubId, int64_t appId,
75                                int32_t transactionId) override;
76   ScopedAStatus enableNanoapp(int32_t contextHubId, int64_t appId,
77                               int32_t transactionId) override;
78   ScopedAStatus onSettingChanged(Setting setting, bool enabled) override;
79   ScopedAStatus queryNanoapps(int32_t contextHubId) override;
80   ScopedAStatus registerCallback(
81       int32_t contextHubId,
82       const std::shared_ptr<IContextHubCallback> &callback) override;
83   ScopedAStatus sendMessageToHub(int32_t contextHubId,
84                                  const ContextHubMessage &message) override;
85   ScopedAStatus onHostEndpointConnected(const HostEndpointInfo &info) override;
86   ScopedAStatus onHostEndpointDisconnected(char16_t in_hostEndpointId) override;
87   ScopedAStatus getPreloadedNanoappIds(int32_t contextHubId,
88                                        std::vector<int64_t> *result) override;
89   ScopedAStatus onNanSessionStateChanged(
90       const NanSessionStateUpdate &in_update) override;
91   ScopedAStatus setTestMode(bool enable) override;
92   ScopedAStatus sendMessageDeliveryStatusToHub(
93       int32_t contextHubId,
94       const MessageDeliveryStatus &messageDeliveryStatus) override;
95   ScopedAStatus getHubs(std::vector<HubInfo> *hubs) override;
96   ScopedAStatus getEndpoints(std::vector<EndpointInfo> *endpoints) override;
97   ScopedAStatus registerEndpoint(const EndpointInfo &endpoint) override;
98   ScopedAStatus unregisterEndpoint(const EndpointInfo &endpoint) override;
99   ScopedAStatus registerEndpointCallback(
100       const std::shared_ptr<IEndpointCallback> &callback) override;
101   ScopedAStatus requestSessionIdRange(int32_t size,
102                                       std::vector<int32_t> *ids) override;
103   ScopedAStatus openEndpointSession(
104       int32_t sessionId, const EndpointId &destination,
105       const EndpointId &initiator,
106       const std::optional<std::string> &serviceDescriptor) override;
107   ScopedAStatus sendMessageToEndpoint(int32_t sessionId,
108                                       const Message &msg) override;
109   ScopedAStatus sendMessageDeliveryStatusToEndpoint(
110       int32_t sessionId, const MessageDeliveryStatus &msgStatus) override;
111   ScopedAStatus closeEndpointSession(int32_t sessionId, Reason reason) override;
112   ScopedAStatus endpointSessionOpenComplete(int32_t sessionId) override;
113 
114   // Functions implementing ChreConnectionCallback.
115   void handleMessageFromChre(const unsigned char *messageBuffer,
116                              size_t messageLen) override;
117   void onChreRestarted() override;
onChreDisconnected()118   void onChreDisconnected() override {
119     mIsChreReady = false;
120   }
121 
122   // Functions for dumping debug information.
123   binder_status_t dump(int fd, const char **args, uint32_t numArgs) override;
124   bool requestDebugDump() override;
125   void writeToDebugFile(const char *str) override;
126 
127  protected:
128   // The timeout for a reliable message.
129   constexpr static std::chrono::nanoseconds kReliableMessageTimeout =
130       std::chrono::seconds(1);
131 
132   // The data needed by the death client to clear states of a client.
133   struct HalDeathRecipientCookie {
134     MultiClientContextHubBase *hal;
135     pid_t clientPid;
HalDeathRecipientCookieHalDeathRecipientCookie136     HalDeathRecipientCookie(MultiClientContextHubBase *hal, pid_t pid) {
137       this->hal = hal;
138       this->clientPid = pid;
139     }
140   };
141 
142   // Contains information about a reliable message that has been received.
143   struct ReliableMessageRecord {
144     std::chrono::time_point<std::chrono::steady_clock> timestamp;
145     int32_t messageSequenceNumber;
146     HostEndpointId hostEndpointId;
147 
isExpiredReliableMessageRecord148     bool isExpired() const {
149       return timestamp + kReliableMessageTimeout <
150              std::chrono::steady_clock::now();
151     }
152 
153     bool operator>(const ReliableMessageRecord &other) const {
154       return timestamp > other.timestamp;
155     }
156   };
157 
tryTimeSync(size_t numOfRetries,useconds_t retryDelayUs)158   void tryTimeSync(size_t numOfRetries, useconds_t retryDelayUs) {
159     if (mConnection->isTimeSyncNeeded()) {
160       TimeSyncer::sendTimeSyncWithRetry(mConnection.get(), numOfRetries,
161                                         retryDelayUs);
162     }
163   }
164 
165   bool sendFragmentedLoadRequest(HalClientId clientId,
166                                  FragmentedLoadRequest &fragmentedLoadRequest);
167 
168   // Functions handling various types of messages
169   void handleHubInfoResponse(const ::chre::fbs::HubInfoResponseT &message);
170   void onNanoappListResponse(const ::chre::fbs::NanoappListResponseT &response,
171                              HalClientId clientid);
172   void onNanoappLoadResponse(const ::chre::fbs::LoadNanoappResponseT &response,
173                              HalClientId clientId);
174   void onNanoappUnloadResponse(
175       const ::chre::fbs::UnloadNanoappResponseT &response,
176       HalClientId clientId);
177   void onNanoappMessage(const ::chre::fbs::NanoappMessageT &message);
178   void onMessageDeliveryStatus(
179       const ::chre::fbs::MessageDeliveryStatusT &status);
180   void onDebugDumpData(const ::chre::fbs::DebugDumpDataT &data);
181   void onDebugDumpComplete(
182       const ::chre::fbs::DebugDumpResponseT & /* response */);
183   void onMetricLog(const ::chre::fbs::MetricLogT &metricMessage);
184   void handleClientDeath(pid_t pid);
185   void handleLogMessageV2(const ::chre::fbs::LogMessageV2T &logMessage);
186 
187   /**
188    * Enables test mode by unloading all the nanoapps except the system nanoapps.
189    *
190    * @return true as long as we have a list of nanoapps to unload.
191    */
192   bool enableTestMode();
193 
194   /**
195    * Disables test mode by reloading all the <b>preloaded</b> nanoapps except
196    * system nanoapps.
197    *
198    * <p>Note that dynamically loaded nanoapps that are unloaded during
199    * enableTestMode() are not reloaded back because HAL doesn't track the
200    * location of their binaries.
201    */
202   void disableTestMode();
203 
isSettingEnabled(Setting setting)204   inline bool isSettingEnabled(Setting setting) {
205     return mSettingEnabled.find(setting) != mSettingEnabled.end() &&
206            mSettingEnabled[setting];
207   }
208 
209   /**
210    * Removes messages from the reliable message queue that have been received
211    * by the host more than kReliableMessageTimeout ago.
212    */
213   void cleanupReliableMessageQueueLocked();
214 
215   HalClientManager::DeadClientUnlinker mDeadClientUnlinker;
216 
217   // HAL is the unique owner of the communication channel to CHRE.
218   std::unique_ptr<ChreConnection> mConnection{};
219 
220   // HalClientManager maintains states of hal clients. Each HAL should only have
221   // one instance of a HalClientManager.
222   std::unique_ptr<HalClientManager> mHalClientManager{};
223 
224   // Implementation of the V4+ API. Should be instantiated by the target HAL
225   // implementation.
226   std::optional<ContextHubV4Impl> mV4Impl{};
227 
228   std::unique_ptr<PreloadedNanoappLoader> mPreloadedNanoappLoader{};
229 
230   std::unique_ptr<ContextHubInfo> mContextHubInfo;
231 
232   // Mutex and CV are used to get context hub info synchronously.
233   std::mutex mHubInfoMutex;
234   std::condition_variable mHubInfoCondition;
235 
236   // Death recipient handling clients' disconnections
237   ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
238 
239   // States of settings
240   std::unordered_map<Setting, bool> mSettingEnabled;
241   std::optional<bool> mIsWifiAvailable;
242   std::optional<bool> mIsBleAvailable;
243 
244   // A mutex to synchronize access to the list of preloaded nanoapp IDs.
245   std::mutex mPreloadedNanoappIdsMutex;
246   std::optional<std::vector<uint64_t>> mPreloadedNanoappIds{};
247 
248   // test mode settings
249   std::mutex mTestModeMutex;
250   std::condition_variable mEnableTestModeCv;
251   bool mIsTestModeEnabled = false;
252   std::optional<bool> mTestModeSyncUnloadResult = std::nullopt;
253   // mTestModeNanoapps records the nanoapps that will be unloaded in
254   // enableTestMode(). it is initialized to an empty vector to prevent it from
255   // unintended population in onNanoappListResponse().
256   std::optional<std::vector<uint64_t>> mTestModeNanoapps{{}};
257   // mTestModeSystemNanoapps records system nanoapps that won't be reloaded in
258   // disableTestMode().
259   std::optional<std::vector<uint64_t>> mTestModeSystemNanoapps;
260 
261   EventLogger mEventLogger;
262 
263   // The parser of buffered logs from CHRE
264   LogMessageParser mLogger;
265 
266   // Metrics reporter that will report metrics if it is initialized to non-null.
267   std::unique_ptr<MetricsReporter> mMetricsReporter;
268 
269   // Used to map message sequence number to host endpoint ID
270   std::mutex mReliableMessageMutex;
271   std::deque<ReliableMessageRecord> mReliableMessageQueue;
272 
273   // A thread safe flag indicating if CHRE is ready for operations.
274   // Outside of the constructor, this boolean flag should only be written by
275   // onChreDisconnected and onChreRestarted, the order of which should be
276   // guaranteed by the CHRE's disconnection handler.
277   std::atomic_bool mIsChreReady = true;
278 
279   // TODO(b/333567700): Remove when cleaning up the bug_fix_hal_reliable_message_record flag
280   std::unordered_map<int32_t, HostEndpointId> mReliableMessageMap;
281 };
282 }  // namespace android::hardware::contexthub::common::implementation
283 #endif  // ANDROID_HARDWARE_CONTEXTHUB_COMMON_MULTICLIENTS_HAL_BASE_H_
284