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 #include "chre/core/event_loop_manager.h"
18 #include "chre/platform/shared/host_protocol_chre.h"
19 #include "chre/platform/shared/nanoapp_load_manager.h"
20
21 namespace chre {
22
23 NanoappLoadManager gLoadManager;
24
getLoadManager()25 inline NanoappLoadManager &getLoadManager() {
26 return gLoadManager;
27 }
28
handleDebugConfiguration(const fbs::DebugConfiguration * debugConfiguration)29 void HostMessageHandlers::handleDebugConfiguration(
30 const fbs::DebugConfiguration *debugConfiguration) {
31 EventLoopManagerSingleton::get()
32 ->getSystemHealthMonitor()
33 .setFatalErrorOnCheckFailure(
34 debugConfiguration->health_monitor_failure_crash());
35 }
36
finishLoadingNanoappCallback(SystemCallbackType,UniquePtr<LoadNanoappCallbackData> && cbData)37 void HostMessageHandlers::finishLoadingNanoappCallback(
38 SystemCallbackType /*type*/, UniquePtr<LoadNanoappCallbackData> &&cbData) {
39 constexpr size_t kInitialBufferSize = 48;
40 ChreFlatBufferBuilder builder(kInitialBufferSize);
41
42 CHRE_ASSERT(cbData != nullptr);
43
44 EventLoop &eventLoop = EventLoopManagerSingleton::get()->getEventLoop();
45 bool success = false;
46
47 if (cbData->nanoapp->isLoaded()) {
48 success = eventLoop.startNanoapp(cbData->nanoapp);
49 } else {
50 LOGE("Nanoapp is not loaded");
51 }
52
53 if (cbData->sendFragmentResponse) {
54 sendFragmentResponse(cbData->hostClientId, cbData->transactionId,
55 cbData->fragmentId, success);
56 }
57 }
58
loadNanoappData(uint16_t hostClientId,uint32_t transactionId,uint64_t appId,uint32_t appVersion,uint32_t appFlags,uint32_t targetApiVersion,const void * buffer,size_t bufferLen,uint32_t fragmentId,size_t appBinaryLen,bool respondBeforeStart)59 void HostMessageHandlers::loadNanoappData(
60 uint16_t hostClientId, uint32_t transactionId, uint64_t appId,
61 uint32_t appVersion, uint32_t appFlags, uint32_t targetApiVersion,
62 const void *buffer, size_t bufferLen, uint32_t fragmentId,
63 size_t appBinaryLen, bool respondBeforeStart) {
64 bool success = true;
65
66 if (fragmentId == 0 || fragmentId == 1) {
67 size_t totalAppBinaryLen = (fragmentId == 0) ? bufferLen : appBinaryLen;
68 LOGD("Load nanoapp request for app ID 0x%016" PRIx64 " ver 0x%" PRIx32
69 " flags 0x%" PRIx32 " target API 0x%08" PRIx32
70 " size %zu (txnId %" PRIu32 " client %" PRIu16 ")",
71 appId, appVersion, appFlags, targetApiVersion, totalAppBinaryLen,
72 transactionId, hostClientId);
73
74 if (getLoadManager().hasPendingLoadTransaction()) {
75 FragmentedLoadInfo info = getLoadManager().getTransactionInfo();
76 sendFragmentResponse(info.hostClientId, info.transactionId,
77 0 /* fragmentId */, false /* success */);
78 getLoadManager().markFailure();
79 }
80
81 success = getLoadManager().prepareForLoad(
82 hostClientId, transactionId, appId, appVersion, appFlags,
83 totalAppBinaryLen, targetApiVersion);
84 }
85
86 if (success) {
87 success = getLoadManager().copyNanoappFragment(
88 hostClientId, transactionId, (fragmentId == 0) ? 1 : fragmentId, buffer,
89 bufferLen);
90 } else {
91 LOGE("Failed to prepare for load");
92 }
93
94 if (getLoadManager().isLoadComplete()) {
95 LOGD("Load manager load complete...");
96 auto cbData = MakeUnique<LoadNanoappCallbackData>();
97 if (cbData.isNull()) {
98 LOG_OOM();
99 } else {
100 cbData->transactionId = transactionId;
101 cbData->hostClientId = hostClientId;
102 cbData->appId = appId;
103 cbData->fragmentId = fragmentId;
104 cbData->nanoapp = getLoadManager().releaseNanoapp();
105 cbData->sendFragmentResponse = !respondBeforeStart;
106
107 LOGD("Instance ID %" PRIu16 " assigned to app ID 0x%" PRIx64,
108 cbData->nanoapp->getInstanceId(), appId);
109
110 // Note that if this fails, we'll generate the error response in
111 // the normal deferred callback
112 EventLoopManagerSingleton::get()->deferCallback(
113 SystemCallbackType::FinishLoadingNanoapp, std::move(cbData),
114 finishLoadingNanoappCallback);
115 if (respondBeforeStart) {
116 sendFragmentResponse(hostClientId, transactionId, fragmentId, success);
117 } // else the response will be sent in finishLoadingNanoappCallback
118 }
119 } else {
120 // send a response for this fragment
121 sendFragmentResponse(hostClientId, transactionId, fragmentId, success);
122 }
123 }
124
125 } // namespace chre
126