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