blob: aa611ced8d554a97ad3d2f3bd5d6ae8f4a155624 [file] [log] [blame]
Arthur Ishiguro4e916c32021-08-12 12:47:03 -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#include <aidl/Gtest.h>
17#include <aidl/Vintf.h>
18
19#include "VtsHalContexthubUtilsCommon.h"
20
21#include <android/hardware/contexthub/BnContextHub.h>
22#include <android/hardware/contexthub/BnContextHubCallback.h>
Matthew Sedam92c2bd82024-11-11 19:52:30 +000023#include <android/hardware/contexthub/BnEndpointCallback.h>
Arthur Ishiguro4e916c32021-08-12 12:47:03 -070024#include <android/hardware/contexthub/IContextHub.h>
25#include <android/hardware/contexthub/IContextHubCallback.h>
Matthew Sedam92c2bd82024-11-11 19:52:30 +000026#include <android/hardware/contexthub/IEndpointCallback.h>
Arthur Ishiguro4e916c32021-08-12 12:47:03 -070027#include <binder/IServiceManager.h>
28#include <binder/ProcessState.h>
29#include <log/log.h>
30
31#include <cinttypes>
32#include <future>
33
34using ::android::ProcessState;
35using ::android::sp;
36using ::android::String16;
37using ::android::binder::Status;
38using ::android::hardware::contexthub::AsyncEventType;
Matthew Sedam92c2bd82024-11-11 19:52:30 +000039using ::android::hardware::contexthub::BnEndpointCallback;
Arthur Ishiguro4e916c32021-08-12 12:47:03 -070040using ::android::hardware::contexthub::ContextHubInfo;
41using ::android::hardware::contexthub::ContextHubMessage;
Matthew Sedam92c2bd82024-11-11 19:52:30 +000042using ::android::hardware::contexthub::EndpointId;
43using ::android::hardware::contexthub::EndpointInfo;
Matthew Sedamadfd5572023-11-21 05:53:00 -080044using ::android::hardware::contexthub::ErrorCode;
Arthur Ishiguro065a9a52021-11-19 00:24:45 +000045using ::android::hardware::contexthub::HostEndpointInfo;
Matthew Sedam92c2bd82024-11-11 19:52:30 +000046using ::android::hardware::contexthub::HubInfo;
Arthur Ishiguro4e916c32021-08-12 12:47:03 -070047using ::android::hardware::contexthub::IContextHub;
48using ::android::hardware::contexthub::IContextHubCallbackDefault;
Matthew Sedam92c2bd82024-11-11 19:52:30 +000049using ::android::hardware::contexthub::Message;
Matthew Sedamadfd5572023-11-21 05:53:00 -080050using ::android::hardware::contexthub::MessageDeliveryStatus;
Arthur Ishiguro4e916c32021-08-12 12:47:03 -070051using ::android::hardware::contexthub::NanoappBinary;
52using ::android::hardware::contexthub::NanoappInfo;
Arthur Ishiguro08103072021-12-09 18:30:49 +000053using ::android::hardware::contexthub::NanoappRpcService;
Anthony Stange7fba1002023-03-02 21:45:20 +000054using ::android::hardware::contexthub::NanSessionRequest;
55using ::android::hardware::contexthub::NanSessionStateUpdate;
Matthew Sedam92c2bd82024-11-11 19:52:30 +000056using ::android::hardware::contexthub::Reason;
57using ::android::hardware::contexthub::Service;
Arthur Ishiguro4e916c32021-08-12 12:47:03 -070058using ::android::hardware::contexthub::Setting;
59using ::android::hardware::contexthub::vts_utils::kNonExistentAppId;
60using ::android::hardware::contexthub::vts_utils::waitForCallback;
61
Lei Ju8787afa2023-06-28 09:36:19 -070062// 6612b522-b717-41c8-b48d-c0b1cc64e142
Lei Ju5b2ded42023-12-05 15:08:21 -080063constexpr std::array<uint8_t, 16> kUuid = {0x66, 0x12, 0xb5, 0x22, 0xb7, 0x17, 0x41, 0xc8,
64 0xb4, 0x8d, 0xc0, 0xb1, 0xcc, 0x64, 0xe1, 0x42};
65const String16 kName{"VtsAidlHalContextHubTargetTest"};
Lei Ju8787afa2023-06-28 09:36:19 -070066
Arthur Ishiguro38712cf2024-12-13 11:40:47 -080067const String16 kEchoServiceName{"android.hardware.contexthub.test.EchoService"};
68
Arthur Ishiguro4e916c32021-08-12 12:47:03 -070069class ContextHubAidl : public testing::TestWithParam<std::tuple<std::string, int32_t>> {
70 public:
71 virtual void SetUp() override {
72 contextHub = android::waitForDeclaredService<IContextHub>(
73 String16(std::get<0>(GetParam()).c_str()));
74 ASSERT_NE(contextHub, nullptr);
Matthew Sedam92c2bd82024-11-11 19:52:30 +000075
76 // Best effort enable test mode - this may not be supported on older HALS, so we
77 // ignore the return value.
78 contextHub->setTestMode(/* enable= */ true);
Arthur Ishiguro4e916c32021-08-12 12:47:03 -070079 }
80
Matthew Sedam92c2bd82024-11-11 19:52:30 +000081 virtual void TearDown() override { contextHub->setTestMode(/* enable= */ false); }
82
Arthur Ishiguro4e916c32021-08-12 12:47:03 -070083 uint32_t getHubId() { return std::get<1>(GetParam()); }
84
85 void testSettingChanged(Setting setting);
86
87 sp<IContextHub> contextHub;
88};
89
90TEST_P(ContextHubAidl, TestGetHubs) {
91 std::vector<ContextHubInfo> hubs;
92 ASSERT_TRUE(contextHub->getContextHubs(&hubs).isOk());
93
94 ALOGD("System reports %zu hubs", hubs.size());
95
96 for (const ContextHubInfo& hub : hubs) {
97 ALOGD("Checking hub ID %" PRIu32, hub.id);
98
99 EXPECT_GT(hub.name.size(), 0);
100 EXPECT_GT(hub.vendor.size(), 0);
101 EXPECT_GT(hub.toolchain.size(), 0);
102 EXPECT_GT(hub.peakMips, 0);
103 EXPECT_GT(hub.chrePlatformId, 0);
104 EXPECT_GT(hub.chreApiMajorVersion, 0);
Arthur Ishiguro6471f612021-10-28 21:59:55 +0000105 EXPECT_GE(hub.chreApiMinorVersion, 0);
106 EXPECT_GE(hub.chrePatchVersion, 0);
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700107
108 // Minimum 128 byte MTU as required by CHRE API v1.0
109 EXPECT_GE(hub.maxSupportedMessageLengthBytes, UINT32_C(128));
110 }
111}
112
Matthew Sedamc8ce4d52023-01-09 20:18:21 +0000113TEST_P(ContextHubAidl, TestEnableTestMode) {
114 Status status = contextHub->setTestMode(true);
115 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
116 status.transactionError() == android::UNKNOWN_TRANSACTION) {
Matthew Sedam121b6d62023-01-19 19:04:53 +0000117 GTEST_SKIP() << "Not supported -> old API; or not implemented";
118 } else {
119 ASSERT_TRUE(status.isOk());
Matthew Sedamc8ce4d52023-01-09 20:18:21 +0000120 }
Matthew Sedamc8ce4d52023-01-09 20:18:21 +0000121}
122
123TEST_P(ContextHubAidl, TestDisableTestMode) {
124 Status status = contextHub->setTestMode(false);
125 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
126 status.transactionError() == android::UNKNOWN_TRANSACTION) {
Matthew Sedam121b6d62023-01-19 19:04:53 +0000127 GTEST_SKIP() << "Not supported -> old API; or not implemented";
128 } else {
129 ASSERT_TRUE(status.isOk());
Matthew Sedamc8ce4d52023-01-09 20:18:21 +0000130 }
Matthew Sedamc8ce4d52023-01-09 20:18:21 +0000131}
132
Arthur Ishiguroe6b540d2021-10-29 16:01:35 +0000133class EmptyContextHubCallback : public android::hardware::contexthub::BnContextHubCallback {
134 public:
135 Status handleNanoappInfo(const std::vector<NanoappInfo>& /* appInfo */) override {
136 return Status::ok();
137 }
138
139 Status handleContextHubMessage(const ContextHubMessage& /* msg */,
140 const std::vector<String16>& /* msgContentPerms */) override {
141 return Status::ok();
142 }
143
144 Status handleContextHubAsyncEvent(AsyncEventType /* evt */) override { return Status::ok(); }
145
146 Status handleTransactionResult(int32_t /* transactionId */, bool /* success */) override {
147 return Status::ok();
148 }
Anthony Stange7344af92022-12-22 14:21:31 +0000149
Anthony Stange7fba1002023-03-02 21:45:20 +0000150 Status handleNanSessionRequest(const NanSessionRequest& /* request */) override {
151 return Status::ok();
152 }
Lei Ju8787afa2023-06-28 09:36:19 -0700153
Matthew Sedamadfd5572023-11-21 05:53:00 -0800154 Status handleMessageDeliveryStatus(
155 char16_t /* hostEndPointId */,
156 const MessageDeliveryStatus& /* messageDeliveryStatus */) override {
157 return Status::ok();
158 }
159
Lei Ju8787afa2023-06-28 09:36:19 -0700160 Status getUuid(std::array<uint8_t, 16>* out_uuid) override {
161 *out_uuid = kUuid;
162 return Status::ok();
163 }
Lei Ju5b2ded42023-12-05 15:08:21 -0800164
165 Status getName(::android::String16* out_name) override {
166 *out_name = kName;
167 return Status::ok();
168 }
Arthur Ishiguroe6b540d2021-10-29 16:01:35 +0000169};
170
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700171TEST_P(ContextHubAidl, TestRegisterCallback) {
Arthur Ishiguroe6b540d2021-10-29 16:01:35 +0000172 sp<EmptyContextHubCallback> cb = sp<EmptyContextHubCallback>::make();
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000173 ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb).isOk());
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700174}
175
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700176// Helper callback that puts the async appInfo callback data into a promise
177class QueryAppsCallback : public android::hardware::contexthub::BnContextHubCallback {
178 public:
179 Status handleNanoappInfo(const std::vector<NanoappInfo>& appInfo) override {
180 ALOGD("Got app info callback with %zu apps", appInfo.size());
181 promise.set_value(appInfo);
182 return Status::ok();
183 }
184
185 Status handleContextHubMessage(const ContextHubMessage& /* msg */,
186 const std::vector<String16>& /* msgContentPerms */) override {
187 return Status::ok();
188 }
189
190 Status handleContextHubAsyncEvent(AsyncEventType /* evt */) override { return Status::ok(); }
191
192 Status handleTransactionResult(int32_t /* transactionId */, bool /* success */) override {
193 return Status::ok();
194 }
195
Anthony Stange7fba1002023-03-02 21:45:20 +0000196 Status handleNanSessionRequest(const NanSessionRequest& /* request */) override {
197 return Status::ok();
198 }
Anthony Stange7344af92022-12-22 14:21:31 +0000199
Matthew Sedamadfd5572023-11-21 05:53:00 -0800200 Status handleMessageDeliveryStatus(
201 char16_t /* hostEndPointId */,
202 const MessageDeliveryStatus& /* messageDeliveryStatus */) override {
203 return Status::ok();
204 }
205
Lei Ju8787afa2023-06-28 09:36:19 -0700206 Status getUuid(std::array<uint8_t, 16>* out_uuid) override {
207 *out_uuid = kUuid;
208 return Status::ok();
209 }
210
Lei Ju5b2ded42023-12-05 15:08:21 -0800211 Status getName(::android::String16* out_name) override {
212 *out_name = kName;
213 return Status::ok();
214 }
215
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700216 std::promise<std::vector<NanoappInfo>> promise;
217};
218
219// Calls queryApps() and checks the returned metadata
220TEST_P(ContextHubAidl, TestQueryApps) {
221 sp<QueryAppsCallback> cb = sp<QueryAppsCallback>::make();
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000222 ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb).isOk());
223 ASSERT_TRUE(contextHub->queryNanoapps(getHubId()).isOk());
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700224
225 std::vector<NanoappInfo> appInfoList;
226 ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &appInfoList));
227 for (const NanoappInfo& appInfo : appInfoList) {
228 EXPECT_NE(appInfo.nanoappId, UINT64_C(0));
229 EXPECT_NE(appInfo.nanoappId, kNonExistentAppId);
Arthur Ishiguro08103072021-12-09 18:30:49 +0000230
231 // Verify services are unique.
232 std::set<uint64_t> existingServiceIds;
233 for (const NanoappRpcService& rpcService : appInfo.rpcServices) {
234 EXPECT_NE(rpcService.id, UINT64_C(0));
235 EXPECT_EQ(existingServiceIds.count(rpcService.id), 0);
236 existingServiceIds.insert(rpcService.id);
237 }
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700238 }
239}
240
Matthew Sedamd70f84d2023-03-06 18:34:24 +0000241// Calls getPreloadedNanoappsIds() and verifies there are preloaded nanoapps
242TEST_P(ContextHubAidl, TestGetPreloadedNanoappIds) {
Arthur Ishigurofd5e65c2022-11-08 16:49:47 +0000243 std::vector<int64_t> preloadedNanoappIds;
Matthew Sedamd70f84d2023-03-06 18:34:24 +0000244 Status status = contextHub->getPreloadedNanoappIds(getHubId(), &preloadedNanoappIds);
Arthur Ishigurofd5e65c2022-11-08 16:49:47 +0000245 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
246 status.transactionError() == android::UNKNOWN_TRANSACTION) {
Matthew Sedam121b6d62023-01-19 19:04:53 +0000247 GTEST_SKIP() << "Not supported -> old API; or not implemented";
248 } else {
249 ASSERT_TRUE(status.isOk());
Arthur Ishigurofd5e65c2022-11-08 16:49:47 +0000250 }
Arthur Ishigurofd5e65c2022-11-08 16:49:47 +0000251}
252
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700253// Helper callback that puts the TransactionResult for the expectedTransactionId into a
254// promise
255class TransactionResultCallback : public android::hardware::contexthub::BnContextHubCallback {
256 public:
257 Status handleNanoappInfo(const std::vector<NanoappInfo>& /* appInfo */) override {
258 return Status::ok();
259 }
260
261 Status handleContextHubMessage(const ContextHubMessage& /* msg */,
262 const std::vector<String16>& /* msgContentPerms */) override {
263 return Status::ok();
264 }
265
266 Status handleContextHubAsyncEvent(AsyncEventType /* evt */) override { return Status::ok(); }
267
268 Status handleTransactionResult(int32_t transactionId, bool success) override {
269 ALOGD("Got transaction result callback for transactionId %" PRIu32 " (expecting %" PRIu32
270 ") with success %d",
271 transactionId, expectedTransactionId, success);
272 if (transactionId == expectedTransactionId) {
273 promise.set_value(success);
274 }
275 return Status::ok();
276 }
277
Anthony Stange7fba1002023-03-02 21:45:20 +0000278 Status handleNanSessionRequest(const NanSessionRequest& /* request */) override {
279 return Status::ok();
280 }
Anthony Stange7344af92022-12-22 14:21:31 +0000281
Matthew Sedamadfd5572023-11-21 05:53:00 -0800282 Status handleMessageDeliveryStatus(
283 char16_t /* hostEndPointId */,
284 const MessageDeliveryStatus& /* messageDeliveryStatus */) override {
285 return Status::ok();
286 }
287
Lei Ju8787afa2023-06-28 09:36:19 -0700288 Status getUuid(std::array<uint8_t, 16>* out_uuid) override {
289 *out_uuid = kUuid;
290 return Status::ok();
291 }
292
Lei Ju5b2ded42023-12-05 15:08:21 -0800293 Status getName(::android::String16* out_name) override {
294 *out_name = kName;
295 return Status::ok();
296 }
297
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700298 uint32_t expectedTransactionId = 0;
299 std::promise<bool> promise;
300};
301
302// Parameterized fixture that sets the callback to TransactionResultCallback
303class ContextHubTransactionTest : public ContextHubAidl {
304 public:
305 virtual void SetUp() override {
306 ContextHubAidl::SetUp();
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000307 ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb).isOk());
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700308 }
309
310 sp<TransactionResultCallback> cb = sp<TransactionResultCallback>::make();
311};
312
313TEST_P(ContextHubTransactionTest, TestSendMessageToNonExistentNanoapp) {
314 ContextHubMessage message;
315 message.nanoappId = kNonExistentAppId;
316 message.messageType = 1;
317 message.messageBody.resize(4);
318 std::fill(message.messageBody.begin(), message.messageBody.end(), 0);
319
320 ALOGD("Sending message to non-existent nanoapp");
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000321 ASSERT_TRUE(contextHub->sendMessageToHub(getHubId(), message).isOk());
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700322}
323
324TEST_P(ContextHubTransactionTest, TestLoadEmptyNanoapp) {
325 cb->expectedTransactionId = 0123;
326 NanoappBinary emptyApp;
327
328 emptyApp.nanoappId = kNonExistentAppId;
329 emptyApp.nanoappVersion = 1;
330 emptyApp.flags = 0;
331 emptyApp.targetChreApiMajorVersion = 1;
332 emptyApp.targetChreApiMinorVersion = 0;
333
334 ALOGD("Loading empty nanoapp");
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000335 bool success = contextHub->loadNanoapp(getHubId(), emptyApp, cb->expectedTransactionId).isOk();
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700336 if (success) {
337 bool transactionSuccess;
338 ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
339 ASSERT_FALSE(transactionSuccess);
340 }
341}
342
343TEST_P(ContextHubTransactionTest, TestUnloadNonexistentNanoapp) {
344 cb->expectedTransactionId = 1234;
345
346 ALOGD("Unloading nonexistent nanoapp");
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000347 bool success =
348 contextHub->unloadNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId)
349 .isOk();
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700350 if (success) {
351 bool transactionSuccess;
352 ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
353 ASSERT_FALSE(transactionSuccess);
354 }
355}
356
357TEST_P(ContextHubTransactionTest, TestEnableNonexistentNanoapp) {
358 cb->expectedTransactionId = 2345;
359
360 ALOGD("Enabling nonexistent nanoapp");
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000361 bool success =
362 contextHub->enableNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId)
363 .isOk();
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700364 if (success) {
365 bool transactionSuccess;
366 ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
367 ASSERT_FALSE(transactionSuccess);
368 }
369}
370
371TEST_P(ContextHubTransactionTest, TestDisableNonexistentNanoapp) {
372 cb->expectedTransactionId = 3456;
373
374 ALOGD("Disabling nonexistent nanoapp");
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000375 bool success =
376 contextHub->disableNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId)
377 .isOk();
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700378 if (success) {
379 bool transactionSuccess;
380 ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
381 ASSERT_FALSE(transactionSuccess);
382 }
383}
384
385void ContextHubAidl::testSettingChanged(Setting setting) {
386 // In VTS, we only test that sending the values doesn't cause things to blow up - GTS tests
387 // verify the expected E2E behavior in CHRE
Arthur Ishiguroe6b540d2021-10-29 16:01:35 +0000388 sp<EmptyContextHubCallback> cb = sp<EmptyContextHubCallback>::make();
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000389 ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb).isOk());
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700390
391 ASSERT_TRUE(contextHub->onSettingChanged(setting, true /* enabled */).isOk());
392 ASSERT_TRUE(contextHub->onSettingChanged(setting, false /* enabled */).isOk());
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700393}
394
395TEST_P(ContextHubAidl, TestOnLocationSettingChanged) {
396 testSettingChanged(Setting::LOCATION);
397}
398
399TEST_P(ContextHubAidl, TestOnWifiMainSettingChanged) {
400 testSettingChanged(Setting::WIFI_MAIN);
401}
402
403TEST_P(ContextHubAidl, TestOnWifiScanningSettingChanged) {
404 testSettingChanged(Setting::WIFI_SCANNING);
405}
406
407TEST_P(ContextHubAidl, TestOnAirplaneModeSettingChanged) {
408 testSettingChanged(Setting::AIRPLANE_MODE);
409}
410
411TEST_P(ContextHubAidl, TestOnMicrophoneSettingChanged) {
412 testSettingChanged(Setting::MICROPHONE);
413}
414
Anthonya6b65002022-01-20 20:49:10 +0000415TEST_P(ContextHubAidl, TestOnBtMainSettingChanged) {
416 testSettingChanged(Setting::BT_MAIN);
417}
418
419TEST_P(ContextHubAidl, TestOnBtScanningSettingChanged) {
420 testSettingChanged(Setting::BT_SCANNING);
421}
422
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700423std::vector<std::tuple<std::string, int32_t>> generateContextHubMapping() {
424 std::vector<std::tuple<std::string, int32_t>> tuples;
425 auto contextHubAidlNames = android::getAidlHalInstanceNames(IContextHub::descriptor);
426 std::vector<ContextHubInfo> contextHubInfos;
427
428 for (int i = 0; i < contextHubAidlNames.size(); i++) {
429 auto contextHubName = contextHubAidlNames[i].c_str();
430 auto contextHub = android::waitForDeclaredService<IContextHub>(String16(contextHubName));
431 if (contextHub->getContextHubs(&contextHubInfos).isOk()) {
432 for (auto& info : contextHubInfos) {
433 tuples.push_back(std::make_tuple(contextHubName, info.id));
434 }
435 }
436 }
437
438 return tuples;
439}
440
Lei Jubc6ead02024-02-05 18:15:08 -0800441TEST_P(ContextHubTransactionTest, TestHostConnection) {
Arthur Ishiguro065a9a52021-11-19 00:24:45 +0000442 constexpr char16_t kHostEndpointId = 1;
443 HostEndpointInfo hostEndpointInfo;
Arthur Ishiguro16f40622023-02-10 18:11:12 +0000444 hostEndpointInfo.type = HostEndpointInfo::Type::NATIVE;
Arthur Ishiguro065a9a52021-11-19 00:24:45 +0000445 hostEndpointInfo.hostEndpointId = kHostEndpointId;
446
447 ASSERT_TRUE(contextHub->onHostEndpointConnected(hostEndpointInfo).isOk());
448 ASSERT_TRUE(contextHub->onHostEndpointDisconnected(kHostEndpointId).isOk());
449}
450
Lei Jubc6ead02024-02-05 18:15:08 -0800451TEST_P(ContextHubTransactionTest, TestInvalidHostConnection) {
Arthur Ishiguro065a9a52021-11-19 00:24:45 +0000452 constexpr char16_t kHostEndpointId = 1;
453
Arthur Ishiguro5dba9212022-02-01 17:03:32 +0000454 ASSERT_TRUE(contextHub->onHostEndpointDisconnected(kHostEndpointId).isOk());
Arthur Ishiguro065a9a52021-11-19 00:24:45 +0000455}
456
Lei Jubc6ead02024-02-05 18:15:08 -0800457TEST_P(ContextHubTransactionTest, TestNanSessionStateChange) {
Anthony Stange7fba1002023-03-02 21:45:20 +0000458 NanSessionStateUpdate update;
459 update.state = true;
Rocky Fang78140982023-06-16 00:42:41 +0000460 Status status = contextHub->onNanSessionStateChanged(update);
461 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
462 status.transactionError() == android::UNKNOWN_TRANSACTION) {
463 GTEST_SKIP() << "Not supported -> old API; or not implemented";
464 } else {
465 ASSERT_TRUE(status.isOk());
466 update.state = false;
467 ASSERT_TRUE(contextHub->onNanSessionStateChanged(update).isOk());
468 }
Anthony Stange7344af92022-12-22 14:21:31 +0000469}
470
Matthew Sedamadfd5572023-11-21 05:53:00 -0800471TEST_P(ContextHubAidl, TestSendMessageDeliveryStatusToHub) {
472 MessageDeliveryStatus messageDeliveryStatus;
473 messageDeliveryStatus.messageSequenceNumber = 123;
474 messageDeliveryStatus.errorCode = ErrorCode::OK;
475
476 Status status = contextHub->sendMessageDeliveryStatusToHub(getHubId(), messageDeliveryStatus);
477 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
478 status.transactionError() == android::UNKNOWN_TRANSACTION) {
479 GTEST_SKIP() << "Not supported -> old API; or not implemented";
480 } else {
481 EXPECT_TRUE(status.isOk());
482 }
483}
484
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000485class TestEndpointCallback : public BnEndpointCallback {
486 public:
487 Status onEndpointStarted(const std::vector<EndpointInfo>& /* endpointInfos */) override {
488 return Status::ok();
489 }
490
491 Status onEndpointStopped(const std::vector<EndpointId>& /* endpointIds */,
492 Reason /* reason */) override {
493 return Status::ok();
494 }
495
496 Status onMessageReceived(int32_t /* sessionId */, const Message& message) override {
Matthew Sedam0ec290c2024-12-11 11:18:15 -0800497 {
498 std::unique_lock<std::mutex> lock(mMutex);
499 mMessages.push_back(message);
500 }
501 mCondVar.notify_one();
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000502 return Status::ok();
503 }
504
505 Status onMessageDeliveryStatusReceived(int32_t /* sessionId */,
506 const MessageDeliveryStatus& /* msgStatus */) override {
507 return Status::ok();
508 }
509
510 Status onEndpointSessionOpenRequest(
511 int32_t /* sessionId */, const EndpointId& /* destination */,
512 const EndpointId& /* initiator */,
513 const std::optional<String16>& /* serviceDescriptor */) override {
514 return Status::ok();
515 }
516
517 Status onCloseEndpointSession(int32_t /* sessionId */, Reason /* reason */) override {
518 return Status::ok();
519 }
520
521 Status onEndpointSessionOpenComplete(int32_t /* sessionId */) override {
Matthew Sedam0ec290c2024-12-11 11:18:15 -0800522 {
523 std::unique_lock<std::mutex> lock(mMutex);
524 mWasOnEndpointSessionOpenCompleteCalled = true;
525 }
526 mCondVar.notify_one();
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000527 return Status::ok();
528 }
529
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000530 bool wasOnEndpointSessionOpenCompleteCalled() {
531 return mWasOnEndpointSessionOpenCompleteCalled;
532 }
Matthew Sedam0ec290c2024-12-11 11:18:15 -0800533
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000534 void resetWasOnEndpointSessionOpenCompleteCalled() {
535 mWasOnEndpointSessionOpenCompleteCalled = false;
536 }
537
Matthew Sedam0ec290c2024-12-11 11:18:15 -0800538 std::mutex& getMutex() { return mMutex; }
539 std::condition_variable& getCondVar() { return mCondVar; }
540 std::vector<Message> getMessages() { return mMessages; }
541
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000542 private:
543 std::vector<Message> mMessages;
Matthew Sedam0ec290c2024-12-11 11:18:15 -0800544 std::mutex mMutex;
545 std::condition_variable mCondVar;
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000546 bool mWasOnEndpointSessionOpenCompleteCalled = false;
547};
548
549TEST_P(ContextHubAidl, RegisterEndpoint) {
550 EndpointInfo endpointInfo;
551 endpointInfo.id.id = 1;
552 endpointInfo.id.hubId = 0xCAFECAFECAFECAFE;
553 endpointInfo.type = EndpointInfo::EndpointType::NATIVE;
554 endpointInfo.name = String16("Test host endpoint 1");
555 endpointInfo.version = 42;
556
557 Status status = contextHub->registerEndpoint(endpointInfo);
558 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
559 status.transactionError() == android::UNKNOWN_TRANSACTION) {
560 GTEST_SKIP() << "Not supported -> old API; or not implemented";
561 } else {
562 EXPECT_TRUE(status.isOk());
563 }
564}
565
566TEST_P(ContextHubAidl, RegisterEndpointSameNameFailure) {
567 EndpointInfo endpointInfo;
568 endpointInfo.id.id = 2;
569 endpointInfo.id.hubId = 0xCAFECAFECAFECAFE;
570 endpointInfo.type = EndpointInfo::EndpointType::NATIVE;
571 endpointInfo.name = String16("Test host endpoint 2");
572 endpointInfo.version = 42;
573
574 EndpointInfo endpointInfo2;
575 endpointInfo2.id.id = 3;
576 endpointInfo2.id.hubId = 0xCAFECAFECAFECAFE;
577 endpointInfo2.type = EndpointInfo::EndpointType::NATIVE;
578 endpointInfo2.name = String16("Test host endpoint 2");
579 endpointInfo2.version = 42;
580
581 Status status = contextHub->registerEndpoint(endpointInfo);
582 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
583 status.transactionError() == android::UNKNOWN_TRANSACTION) {
584 GTEST_SKIP() << "Not supported -> old API; or not implemented";
585 } else {
586 EXPECT_TRUE(status.isOk());
587 }
588
589 EXPECT_FALSE(contextHub->registerEndpoint(endpointInfo2).isOk());
590}
591
592TEST_P(ContextHubAidl, RegisterEndpointSameIdFailure) {
593 EndpointInfo endpointInfo;
594 endpointInfo.id.id = 4;
595 endpointInfo.id.hubId = 0xCAFECAFECAFECAFE;
596 endpointInfo.type = EndpointInfo::EndpointType::NATIVE;
597 endpointInfo.name = String16("Test host endpoint 4");
598 endpointInfo.version = 42;
599
600 EndpointInfo endpointInfo2;
601 endpointInfo2.id.id = 4;
602 endpointInfo2.id.hubId = 0xCAFECAFECAFECAFE;
603 endpointInfo2.type = EndpointInfo::EndpointType::NATIVE;
604 endpointInfo2.name = String16("Test host endpoint - same ID test");
605 endpointInfo2.version = 42;
606
607 Status status = contextHub->registerEndpoint(endpointInfo);
608 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
609 status.transactionError() == android::UNKNOWN_TRANSACTION) {
610 GTEST_SKIP() << "Not supported -> old API; or not implemented";
611 } else {
612 EXPECT_TRUE(status.isOk());
613 }
614
615 EXPECT_FALSE(contextHub->registerEndpoint(endpointInfo2).isOk());
616}
617
618TEST_P(ContextHubAidl, UnregisterEndpoint) {
619 EndpointInfo endpointInfo;
620 endpointInfo.id.id = 6;
621 endpointInfo.id.hubId = 0xCAFECAFECAFECAFE;
622 endpointInfo.type = EndpointInfo::EndpointType::NATIVE;
623 endpointInfo.name = String16("Test host endpoint 6");
624 endpointInfo.version = 42;
625
626 Status status = contextHub->registerEndpoint(endpointInfo);
627 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
628 status.transactionError() == android::UNKNOWN_TRANSACTION) {
629 GTEST_SKIP() << "Not supported -> old API; or not implemented";
630 } else {
631 EXPECT_TRUE(status.isOk());
632 }
633
634 EXPECT_TRUE(contextHub->unregisterEndpoint(endpointInfo).isOk());
635}
636
637TEST_P(ContextHubAidl, UnregisterEndpointNonexistent) {
638 EndpointInfo endpointInfo;
639 endpointInfo.id.id = 100;
640 endpointInfo.id.hubId = 0xCAFECAFECAFECAFE;
641 endpointInfo.type = EndpointInfo::EndpointType::NATIVE;
642 endpointInfo.name = String16("Test host endpoint 100");
643 endpointInfo.version = 42;
644
645 Status status = contextHub->unregisterEndpoint(endpointInfo);
646 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
647 status.transactionError() == android::UNKNOWN_TRANSACTION) {
648 GTEST_SKIP() << "Not supported -> old API; or not implemented";
649 } else {
650 EXPECT_FALSE(status.isOk());
651 }
652}
653
654TEST_P(ContextHubAidl, RegisterCallback) {
655 auto cb = sp<TestEndpointCallback>::make();
656 Status status = contextHub->registerEndpointCallback(cb);
657 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
658 status.transactionError() == android::UNKNOWN_TRANSACTION) {
659 GTEST_SKIP() << "Not supported -> old API; or not implemented";
660 } else {
661 EXPECT_TRUE(status.isOk());
662 }
663}
664
665TEST_P(ContextHubAidl, OpenEndpointSessionInvalidRange) {
666 auto cb = sp<TestEndpointCallback>::make();
667 Status status = contextHub->registerEndpointCallback(cb);
668 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
669 status.transactionError() == android::UNKNOWN_TRANSACTION) {
670 GTEST_SKIP() << "Not supported -> old API; or not implemented";
671 } else {
672 EXPECT_TRUE(status.isOk());
673 }
674
675 // Register the endpoint
676 EndpointInfo initiatorEndpoint;
677 initiatorEndpoint.id.id = 7;
678 initiatorEndpoint.id.hubId = 0xCAFECAFECAFECAFE;
679 initiatorEndpoint.type = EndpointInfo::EndpointType::NATIVE;
680 initiatorEndpoint.name = String16("Test host endpoint 7");
681 initiatorEndpoint.version = 42;
682 EXPECT_TRUE(contextHub->registerEndpoint(initiatorEndpoint).isOk());
683
684 // Find the destination, if it exists
685 std::vector<EndpointInfo> endpoints;
686 EXPECT_TRUE(contextHub->getEndpoints(&endpoints).isOk());
687 const EndpointInfo* destinationEndpoint = nullptr;
688 for (const EndpointInfo& endpoint : endpoints) {
689 for (const Service& service : endpoint.services) {
Arthur Ishiguro38712cf2024-12-13 11:40:47 -0800690 if (service.serviceDescriptor == kEchoServiceName) {
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000691 destinationEndpoint = &endpoint;
692 break;
693 }
694 }
695 }
696 if (destinationEndpoint == nullptr) {
697 return; // no echo service endpoint -> just return
698 }
699
700 // Request the range
701 constexpr int32_t requestedRange = 100;
Yifei Zhangcef8f662024-12-06 16:03:26 -0800702 std::array<int32_t, 2> range;
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000703 ASSERT_TRUE(contextHub->requestSessionIdRange(requestedRange, &range).isOk());
704 EXPECT_EQ(range.size(), 2);
705 EXPECT_GE(range[1] - range[0] + 1, requestedRange);
706
707 // Open the session
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000708 int32_t sessionId = range[1] + 10; // invalid
709 EXPECT_FALSE(contextHub
710 ->openEndpointSession(sessionId, destinationEndpoint->id,
711 initiatorEndpoint.id,
Arthur Ishiguro38712cf2024-12-13 11:40:47 -0800712 /* in_serviceDescriptor= */ kEchoServiceName)
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000713 .isOk());
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000714}
715
716TEST_P(ContextHubAidl, OpenEndpointSessionAndSendMessageEchoesBack) {
717 auto cb = sp<TestEndpointCallback>::make();
718 Status status = contextHub->registerEndpointCallback(cb);
719 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
720 status.transactionError() == android::UNKNOWN_TRANSACTION) {
721 GTEST_SKIP() << "Not supported -> old API; or not implemented";
722 } else {
723 EXPECT_TRUE(status.isOk());
724 }
725
Matthew Sedam0ec290c2024-12-11 11:18:15 -0800726 std::unique_lock<std::mutex> lock(cb->getMutex());
727
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000728 // Register the endpoint
729 EndpointInfo initiatorEndpoint;
730 initiatorEndpoint.id.id = 8;
731 initiatorEndpoint.id.hubId = 0xCAFECAFECAFECAFE;
732 initiatorEndpoint.type = EndpointInfo::EndpointType::NATIVE;
733 initiatorEndpoint.name = String16("Test host endpoint 7");
734 initiatorEndpoint.version = 42;
735 EXPECT_TRUE(contextHub->registerEndpoint(initiatorEndpoint).isOk());
736
737 // Find the destination, if it exists
738 std::vector<EndpointInfo> endpoints;
739 EXPECT_TRUE(contextHub->getEndpoints(&endpoints).isOk());
740 const EndpointInfo* destinationEndpoint = nullptr;
741 for (const EndpointInfo& endpoint : endpoints) {
742 for (const Service& service : endpoint.services) {
Arthur Ishiguro38712cf2024-12-13 11:40:47 -0800743 if (service.serviceDescriptor == kEchoServiceName) {
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000744 destinationEndpoint = &endpoint;
745 break;
746 }
747 }
748 }
749 if (destinationEndpoint == nullptr) {
750 return; // no echo service endpoint -> just return
751 }
752
753 // Request the range
754 constexpr int32_t requestedRange = 100;
Yifei Zhangcef8f662024-12-06 16:03:26 -0800755 std::array<int32_t, 2> range;
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000756 ASSERT_TRUE(contextHub->requestSessionIdRange(requestedRange, &range).isOk());
757 EXPECT_EQ(range.size(), 2);
758 EXPECT_GE(range[1] - range[0] + 1, requestedRange);
759
760 // Open the session
761 cb->resetWasOnEndpointSessionOpenCompleteCalled();
762 int32_t sessionId = range[0];
763 ASSERT_TRUE(contextHub
764 ->openEndpointSession(sessionId, destinationEndpoint->id,
765 initiatorEndpoint.id,
Arthur Ishiguro38712cf2024-12-13 11:40:47 -0800766 /* in_serviceDescriptor= */ kEchoServiceName)
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000767 .isOk());
Matthew Sedam0ec290c2024-12-11 11:18:15 -0800768 cb->getCondVar().wait(lock);
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000769 EXPECT_TRUE(cb->wasOnEndpointSessionOpenCompleteCalled());
770
771 // Send the message
772 Message message;
773 message.flags = 0;
774 message.sequenceNumber = 0;
775 message.content.push_back(42);
776 ASSERT_TRUE(contextHub->sendMessageToEndpoint(sessionId, message).isOk());
777
778 // Check for echo
Matthew Sedam0ec290c2024-12-11 11:18:15 -0800779 cb->getCondVar().wait(lock);
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000780 EXPECT_FALSE(cb->getMessages().empty());
781 EXPECT_EQ(cb->getMessages().back().content.back(), 42);
782}
783
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700784std::string PrintGeneratedTest(const testing::TestParamInfo<ContextHubAidl::ParamType>& info) {
785 return std::string("CONTEXT_HUB_ID_") + std::to_string(std::get<1>(info.param));
786}
787
788GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContextHubAidl);
789INSTANTIATE_TEST_SUITE_P(ContextHub, ContextHubAidl, testing::ValuesIn(generateContextHubMapping()),
790 PrintGeneratedTest);
791
792GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContextHubTransactionTest);
793INSTANTIATE_TEST_SUITE_P(ContextHub, ContextHubTransactionTest,
794 testing::ValuesIn(generateContextHubMapping()), PrintGeneratedTest);
795
796int main(int argc, char** argv) {
797 ::testing::InitGoogleTest(&argc, argv);
798 ProcessState::self()->setThreadPoolMaxThreadCount(1);
799 ProcessState::self()->startThreadPool();
800 return RUN_ALL_TESTS();
801}