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 = 88;
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         message->isReliable, message->messageSequenceNumber);
103     success = (send(builder.GetBufferPointer(), builder.GetSize()) == 0);
104 
105     // Only invoke on success as returning false from this method will cause
106     // core logic to do the appropriate cleanup.
107     if (success) {
108       EventLoopManagerSingleton::get()
109           ->getHostCommsManager()
110           .onMessageToHostComplete(message);
111     }
112   } else {
113     LOGW("Dropping outbound message: host link not initialized yet");
114   }
115   return success;
116 }
117 
sendMessageDeliveryStatus(uint32_t,uint8_t)118 bool HostLink::sendMessageDeliveryStatus(uint32_t /* messageSequenceNumber */,
119                                          uint8_t /* errorCode */) {
120   return false;
121 }
122 
123 // TODO(b/239096709): HostMessageHandlers member function implementations are
124 // expected to be (mostly) identical for any platform that uses flatbuffers
125 // to encode messages - refactor the host link to merge the multiple copies
126 // we currently have.
handleNanoappMessage(uint64_t appId,uint32_t messageType,uint16_t hostEndpoint,const void *,size_t messageDataLen,bool,uint32_t)127 void HostMessageHandlers::handleNanoappMessage(
128     uint64_t appId, uint32_t messageType, uint16_t hostEndpoint,
129     const void * /* messageData */, size_t messageDataLen,
130     bool /* isReliable */, uint32_t /* messageSequenceNumber */) {
131   LOGD("Parsed nanoapp message from host: app ID 0x%016" PRIx64
132        ", endpoint "
133        "0x%" PRIx16 ", msgType %" PRIu32 ", payload size %zu",
134        appId, hostEndpoint, messageType, messageDataLen);
135 
136   // TODO(b/230134803): Implement this.
137 }
138 
handleMessageDeliveryStatus(uint32_t,uint8_t)139 void HostMessageHandlers::handleMessageDeliveryStatus(
140     uint32_t /* messageSequenceNumber */, uint8_t /* errorCode */) {}
141 
handleHubInfoRequest(uint16_t)142 void HostMessageHandlers::handleHubInfoRequest(uint16_t /* hostClientId */) {
143   // TODO(b/230134803): Implement this.
144 }
145 
handleNanoappListRequest(uint16_t hostClientId)146 void HostMessageHandlers::handleNanoappListRequest(uint16_t hostClientId) {
147   // TODO(b/230134803): Implement this.
148 }
149 
handlePulseRequest()150 void HostMessageHandlers::handlePulseRequest() {}
151 
sendFragmentResponse(uint16_t hostClientId,uint32_t transactionId,uint32_t fragmentId,bool success)152 void HostMessageHandlers::sendFragmentResponse(uint16_t hostClientId,
153                                                uint32_t transactionId,
154                                                uint32_t fragmentId,
155                                                bool success) {
156   constexpr size_t kInitialBufferSize = 52;
157   ChreFlatBufferBuilder builder(kInitialBufferSize);
158   HostProtocolChre::encodeLoadNanoappResponse(
159       builder, hostClientId, transactionId, success, fragmentId);
160 
161   if (!getHostCommsManager().send(builder.GetBufferPointer(),
162                                   builder.GetSize())) {
163     LOGE("Failed to send fragment response for HostClientID: %" PRIx16
164          " , FragmentID: %" PRIx32 " transactionID: %" PRIx32,
165          hostClientId, fragmentId, transactionId);
166   }
167 }
168 
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)169 void HostMessageHandlers::handleLoadNanoappRequest(
170     uint16_t hostClientId, uint32_t transactionId, uint64_t appId,
171     uint32_t appVersion, uint32_t appFlags, uint32_t targetApiVersion,
172     const void *buffer, size_t bufferLen, const char *appFileName,
173     uint32_t fragmentId, size_t appBinaryLen, bool respondBeforeStart) {
174   UNUSED_VAR(appFileName);
175 
176   loadNanoappData(hostClientId, transactionId, appId, appVersion, appFlags,
177                   targetApiVersion, buffer, bufferLen, fragmentId, appBinaryLen,
178                   respondBeforeStart);
179 }
180 
handleUnloadNanoappRequest(uint16_t hostClientId,uint32_t transactionId,uint64_t appId,bool allowSystemNanoappUnload)181 void HostMessageHandlers::handleUnloadNanoappRequest(
182     uint16_t hostClientId, uint32_t transactionId, uint64_t appId,
183     bool allowSystemNanoappUnload) {
184   LOGD("Unload nanoapp request from client %" PRIu16 " (txnID %" PRIu32
185        ") for appId 0x%016" PRIx64 " system %d",
186        hostClientId, transactionId, appId, allowSystemNanoappUnload);
187   // TODO(b/230134803): Implement this.
188 }
189 
handleTimeSyncMessage(int64_t offset)190 void HostMessageHandlers::handleTimeSyncMessage(int64_t offset) {
191   LOGD("Time sync msg received with offset %" PRId64, offset);
192 
193   SystemTime::setEstimatedHostTimeOffset(offset);
194 
195   // Schedule a time sync request since offset may drift
196   constexpr Seconds kClockDriftTimeSyncPeriod =
197       Seconds(60 * 60 * 6);  // 6 hours
198   setTimeSyncRequestTimer(kClockDriftTimeSyncPeriod);
199 }
200 
handleDebugDumpRequest(uint16_t)201 void HostMessageHandlers::handleDebugDumpRequest(uint16_t /* hostClientId */) {
202   // TODO(b/230134803): Implement this.
203 }
204 
handleSettingChangeMessage(fbs::Setting setting,fbs::SettingState state)205 void HostMessageHandlers::handleSettingChangeMessage(fbs::Setting setting,
206                                                      fbs::SettingState state) {
207   Setting chreSetting;
208   bool chreSettingEnabled;
209   if (HostProtocolChre::getSettingFromFbs(setting, &chreSetting) &&
210       HostProtocolChre::getSettingEnabledFromFbs(state, &chreSettingEnabled)) {
211     EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
212         chreSetting, chreSettingEnabled);
213   }
214 }
215 
handleSelfTestRequest(uint16_t)216 void HostMessageHandlers::handleSelfTestRequest(uint16_t /* hostClientId */) {
217   // TODO(b/230134803): Implement this.
218 }
219 
handleNanConfigurationUpdate(bool)220 void HostMessageHandlers::handleNanConfigurationUpdate(bool /* enabled */) {
221   LOGE("NAN unsupported.");
222 }
223 
224 }  // namespace chre
225