1 /* 2 * Copyright (C) 2017 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_V1_0_CONTEXTHUB_H 18 #define ANDROID_HARDWARE_CONTEXTHUB_V1_0_CONTEXTHUB_H 19 20 #include <condition_variable> 21 #include <functional> 22 #include <mutex> 23 #include <optional> 24 25 #include <android/hardware/contexthub/1.0/IContexthub.h> 26 #include <hidl/MQDescriptor.h> 27 #include <hidl/Status.h> 28 29 #include "chre_host/socket_client.h" 30 #include "chre_host/host_protocol_host.h" 31 #include "chre_host/fragmented_load_transaction.h" 32 33 namespace android { 34 namespace hardware { 35 namespace contexthub { 36 namespace V1_0 { 37 namespace implementation { 38 39 using ::android::chre::FragmentedLoadRequest; 40 using ::android::chre::FragmentedLoadTransaction; 41 using ::android::hardware::contexthub::V1_0::ContextHub; 42 using ::android::hardware::contexthub::V1_0::ContextHubMsg; 43 using ::android::hardware::contexthub::V1_0::IContexthub; 44 using ::android::hardware::contexthub::V1_0::IContexthubCallback; 45 using ::android::hardware::contexthub::V1_0::NanoAppBinary; 46 using ::android::hardware::contexthub::V1_0::Result; 47 using ::android::hardware::hidl_handle; 48 using ::android::hardware::hidl_string; 49 using ::android::hardware::hidl_vec; 50 using ::android::hardware::Return; 51 using ::android::sp; 52 53 class GenericContextHub : public IContexthub { 54 public: 55 GenericContextHub(); 56 57 Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override; 58 59 // Methods from ::android::hardware::contexthub::V1_0::IContexthub follow. 60 Return<void> getHubs(getHubs_cb _hidl_cb) override; 61 Return<Result> registerCallback(uint32_t hubId, const sp<IContexthubCallback>& cb) override; 62 Return<Result> sendMessageToHub(uint32_t hubId, const ContextHubMsg& msg) override; 63 Return<Result> loadNanoApp(uint32_t hubId, const NanoAppBinary& appBinary, uint32_t transactionId) override; 64 Return<Result> unloadNanoApp(uint32_t hubId, uint64_t appId, uint32_t transactionId) override; 65 Return<Result> enableNanoApp(uint32_t hubId, uint64_t appId, uint32_t transactionId) override; 66 Return<Result> disableNanoApp(uint32_t hubId, uint64_t appId, uint32_t transactionId) override; 67 Return<Result> queryApps(uint32_t hubId) override; 68 69 private: 70 ::android::chre::SocketClient mClient; 71 sp<IContexthubCallback> mCallbacks; 72 std::mutex mCallbacksLock; 73 74 class SocketCallbacks : public ::android::chre::SocketClient::ICallbacks, 75 public ::android::chre::IChreMessageHandlers { 76 public: 77 explicit SocketCallbacks(GenericContextHub& parent); 78 void onMessageReceived(const void *data, size_t length) override; 79 void onConnected() override; 80 void onDisconnected() override; 81 82 void handleNanoappMessage( 83 const ::chre::fbs::NanoappMessageT& message) override; 84 85 void handleHubInfoResponse( 86 const ::chre::fbs::HubInfoResponseT& response) override; 87 88 void handleNanoappListResponse( 89 const ::chre::fbs::NanoappListResponseT& response) override; 90 91 void handleLoadNanoappResponse( 92 const ::chre::fbs::LoadNanoappResponseT& response) override; 93 94 void handleUnloadNanoappResponse( 95 const ::chre::fbs::UnloadNanoappResponseT& response) override; 96 97 void handleDebugDumpData( 98 const ::chre::fbs::DebugDumpDataT& data) override; 99 100 void handleDebugDumpResponse( 101 const ::chre::fbs::DebugDumpResponseT& response) override; 102 103 private: 104 GenericContextHub& mParent; 105 bool mHaveConnected = false; 106 107 /** 108 * Acquires mParent.mCallbacksLock and invokes the synchronous callback 109 * argument if mParent.mCallbacks is not null. 110 */ 111 void invokeClientCallback(std::function<Return<void>()> callback); 112 }; 113 114 class DeathRecipient : public hidl_death_recipient { 115 public: 116 explicit DeathRecipient(const sp<GenericContextHub> contexthub); 117 void serviceDied(uint64_t cookie, 118 const wp<::android::hidl::base::V1_0::IBase>& who) 119 override; 120 121 private: 122 sp<GenericContextHub> mGenericContextHub; 123 }; 124 125 sp<SocketCallbacks> mSocketCallbacks; 126 sp<DeathRecipient> mDeathRecipient; 127 128 // Cached hub info used for getHubs(), and synchronization primitives to make 129 // that function call synchronous if we need to query it 130 ContextHub mHubInfo; 131 bool mHubInfoValid = false; 132 std::mutex mHubInfoMutex; 133 std::condition_variable mHubInfoCond; 134 135 static constexpr int kInvalidFd = -1; 136 int mDebugFd = kInvalidFd; 137 bool mDebugDumpPending = false; 138 std::mutex mDebugDumpMutex; 139 std::condition_variable mDebugDumpCond; 140 141 // The pending fragmented load request 142 uint32_t mCurrentFragmentId = 0; 143 std::optional<FragmentedLoadTransaction> mPendingLoadTransaction; 144 std::mutex mPendingLoadTransactionMutex; 145 146 // Use 30KB fragment size to fit within 32KB memory fragments at the kernel 147 static constexpr size_t kLoadFragmentSizeBytes = 30 * 1024; 148 149 // Write a string to mDebugFd 150 void writeToDebugFile(const char *str); 151 void writeToDebugFile(const char *str, size_t len); 152 153 // Unregisters callback when context hub service dies 154 void handleServiceDeath(uint32_t hubId); 155 156 /** 157 * Checks to see if a load response matches the currently pending 158 * fragmented load transaction. mPendingLoadTransactionMutex must 159 * be acquired prior to calling this function. 160 * 161 * @param response the received load response 162 * 163 * @return true if the response matches a pending load transaction 164 * (if any), false otherwise 165 */ 166 bool isExpectedLoadResponseLocked( 167 const ::chre::fbs::LoadNanoappResponseT& response); 168 169 /** 170 * Sends a fragmented load request to CHRE. The caller must ensure that 171 * transaction.isComplete() returns false prior to invoking this method. 172 * 173 * @param transaction the FragmentedLoadTransaction object 174 * 175 * @return the result of the request 176 */ 177 Result sendFragmentedLoadNanoAppRequest( 178 FragmentedLoadTransaction& transaction); 179 }; 180 181 extern "C" IContexthub* HIDL_FETCH_IContexthub(const char* name); 182 183 } // namespace implementation 184 } // namespace V1_0 185 } // namespace contexthub 186 } // namespace hardware 187 } // namespace android 188 189 #endif // ANDROID_HARDWARE_CONTEXTHUB_V1_0_CONTEXTHUB_H 190