xref: /aosp_15_r20/system/chre/host/common/include/chre_host/preloaded_nanoapp_loader.h (revision 84e339476a462649f82315436d70fd732297a399)
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   /** The possible results of verification of a fragment load response. */
105   enum class ResponseVerificationResult {
106     SUCCESS = 0,
107     FAILURE = 1,
108     IGNORED = 2,
109   };
110 
111   /**
112    * Loads a preloaded nanoapp.
113    *
114    * @param appHeader The nanoapp header binary blob.
115    * @param nanoappFileName The nanoapp binary file name.
116    * @param transactionId The transaction ID identifying this load transaction.
117    * @return true if successful, false otherwise.
118    */
119   bool loadNanoapp(const NanoAppBinaryHeader *appHeader,
120                    const std::string &nanoappFileName, uint32_t transactionId);
121 
122   /**
123    * Chunks the nanoapp binary into fragments and load each fragment
124    * sequentially.
125    */
126   bool sendFragmentedLoadAndWaitForEachResponse(
127       uint64_t appId, uint32_t appVersion, uint32_t appFlags,
128       uint32_t appTargetApiVersion, const uint8_t *appBinary, size_t appSize,
129       uint32_t transactionId);
130 
131   /** Sends the FragmentedLoadRequest to CHRE. */
132   std::future<bool> sendFragmentedLoadRequest(
133       ::android::chre::FragmentedLoadRequest &request);
134 
135   /** Verifies the future returned by sendFragmentedLoadRequest(). */
136   [[nodiscard]] bool waitAndVerifyFuture(std::future<bool> &future,
137                                          const FragmentedLoadRequest &request);
138 
139   /** Verifies the response of a loading request. */
140   [[nodiscard]] ResponseVerificationResult verifyFragmentLoadResponse(
141       const ::chre::fbs::LoadNanoappResponseT &response) const;
142 
143   Transaction mPendingTransaction{/* transactionId= */ 0,
144                                   /* fragmentId= */ 0};
145 
146   /** The value of this promise carries the result in the load response. */
147   std::optional<std::promise<bool>> mFragmentedLoadPromise = std::nullopt;
148 
149   /** The mutex used to guard states change for preloading. */
150   std::mutex mPreloadedNanoappsMutex;
151 
152   std::atomic_bool mIsPreloadingOngoing = false;
153 
154   ChreConnection *mConnection;
155   EventLogger &mEventLogger;
156   MetricsReporter *mMetricsReporter;
157   std::string mConfigPath;
158 
159   INanoappLoadListener *mNanoappLoadListener;
160 };
161 
162 }  // namespace android::chre
163 
164 #endif  // CHRE_HOST_PRELOADED_NANOAPP_LOADER_H_
165