• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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