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