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