• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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