1 /* 2 * Copyright (C) 2021 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_AIDL_CONTEXTHUB_H 18 #define ANDROID_HARDWARE_CONTEXTHUB_AIDL_CONTEXTHUB_H 19 20 #include <aidl/android/hardware/contexthub/BnContextHub.h> 21 #include <android_chre_flags.h> 22 #include <log/log.h> 23 #include <atomic> 24 #include <functional> 25 #include <future> 26 #include <map> 27 #include <mutex> 28 #include <optional> 29 #include <unordered_set> 30 31 #include "chre_host/napp_header.h" 32 #include "context_hub_v4_impl.h" 33 #include "debug_dump_helper.h" 34 #include "event_logger.h" 35 #include "hal_chre_socket_connection.h" 36 37 namespace aidl::android::hardware::contexthub { 38 39 using ::android::chre::NanoAppBinaryHeader; 40 41 /** 42 * Contains information about a preloaded nanoapp. Used when getting 43 * preloaded nanoapp information from the config. 44 */ 45 struct chrePreloadedNanoappInfo { chrePreloadedNanoappInfochrePreloadedNanoappInfo46 chrePreloadedNanoappInfo(int64_t _id, const std::string &_name, 47 const NanoAppBinaryHeader &_header) 48 : id(_id), name(_name), header(_header) {} 49 50 int64_t id; 51 std::string name; 52 NanoAppBinaryHeader header; 53 }; 54 55 class ContextHub : public BnContextHub, 56 public ::android::hardware::contexthub::DebugDumpHelper, 57 public ::android::hardware::contexthub::common:: 58 implementation::IChreSocketCallback { 59 public: ContextHub()60 ContextHub() 61 : mDeathRecipient( 62 AIBinder_DeathRecipient_new(ContextHub::onServiceDied)) { 63 if (::android::chre::flags::offload_implementation()) { 64 mV4Impl.emplace([this](uint8_t *data, size_t size) { 65 return mConnection.sendRawMessage(data, size); 66 }); 67 } 68 } 69 ::ndk::ScopedAStatus getContextHubs( 70 std::vector<ContextHubInfo> *out_contextHubInfos) override; 71 ::ndk::ScopedAStatus loadNanoapp(int32_t contextHubId, 72 const NanoappBinary &appBinary, 73 int32_t transactionId) override; 74 ::ndk::ScopedAStatus unloadNanoapp(int32_t contextHubId, int64_t appId, 75 int32_t transactionId) override; 76 ::ndk::ScopedAStatus disableNanoapp(int32_t contextHubId, int64_t appId, 77 int32_t transactionId) override; 78 ::ndk::ScopedAStatus enableNanoapp(int32_t contextHubId, int64_t appId, 79 int32_t transactionId) override; 80 ::ndk::ScopedAStatus onSettingChanged(Setting setting, bool enabled) override; 81 ::ndk::ScopedAStatus queryNanoapps(int32_t contextHubId) override; 82 ::ndk::ScopedAStatus getPreloadedNanoappIds( 83 int32_t contextHubId, 84 std::vector<int64_t> *out_preloadedNanoappIds) override; 85 ::ndk::ScopedAStatus registerCallback( 86 int32_t contextHubId, 87 const std::shared_ptr<IContextHubCallback> &cb) override; 88 ::ndk::ScopedAStatus sendMessageToHub( 89 int32_t contextHubId, const ContextHubMessage &message) override; 90 ::ndk::ScopedAStatus setTestMode(bool enable) override; 91 ::ndk::ScopedAStatus sendMessageDeliveryStatusToHub( 92 int32_t contextHubId, 93 const MessageDeliveryStatus &messageDeliveryStatus) override; 94 ::ndk::ScopedAStatus onHostEndpointConnected( 95 const HostEndpointInfo &in_info) override; 96 ::ndk::ScopedAStatus onHostEndpointDisconnected( 97 char16_t in_hostEndpointId) override; 98 ::ndk::ScopedAStatus onNanSessionStateChanged( 99 const NanSessionStateUpdate &in_update) override; 100 ::ndk::ScopedAStatus getHubs(std::vector<HubInfo> *hubs) override; 101 ::ndk::ScopedAStatus getEndpoints( 102 std::vector<EndpointInfo> *endpoints) override; 103 ::ndk::ScopedAStatus registerEndpoint(const EndpointInfo &endpoint) override; 104 ::ndk::ScopedAStatus unregisterEndpoint( 105 const EndpointInfo &endpoint) override; 106 ::ndk::ScopedAStatus registerEndpointCallback( 107 const std::shared_ptr<IEndpointCallback> &callback) override; 108 ::ndk::ScopedAStatus requestSessionIdRange( 109 int32_t size, std::vector<int32_t> *ids) override; 110 ::ndk::ScopedAStatus openEndpointSession( 111 int32_t sessionId, const EndpointId &destination, 112 const EndpointId &initiator, 113 const std::optional<std::string> &serviceDescriptor) override; 114 ::ndk::ScopedAStatus sendMessageToEndpoint(int32_t sessionId, 115 const Message &msg) override; 116 ::ndk::ScopedAStatus sendMessageDeliveryStatusToEndpoint( 117 int32_t sessionId, const MessageDeliveryStatus &msgStatus) override; 118 ::ndk::ScopedAStatus closeEndpointSession(int32_t sessionId, 119 Reason reason) override; 120 ::ndk::ScopedAStatus endpointSessionOpenComplete(int32_t sessionId) override; 121 122 void onNanoappMessage(const ::chre::fbs::NanoappMessageT &message) override; 123 124 void onNanoappListResponse( 125 const ::chre::fbs::NanoappListResponseT &response) override; 126 127 void onTransactionResult(uint32_t transactionId, bool success) override; 128 129 void onContextHubRestarted() override; 130 131 void onDebugDumpData(const ::chre::fbs::DebugDumpDataT &data) override; 132 133 void onDebugDumpComplete( 134 const ::chre::fbs::DebugDumpResponseT &response) override; 135 136 bool onContextHubV4Message( 137 const ::chre::fbs::ChreMessageUnion &message) override; 138 139 void handleServiceDeath(); 140 static void onServiceDied(void *cookie); 141 142 binder_status_t dump(int fd, const char **args, uint32_t numArgs) override; 143 requestDebugDump()144 bool requestDebugDump() override { 145 return mConnection.requestDebugDump(); 146 } 147 148 void debugDumpFinish() override; 149 150 void writeToDebugFile(const char *str) override; 151 152 private: 153 /** 154 * Enables test mode on the context hub. This unloads all nanoapps and puts 155 * CHRE in a state that is consistent for testing. 156 * 157 * @return the status. 158 */ 159 ::ndk::ScopedAStatus enableTestMode(); 160 161 /** 162 * Disables test mode. Reverses the affects of enableTestMode() by loading all 163 * preloaded nanoapps. This puts CHRE back in a normal state. 164 * 165 * @return the status. 166 */ 167 ::ndk::ScopedAStatus disableTestMode(); 168 169 /** 170 * Queries the list of loaded nanoapps in a synchronous manner. 171 * The list is stored in the mQueryNanoappsInternalList variable. 172 * 173 * @param contextHubId the ID of the context hub. 174 * @param nanoappIdList (out) optional out parameter that 175 * contains the nanoapp IDs. 176 * 177 * @return true the operation was successful. 178 * @return false the operation was not successful. 179 */ 180 bool queryNanoappsInternal(int32_t contextHubId, 181 std::vector<int64_t> *nanoappIdList); 182 183 /** 184 * Loads a nanoapp. 185 * 186 * @param appBinary the nanoapp binary to load. 187 * @param transactionId the transaction ID. 188 * 189 * @return true the operation was successful. 190 * @return false the operation was not successful. 191 */ 192 bool loadNanoappInternal(const NanoappBinary &appBinary, 193 int32_t transactionId); 194 195 /** 196 * Loads the nanoapps in a synchronous manner. 197 * 198 * @param contextHubId the ID of the context hub. 199 * @param nanoappBinaryList the list of NanoappBinary's to load. 200 * @return true the operation was successful. 201 * @return false the operation was not successful. 202 */ 203 bool loadNanoappsInternal( 204 int32_t contextHubId, 205 const std::vector<NanoappBinary> &nanoappBinaryList); 206 207 /** 208 * Unloads a nanoapp. 209 * 210 * @param appId the nanoapp ID to unload. 211 * @param transactionId the transaction ID. 212 * 213 * @return true the operation was successful. 214 * @return false the operation was not successful. 215 */ 216 bool unloadNanoappInternal(int64_t appId, int32_t transactionId); 217 218 /** 219 * Unloads the nanoapps in a synchronous manner. 220 * 221 * @param contextHubId the ID of the context hub. 222 * @param nanoappIdsToUnload the list of nanoapp IDs to unload. 223 * @return true the operation was successful. 224 * @return false the operation was not successful. 225 */ 226 bool unloadNanoappsInternal(int32_t contextHubId, 227 const std::vector<int64_t> &nanoappIdList); 228 229 /** 230 * Get the preloaded nanoapp IDs from the config file and headers. All IDs, 231 * names and headers are in the same order (one nanoapp has the same index in 232 * each). 233 * 234 * @param out_preloadedNanoapps out parameter, the nanoapp information. 235 * @param out_directory out parameter, optional, the directory 236 * that contains the nanoapps. 237 * @return true the operation was successful. 238 * @return false the operation was not successful. 239 */ 240 bool getPreloadedNanoappIdsFromConfigFile( 241 std::vector<chrePreloadedNanoappInfo> &out_preloadedNanoapps, 242 std::string *out_directory) const; 243 244 /** 245 * Selects the nanoapps to load -> all preloaded and non-system nanoapps. 246 * 247 * @param preloadedNanoapps the preloaded nanoapps. 248 * @param preloadedNanoappDirectory the preloaded nanoapp directory. 249 * @return the nanoapps to load. 250 */ 251 std::vector<NanoappBinary> selectPreloadedNanoappsToLoad( 252 std::vector<chrePreloadedNanoappInfo> &preloadedNanoapps, 253 const std::string &preloadedNanoappDirectory); 254 isSettingEnabled(Setting setting)255 bool isSettingEnabled(Setting setting) { 256 return mSettingEnabled.count(setting) > 0 && mSettingEnabled[setting]; 257 } 258 toFbsSettingState(bool enabled)259 chre::fbs::SettingState toFbsSettingState(bool enabled) const { 260 return enabled ? chre::fbs::SettingState::ENABLED 261 : chre::fbs::SettingState::DISABLED; 262 } 263 264 ::android::hardware::contexthub::common::implementation:: 265 HalChreSocketConnection mConnection{this}; 266 267 // A mutex to protect concurrent modifications to the callback pointer and 268 // access (invocations). 269 std::mutex mCallbackMutex; 270 std::shared_ptr<IContextHubCallback> mCallback; 271 272 ndk::ScopedAIBinder_DeathRecipient mDeathRecipient; 273 274 // Implementation of the V4 API. 275 std::optional< 276 ::android::hardware::contexthub::common::implementation::ContextHubV4Impl> 277 mV4Impl{}; 278 279 std::map<Setting, bool> mSettingEnabled; 280 std::optional<bool> mIsWifiAvailable; 281 std::optional<bool> mIsBleAvailable; 282 283 std::mutex mConnectedHostEndpointsMutex; 284 std::unordered_set<char16_t> mConnectedHostEndpoints; 285 286 // Logs events to be reported in debug dumps. 287 EventLogger mEventLogger; 288 289 // A mutex to synchronize access to the list of preloaded nanoapp IDs. 290 std::mutex mPreloadedNanoappIdsMutex; 291 std::optional<std::vector<int64_t>> mPreloadedNanoappIds; 292 293 // A mutex and condition variable to synchronize queryNanoappsInternal. 294 std::mutex mQueryNanoappsInternalMutex; 295 std::condition_variable mQueryNanoappsInternalCondVar; 296 std::optional<std::vector<NanoappInfo>> mQueryNanoappsInternalList; 297 298 // State for synchronous loads and unloads. Primarily used for test mode. 299 std::mutex mSynchronousLoadUnloadMutex; 300 std::condition_variable mSynchronousLoadUnloadCondVar; 301 std::optional<bool> mSynchronousLoadUnloadSuccess; 302 std::optional<int32_t> mSynchronousLoadUnloadTransactionId; 303 304 // A boolean and mutex to synchronize test mode state changes and 305 // load/unloads. 306 std::mutex mTestModeMutex; 307 bool mIsTestModeEnabled = false; 308 309 // List of system nanoapp Ids. 310 std::vector<int64_t> mSystemNanoappIds; 311 }; 312 313 } // namespace aidl::android::hardware::contexthub 314 315 #endif // ANDROID_HARDWARE_CONTEXTHUB_AIDL_CONTEXTHUB_H 316