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