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 CHRE_HOST_PRELOADED_NANOAPP_LOADER_H_ 18 #define CHRE_HOST_PRELOADED_NANOAPP_LOADER_H_ 19 20 #include <android/binder_to_string.h> 21 #include <cstdint> 22 #include <mutex> 23 #include <optional> 24 #include <string> 25 #include <utility> 26 27 #include "chre_connection.h" 28 #include "chre_host/generated/host_messages_generated.h" 29 #include "chre_host/napp_header.h" 30 #include "fragmented_load_transaction.h" 31 #include "hal_client_id.h" 32 33 namespace android::chre { 34 35 using namespace ::android::hardware::contexthub::common::implementation; 36 37 /** 38 * A class loads preloaded nanoapps. 39 * 40 * A context hub can include a set of nanoapps that are included in the device 41 * image and are loaded when CHRE starts. These are known as preloaded nanoapps. 42 * A HAL implementation should use this class to load preloaded nanoapps before 43 * exposing API to HAL clients. 44 */ 45 class PreloadedNanoappLoader { 46 public: PreloadedNanoappLoader(ChreConnection * connection,std::string configPath)47 explicit PreloadedNanoappLoader(ChreConnection *connection, 48 std::string configPath) 49 : mConnection(connection), mConfigPath(std::move(configPath)){}; 50 51 ~PreloadedNanoappLoader() = default; 52 /** 53 * Attempts to load all preloaded nanoapps from a config file. 54 * 55 * The config file is expected to be valid JSON with the following structure: 56 * 57 * { "nanoapps": [ 58 * "/path/to/nanoapp_1", 59 * "/path/to/nanoapp_2" 60 * ]} 61 * 62 * The napp_header and so files will both be used. 63 */ 64 void loadPreloadedNanoapps(); 65 66 /** Callback function to handle the response from CHRE. */ 67 bool onLoadNanoappResponse(const ::chre::fbs::LoadNanoappResponseT &response, 68 HalClientId clientId); 69 70 void getPreloadedNanoappIds(std::vector<uint64_t> &out_preloadedNanoappIds); 71 72 /** Returns true if the loading is ongoing. */ isPreloadOngoing()73 [[nodiscard]] bool isPreloadOngoing() const { 74 return mIsPreloadingOngoing; 75 }; 76 77 private: 78 /** Timeout value of waiting for the response of a fragmented load */ 79 static constexpr auto kTimeoutInMs = std::chrono::milliseconds(2000); 80 81 /** 82 * Loads a preloaded nanoapp given a filename. 83 * 84 * This function allows the transaction to complete before the nanoapp starts 85 * so the server can start serving requests as soon as possible. 86 * 87 * @param directory The directory to load the nanoapp from. 88 * @param name The filename of the nanoapp to load. 89 * @param transactionId The transaction ID to use when loading the app. 90 */ 91 void loadPreloadedNanoapp(const std::string &directory, 92 const std::string &name, uint32_t transactionId); 93 94 /** 95 * Loads a preloaded nanoapp. 96 * 97 * @param header The nanoapp header binary blob. 98 * @param nanoapp The nanoapp binary. 99 * @param transactionId The transaction ID identifying this load transaction. 100 * @return true if successful, false otherwise. 101 */ 102 bool loadNanoapp(const std::vector<uint8_t> &header, 103 const std::vector<uint8_t> &nanoapp, uint32_t transactionId); 104 105 /** 106 * Chunks the nanoapp binary into fragments and load each fragment 107 * sequentially. 108 */ 109 bool sendFragmentedLoadAndWaitForEachResponse( 110 uint64_t appId, uint32_t appVersion, uint32_t appFlags, 111 uint32_t appTargetApiVersion, const uint8_t *appBinary, size_t appSize, 112 uint32_t transactionId); 113 114 /** Sends the FragmentedLoadRequest to CHRE. */ 115 std::future<bool> sendFragmentedLoadRequest( 116 ::android::chre::FragmentedLoadRequest &request); 117 118 /** Verifies the future returned by sendFragmentedLoadRequest(). */ 119 [[nodiscard]] static bool waitAndVerifyFuture( 120 std::future<bool> &future, const FragmentedLoadRequest &request); 121 122 /** Verifies the response of a loading request. */ 123 [[nodiscard]] bool verifyFragmentLoadResponse( 124 const ::chre::fbs::LoadNanoappResponseT &response) const; 125 126 /** Tracks the transaction state of the ongoing nanoapp loading */ 127 struct Transaction { 128 uint32_t transactionId; 129 size_t fragmentId; 130 }; 131 Transaction mPreloadedNanoappPendingTransaction{0, 0}; 132 133 /** The value of this promise carries the result in the load response. */ 134 std::optional<std::promise<bool>> mFragmentedLoadPromise = std::nullopt; 135 136 /** The mutex used to guard states change for preloading. */ 137 std::mutex mPreloadedNanoappsMutex; 138 139 bool mIsPreloadingOngoing = false; 140 141 ChreConnection *mConnection; 142 std::string mConfigPath; 143 }; 144 145 } // namespace android::chre 146 147 #endif // CHRE_HOST_PRELOADED_NANOAPP_LOADER_H_ 148