1 /*
2 * Copyright (C) 2024 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 "context_hub_v4_impl.h"
18
19 #include <inttypes.h>
20
21 #include <functional>
22 #include <optional>
23 #include <string>
24 #include <vector>
25
26 #include <aidl/android/hardware/contexthub/BnContextHub.h>
27 #include <aidl/android/hardware/contexthub/BnEndpointCommunication.h>
28 #include <chre_host/generated/host_messages_generated.h>
29 #include <chre_host/log.h>
30
31 #include "host_protocol_host_v4.h"
32
33 namespace android::hardware::contexthub::common::implementation {
34
35 using ::aidl::android::hardware::contexthub::BnContextHub;
36 using ::chre::fbs::ChreMessage;
37 using HostHub = MessageHubManager::HostHub;
38
init()39 void ContextHubV4Impl::init() {
40 std::lock_guard lock(mHostHubOpLock); // See header documentation.
41 flatbuffers::FlatBufferBuilder builder;
42 // NOTE: This message should be renamed as on initialization/CHRE restart it
43 // is used both to initialize the CHRE-side host hub proxies and to request
44 // embedded hub state.
45 HostProtocolHostV4::encodeGetMessageHubsAndEndpointsRequest(builder);
46 if (!mSendMessageFn(builder))
47 LOGE("Failed to initialize CHRE host hub proxies");
48 mManager.forEachHostHub([this](HostHub &hub) {
49 flatbuffers::FlatBufferBuilder builder;
50 HostProtocolHostV4::encodeRegisterMessageHub(builder, hub.info());
51 if (!mSendMessageFn(builder)) {
52 LOGE("Failed to initialize proxy for host hub %" PRIu64, hub.id());
53 return;
54 }
55 for (const auto &endpoint : hub.getEndpoints()) {
56 flatbuffers::FlatBufferBuilder builder;
57 HostProtocolHostV4::encodeRegisterEndpoint(builder, endpoint);
58 if (!mSendMessageFn(builder)) {
59 LOGE("Failed to initialize proxy for host endpoint (%" PRIu64
60 ", %" PRIu64 ")",
61 endpoint.id.hubId, endpoint.id.id);
62 return;
63 }
64 }
65 });
66 }
67
onChreDisconnected()68 void ContextHubV4Impl::onChreDisconnected() {
69 LOGI("Clearing embedded message hub state.");
70 mManager.clearEmbeddedState();
71 }
72
onChreRestarted()73 void ContextHubV4Impl::onChreRestarted() {
74 init();
75 }
76
77 namespace {
78
fromPwStatus(pw::Status status)79 ScopedAStatus fromPwStatus(pw::Status status) {
80 switch (status.code()) {
81 case PW_STATUS_OK:
82 return ScopedAStatus::ok();
83 case PW_STATUS_NOT_FOUND:
84 [[fallthrough]];
85 case PW_STATUS_ALREADY_EXISTS:
86 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
87 case PW_STATUS_OUT_OF_RANGE:
88 [[fallthrough]];
89 case PW_STATUS_PERMISSION_DENIED:
90 [[fallthrough]];
91 case PW_STATUS_INVALID_ARGUMENT:
92 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
93 case PW_STATUS_UNIMPLEMENTED:
94 return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
95 default:
96 return ScopedAStatus::fromServiceSpecificError(
97 BnContextHub::EX_CONTEXT_HUB_UNSPECIFIED);
98 }
99 }
100
101 } // namespace
102
getHubs(std::vector<HubInfo> * hubs)103 ScopedAStatus ContextHubV4Impl::getHubs(std::vector<HubInfo> *hubs) {
104 *hubs = mManager.getEmbeddedHubs();
105 return ScopedAStatus::ok();
106 }
107
getEndpoints(std::vector<EndpointInfo> * endpoints)108 ScopedAStatus ContextHubV4Impl::getEndpoints(
109 std::vector<EndpointInfo> *endpoints) {
110 *endpoints = mManager.getEmbeddedEndpoints();
111 return ScopedAStatus::ok();
112 }
113
registerEndpointHub(const std::shared_ptr<IEndpointCallback> & callback,const HubInfo & hubInfo,std::shared_ptr<IEndpointCommunication> * hubInterface)114 ScopedAStatus ContextHubV4Impl::registerEndpointHub(
115 const std::shared_ptr<IEndpointCallback> &callback, const HubInfo &hubInfo,
116 std::shared_ptr<IEndpointCommunication> *hubInterface) {
117 std::lock_guard lock(mHostHubOpLock); // See header documentation.
118 auto statusOrHub = mManager.createHostHub(
119 callback, hubInfo, AIBinder_getCallingUid(), AIBinder_getCallingPid());
120 if (!statusOrHub.ok()) {
121 LOGE("Failed to register message hub 0x%" PRIx64 " with %" PRId32,
122 hubInfo.hubId, statusOrHub.status().ok());
123 return fromPwStatus(statusOrHub.status());
124 }
125 flatbuffers::FlatBufferBuilder builder;
126 HostProtocolHostV4::encodeRegisterMessageHub(builder, hubInfo);
127 if (!mSendMessageFn(builder)) {
128 LOGE("Failed to send RegisterMessageHub for hub 0x%" PRIx64, hubInfo.hubId);
129 (*statusOrHub)->unregister();
130 return ScopedAStatus::fromServiceSpecificError(
131 BnContextHub::EX_CONTEXT_HUB_UNSPECIFIED);
132 }
133 *hubInterface = ndk::SharedRefBase::make<HostHubInterface>(
134 std::move(*statusOrHub), mSendMessageFn, mHostHubOpLock);
135 return ScopedAStatus::ok();
136 }
137
registerEndpoint(const EndpointInfo & endpoint)138 ScopedAStatus HostHubInterface::registerEndpoint(const EndpointInfo &endpoint) {
139 std::lock_guard lock(mHostHubOpLock); // See header documentation.
140 if (auto status = mHub->addEndpoint(endpoint); !status.ok()) {
141 LOGE("Failed to register endpoint 0x%" PRIx64 " on hub 0x%" PRIx64
142 " with %" PRId32,
143 endpoint.id.id, mHub->id(), status.code());
144 return fromPwStatus(status);
145 }
146 flatbuffers::FlatBufferBuilder builder;
147 HostProtocolHostV4::encodeRegisterEndpoint(builder, endpoint);
148 if (!mSendMessageFn(builder)) {
149 LOGE("Failed to send RegisterEndpoint for (0x%" PRIx64 ", 0x%" PRIx64 ")",
150 endpoint.id.hubId, endpoint.id.id);
151 mHub->removeEndpoint(endpoint.id).IgnoreError();
152 return ScopedAStatus::fromServiceSpecificError(
153 BnContextHub::EX_CONTEXT_HUB_UNSPECIFIED);
154 }
155 return ScopedAStatus::ok();
156 }
157
unregisterEndpoint(const EndpointInfo & endpoint)158 ScopedAStatus HostHubInterface::unregisterEndpoint(
159 const EndpointInfo &endpoint) {
160 std::lock_guard lock(mHostHubOpLock); // See header documentation.
161 auto statusOrSessions = mHub->removeEndpoint(endpoint.id);
162 if (!statusOrSessions.ok()) {
163 LOGE("Failed to unregister endpoint 0x%" PRIx64 " on hub 0x%" PRIx64
164 " with %" PRId32,
165 endpoint.id.id, mHub->id(), statusOrSessions.status().code());
166 return fromPwStatus(statusOrSessions.status());
167 }
168 flatbuffers::FlatBufferBuilder builder;
169 HostProtocolHostV4::encodeUnregisterEndpoint(builder, endpoint.id);
170 if (!mSendMessageFn(builder)) {
171 LOGE("Failed to send RegisterEndpoint for (0x%" PRIx64 ", 0x%" PRIx64 ")",
172 endpoint.id.hubId, endpoint.id.id);
173 return ScopedAStatus::fromServiceSpecificError(
174 BnContextHub::EX_CONTEXT_HUB_UNSPECIFIED);
175 }
176 return ScopedAStatus::ok();
177 }
178
requestSessionIdRange(int32_t size,std::array<int32_t,2> * ids)179 ScopedAStatus HostHubInterface::requestSessionIdRange(
180 int32_t size, std::array<int32_t, 2> *ids) {
181 auto statusOrRange = mHub->reserveSessionIdRange(size);
182 if (!statusOrRange.ok()) {
183 LOGE("Failed to reserve %" PRId32 " session ids on hub 0x%" PRIx64
184 " with %" PRId32,
185 size, mHub->id(), statusOrRange.status().code());
186 return fromPwStatus(statusOrRange.status());
187 }
188 (*ids)[0] = statusOrRange->first;
189 (*ids)[1] = statusOrRange->second;
190 return ScopedAStatus::ok();
191 }
192
openEndpointSession(int32_t sessionId,const EndpointId & destination,const EndpointId & initiator,const std::optional<std::string> & serviceDescriptor)193 ScopedAStatus HostHubInterface::openEndpointSession(
194 int32_t sessionId, const EndpointId &destination,
195 const EndpointId &initiator,
196 const std::optional<std::string> &serviceDescriptor) {
197 // Ignore the flag to send a close. This hub overriding its own session is an
198 // should just return error.
199 auto status = mHub->openSession(initiator, destination, sessionId,
200 serviceDescriptor, /*hostInitiated=*/true);
201 if (!status.ok()) {
202 LOGE("Failed to open session %" PRId32 " from (0x%" PRIx64 ", 0x%" PRIx64
203 ") to (0x%" PRIx64 ", 0x%" PRIx64 ") with %" PRId32,
204 sessionId, initiator.hubId, initiator.id, destination.hubId,
205 destination.id, status.code());
206 return fromPwStatus(status);
207 }
208 flatbuffers::FlatBufferBuilder builder;
209 HostProtocolHostV4::encodeOpenEndpointSessionRequest(
210 builder, mHub->id(), sessionId, initiator, destination,
211 serviceDescriptor);
212 if (!mSendMessageFn(builder)) {
213 LOGE("Failed to send OpenEndpointSessionRequest for session %" PRId32,
214 sessionId);
215 mHub->closeSession(sessionId, Reason::UNSPECIFIED).IgnoreError();
216 return ScopedAStatus::fromServiceSpecificError(
217 BnContextHub::EX_CONTEXT_HUB_UNSPECIFIED);
218 }
219 return ScopedAStatus::ok();
220 }
221
sendMessageToEndpoint(int32_t sessionId,const Message & msg)222 ScopedAStatus HostHubInterface::sendMessageToEndpoint(int32_t sessionId,
223 const Message &msg) {
224 if (auto status = mHub->checkSessionOpen(sessionId); !status.ok()) {
225 LOGE("Failed to verify session %" PRId32 " on hub 0x%" PRIx64
226 " with %" PRId32,
227 sessionId, mHub->id(), status.code());
228 return fromPwStatus(status);
229 }
230 // TODO(b/378545373): Handle reliable messages.
231 flatbuffers::FlatBufferBuilder builder;
232 HostProtocolHostV4::encodeEndpointSessionMessage(builder, mHub->id(),
233 sessionId, msg);
234 if (!mSendMessageFn(builder)) {
235 LOGE("Failed to send EndpointSessionMessage over session %" PRId32,
236 sessionId);
237 return ScopedAStatus::fromServiceSpecificError(
238 BnContextHub::EX_CONTEXT_HUB_UNSPECIFIED);
239 }
240 return ScopedAStatus::ok();
241 }
242
sendMessageDeliveryStatusToEndpoint(int32_t sessionId,const MessageDeliveryStatus & msgStatus)243 ScopedAStatus HostHubInterface::sendMessageDeliveryStatusToEndpoint(
244 int32_t sessionId, const MessageDeliveryStatus &msgStatus) {
245 if (auto status = mHub->checkSessionOpen(sessionId); !status.ok()) {
246 LOGE("Failed to verify session %" PRId32 " on hub 0x%" PRIx64
247 " with %" PRId32,
248 sessionId, mHub->id(), status.code());
249 return fromPwStatus(status);
250 }
251 flatbuffers::FlatBufferBuilder builder;
252 HostProtocolHostV4::encodeEndpointSessionMessageDeliveryStatus(
253 builder, mHub->id(), sessionId, msgStatus);
254 if (!mSendMessageFn(builder)) {
255 LOGE(
256 "Failed to send EndpointSessionMessageDeliveryStatus over session "
257 "%" PRId32,
258 sessionId);
259 return ScopedAStatus::fromServiceSpecificError(
260 BnContextHub::EX_CONTEXT_HUB_UNSPECIFIED);
261 }
262 return ScopedAStatus::ok();
263 }
264
closeEndpointSession(int32_t sessionId,Reason reason)265 ScopedAStatus HostHubInterface::closeEndpointSession(int32_t sessionId,
266 Reason reason) {
267 if (auto status = mHub->closeSession(sessionId); !status.ok()) {
268 LOGE("Failed to close session %" PRId32 " on hub 0x%" PRIx64
269 " with %" PRId32,
270 sessionId, mHub->id(), status.code());
271 return fromPwStatus(status);
272 }
273 flatbuffers::FlatBufferBuilder builder;
274 HostProtocolHostV4::encodeEndpointSessionClosed(builder, mHub->id(),
275 sessionId, reason);
276 if (!mSendMessageFn(builder)) {
277 LOGE("Failed to send EndpointSessionClosed for session %" PRId32,
278 sessionId);
279 return ScopedAStatus::fromServiceSpecificError(
280 BnContextHub::EX_CONTEXT_HUB_UNSPECIFIED);
281 }
282 return ScopedAStatus::ok();
283 }
284
endpointSessionOpenComplete(int32_t sessionId)285 ScopedAStatus HostHubInterface::endpointSessionOpenComplete(int32_t sessionId) {
286 if (auto status = mHub->ackSession(sessionId, /*hostAcked=*/true);
287 !status.ok()) {
288 LOGE("Failed to verify session %" PRId32 " on hub 0x%" PRIx64
289 " with %" PRId32,
290 sessionId, mHub->id(), status.code());
291 return fromPwStatus(status);
292 }
293 flatbuffers::FlatBufferBuilder builder;
294 HostProtocolHostV4::encodeEndpointSessionOpened(builder, mHub->id(),
295 sessionId);
296 if (!mSendMessageFn(builder)) {
297 LOGE("Failed to send EndpointSessionOpened for session %" PRId32,
298 sessionId);
299 return ScopedAStatus::fromServiceSpecificError(
300 BnContextHub::EX_CONTEXT_HUB_UNSPECIFIED);
301 }
302 return ScopedAStatus::ok();
303 }
304
unregister()305 ScopedAStatus HostHubInterface::unregister() {
306 std::lock_guard lock(mHostHubOpLock); // See header documentation.
307 if (auto status = mHub->unregister(); !status.ok())
308 return fromPwStatus(status);
309 flatbuffers::FlatBufferBuilder builder;
310 HostProtocolHostV4::encodeUnregisterMessageHub(builder, mHub->id());
311 if (!mSendMessageFn(builder))
312 LOGE("Failed to send UnregisterMessageHub for hub 0x%" PRIx64, mHub->id());
313 return ScopedAStatus::ok();
314 }
315
handleMessageFromChre(const::chre::fbs::ChreMessageUnion & message)316 bool ContextHubV4Impl::handleMessageFromChre(
317 const ::chre::fbs::ChreMessageUnion &message) {
318 switch (message.type) {
319 case ChreMessage::GetMessageHubsAndEndpointsResponse:
320 onGetMessageHubsAndEndpointsResponse(
321 *message.AsGetMessageHubsAndEndpointsResponse());
322 break;
323 case ChreMessage::RegisterMessageHub:
324 onRegisterMessageHub(*message.AsRegisterMessageHub());
325 break;
326 case ChreMessage::UnregisterMessageHub:
327 onUnregisterMessageHub(*message.AsUnregisterMessageHub());
328 break;
329 case ChreMessage::RegisterEndpoint:
330 onRegisterEndpoint(*message.AsRegisterEndpoint());
331 break;
332 case ChreMessage::UnregisterEndpoint:
333 onUnregisterEndpoint(*message.AsUnregisterEndpoint());
334 break;
335 case ChreMessage::OpenEndpointSessionRequest:
336 onOpenEndpointSessionRequest(*message.AsOpenEndpointSessionRequest());
337 break;
338 case ChreMessage::EndpointSessionOpened:
339 onEndpointSessionOpened(*message.AsEndpointSessionOpened());
340 break;
341 case ChreMessage::EndpointSessionClosed:
342 onEndpointSessionClosed(*message.AsEndpointSessionClosed());
343 break;
344 case ChreMessage::EndpointSessionMessage:
345 onEndpointSessionMessage(*message.AsEndpointSessionMessage());
346 break;
347 case ChreMessage::EndpointSessionMessageDeliveryStatus:
348 onEndpointSessionMessageDeliveryStatus(
349 *message.AsEndpointSessionMessageDeliveryStatus());
350 break;
351 case ChreMessage::AddServiceToEndpoint:
352 onAddServiceToEndpoint(*message.AsAddServiceToEndpoint());
353 break;
354 case ChreMessage::EndpointReady:
355 onEndpointReady(*message.AsEndpointReady());
356 break;
357 default:
358 LOGW("Got unexpected message type %" PRIu8,
359 static_cast<uint8_t>(message.type));
360 return false;
361 }
362 return true;
363 }
364
onGetMessageHubsAndEndpointsResponse(const::chre::fbs::GetMessageHubsAndEndpointsResponseT &)365 void ContextHubV4Impl::onGetMessageHubsAndEndpointsResponse(
366 const ::chre::fbs::GetMessageHubsAndEndpointsResponseT & /*msg*/) {
367 LOGI("Initializing embedded message hub cache");
368 mManager.initEmbeddedState();
369 }
370
onRegisterMessageHub(const::chre::fbs::RegisterMessageHubT & msg)371 void ContextHubV4Impl::onRegisterMessageHub(
372 const ::chre::fbs::RegisterMessageHubT &msg) {
373 HubInfo hub;
374 HostProtocolHostV4::decodeRegisterMessageHub(msg, hub);
375 LOGI("Embedded message hub 0x%" PRIx64 " registered", hub.hubId);
376 mManager.addEmbeddedHub(hub);
377 }
378
onUnregisterMessageHub(const::chre::fbs::UnregisterMessageHubT & msg)379 void ContextHubV4Impl::onUnregisterMessageHub(
380 const ::chre::fbs::UnregisterMessageHubT &msg) {
381 int64_t id = 0;
382 HostProtocolHostV4::decodeUnregisterMessageHub(msg, id);
383 LOGI("Embedded message hub 0x%" PRIx64 " unregistered", id);
384 mManager.removeEmbeddedHub(id);
385 }
386
onRegisterEndpoint(const::chre::fbs::RegisterEndpointT & msg)387 void ContextHubV4Impl::onRegisterEndpoint(
388 const ::chre::fbs::RegisterEndpointT &msg) {
389 EndpointInfo endpoint;
390 HostProtocolHostV4::decodeRegisterEndpoint(msg, endpoint);
391 LOGI("Adding embedded endpoint (0x%" PRIx64 ", 0x%" PRIx64 ")",
392 endpoint.id.hubId, endpoint.id.id);
393 mManager.addEmbeddedEndpoint(endpoint);
394 }
395
onAddServiceToEndpoint(const::chre::fbs::AddServiceToEndpointT & msg)396 void ContextHubV4Impl::onAddServiceToEndpoint(
397 const ::chre::fbs::AddServiceToEndpointT &msg) {
398 EndpointId endpoint;
399 Service service;
400 HostProtocolHostV4::decodeAddServiceToEndpoint(msg, endpoint, service);
401 mManager.addEmbeddedEndpointService(endpoint, service);
402 }
403
onEndpointReady(const::chre::fbs::EndpointReadyT & msg)404 void ContextHubV4Impl::onEndpointReady(const ::chre::fbs::EndpointReadyT &msg) {
405 EndpointId endpoint;
406 HostProtocolHostV4::decodeEndpointReady(msg, endpoint);
407 LOGI("Embedded endpoint (0x%" PRIx64 ", 0x%" PRIx64 ") ready", endpoint.hubId,
408 endpoint.id);
409 mManager.setEmbeddedEndpointReady(endpoint);
410 }
411
onUnregisterEndpoint(const::chre::fbs::UnregisterEndpointT & msg)412 void ContextHubV4Impl::onUnregisterEndpoint(
413 const ::chre::fbs::UnregisterEndpointT &msg) {
414 EndpointId endpoint;
415 HostProtocolHostV4::decodeUnregisterEndpoint(msg, endpoint);
416 LOGI("Removing embedded endpoint (0x%" PRIx64 ", 0x%" PRIx64 ")",
417 endpoint.hubId, endpoint.id);
418 mManager.removeEmbeddedEndpoint(endpoint);
419 }
420
onOpenEndpointSessionRequest(const::chre::fbs::OpenEndpointSessionRequestT & msg)421 void ContextHubV4Impl::onOpenEndpointSessionRequest(
422 const ::chre::fbs::OpenEndpointSessionRequestT &msg) {
423 std::optional<std::string> serviceDescriptor;
424 EndpointId local, remote;
425 int64_t hubId = 0;
426 uint16_t sessionId = 0;
427 HostProtocolHostV4::decodeOpenEndpointSessionRequest(
428 msg, hubId, sessionId, local, remote, serviceDescriptor);
429 LOGD("New session (%" PRIu16 ") request from (0x%" PRIx64 ", 0x%" PRIx64
430 ") to "
431 "(0x%" PRIx64 ", 0x%" PRIx64 ")",
432 sessionId, remote.hubId, remote.id, local.hubId, local.id);
433 std::shared_ptr<HostHub> hub = mManager.getHostHub(hubId);
434 if (!hub) {
435 LOGW("Unable to find host hub");
436 return;
437 }
438
439 // Record the open session request and pass it on to the appropriate client.
440 auto status =
441 hub->openSession(local, remote, sessionId, std::move(serviceDescriptor),
442 /*hostInitiated=*/false);
443 if (!status.ok()) {
444 LOGE("Failed to request session %" PRIu16 " with %" PRId32, sessionId,
445 status.code());
446 flatbuffers::FlatBufferBuilder builder;
447 HostProtocolHostV4::encodeEndpointSessionClosed(
448 builder, hub->id(), sessionId, Reason::UNSPECIFIED);
449 mSendMessageFn(builder);
450 return;
451 }
452 }
453
onEndpointSessionOpened(const::chre::fbs::EndpointSessionOpenedT & msg)454 void ContextHubV4Impl::onEndpointSessionOpened(
455 const ::chre::fbs::EndpointSessionOpenedT &msg) {
456 int64_t hubId = 0;
457 uint16_t sessionId = 0;
458 HostProtocolHostV4::decodeEndpointSessionOpened(msg, hubId, sessionId);
459 LOGD("New session ack for id %" PRIu16 " on hub 0x%" PRIx64, sessionId,
460 hubId);
461 std::shared_ptr<HostHub> hub = mManager.getHostHub(hubId);
462 if (!hub) {
463 LOGW("Unable to find host hub");
464 return;
465 }
466 if (auto status = hub->ackSession(sessionId, /*hostAcked=*/false);
467 !status.ok()) {
468 handleSessionFailure(hub, sessionId, status);
469 return;
470 }
471 }
472
onEndpointSessionClosed(const::chre::fbs::EndpointSessionClosedT & msg)473 void ContextHubV4Impl::onEndpointSessionClosed(
474 const ::chre::fbs::EndpointSessionClosedT &msg) {
475 int64_t hubId = 0;
476 uint16_t sessionId = 0;
477 Reason reason = Reason::UNSPECIFIED;
478 HostProtocolHostV4::decodeEndpointSessionClosed(msg, hubId, sessionId,
479 reason);
480 LOGD("Closing session id %" PRIu16 " for %" PRIu8, sessionId, reason);
481 std::shared_ptr<HostHub> hub = mManager.getHostHub(hubId);
482 if (!hub) {
483 LOGW("Unable to find host hub");
484 return;
485 }
486 hub->closeSession(sessionId, reason).IgnoreError();
487 }
488
onEndpointSessionMessage(const::chre::fbs::EndpointSessionMessageT & msg)489 void ContextHubV4Impl::onEndpointSessionMessage(
490 const ::chre::fbs::EndpointSessionMessageT &msg) {
491 Message message;
492 int64_t hubId = 0;
493 uint16_t sessionId = 0;
494 HostProtocolHostV4::decodeEndpointSessionMessage(msg, hubId, sessionId,
495 message);
496 std::shared_ptr<HostHub> hub = mManager.getHostHub(hubId);
497 if (!hub) {
498 LOGW("Unable to find host hub");
499 return;
500 }
501 auto status = hub->handleMessage(sessionId, message);
502 if (status.ok()) return;
503 handleSessionFailure(hub, sessionId, status);
504 }
505
onEndpointSessionMessageDeliveryStatus(const::chre::fbs::EndpointSessionMessageDeliveryStatusT & msg)506 void ContextHubV4Impl::onEndpointSessionMessageDeliveryStatus(
507 const ::chre::fbs::EndpointSessionMessageDeliveryStatusT &msg) {
508 MessageDeliveryStatus deliveryStatus;
509 int64_t hubId = 0;
510 uint16_t sessionId = 0;
511 HostProtocolHostV4::decodeEndpointSessionMessageDeliveryStatus(
512 msg, hubId, sessionId, deliveryStatus);
513 std::shared_ptr<HostHub> hub = mManager.getHostHub(hubId);
514 if (!hub) {
515 LOGW("Unable to find host hub");
516 return;
517 }
518 auto status = hub->handleMessageDeliveryStatus(sessionId, deliveryStatus);
519 if (status.ok()) return;
520 handleSessionFailure(hub, sessionId, status);
521 }
522
unlinkDeadHostHub(std::function<pw::Result<int64_t> ()> unlinkFn)523 void ContextHubV4Impl::unlinkDeadHostHub(
524 std::function<pw::Result<int64_t>()> unlinkFn) {
525 std::lock_guard lock(mHostHubOpLock); // See header documentation.
526 auto statusOrHubId = unlinkFn();
527 if (!statusOrHubId.ok()) return;
528 flatbuffers::FlatBufferBuilder builder;
529 HostProtocolHostV4::encodeUnregisterMessageHub(builder, *statusOrHubId);
530 if (!mSendMessageFn(builder)) {
531 LOGE("Failed to send UnregisterMessageHub for hub 0x%" PRIx64,
532 *statusOrHubId);
533 }
534 }
535
handleSessionFailure(const std::shared_ptr<HostHub> & hub,uint16_t session,pw::Status status)536 void ContextHubV4Impl::handleSessionFailure(const std::shared_ptr<HostHub> &hub,
537 uint16_t session,
538 pw::Status status) {
539 LOGE("Failed to operate on session %" PRIu16 " on hub 0x%" PRIx64
540 " with %" PRId32,
541 session, hub->id(), status.code());
542 flatbuffers::FlatBufferBuilder builder;
543 HostProtocolHostV4::encodeEndpointSessionClosed(builder, hub->id(), session,
544 Reason::UNSPECIFIED);
545 mSendMessageFn(builder);
546 hub->closeSession(session, Reason::UNSPECIFIED).IgnoreError();
547 }
548
549 } // namespace android::hardware::contexthub::common::implementation
550