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/platform/host_link.h"
18 #include "chre/core/event_loop_manager.h"
19 #include "chre/core/host_comms_manager.h"
20 #include "chre/platform/shared/host_protocol_chre.h"
21 #include "chre/platform/shared/nanoapp_load_manager.h"
22 #include "chre/platform/system_time.h"
23 #include "chre/platform/system_timer.h"
24 #include "chre/util/flatbuffers/helpers.h"
25 #include "chre/util/nested_data_ptr.h"
26 #include "include/chre/target_platform/host_link_base.h"
27 #include "mailbox.h"
28
29 // The delete operator is generated by the compiler but not actually called,
30 // empty implementations are provided to avoid linker warnings.
operator delete(void *)31 void operator delete(void * /*ptr*/) {}
operator delete(void *,size_t)32 void operator delete(void * /*ptr*/, size_t /*sz*/) {}
33
34 namespace chre {
35 namespace {
36
37 struct UnloadNanoappCallbackData {
38 uint64_t appId;
39 uint32_t transactionId;
40 uint16_t hostClientId;
41 bool allowSystemNanoappUnload;
42 };
43
getHostCommsManager()44 inline HostCommsManager &getHostCommsManager() {
45 return EventLoopManagerSingleton::get()->getHostCommsManager();
46 }
47
setTimeSyncRequestTimer(Nanoseconds delay)48 void setTimeSyncRequestTimer(Nanoseconds delay) {
49 static TimerHandle sHandle;
50 static bool sHandleInitialized;
51
52 if (sHandleInitialized) {
53 EventLoopManagerSingleton::get()->cancelDelayedCallback(sHandle);
54 }
55
56 auto callback = [](uint16_t /*type*/, void * /*data*/, void * /*extraData*/) {
57 HostLinkBase::sendTimeSyncRequest();
58 };
59 sHandle = EventLoopManagerSingleton::get()->setDelayedCallback(
60 SystemCallbackType::TimerSyncRequest, nullptr /*data*/, callback, delay);
61 sHandleInitialized = true;
62 }
63
64 } // anonymous namespace
65
sendDebugDumpResultToHost(uint16_t,const char *,size_t,bool,uint32_t)66 void sendDebugDumpResultToHost(uint16_t /*hostClientId*/,
67 const char * /*debugStr*/,
68 size_t /*debugStrSize*/, bool /*complete*/,
69 uint32_t /*dataCount*/) {
70 // TODO(b/230134803): Implement this.
71 }
72
HostLinkBase()73 HostLinkBase::HostLinkBase() {
74 int32_t rv = mailboxReadChre(mMsgBuffer, CHRE_MESSAGE_TO_HOST_MAX_SIZE,
75 receive, this /*cookie*/);
76 CHRE_ASSERT_LOG((rv == 0),
77 "Failed to register inbound message handler %" PRId32, rv);
78 }
79
receive(void * cookie,void * message,int messageLen)80 void HostLinkBase::receive(void *cookie, void *message, int messageLen) {
81 auto *instance = static_cast<HostLinkBase *>(cookie);
82 // TODO(b/237819962): A crude way to initially determine daemon's up - set
83 // a flag on the first message received. This is temporary until a better
84 // way to do this is available.
85 instance->setInitialized(true);
86
87 if (!HostProtocolChre::decodeMessageFromHost(message, messageLen)) {
88 LOGE("Failed to decode msg %p of len %zu", message, messageLen);
89 }
90 }
91
sendMessage(const MessageToHost * message)92 bool HostLink::sendMessage(const MessageToHost *message) {
93 bool success = false;
94 if (isInitialized()) {
95 constexpr size_t kFixedReserveSize = 80;
96 ChreFlatBufferBuilder builder(message->message.size() + kFixedReserveSize);
97 HostProtocolChre::encodeNanoappMessage(
98 builder, message->appId, message->toHostData.messageType,
99 message->toHostData.hostEndpoint, message->message.data(),
100 message->message.size(), message->toHostData.appPermissions,
101 message->toHostData.messagePermissions, message->toHostData.wokeHost);
102 success = (send(builder.GetBufferPointer(), builder.GetSize()) == 0);
103
104 // Only invoke on success as returning false from this method will cause
105 // core logic to do the appropriate cleanup.
106 if (success) {
107 EventLoopManagerSingleton::get()
108 ->getHostCommsManager()
109 .onMessageToHostComplete(message);
110 }
111 } else {
112 LOGW("Dropping outbound message: host link not initialized yet");
113 }
114 return success;
115 }
116
117 // TODO(b/239096709): HostMessageHandlers member function implementations are
118 // expected to be (mostly) identical for any platform that uses flatbuffers
119 // to encode messages - refactor the host link to merge the multiple copies
120 // we currently have.
handleNanoappMessage(uint64_t appId,uint32_t messageType,uint16_t hostEndpoint,const void *,size_t messageDataLen)121 void HostMessageHandlers::handleNanoappMessage(uint64_t appId,
122 uint32_t messageType,
123 uint16_t hostEndpoint,
124 const void * /* messageData */,
125 size_t messageDataLen) {
126 LOGD("Parsed nanoapp message from host: app ID 0x%016" PRIx64
127 ", endpoint "
128 "0x%" PRIx16 ", msgType %" PRIu32 ", payload size %zu",
129 appId, hostEndpoint, messageType, messageDataLen);
130
131 // TODO(b/230134803): Implement this.
132 }
133
handleHubInfoRequest(uint16_t)134 void HostMessageHandlers::handleHubInfoRequest(uint16_t /* hostClientId */) {
135 // TODO(b/230134803): Implement this.
136 }
137
handleNanoappListRequest(uint16_t hostClientId)138 void HostMessageHandlers::handleNanoappListRequest(uint16_t hostClientId) {
139 // TODO(b/230134803): Implement this.
140 }
141
sendFragmentResponse(uint16_t hostClientId,uint32_t transactionId,uint32_t fragmentId,bool success)142 void HostMessageHandlers::sendFragmentResponse(uint16_t hostClientId,
143 uint32_t transactionId,
144 uint32_t fragmentId,
145 bool success) {
146 constexpr size_t kInitialBufferSize = 52;
147 ChreFlatBufferBuilder builder(kInitialBufferSize);
148 HostProtocolChre::encodeLoadNanoappResponse(
149 builder, hostClientId, transactionId, success, fragmentId);
150
151 if (!getHostCommsManager().send(builder.GetBufferPointer(),
152 builder.GetSize())) {
153 LOGE("Failed to send fragment response for HostClientID: %" PRIx16
154 " , FragmentID: %" PRIx32 " transactionID: %" PRIx32,
155 hostClientId, fragmentId, transactionId);
156 }
157 }
158
handleLoadNanoappRequest(uint16_t hostClientId,uint32_t transactionId,uint64_t appId,uint32_t appVersion,uint32_t appFlags,uint32_t targetApiVersion,const void * buffer,size_t bufferLen,const char * appFileName,uint32_t fragmentId,size_t appBinaryLen,bool respondBeforeStart)159 void HostMessageHandlers::handleLoadNanoappRequest(
160 uint16_t hostClientId, uint32_t transactionId, uint64_t appId,
161 uint32_t appVersion, uint32_t appFlags, uint32_t targetApiVersion,
162 const void *buffer, size_t bufferLen, const char *appFileName,
163 uint32_t fragmentId, size_t appBinaryLen, bool respondBeforeStart) {
164 UNUSED_VAR(appFileName);
165
166 loadNanoappData(hostClientId, transactionId, appId, appVersion, appFlags,
167 targetApiVersion, buffer, bufferLen, fragmentId, appBinaryLen,
168 respondBeforeStart);
169 }
170
handleUnloadNanoappRequest(uint16_t hostClientId,uint32_t transactionId,uint64_t appId,bool allowSystemNanoappUnload)171 void HostMessageHandlers::handleUnloadNanoappRequest(
172 uint16_t hostClientId, uint32_t transactionId, uint64_t appId,
173 bool allowSystemNanoappUnload) {
174 LOGD("Unload nanoapp request from client %" PRIu16 " (txnID %" PRIu32
175 ") for appId 0x%016" PRIx64 " system %d",
176 hostClientId, transactionId, appId, allowSystemNanoappUnload);
177 // TODO(b/230134803): Implement this.
178 }
179
handleTimeSyncMessage(int64_t offset)180 void HostMessageHandlers::handleTimeSyncMessage(int64_t offset) {
181 LOGD("Time sync msg received with offset %" PRId64, offset);
182
183 SystemTime::setEstimatedHostTimeOffset(offset);
184
185 // Schedule a time sync request since offset may drift
186 constexpr Seconds kClockDriftTimeSyncPeriod =
187 Seconds(60 * 60 * 6); // 6 hours
188 setTimeSyncRequestTimer(kClockDriftTimeSyncPeriod);
189 }
190
handleDebugDumpRequest(uint16_t)191 void HostMessageHandlers::handleDebugDumpRequest(uint16_t /* hostClientId */) {
192 // TODO(b/230134803): Implement this.
193 }
194
handleSettingChangeMessage(fbs::Setting setting,fbs::SettingState state)195 void HostMessageHandlers::handleSettingChangeMessage(fbs::Setting setting,
196 fbs::SettingState state) {
197 Setting chreSetting;
198 bool chreSettingEnabled;
199 if (HostProtocolChre::getSettingFromFbs(setting, &chreSetting) &&
200 HostProtocolChre::getSettingEnabledFromFbs(state, &chreSettingEnabled)) {
201 EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
202 chreSetting, chreSettingEnabled);
203 }
204 }
205
handleSelfTestRequest(uint16_t)206 void HostMessageHandlers::handleSelfTestRequest(uint16_t /* hostClientId */) {
207 // TODO(b/230134803): Implement this.
208 }
209
handleNanConfigurationUpdate(bool)210 void HostMessageHandlers::handleNanConfigurationUpdate(bool /* enabled */) {
211 LOGE("NAN unsupported.");
212 }
213
214 } // namespace chre
215