xref: /aosp_15_r20/system/chre/host/common/preloaded_nanoapp_loader.cc (revision 84e339476a462649f82315436d70fd732297a399)
1*84e33947SAndroid Build Coastguard Worker /*
2*84e33947SAndroid Build Coastguard Worker  * Copyright (C) 2022 The Android Open Source Project
3*84e33947SAndroid Build Coastguard Worker  *
4*84e33947SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*84e33947SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*84e33947SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*84e33947SAndroid Build Coastguard Worker  *
8*84e33947SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*84e33947SAndroid Build Coastguard Worker  *
10*84e33947SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*84e33947SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*84e33947SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*84e33947SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*84e33947SAndroid Build Coastguard Worker  * limitations under the License.
15*84e33947SAndroid Build Coastguard Worker  */
16*84e33947SAndroid Build Coastguard Worker 
17*84e33947SAndroid Build Coastguard Worker #include "chre_host/preloaded_nanoapp_loader.h"
18*84e33947SAndroid Build Coastguard Worker #include <chre_host/host_protocol_host.h>
19*84e33947SAndroid Build Coastguard Worker #include <fstream>
20*84e33947SAndroid Build Coastguard Worker #include "chre_host/config_util.h"
21*84e33947SAndroid Build Coastguard Worker #include "chre_host/file_stream.h"
22*84e33947SAndroid Build Coastguard Worker #include "chre_host/fragmented_load_transaction.h"
23*84e33947SAndroid Build Coastguard Worker #include "chre_host/log.h"
24*84e33947SAndroid Build Coastguard Worker #include "chre_host/nanoapp_load_listener.h"
25*84e33947SAndroid Build Coastguard Worker #include "hal_client_id.h"
26*84e33947SAndroid Build Coastguard Worker 
27*84e33947SAndroid Build Coastguard Worker namespace android::chre {
28*84e33947SAndroid Build Coastguard Worker 
29*84e33947SAndroid Build Coastguard Worker namespace {
30*84e33947SAndroid Build Coastguard Worker 
31*84e33947SAndroid Build Coastguard Worker /** Timeout value of waiting for the response of a loading fragment. */
32*84e33947SAndroid Build Coastguard Worker constexpr auto kTimeoutInMs = std::chrono::milliseconds(2000);
33*84e33947SAndroid Build Coastguard Worker 
34*84e33947SAndroid Build Coastguard Worker using ::android::chre::readFileContents;
35*84e33947SAndroid Build Coastguard Worker using ::android::chre::Atoms::ChreHalNanoappLoadFailed;
36*84e33947SAndroid Build Coastguard Worker using ::android::hardware::contexthub::common::implementation::kHalId;
37*84e33947SAndroid Build Coastguard Worker 
getNanoappHeaderFromFile(const char * headerFileName,std::vector<uint8_t> & headerBuffer)38*84e33947SAndroid Build Coastguard Worker bool getNanoappHeaderFromFile(const char *headerFileName,
39*84e33947SAndroid Build Coastguard Worker                               std::vector<uint8_t> &headerBuffer) {
40*84e33947SAndroid Build Coastguard Worker   if (!readFileContents(headerFileName, headerBuffer)) {
41*84e33947SAndroid Build Coastguard Worker     LOGE("Failed to read header file for nanoapp %s", headerFileName);
42*84e33947SAndroid Build Coastguard Worker     return false;
43*84e33947SAndroid Build Coastguard Worker   }
44*84e33947SAndroid Build Coastguard Worker   if (headerBuffer.size() != sizeof(NanoAppBinaryHeader)) {
45*84e33947SAndroid Build Coastguard Worker     LOGE("Nanoapp binary's header size is incorrect");
46*84e33947SAndroid Build Coastguard Worker     return false;
47*84e33947SAndroid Build Coastguard Worker   }
48*84e33947SAndroid Build Coastguard Worker   return true;
49*84e33947SAndroid Build Coastguard Worker }
50*84e33947SAndroid Build Coastguard Worker 
shouldSkipNanoapp(std::optional<const std::vector<uint64_t>> nanoappIds,uint64_t theAppId)51*84e33947SAndroid Build Coastguard Worker inline bool shouldSkipNanoapp(
52*84e33947SAndroid Build Coastguard Worker     std::optional<const std::vector<uint64_t>> nanoappIds, uint64_t theAppId) {
53*84e33947SAndroid Build Coastguard Worker   return nanoappIds.has_value() &&
54*84e33947SAndroid Build Coastguard Worker          std::find(nanoappIds->begin(), nanoappIds->end(), theAppId) !=
55*84e33947SAndroid Build Coastguard Worker              nanoappIds->end();
56*84e33947SAndroid Build Coastguard Worker }
57*84e33947SAndroid Build Coastguard Worker }  // namespace
58*84e33947SAndroid Build Coastguard Worker 
getPreloadedNanoappIds(std::vector<uint64_t> & out_preloadedNanoappIds)59*84e33947SAndroid Build Coastguard Worker void PreloadedNanoappLoader::getPreloadedNanoappIds(
60*84e33947SAndroid Build Coastguard Worker     std::vector<uint64_t> &out_preloadedNanoappIds) {
61*84e33947SAndroid Build Coastguard Worker   std::vector<std::string> nanoappNames;
62*84e33947SAndroid Build Coastguard Worker   std::string directory;
63*84e33947SAndroid Build Coastguard Worker   out_preloadedNanoappIds.clear();
64*84e33947SAndroid Build Coastguard Worker   if (!getPreloadedNanoappsFromConfigFile(mConfigPath, directory,
65*84e33947SAndroid Build Coastguard Worker                                           nanoappNames)) {
66*84e33947SAndroid Build Coastguard Worker     LOGE("Failed to parse preloaded nanoapps config file");
67*84e33947SAndroid Build Coastguard Worker   }
68*84e33947SAndroid Build Coastguard Worker   for (const std::string &nanoappName : nanoappNames) {
69*84e33947SAndroid Build Coastguard Worker     std::string headerFileName = directory + "/" + nanoappName + ".napp_header";
70*84e33947SAndroid Build Coastguard Worker     std::vector<uint8_t> headerBuffer;
71*84e33947SAndroid Build Coastguard Worker     if (!getNanoappHeaderFromFile(headerFileName.c_str(), headerBuffer)) {
72*84e33947SAndroid Build Coastguard Worker       LOGE("Failed to parse the nanoapp header for %s", headerFileName.c_str());
73*84e33947SAndroid Build Coastguard Worker       continue;
74*84e33947SAndroid Build Coastguard Worker     }
75*84e33947SAndroid Build Coastguard Worker     auto header =
76*84e33947SAndroid Build Coastguard Worker         reinterpret_cast<const NanoAppBinaryHeader *>(headerBuffer.data());
77*84e33947SAndroid Build Coastguard Worker     out_preloadedNanoappIds.emplace_back(header->appId);
78*84e33947SAndroid Build Coastguard Worker   }
79*84e33947SAndroid Build Coastguard Worker }
80*84e33947SAndroid Build Coastguard Worker 
loadPreloadedNanoapps(const std::optional<const std::vector<uint64_t>> & skippedNanoappIds)81*84e33947SAndroid Build Coastguard Worker int PreloadedNanoappLoader::loadPreloadedNanoapps(
82*84e33947SAndroid Build Coastguard Worker     const std::optional<const std::vector<uint64_t>> &skippedNanoappIds) {
83*84e33947SAndroid Build Coastguard Worker   std::string directory;
84*84e33947SAndroid Build Coastguard Worker   std::vector<std::string> nanoapps;
85*84e33947SAndroid Build Coastguard Worker   int numOfNanoappsLoaded = 0;
86*84e33947SAndroid Build Coastguard Worker   if (!getPreloadedNanoappsFromConfigFile(mConfigPath, directory, nanoapps)) {
87*84e33947SAndroid Build Coastguard Worker     LOGE("Failed to load any preloaded nanoapp");
88*84e33947SAndroid Build Coastguard Worker     return numOfNanoappsLoaded;
89*84e33947SAndroid Build Coastguard Worker   }
90*84e33947SAndroid Build Coastguard Worker   if (mIsPreloadingOngoing.exchange(true)) {
91*84e33947SAndroid Build Coastguard Worker     LOGE("Preloading is ongoing. A new request shouldn't happen.");
92*84e33947SAndroid Build Coastguard Worker     return numOfNanoappsLoaded;
93*84e33947SAndroid Build Coastguard Worker   }
94*84e33947SAndroid Build Coastguard Worker 
95*84e33947SAndroid Build Coastguard Worker   for (uint32_t i = 0; i < nanoapps.size(); ++i) {
96*84e33947SAndroid Build Coastguard Worker     std::string headerFilename = directory + "/" + nanoapps[i] + ".napp_header";
97*84e33947SAndroid Build Coastguard Worker     std::string nanoappFilename = directory + "/" + nanoapps[i] + ".so";
98*84e33947SAndroid Build Coastguard Worker     // parse the header
99*84e33947SAndroid Build Coastguard Worker     std::vector<uint8_t> headerBuffer;
100*84e33947SAndroid Build Coastguard Worker     if (!getNanoappHeaderFromFile(headerFilename.c_str(), headerBuffer)) {
101*84e33947SAndroid Build Coastguard Worker       LOGE("Failed to parse the nanoapp header for %s",
102*84e33947SAndroid Build Coastguard Worker            nanoappFilename.c_str());
103*84e33947SAndroid Build Coastguard Worker       continue;
104*84e33947SAndroid Build Coastguard Worker     }
105*84e33947SAndroid Build Coastguard Worker     const auto header =
106*84e33947SAndroid Build Coastguard Worker         reinterpret_cast<const NanoAppBinaryHeader *>(headerBuffer.data());
107*84e33947SAndroid Build Coastguard Worker     // check if the app should be skipped
108*84e33947SAndroid Build Coastguard Worker     if (shouldSkipNanoapp(skippedNanoappIds, header->appId)) {
109*84e33947SAndroid Build Coastguard Worker       LOGI("Loading of %s is skipped.", nanoappFilename.c_str());
110*84e33947SAndroid Build Coastguard Worker       continue;
111*84e33947SAndroid Build Coastguard Worker     }
112*84e33947SAndroid Build Coastguard Worker     // load the binary
113*84e33947SAndroid Build Coastguard Worker     if (loadNanoapp(header, nanoappFilename, /* transactionId= */ i)) {
114*84e33947SAndroid Build Coastguard Worker       numOfNanoappsLoaded++;
115*84e33947SAndroid Build Coastguard Worker     } else {
116*84e33947SAndroid Build Coastguard Worker       LOGE("Failed to load nanoapp 0x%" PRIx64 " in preloaded nanoapp loader",
117*84e33947SAndroid Build Coastguard Worker            header->appId);
118*84e33947SAndroid Build Coastguard Worker       if (mNanoappLoadListener != nullptr) {
119*84e33947SAndroid Build Coastguard Worker         mNanoappLoadListener->onNanoappLoadFailed(header->appId);
120*84e33947SAndroid Build Coastguard Worker       }
121*84e33947SAndroid Build Coastguard Worker     }
122*84e33947SAndroid Build Coastguard Worker   }
123*84e33947SAndroid Build Coastguard Worker   mIsPreloadingOngoing.store(false);
124*84e33947SAndroid Build Coastguard Worker   return numOfNanoappsLoaded;
125*84e33947SAndroid Build Coastguard Worker }
126*84e33947SAndroid Build Coastguard Worker 
loadNanoapp(const NanoAppBinaryHeader * appHeader,const std::string & nanoappFileName,uint32_t transactionId)127*84e33947SAndroid Build Coastguard Worker bool PreloadedNanoappLoader::loadNanoapp(const NanoAppBinaryHeader *appHeader,
128*84e33947SAndroid Build Coastguard Worker                                          const std::string &nanoappFileName,
129*84e33947SAndroid Build Coastguard Worker                                          uint32_t transactionId) {
130*84e33947SAndroid Build Coastguard Worker   // parse the binary
131*84e33947SAndroid Build Coastguard Worker   auto nanoappBuffer = std::make_shared<std::vector<uint8_t>>();
132*84e33947SAndroid Build Coastguard Worker   if (!readFileContents(nanoappFileName.c_str(), *nanoappBuffer)) {
133*84e33947SAndroid Build Coastguard Worker     LOGE("Unable to read %s.", nanoappFileName.c_str());
134*84e33947SAndroid Build Coastguard Worker     return false;
135*84e33947SAndroid Build Coastguard Worker   }
136*84e33947SAndroid Build Coastguard Worker   if (mNanoappLoadListener != nullptr) {
137*84e33947SAndroid Build Coastguard Worker     mNanoappLoadListener->onNanoappLoadStarted(appHeader->appId, nanoappBuffer);
138*84e33947SAndroid Build Coastguard Worker   }
139*84e33947SAndroid Build Coastguard Worker   // Build the target API version from major and minor.
140*84e33947SAndroid Build Coastguard Worker   uint32_t targetApiVersion = (appHeader->targetChreApiMajorVersion << 24) |
141*84e33947SAndroid Build Coastguard Worker                               (appHeader->targetChreApiMinorVersion << 16);
142*84e33947SAndroid Build Coastguard Worker   bool success = sendFragmentedLoadAndWaitForEachResponse(
143*84e33947SAndroid Build Coastguard Worker       appHeader->appId, appHeader->appVersion, appHeader->flags,
144*84e33947SAndroid Build Coastguard Worker       targetApiVersion, nanoappBuffer->data(), nanoappBuffer->size(),
145*84e33947SAndroid Build Coastguard Worker       transactionId);
146*84e33947SAndroid Build Coastguard Worker   mEventLogger.logNanoappLoad(appHeader->appId, nanoappBuffer->size(),
147*84e33947SAndroid Build Coastguard Worker                               appHeader->appVersion, success);
148*84e33947SAndroid Build Coastguard Worker   return success;
149*84e33947SAndroid Build Coastguard Worker }
150*84e33947SAndroid Build Coastguard Worker 
sendFragmentedLoadAndWaitForEachResponse(uint64_t appId,uint32_t appVersion,uint32_t appFlags,uint32_t appTargetApiVersion,const uint8_t * appBinary,size_t appSize,uint32_t transactionId)151*84e33947SAndroid Build Coastguard Worker bool PreloadedNanoappLoader::sendFragmentedLoadAndWaitForEachResponse(
152*84e33947SAndroid Build Coastguard Worker     uint64_t appId, uint32_t appVersion, uint32_t appFlags,
153*84e33947SAndroid Build Coastguard Worker     uint32_t appTargetApiVersion, const uint8_t *appBinary, size_t appSize,
154*84e33947SAndroid Build Coastguard Worker     uint32_t transactionId) {
155*84e33947SAndroid Build Coastguard Worker   std::vector<uint8_t> binary(appSize);
156*84e33947SAndroid Build Coastguard Worker   std::copy(appBinary, appBinary + appSize, binary.begin());
157*84e33947SAndroid Build Coastguard Worker 
158*84e33947SAndroid Build Coastguard Worker   FragmentedLoadTransaction transaction(transactionId, appId, appVersion,
159*84e33947SAndroid Build Coastguard Worker                                         appFlags, appTargetApiVersion, binary);
160*84e33947SAndroid Build Coastguard Worker   while (!transaction.isComplete()) {
161*84e33947SAndroid Build Coastguard Worker     auto nextRequest = transaction.getNextRequest();
162*84e33947SAndroid Build Coastguard Worker     auto future = sendFragmentedLoadRequest(nextRequest);
163*84e33947SAndroid Build Coastguard Worker     if (!waitAndVerifyFuture(future, nextRequest)) {
164*84e33947SAndroid Build Coastguard Worker       return false;
165*84e33947SAndroid Build Coastguard Worker     }
166*84e33947SAndroid Build Coastguard Worker   }
167*84e33947SAndroid Build Coastguard Worker   return true;
168*84e33947SAndroid Build Coastguard Worker }
169*84e33947SAndroid Build Coastguard Worker 
waitAndVerifyFuture(std::future<bool> & future,const FragmentedLoadRequest & request)170*84e33947SAndroid Build Coastguard Worker bool PreloadedNanoappLoader::waitAndVerifyFuture(
171*84e33947SAndroid Build Coastguard Worker     std::future<bool> &future, const FragmentedLoadRequest &request) {
172*84e33947SAndroid Build Coastguard Worker   bool success = false;
173*84e33947SAndroid Build Coastguard Worker   auto failureReason =
174*84e33947SAndroid Build Coastguard Worker       ChreHalNanoappLoadFailed::Reason::REASON_CONNECTION_ERROR;
175*84e33947SAndroid Build Coastguard Worker   if (!future.valid()) {
176*84e33947SAndroid Build Coastguard Worker     LOGE("Failed to send out the fragmented load fragment");
177*84e33947SAndroid Build Coastguard Worker   } else if (future.wait_for(kTimeoutInMs) != std::future_status::ready) {
178*84e33947SAndroid Build Coastguard Worker     LOGE(
179*84e33947SAndroid Build Coastguard Worker         "Waiting for response of fragment %zu transaction %d times out "
180*84e33947SAndroid Build Coastguard Worker         "after %lld ms",
181*84e33947SAndroid Build Coastguard Worker         request.fragmentId, request.transactionId, kTimeoutInMs.count());
182*84e33947SAndroid Build Coastguard Worker   } else if (!future.get()) {
183*84e33947SAndroid Build Coastguard Worker     LOGE(
184*84e33947SAndroid Build Coastguard Worker         "Received a failure result for loading fragment %zu of "
185*84e33947SAndroid Build Coastguard Worker         "transaction %d",
186*84e33947SAndroid Build Coastguard Worker         request.fragmentId, request.transactionId);
187*84e33947SAndroid Build Coastguard Worker     failureReason = ChreHalNanoappLoadFailed::Reason::REASON_ERROR_GENERIC;
188*84e33947SAndroid Build Coastguard Worker   } else {
189*84e33947SAndroid Build Coastguard Worker     success = true;
190*84e33947SAndroid Build Coastguard Worker   }
191*84e33947SAndroid Build Coastguard Worker 
192*84e33947SAndroid Build Coastguard Worker   if (!success && mMetricsReporter != nullptr) {
193*84e33947SAndroid Build Coastguard Worker     mMetricsReporter->logNanoappLoadFailed(
194*84e33947SAndroid Build Coastguard Worker         request.appId, ChreHalNanoappLoadFailed::Type::TYPE_PRELOADED,
195*84e33947SAndroid Build Coastguard Worker         failureReason);
196*84e33947SAndroid Build Coastguard Worker   }
197*84e33947SAndroid Build Coastguard Worker   return success;
198*84e33947SAndroid Build Coastguard Worker }
199*84e33947SAndroid Build Coastguard Worker 
200*84e33947SAndroid Build Coastguard Worker PreloadedNanoappLoader::ResponseVerificationResult
verifyFragmentLoadResponse(const::chre::fbs::LoadNanoappResponseT & response) const201*84e33947SAndroid Build Coastguard Worker PreloadedNanoappLoader::verifyFragmentLoadResponse(
202*84e33947SAndroid Build Coastguard Worker     const ::chre::fbs::LoadNanoappResponseT &response) const {
203*84e33947SAndroid Build Coastguard Worker   // Allow seen fragment ids to be ignored to tolerate duplicated responses.
204*84e33947SAndroid Build Coastguard Worker   if (response.fragment_id >= 0 &&
205*84e33947SAndroid Build Coastguard Worker       response.fragment_id < mPendingTransaction.fragmentId) {
206*84e33947SAndroid Build Coastguard Worker     LOGW(
207*84e33947SAndroid Build Coastguard Worker         "Fragmented load response has a fragment id %u while %zu is expected. "
208*84e33947SAndroid Build Coastguard Worker         "Ignored",
209*84e33947SAndroid Build Coastguard Worker         response.fragment_id, mPendingTransaction.fragmentId);
210*84e33947SAndroid Build Coastguard Worker     return ResponseVerificationResult::IGNORED;
211*84e33947SAndroid Build Coastguard Worker   }
212*84e33947SAndroid Build Coastguard Worker 
213*84e33947SAndroid Build Coastguard Worker   // Future or negative fragment ids are not acceptable.
214*84e33947SAndroid Build Coastguard Worker   if (response.fragment_id != mPendingTransaction.fragmentId) {
215*84e33947SAndroid Build Coastguard Worker     LOGE(
216*84e33947SAndroid Build Coastguard Worker         "Fragmented load response with unexpected fragment id %u while "
217*84e33947SAndroid Build Coastguard Worker         "%zu is expected",
218*84e33947SAndroid Build Coastguard Worker         response.fragment_id, mPendingTransaction.fragmentId);
219*84e33947SAndroid Build Coastguard Worker     return ResponseVerificationResult::FAILURE;
220*84e33947SAndroid Build Coastguard Worker   }
221*84e33947SAndroid Build Coastguard Worker 
222*84e33947SAndroid Build Coastguard Worker   // Once fragment id is matched the result is taken.
223*84e33947SAndroid Build Coastguard Worker   if (!response.success) {
224*84e33947SAndroid Build Coastguard Worker     LOGE("Loading nanoapp binary fragment %d of transaction %u failed.",
225*84e33947SAndroid Build Coastguard Worker          response.fragment_id, response.transaction_id);
226*84e33947SAndroid Build Coastguard Worker     return ResponseVerificationResult::FAILURE;
227*84e33947SAndroid Build Coastguard Worker   }
228*84e33947SAndroid Build Coastguard Worker   return ResponseVerificationResult::SUCCESS;
229*84e33947SAndroid Build Coastguard Worker }
230*84e33947SAndroid Build Coastguard Worker 
onLoadNanoappResponse(const::chre::fbs::LoadNanoappResponseT & response,HalClientId clientId)231*84e33947SAndroid Build Coastguard Worker bool PreloadedNanoappLoader::onLoadNanoappResponse(
232*84e33947SAndroid Build Coastguard Worker     const ::chre::fbs::LoadNanoappResponseT &response, HalClientId clientId) {
233*84e33947SAndroid Build Coastguard Worker   std::unique_lock<std::mutex> lock(mPreloadedNanoappsMutex);
234*84e33947SAndroid Build Coastguard Worker   if (clientId != kHalId || !mFragmentedLoadPromise.has_value()) {
235*84e33947SAndroid Build Coastguard Worker     LOGE(
236*84e33947SAndroid Build Coastguard Worker         "Received an unexpected preload nanoapp %s response for client %d "
237*84e33947SAndroid Build Coastguard Worker         "transaction %u fragment %u",
238*84e33947SAndroid Build Coastguard Worker         response.success ? "success" : "failure", clientId,
239*84e33947SAndroid Build Coastguard Worker         response.transaction_id, response.fragment_id);
240*84e33947SAndroid Build Coastguard Worker     return false;
241*84e33947SAndroid Build Coastguard Worker   }
242*84e33947SAndroid Build Coastguard Worker   if (mPendingTransaction.transactionId != response.transaction_id) {
243*84e33947SAndroid Build Coastguard Worker     LOGE(
244*84e33947SAndroid Build Coastguard Worker         "Fragmented load response with transactionId %u but transactionId "
245*84e33947SAndroid Build Coastguard Worker         "%u is expected. Ignored.",
246*84e33947SAndroid Build Coastguard Worker         response.transaction_id, mPendingTransaction.transactionId);
247*84e33947SAndroid Build Coastguard Worker     return false;
248*84e33947SAndroid Build Coastguard Worker   }
249*84e33947SAndroid Build Coastguard Worker 
250*84e33947SAndroid Build Coastguard Worker   // set value for the future instance.
251*84e33947SAndroid Build Coastguard Worker   ResponseVerificationResult result = verifyFragmentLoadResponse(response);
252*84e33947SAndroid Build Coastguard Worker   if (result != ResponseVerificationResult::IGNORED) {
253*84e33947SAndroid Build Coastguard Worker     mFragmentedLoadPromise->set_value(result ==
254*84e33947SAndroid Build Coastguard Worker                                       ResponseVerificationResult::SUCCESS);
255*84e33947SAndroid Build Coastguard Worker     // reset the promise as the value can only be retrieved once from it.
256*84e33947SAndroid Build Coastguard Worker     mFragmentedLoadPromise = std::nullopt;
257*84e33947SAndroid Build Coastguard Worker   }
258*84e33947SAndroid Build Coastguard Worker 
259*84e33947SAndroid Build Coastguard Worker   return true;
260*84e33947SAndroid Build Coastguard Worker }
261*84e33947SAndroid Build Coastguard Worker 
sendFragmentedLoadRequest(::android::chre::FragmentedLoadRequest & request)262*84e33947SAndroid Build Coastguard Worker std::future<bool> PreloadedNanoappLoader::sendFragmentedLoadRequest(
263*84e33947SAndroid Build Coastguard Worker     ::android::chre::FragmentedLoadRequest &request) {
264*84e33947SAndroid Build Coastguard Worker   flatbuffers::FlatBufferBuilder builder(request.binary.size() + 128);
265*84e33947SAndroid Build Coastguard Worker   // TODO(b/247124878): Confirm if respondBeforeStart can be set to true on all
266*84e33947SAndroid Build Coastguard Worker   //  the devices.
267*84e33947SAndroid Build Coastguard Worker   HostProtocolHost::encodeFragmentedLoadNanoappRequest(
268*84e33947SAndroid Build Coastguard Worker       builder, request, /* respondBeforeStart= */ true);
269*84e33947SAndroid Build Coastguard Worker   HostProtocolHost::mutateHostClientId(builder.GetBufferPointer(),
270*84e33947SAndroid Build Coastguard Worker                                        builder.GetSize(), kHalId);
271*84e33947SAndroid Build Coastguard Worker 
272*84e33947SAndroid Build Coastguard Worker   std::unique_lock<std::mutex> lock(mPreloadedNanoappsMutex);
273*84e33947SAndroid Build Coastguard Worker   if (!mConnection->sendMessage(builder.GetBufferPointer(),
274*84e33947SAndroid Build Coastguard Worker                                 builder.GetSize())) {
275*84e33947SAndroid Build Coastguard Worker     // Returns an invalid future to indicate the failure
276*84e33947SAndroid Build Coastguard Worker     return std::future<bool>{};
277*84e33947SAndroid Build Coastguard Worker   }
278*84e33947SAndroid Build Coastguard Worker   mPendingTransaction = {
279*84e33947SAndroid Build Coastguard Worker       .transactionId = request.transactionId,
280*84e33947SAndroid Build Coastguard Worker       .fragmentId = request.fragmentId,
281*84e33947SAndroid Build Coastguard Worker   };
282*84e33947SAndroid Build Coastguard Worker   mFragmentedLoadPromise = std::make_optional<std::promise<bool>>();
283*84e33947SAndroid Build Coastguard Worker   return mFragmentedLoadPromise->get_future();
284*84e33947SAndroid Build Coastguard Worker }
285*84e33947SAndroid Build Coastguard Worker }  // namespace android::chre