blob: 433617e9a37da67aacfb29ede73c0fde4c233099 [file] [log] [blame]
Arthur Ishiguroa257b782021-08-04 10:40:29 -07001/*
2 * Copyright (C) 2021 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 "contexthub-impl/ContextHub.h"
Matthew Sedam0ec290c2024-12-11 11:18:15 -080018#include "aidl/android/hardware/contexthub/IContextHubCallback.h"
Arthur Ishiguroa257b782021-08-04 10:40:29 -070019
Matthew Sedam92c2bd82024-11-11 19:52:30 +000020#ifndef LOG_TAG
21#define LOG_TAG "CHRE"
22#endif
23
24#include <inttypes.h>
25#include <log/log.h>
Matthew Sedam0ec290c2024-12-11 11:18:15 -080026#include <optional>
27#include <thread>
Arthur Ishiguroa257b782021-08-04 10:40:29 -070028
Arthur Ishiguro070f47d2022-01-06 22:42:10 +000029using ::ndk::ScopedAStatus;
30
Matthew Sedam92c2bd82024-11-11 19:52:30 +000031namespace aidl::android::hardware::contexthub {
32
33namespace {
34
35constexpr uint64_t kMockVendorHubId = 0x1234567812345678;
36constexpr uint64_t kMockVendorHub2Id = 0x0EADBEEFDEADBEEF;
37
38// Mock endpoints for the default implementation.
39// These endpoints just echo back any messages sent to them.
40constexpr size_t kMockEndpointCount = 4;
41const EndpointInfo kMockEndpointInfos[kMockEndpointCount] = {
42 {
43 .id = {.hubId = kMockVendorHubId, .id = UINT64_C(0x1)},
44 .type = EndpointInfo::EndpointType::GENERIC,
45 .name = "Mock Endpoint 1",
46 .version = 1,
47 },
48 {
49 .id = {.hubId = kMockVendorHubId, .id = UINT64_C(0x2)},
50 .type = EndpointInfo::EndpointType::GENERIC,
51 .name = "Mock Endpoint 2",
52 .version = 2,
53 },
54 {
55 .id = {.hubId = kMockVendorHub2Id, .id = UINT64_C(0x1)},
56 .type = EndpointInfo::EndpointType::GENERIC,
57 .name = "Mock Endpoint 3",
58 .version = 1,
59 },
60 {
61 .id = {.hubId = kMockVendorHub2Id, .id = UINT64_C(0x2)},
62 .type = EndpointInfo::EndpointType::GENERIC,
63 .name = "Mock Endpoint 4",
64 .version = 2,
65 },
66};
67
Matthew Sedam0ec290c2024-12-11 11:18:15 -080068//! Mutex used to ensure callbacks are called after the initial function returns.
69std::mutex gCallbackMutex;
70
Matthew Sedam92c2bd82024-11-11 19:52:30 +000071} // anonymous namespace
72
Arthur Ishiguro0d6009e2024-12-24 16:31:20 -080073ScopedAStatus ContextHub::getContextHubs(std::vector<ContextHubInfo>* /* out_contextHubInfos */) {
Matthew Sedamadfd5572023-11-21 05:53:00 -080074 return ScopedAStatus::ok();
Arthur Ishiguroa257b782021-08-04 10:40:29 -070075}
76
Arthur Ishiguro94e1aa22021-10-26 17:25:19 +000077// We don't expose any nanoapps for the default impl, therefore all nanoapp-related APIs fail.
Arthur Ishiguro070f47d2022-01-06 22:42:10 +000078ScopedAStatus ContextHub::loadNanoapp(int32_t /* in_contextHubId */,
79 const NanoappBinary& /* in_appBinary */,
80 int32_t /* in_transactionId */) {
81 return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
82}
83
84ScopedAStatus ContextHub::unloadNanoapp(int32_t /* in_contextHubId */, int64_t /* in_appId */,
85 int32_t /* in_transactionId */) {
86 return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
87}
88
89ScopedAStatus ContextHub::disableNanoapp(int32_t /* in_contextHubId */, int64_t /* in_appId */,
90 int32_t /* in_transactionId */) {
91 return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
92}
93
94ScopedAStatus ContextHub::enableNanoapp(int32_t /* in_contextHubId */, int64_t /* in_appId */,
95 int32_t /* in_transactionId */) {
96 return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
97}
98
99ScopedAStatus ContextHub::onSettingChanged(Setting /* in_setting */, bool /*in_enabled */) {
Matthew Sedamadfd5572023-11-21 05:53:00 -0800100 return ScopedAStatus::ok();
Arthur Ishiguroa257b782021-08-04 10:40:29 -0700101}
102
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000103ScopedAStatus ContextHub::queryNanoapps(int32_t in_contextHubId) {
Arthur Ishiguro94e1aa22021-10-26 17:25:19 +0000104 if (in_contextHubId == kMockHubId && mCallback != nullptr) {
105 std::vector<NanoappInfo> nanoapps;
106 mCallback->handleNanoappInfo(nanoapps);
Matthew Sedamadfd5572023-11-21 05:53:00 -0800107 return ScopedAStatus::ok();
Arthur Ishiguro94e1aa22021-10-26 17:25:19 +0000108 } else {
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000109 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
Arthur Ishiguro94e1aa22021-10-26 17:25:19 +0000110 }
Arthur Ishiguroa257b782021-08-04 10:40:29 -0700111}
112
Matthew Sedamd70f84d2023-03-06 18:34:24 +0000113ScopedAStatus ContextHub::getPreloadedNanoappIds(int32_t /* in_contextHubId */,
114 std::vector<int64_t>* out_preloadedNanoappIds) {
Arthur Ishigurofd5e65c2022-11-08 16:49:47 +0000115 if (out_preloadedNanoappIds == nullptr) {
116 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
117 }
118
119 for (uint64_t i = 0; i < 10; ++i) {
120 out_preloadedNanoappIds->push_back(i);
121 }
Matthew Sedamadfd5572023-11-21 05:53:00 -0800122 return ScopedAStatus::ok();
Arthur Ishigurofd5e65c2022-11-08 16:49:47 +0000123}
124
Anthony Stange7fba1002023-03-02 21:45:20 +0000125ScopedAStatus ContextHub::onNanSessionStateChanged(const NanSessionStateUpdate& /*in_update*/) {
Matthew Sedamadfd5572023-11-21 05:53:00 -0800126 return ScopedAStatus::ok();
Anthony Stange7344af92022-12-22 14:21:31 +0000127}
128
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000129ScopedAStatus ContextHub::registerCallback(int32_t in_contextHubId,
130 const std::shared_ptr<IContextHubCallback>& in_cb) {
Arthur Ishiguro94e1aa22021-10-26 17:25:19 +0000131 if (in_contextHubId == kMockHubId) {
132 mCallback = in_cb;
Matthew Sedamadfd5572023-11-21 05:53:00 -0800133 return ScopedAStatus::ok();
Arthur Ishiguro94e1aa22021-10-26 17:25:19 +0000134 } else {
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000135 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
Arthur Ishiguro94e1aa22021-10-26 17:25:19 +0000136 }
Arthur Ishiguroa257b782021-08-04 10:40:29 -0700137}
138
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000139ScopedAStatus ContextHub::sendMessageToHub(int32_t in_contextHubId,
140 const ContextHubMessage& /* in_message */) {
Arthur Ishiguro94e1aa22021-10-26 17:25:19 +0000141 if (in_contextHubId == kMockHubId) {
142 // Return true here to indicate that the HAL has accepted the message.
143 // Successful delivery of the message to a nanoapp should be handled at
144 // a higher level protocol.
Matthew Sedamadfd5572023-11-21 05:53:00 -0800145 return ScopedAStatus::ok();
Arthur Ishiguro94e1aa22021-10-26 17:25:19 +0000146 } else {
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000147 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
Arthur Ishiguro94e1aa22021-10-26 17:25:19 +0000148 }
Arthur Ishiguroa257b782021-08-04 10:40:29 -0700149}
150
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000151ScopedAStatus ContextHub::setTestMode(bool enable) {
152 if (enable) {
Madhav Iyengaree25d072024-12-17 17:08:55 +0000153 std::lock_guard lock(mHostHubsLock);
154 for (auto& [id, hub] : mIdToHostHub) {
155 hub->mActive = false;
156 }
157 mIdToHostHub.clear();
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000158 }
Matthew Sedamadfd5572023-11-21 05:53:00 -0800159 return ScopedAStatus::ok();
Matthew Sedamc8ce4d52023-01-09 20:18:21 +0000160}
161
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000162ScopedAStatus ContextHub::onHostEndpointConnected(const HostEndpointInfo& in_info) {
Arthur Ishiguro065a9a52021-11-19 00:24:45 +0000163 mConnectedHostEndpoints.insert(in_info.hostEndpointId);
164
Matthew Sedamadfd5572023-11-21 05:53:00 -0800165 return ScopedAStatus::ok();
Arthur Ishiguro065a9a52021-11-19 00:24:45 +0000166}
167
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000168ScopedAStatus ContextHub::onHostEndpointDisconnected(char16_t in_hostEndpointId) {
Arthur Ishiguro065a9a52021-11-19 00:24:45 +0000169 if (mConnectedHostEndpoints.count(in_hostEndpointId) > 0) {
170 mConnectedHostEndpoints.erase(in_hostEndpointId);
Arthur Ishiguro065a9a52021-11-19 00:24:45 +0000171 }
Arthur Ishigurobb1d8bf2022-07-06 15:29:13 +0000172
Matthew Sedamadfd5572023-11-21 05:53:00 -0800173 return ScopedAStatus::ok();
Arthur Ishiguro065a9a52021-11-19 00:24:45 +0000174}
175
Matthew Sedamadfd5572023-11-21 05:53:00 -0800176ScopedAStatus ContextHub::sendMessageDeliveryStatusToHub(
177 int32_t /* in_contextHubId */,
178 const MessageDeliveryStatus& /* in_messageDeliveryStatus */) {
179 return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
180}
181
Yifei Zhang51eba2e2024-10-24 15:11:54 -0700182ScopedAStatus ContextHub::getHubs(std::vector<HubInfo>* _aidl_return) {
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000183 if (_aidl_return == nullptr) {
184 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
185 }
186
Yifei Zhang51eba2e2024-10-24 15:11:54 -0700187 VendorHubInfo vendorHub = {};
188 vendorHub.name = "Mock Vendor Hub";
189 vendorHub.version = 42;
190
Arthur Ishiguro0d6009e2024-12-24 16:31:20 -0800191 HubInfo hubInfo1 = {};
192 hubInfo1.hubId = kMockVendorHubId;
193 hubInfo1.hubDetails =
Yifei Zhang51eba2e2024-10-24 15:11:54 -0700194 HubInfo::HubDetails::make<HubInfo::HubDetails::Tag::vendorHubInfo>(vendorHub);
195
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000196 VendorHubInfo vendorHub2 = {};
197 vendorHub2.name = "Mock Vendor Hub 2";
198 vendorHub2.version = 24;
199
Arthur Ishiguro0d6009e2024-12-24 16:31:20 -0800200 HubInfo hubInfo2 = {};
201 hubInfo2.hubId = kMockVendorHub2Id;
202 hubInfo2.hubDetails =
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000203 HubInfo::HubDetails::make<HubInfo::HubDetails::Tag::vendorHubInfo>(vendorHub2);
204
Yifei Zhang51eba2e2024-10-24 15:11:54 -0700205 _aidl_return->push_back(hubInfo1);
206 _aidl_return->push_back(hubInfo2);
207
208 return ScopedAStatus::ok();
209};
210
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000211ScopedAStatus ContextHub::getEndpoints(std::vector<EndpointInfo>* _aidl_return) {
212 if (_aidl_return == nullptr) {
213 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
214 }
215
216 Service echoService;
217 echoService.format = Service::RpcFormat::CUSTOM;
Arthur Ishiguro39087712024-12-13 09:48:13 -0800218 echoService.serviceDescriptor = "android.hardware.contexthub.test.EchoService";
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000219 echoService.majorVersion = 1;
220 echoService.minorVersion = 0;
221
222 for (const EndpointInfo& endpoint : kMockEndpointInfos) {
223 EndpointInfo endpointWithService(endpoint);
224 endpointWithService.services.push_back(echoService);
225 _aidl_return->push_back(std::move(endpointWithService));
226 }
227
228 return ScopedAStatus::ok();
Yifei Zhang51eba2e2024-10-24 15:11:54 -0700229};
230
Madhav Iyengaree25d072024-12-17 17:08:55 +0000231ScopedAStatus ContextHub::registerEndpointHub(
232 const std::shared_ptr<IEndpointCallback>& in_callback, const HubInfo& in_hubInfo,
233 std::shared_ptr<IEndpointCommunication>* _aidl_return) {
234 std::lock_guard lock(mHostHubsLock);
235 if (mIdToHostHub.count(in_hubInfo.hubId)) {
236 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
237 }
238 auto hub = ndk::SharedRefBase::make<HubInterface>(*this, in_callback, in_hubInfo);
239 mIdToHostHub.insert({in_hubInfo.hubId, hub});
240 *_aidl_return = std::move(hub);
241 return ScopedAStatus::ok();
242}
243
244ScopedAStatus ContextHub::HubInterface::registerEndpoint(const EndpointInfo& in_endpoint) {
245 if (!mActive) {
246 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
247 }
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000248 std::unique_lock<std::mutex> lock(mEndpointMutex);
249
250 for (const EndpointInfo& endpoint : mEndpoints) {
251 if ((endpoint.id.id == in_endpoint.id.id && endpoint.id.hubId == in_endpoint.id.hubId) ||
252 endpoint.name == in_endpoint.name) {
253 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
254 }
255 }
256 mEndpoints.push_back(in_endpoint);
257 return ScopedAStatus::ok();
Yifei Zhang51eba2e2024-10-24 15:11:54 -0700258};
259
Madhav Iyengaree25d072024-12-17 17:08:55 +0000260ScopedAStatus ContextHub::HubInterface::unregisterEndpoint(const EndpointInfo& in_endpoint) {
261 if (!mActive) {
262 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
263 }
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000264 std::unique_lock<std::mutex> lock(mEndpointMutex);
265
266 for (auto it = mEndpoints.begin(); it != mEndpoints.end(); ++it) {
267 if (it->id.id == in_endpoint.id.id && it->id.hubId == in_endpoint.id.hubId) {
268 mEndpoints.erase(it);
269 return ScopedAStatus::ok();
270 }
271 }
272 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
Yifei Zhang51eba2e2024-10-24 15:11:54 -0700273};
274
Madhav Iyengaree25d072024-12-17 17:08:55 +0000275ScopedAStatus ContextHub::HubInterface::requestSessionIdRange(
276 int32_t in_size, std::array<int32_t, 2>* _aidl_return) {
277 if (!mActive) {
278 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
279 }
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000280 constexpr int32_t kMaxSize = 1024;
281 if (in_size > kMaxSize || _aidl_return == nullptr) {
282 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
283 }
284
Madhav Iyengaree25d072024-12-17 17:08:55 +0000285 uint16_t base = 0;
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000286 {
Madhav Iyengaree25d072024-12-17 17:08:55 +0000287 std::lock_guard lock(mHal.mHostHubsLock);
288 if (static_cast<int32_t>(USHRT_MAX) - mHal.mNextSessionIdBase + 1 < in_size) {
289 return ScopedAStatus::fromServiceSpecificError(EX_CONTEXT_HUB_UNSPECIFIED);
290 }
291 base = mHal.mNextSessionIdBase;
292 mHal.mNextSessionIdBase += in_size;
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000293 }
294
Madhav Iyengaree25d072024-12-17 17:08:55 +0000295 {
296 std::lock_guard<std::mutex> lock(mEndpointMutex);
297 (*_aidl_return)[0] = mBaseSessionId = base;
298 (*_aidl_return)[1] = mMaxSessionId = base + (in_size - 1);
299 }
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000300 return ScopedAStatus::ok();
Yifei Zhang51eba2e2024-10-24 15:11:54 -0700301};
302
Madhav Iyengaree25d072024-12-17 17:08:55 +0000303ScopedAStatus ContextHub::HubInterface::openEndpointSession(
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000304 int32_t in_sessionId, const EndpointId& in_destination, const EndpointId& in_initiator,
305 const std::optional<std::string>& in_serviceDescriptor) {
Madhav Iyengaree25d072024-12-17 17:08:55 +0000306 if (!mActive) {
307 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
308 }
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000309 // We are not calling onCloseEndpointSession on failure because the remote endpoints (our
310 // mock endpoints) always accept the session.
311
Matthew Sedam0ec290c2024-12-11 11:18:15 -0800312 std::weak_ptr<IEndpointCallback> callback;
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000313 {
314 std::unique_lock<std::mutex> lock(mEndpointMutex);
Madhav Iyengaree25d072024-12-17 17:08:55 +0000315 if (in_sessionId < mBaseSessionId || in_sessionId > mMaxSessionId) {
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000316 ALOGE("openEndpointSession: session ID %" PRId32 " is invalid", in_sessionId);
317 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
318 }
319
320 for (const EndpointSession& session : mEndpointSessions) {
321 bool sessionAlreadyExists =
322 (session.initiator == in_destination && session.peer == in_initiator) ||
323 (session.peer == in_destination && session.initiator == in_initiator);
324 if (sessionAlreadyExists) {
325 ALOGD("openEndpointSession: session ID %" PRId32 " already exists", in_sessionId);
326 return (session.sessionId == in_sessionId &&
327 session.serviceDescriptor == in_serviceDescriptor)
328 ? ScopedAStatus::ok()
329 : ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
330 } else if (session.sessionId == in_sessionId) {
331 ALOGE("openEndpointSession: session ID %" PRId32 " is invalid: endpoint mismatch",
332 in_sessionId);
333 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
334 }
335 }
336
337 // Verify the initiator and destination are valid endpoints
338 bool initiatorIsValid = findEndpoint(in_initiator, mEndpoints.begin(), mEndpoints.end());
339 if (!initiatorIsValid) {
340 ALOGE("openEndpointSession: initiator %" PRIu64 ":%" PRIu64 " is invalid",
341 in_initiator.id, in_initiator.hubId);
342 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
343 }
344 bool destinationIsValid = findEndpoint(in_destination, &kMockEndpointInfos[0],
345 &kMockEndpointInfos[kMockEndpointCount]);
346 if (!destinationIsValid) {
347 ALOGE("openEndpointSession: destination %" PRIu64 ":%" PRIu64 " is invalid",
348 in_destination.id, in_destination.hubId);
349 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
350 }
351
352 mEndpointSessions.push_back({
353 .sessionId = in_sessionId,
354 .initiator = in_initiator,
355 .peer = in_destination,
356 .serviceDescriptor = in_serviceDescriptor,
357 });
358
Matthew Sedam0ec290c2024-12-11 11:18:15 -0800359 if (mEndpointCallback == nullptr) {
360 return ScopedAStatus::ok();
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000361 }
Matthew Sedam0ec290c2024-12-11 11:18:15 -0800362 callback = mEndpointCallback;
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000363 }
364
Matthew Sedam0ec290c2024-12-11 11:18:15 -0800365 std::unique_lock<std::mutex> lock(gCallbackMutex);
366 std::thread{[callback, in_sessionId]() {
367 std::unique_lock<std::mutex> lock(gCallbackMutex);
368 if (auto cb = callback.lock(); cb != nullptr) {
369 cb->onEndpointSessionOpenComplete(in_sessionId);
370 }
371 }}.detach();
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000372 return ScopedAStatus::ok();
Yifei Zhang51eba2e2024-10-24 15:11:54 -0700373};
374
Madhav Iyengaree25d072024-12-17 17:08:55 +0000375ScopedAStatus ContextHub::HubInterface::sendMessageToEndpoint(int32_t in_sessionId,
376 const Message& in_msg) {
377 if (!mActive) {
378 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
379 }
Matthew Sedam0ec290c2024-12-11 11:18:15 -0800380 std::weak_ptr<IEndpointCallback> callback;
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000381 {
382 std::unique_lock<std::mutex> lock(mEndpointMutex);
Matthew Sedam0ec290c2024-12-11 11:18:15 -0800383 bool foundSession = false;
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000384 for (const EndpointSession& session : mEndpointSessions) {
385 if (session.sessionId == in_sessionId) {
386 foundSession = true;
387 break;
388 }
389 }
390
Matthew Sedam0ec290c2024-12-11 11:18:15 -0800391 if (!foundSession) {
392 ALOGE("sendMessageToEndpoint: session ID %" PRId32 " is invalid", in_sessionId);
393 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000394 }
395
Matthew Sedam0ec290c2024-12-11 11:18:15 -0800396 if (mEndpointCallback == nullptr) {
397 return ScopedAStatus::ok();
398 }
399 callback = mEndpointCallback;
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000400 }
Matthew Sedam0ec290c2024-12-11 11:18:15 -0800401
402 std::unique_lock<std::mutex> lock(gCallbackMutex);
403 if ((in_msg.flags & Message::FLAG_REQUIRES_DELIVERY_STATUS) != 0) {
404 MessageDeliveryStatus msgStatus = {};
405 msgStatus.messageSequenceNumber = in_msg.sequenceNumber;
406 msgStatus.errorCode = ErrorCode::OK;
407
408 std::thread{[callback, in_sessionId, msgStatus]() {
409 std::unique_lock<std::mutex> lock(gCallbackMutex);
410 if (auto cb = callback.lock(); cb != nullptr) {
411 cb->onMessageDeliveryStatusReceived(in_sessionId, msgStatus);
412 }
413 }}.detach();
414 }
415
416 // Echo the message back
417 std::thread{[callback, in_sessionId, in_msg]() {
418 std::unique_lock<std::mutex> lock(gCallbackMutex);
419 if (auto cb = callback.lock(); cb != nullptr) {
420 cb->onMessageReceived(in_sessionId, in_msg);
421 }
422 }}.detach();
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000423 return ScopedAStatus::ok();
Yifei Zhang51eba2e2024-10-24 15:11:54 -0700424};
425
Madhav Iyengaree25d072024-12-17 17:08:55 +0000426ScopedAStatus ContextHub::HubInterface::sendMessageDeliveryStatusToEndpoint(
Yifei Zhang51eba2e2024-10-24 15:11:54 -0700427 int32_t /* in_sessionId */, const MessageDeliveryStatus& /* in_msgStatus */) {
Madhav Iyengaree25d072024-12-17 17:08:55 +0000428 if (!mActive) {
429 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
430 }
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000431 return ScopedAStatus::ok();
Yifei Zhang51eba2e2024-10-24 15:11:54 -0700432};
433
Madhav Iyengaree25d072024-12-17 17:08:55 +0000434ScopedAStatus ContextHub::HubInterface::closeEndpointSession(int32_t in_sessionId,
435 Reason /* in_reason */) {
436 if (!mActive) {
437 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
438 }
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000439 std::unique_lock<std::mutex> lock(mEndpointMutex);
440
441 for (auto it = mEndpointSessions.begin(); it != mEndpointSessions.end(); ++it) {
442 if (it->sessionId == in_sessionId) {
443 mEndpointSessions.erase(it);
444 return ScopedAStatus::ok();
445 }
446 }
447 ALOGE("closeEndpointSession: session ID %" PRId32 " is invalid", in_sessionId);
448 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
Yifei Zhang51eba2e2024-10-24 15:11:54 -0700449};
450
Madhav Iyengaree25d072024-12-17 17:08:55 +0000451ScopedAStatus ContextHub::HubInterface::endpointSessionOpenComplete(int32_t /* in_sessionId */) {
452 if (!mActive) {
453 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
454 }
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000455 return ScopedAStatus::ok();
Yifei Zhang51eba2e2024-10-24 15:11:54 -0700456};
457
Madhav Iyengaree25d072024-12-17 17:08:55 +0000458ScopedAStatus ContextHub::HubInterface::unregister() {
459 if (!mActive.exchange(false)) {
460 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
461 }
462 std::lock_guard lock(mHal.mHostHubsLock);
463 mHal.mIdToHostHub.erase(kInfo.hubId);
464 return ScopedAStatus::ok();
465}
466
Matthew Sedamadfd5572023-11-21 05:53:00 -0800467} // namespace aidl::android::hardware::contexthub