blob: 1df1a9902321d1b6139e69d919739198091b23ae [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};
Matthew Sedam41db0932025-01-02 11:17:46 -080065
Lei Ju5b2ded42023-12-05 15:08:21 -080066const String16 kName{"VtsAidlHalContextHubTargetTest"};
Lei Ju8787afa2023-06-28 09:36:19 -070067
Arthur Ishiguro38712cf2024-12-13 11:40:47 -080068const String16 kEchoServiceName{"android.hardware.contexthub.test.EchoService"};
69
Arthur Ishiguro4e916c32021-08-12 12:47:03 -070070class ContextHubAidl : public testing::TestWithParam<std::tuple<std::string, int32_t>> {
71 public:
72 virtual void SetUp() override {
73 contextHub = android::waitForDeclaredService<IContextHub>(
74 String16(std::get<0>(GetParam()).c_str()));
75 ASSERT_NE(contextHub, nullptr);
Matthew Sedam41db0932025-01-02 11:17:46 -080076 }
77
78 uint32_t getHubId() { return std::get<1>(GetParam()); }
79
80 sp<IContextHub> contextHub;
81
82 void testSettingChanged(Setting setting);
83};
84
85class ContextHubAidlWithTestMode : public ContextHubAidl {
86 public:
87 virtual void SetUp() override {
88 ContextHubAidl::SetUp();
Matthew Sedam92c2bd82024-11-11 19:52:30 +000089
90 // Best effort enable test mode - this may not be supported on older HALS, so we
91 // ignore the return value.
92 contextHub->setTestMode(/* enable= */ true);
Arthur Ishiguro4e916c32021-08-12 12:47:03 -070093 }
94
Matthew Sedam41db0932025-01-02 11:17:46 -080095 virtual void TearDown() override {
96 contextHub->setTestMode(/* enable= */ false);
97 ContextHubAidl::TearDown();
98 }
Arthur Ishiguro4e916c32021-08-12 12:47:03 -070099};
100
101TEST_P(ContextHubAidl, TestGetHubs) {
102 std::vector<ContextHubInfo> hubs;
103 ASSERT_TRUE(contextHub->getContextHubs(&hubs).isOk());
104
105 ALOGD("System reports %zu hubs", hubs.size());
106
107 for (const ContextHubInfo& hub : hubs) {
108 ALOGD("Checking hub ID %" PRIu32, hub.id);
109
110 EXPECT_GT(hub.name.size(), 0);
111 EXPECT_GT(hub.vendor.size(), 0);
112 EXPECT_GT(hub.toolchain.size(), 0);
113 EXPECT_GT(hub.peakMips, 0);
114 EXPECT_GT(hub.chrePlatformId, 0);
115 EXPECT_GT(hub.chreApiMajorVersion, 0);
Arthur Ishiguro6471f612021-10-28 21:59:55 +0000116 EXPECT_GE(hub.chreApiMinorVersion, 0);
117 EXPECT_GE(hub.chrePatchVersion, 0);
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700118
119 // Minimum 128 byte MTU as required by CHRE API v1.0
120 EXPECT_GE(hub.maxSupportedMessageLengthBytes, UINT32_C(128));
121 }
122}
123
Matthew Sedamc8ce4d52023-01-09 20:18:21 +0000124TEST_P(ContextHubAidl, TestEnableTestMode) {
125 Status status = contextHub->setTestMode(true);
126 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
127 status.transactionError() == android::UNKNOWN_TRANSACTION) {
Matthew Sedam121b6d62023-01-19 19:04:53 +0000128 GTEST_SKIP() << "Not supported -> old API; or not implemented";
129 } else {
130 ASSERT_TRUE(status.isOk());
Matthew Sedamc8ce4d52023-01-09 20:18:21 +0000131 }
Matthew Sedamc8ce4d52023-01-09 20:18:21 +0000132}
133
134TEST_P(ContextHubAidl, TestDisableTestMode) {
135 Status status = contextHub->setTestMode(false);
136 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
137 status.transactionError() == android::UNKNOWN_TRANSACTION) {
Matthew Sedam121b6d62023-01-19 19:04:53 +0000138 GTEST_SKIP() << "Not supported -> old API; or not implemented";
139 } else {
140 ASSERT_TRUE(status.isOk());
Matthew Sedamc8ce4d52023-01-09 20:18:21 +0000141 }
Matthew Sedamc8ce4d52023-01-09 20:18:21 +0000142}
143
Arthur Ishiguroe6b540d2021-10-29 16:01:35 +0000144class EmptyContextHubCallback : public android::hardware::contexthub::BnContextHubCallback {
145 public:
146 Status handleNanoappInfo(const std::vector<NanoappInfo>& /* appInfo */) override {
147 return Status::ok();
148 }
149
150 Status handleContextHubMessage(const ContextHubMessage& /* msg */,
151 const std::vector<String16>& /* msgContentPerms */) override {
152 return Status::ok();
153 }
154
155 Status handleContextHubAsyncEvent(AsyncEventType /* evt */) override { return Status::ok(); }
156
157 Status handleTransactionResult(int32_t /* transactionId */, bool /* success */) override {
158 return Status::ok();
159 }
Anthony Stange7344af92022-12-22 14:21:31 +0000160
Anthony Stange7fba1002023-03-02 21:45:20 +0000161 Status handleNanSessionRequest(const NanSessionRequest& /* request */) override {
162 return Status::ok();
163 }
Lei Ju8787afa2023-06-28 09:36:19 -0700164
Matthew Sedamadfd5572023-11-21 05:53:00 -0800165 Status handleMessageDeliveryStatus(
166 char16_t /* hostEndPointId */,
167 const MessageDeliveryStatus& /* messageDeliveryStatus */) override {
168 return Status::ok();
169 }
170
Lei Ju8787afa2023-06-28 09:36:19 -0700171 Status getUuid(std::array<uint8_t, 16>* out_uuid) override {
172 *out_uuid = kUuid;
173 return Status::ok();
174 }
Lei Ju5b2ded42023-12-05 15:08:21 -0800175
176 Status getName(::android::String16* out_name) override {
177 *out_name = kName;
178 return Status::ok();
179 }
Arthur Ishiguroe6b540d2021-10-29 16:01:35 +0000180};
181
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700182TEST_P(ContextHubAidl, TestRegisterCallback) {
Arthur Ishiguroe6b540d2021-10-29 16:01:35 +0000183 sp<EmptyContextHubCallback> cb = sp<EmptyContextHubCallback>::make();
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000184 ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb).isOk());
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700185}
186
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700187// Helper callback that puts the async appInfo callback data into a promise
188class QueryAppsCallback : public android::hardware::contexthub::BnContextHubCallback {
189 public:
190 Status handleNanoappInfo(const std::vector<NanoappInfo>& appInfo) override {
191 ALOGD("Got app info callback with %zu apps", appInfo.size());
192 promise.set_value(appInfo);
193 return Status::ok();
194 }
195
196 Status handleContextHubMessage(const ContextHubMessage& /* msg */,
197 const std::vector<String16>& /* msgContentPerms */) override {
198 return Status::ok();
199 }
200
201 Status handleContextHubAsyncEvent(AsyncEventType /* evt */) override { return Status::ok(); }
202
203 Status handleTransactionResult(int32_t /* transactionId */, bool /* success */) override {
204 return Status::ok();
205 }
206
Anthony Stange7fba1002023-03-02 21:45:20 +0000207 Status handleNanSessionRequest(const NanSessionRequest& /* request */) override {
208 return Status::ok();
209 }
Anthony Stange7344af92022-12-22 14:21:31 +0000210
Matthew Sedamadfd5572023-11-21 05:53:00 -0800211 Status handleMessageDeliveryStatus(
212 char16_t /* hostEndPointId */,
213 const MessageDeliveryStatus& /* messageDeliveryStatus */) override {
214 return Status::ok();
215 }
216
Lei Ju8787afa2023-06-28 09:36:19 -0700217 Status getUuid(std::array<uint8_t, 16>* out_uuid) override {
218 *out_uuid = kUuid;
219 return Status::ok();
220 }
221
Lei Ju5b2ded42023-12-05 15:08:21 -0800222 Status getName(::android::String16* out_name) override {
223 *out_name = kName;
224 return Status::ok();
225 }
226
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700227 std::promise<std::vector<NanoappInfo>> promise;
228};
229
230// Calls queryApps() and checks the returned metadata
231TEST_P(ContextHubAidl, TestQueryApps) {
232 sp<QueryAppsCallback> cb = sp<QueryAppsCallback>::make();
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000233 ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb).isOk());
234 ASSERT_TRUE(contextHub->queryNanoapps(getHubId()).isOk());
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700235
236 std::vector<NanoappInfo> appInfoList;
237 ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &appInfoList));
238 for (const NanoappInfo& appInfo : appInfoList) {
239 EXPECT_NE(appInfo.nanoappId, UINT64_C(0));
240 EXPECT_NE(appInfo.nanoappId, kNonExistentAppId);
Arthur Ishiguro08103072021-12-09 18:30:49 +0000241
242 // Verify services are unique.
243 std::set<uint64_t> existingServiceIds;
244 for (const NanoappRpcService& rpcService : appInfo.rpcServices) {
245 EXPECT_NE(rpcService.id, UINT64_C(0));
246 EXPECT_EQ(existingServiceIds.count(rpcService.id), 0);
247 existingServiceIds.insert(rpcService.id);
248 }
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700249 }
250}
251
Matthew Sedamd70f84d2023-03-06 18:34:24 +0000252// Calls getPreloadedNanoappsIds() and verifies there are preloaded nanoapps
253TEST_P(ContextHubAidl, TestGetPreloadedNanoappIds) {
Arthur Ishigurofd5e65c2022-11-08 16:49:47 +0000254 std::vector<int64_t> preloadedNanoappIds;
Matthew Sedamd70f84d2023-03-06 18:34:24 +0000255 Status status = contextHub->getPreloadedNanoappIds(getHubId(), &preloadedNanoappIds);
Arthur Ishigurofd5e65c2022-11-08 16:49:47 +0000256 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
257 status.transactionError() == android::UNKNOWN_TRANSACTION) {
Matthew Sedam121b6d62023-01-19 19:04:53 +0000258 GTEST_SKIP() << "Not supported -> old API; or not implemented";
259 } else {
260 ASSERT_TRUE(status.isOk());
Arthur Ishigurofd5e65c2022-11-08 16:49:47 +0000261 }
Arthur Ishigurofd5e65c2022-11-08 16:49:47 +0000262}
263
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700264// Helper callback that puts the TransactionResult for the expectedTransactionId into a
265// promise
266class TransactionResultCallback : public android::hardware::contexthub::BnContextHubCallback {
267 public:
268 Status handleNanoappInfo(const std::vector<NanoappInfo>& /* appInfo */) override {
269 return Status::ok();
270 }
271
272 Status handleContextHubMessage(const ContextHubMessage& /* msg */,
273 const std::vector<String16>& /* msgContentPerms */) override {
274 return Status::ok();
275 }
276
277 Status handleContextHubAsyncEvent(AsyncEventType /* evt */) override { return Status::ok(); }
278
279 Status handleTransactionResult(int32_t transactionId, bool success) override {
280 ALOGD("Got transaction result callback for transactionId %" PRIu32 " (expecting %" PRIu32
281 ") with success %d",
282 transactionId, expectedTransactionId, success);
283 if (transactionId == expectedTransactionId) {
284 promise.set_value(success);
285 }
286 return Status::ok();
287 }
288
Anthony Stange7fba1002023-03-02 21:45:20 +0000289 Status handleNanSessionRequest(const NanSessionRequest& /* request */) override {
290 return Status::ok();
291 }
Anthony Stange7344af92022-12-22 14:21:31 +0000292
Matthew Sedamadfd5572023-11-21 05:53:00 -0800293 Status handleMessageDeliveryStatus(
294 char16_t /* hostEndPointId */,
295 const MessageDeliveryStatus& /* messageDeliveryStatus */) override {
296 return Status::ok();
297 }
298
Lei Ju8787afa2023-06-28 09:36:19 -0700299 Status getUuid(std::array<uint8_t, 16>* out_uuid) override {
300 *out_uuid = kUuid;
301 return Status::ok();
302 }
303
Lei Ju5b2ded42023-12-05 15:08:21 -0800304 Status getName(::android::String16* out_name) override {
305 *out_name = kName;
306 return Status::ok();
307 }
308
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700309 uint32_t expectedTransactionId = 0;
310 std::promise<bool> promise;
311};
312
313// Parameterized fixture that sets the callback to TransactionResultCallback
314class ContextHubTransactionTest : public ContextHubAidl {
315 public:
316 virtual void SetUp() override {
317 ContextHubAidl::SetUp();
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000318 ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb).isOk());
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700319 }
320
321 sp<TransactionResultCallback> cb = sp<TransactionResultCallback>::make();
322};
323
324TEST_P(ContextHubTransactionTest, TestSendMessageToNonExistentNanoapp) {
325 ContextHubMessage message;
326 message.nanoappId = kNonExistentAppId;
327 message.messageType = 1;
328 message.messageBody.resize(4);
329 std::fill(message.messageBody.begin(), message.messageBody.end(), 0);
330
331 ALOGD("Sending message to non-existent nanoapp");
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000332 ASSERT_TRUE(contextHub->sendMessageToHub(getHubId(), message).isOk());
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700333}
334
335TEST_P(ContextHubTransactionTest, TestLoadEmptyNanoapp) {
336 cb->expectedTransactionId = 0123;
337 NanoappBinary emptyApp;
338
339 emptyApp.nanoappId = kNonExistentAppId;
340 emptyApp.nanoappVersion = 1;
341 emptyApp.flags = 0;
342 emptyApp.targetChreApiMajorVersion = 1;
343 emptyApp.targetChreApiMinorVersion = 0;
344
345 ALOGD("Loading empty nanoapp");
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000346 bool success = contextHub->loadNanoapp(getHubId(), emptyApp, cb->expectedTransactionId).isOk();
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700347 if (success) {
348 bool transactionSuccess;
349 ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
350 ASSERT_FALSE(transactionSuccess);
351 }
352}
353
354TEST_P(ContextHubTransactionTest, TestUnloadNonexistentNanoapp) {
355 cb->expectedTransactionId = 1234;
356
357 ALOGD("Unloading nonexistent nanoapp");
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000358 bool success =
359 contextHub->unloadNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId)
360 .isOk();
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700361 if (success) {
362 bool transactionSuccess;
363 ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
364 ASSERT_FALSE(transactionSuccess);
365 }
366}
367
368TEST_P(ContextHubTransactionTest, TestEnableNonexistentNanoapp) {
369 cb->expectedTransactionId = 2345;
370
371 ALOGD("Enabling nonexistent nanoapp");
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000372 bool success =
373 contextHub->enableNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId)
374 .isOk();
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700375 if (success) {
376 bool transactionSuccess;
377 ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
378 ASSERT_FALSE(transactionSuccess);
379 }
380}
381
382TEST_P(ContextHubTransactionTest, TestDisableNonexistentNanoapp) {
383 cb->expectedTransactionId = 3456;
384
385 ALOGD("Disabling nonexistent nanoapp");
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000386 bool success =
387 contextHub->disableNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId)
388 .isOk();
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700389 if (success) {
390 bool transactionSuccess;
391 ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
392 ASSERT_FALSE(transactionSuccess);
393 }
394}
395
396void ContextHubAidl::testSettingChanged(Setting setting) {
397 // In VTS, we only test that sending the values doesn't cause things to blow up - GTS tests
398 // verify the expected E2E behavior in CHRE
Arthur Ishiguroe6b540d2021-10-29 16:01:35 +0000399 sp<EmptyContextHubCallback> cb = sp<EmptyContextHubCallback>::make();
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000400 ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb).isOk());
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700401
402 ASSERT_TRUE(contextHub->onSettingChanged(setting, true /* enabled */).isOk());
403 ASSERT_TRUE(contextHub->onSettingChanged(setting, false /* enabled */).isOk());
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700404}
405
406TEST_P(ContextHubAidl, TestOnLocationSettingChanged) {
407 testSettingChanged(Setting::LOCATION);
408}
409
410TEST_P(ContextHubAidl, TestOnWifiMainSettingChanged) {
411 testSettingChanged(Setting::WIFI_MAIN);
412}
413
414TEST_P(ContextHubAidl, TestOnWifiScanningSettingChanged) {
415 testSettingChanged(Setting::WIFI_SCANNING);
416}
417
418TEST_P(ContextHubAidl, TestOnAirplaneModeSettingChanged) {
419 testSettingChanged(Setting::AIRPLANE_MODE);
420}
421
422TEST_P(ContextHubAidl, TestOnMicrophoneSettingChanged) {
423 testSettingChanged(Setting::MICROPHONE);
424}
425
Anthonya6b65002022-01-20 20:49:10 +0000426TEST_P(ContextHubAidl, TestOnBtMainSettingChanged) {
427 testSettingChanged(Setting::BT_MAIN);
428}
429
430TEST_P(ContextHubAidl, TestOnBtScanningSettingChanged) {
431 testSettingChanged(Setting::BT_SCANNING);
432}
433
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700434std::vector<std::tuple<std::string, int32_t>> generateContextHubMapping() {
435 std::vector<std::tuple<std::string, int32_t>> tuples;
436 auto contextHubAidlNames = android::getAidlHalInstanceNames(IContextHub::descriptor);
437 std::vector<ContextHubInfo> contextHubInfos;
438
439 for (int i = 0; i < contextHubAidlNames.size(); i++) {
440 auto contextHubName = contextHubAidlNames[i].c_str();
441 auto contextHub = android::waitForDeclaredService<IContextHub>(String16(contextHubName));
442 if (contextHub->getContextHubs(&contextHubInfos).isOk()) {
443 for (auto& info : contextHubInfos) {
444 tuples.push_back(std::make_tuple(contextHubName, info.id));
445 }
446 }
447 }
448
449 return tuples;
450}
451
Lei Jubc6ead02024-02-05 18:15:08 -0800452TEST_P(ContextHubTransactionTest, TestHostConnection) {
Arthur Ishiguro065a9a52021-11-19 00:24:45 +0000453 constexpr char16_t kHostEndpointId = 1;
454 HostEndpointInfo hostEndpointInfo;
Arthur Ishiguro16f40622023-02-10 18:11:12 +0000455 hostEndpointInfo.type = HostEndpointInfo::Type::NATIVE;
Arthur Ishiguro065a9a52021-11-19 00:24:45 +0000456 hostEndpointInfo.hostEndpointId = kHostEndpointId;
457
458 ASSERT_TRUE(contextHub->onHostEndpointConnected(hostEndpointInfo).isOk());
459 ASSERT_TRUE(contextHub->onHostEndpointDisconnected(kHostEndpointId).isOk());
460}
461
Lei Jubc6ead02024-02-05 18:15:08 -0800462TEST_P(ContextHubTransactionTest, TestInvalidHostConnection) {
Arthur Ishiguro065a9a52021-11-19 00:24:45 +0000463 constexpr char16_t kHostEndpointId = 1;
464
Arthur Ishiguro5dba9212022-02-01 17:03:32 +0000465 ASSERT_TRUE(contextHub->onHostEndpointDisconnected(kHostEndpointId).isOk());
Arthur Ishiguro065a9a52021-11-19 00:24:45 +0000466}
467
Lei Jubc6ead02024-02-05 18:15:08 -0800468TEST_P(ContextHubTransactionTest, TestNanSessionStateChange) {
Anthony Stange7fba1002023-03-02 21:45:20 +0000469 NanSessionStateUpdate update;
470 update.state = true;
Rocky Fang78140982023-06-16 00:42:41 +0000471 Status status = contextHub->onNanSessionStateChanged(update);
472 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
473 status.transactionError() == android::UNKNOWN_TRANSACTION) {
474 GTEST_SKIP() << "Not supported -> old API; or not implemented";
475 } else {
476 ASSERT_TRUE(status.isOk());
477 update.state = false;
478 ASSERT_TRUE(contextHub->onNanSessionStateChanged(update).isOk());
479 }
Anthony Stange7344af92022-12-22 14:21:31 +0000480}
481
Matthew Sedamadfd5572023-11-21 05:53:00 -0800482TEST_P(ContextHubAidl, TestSendMessageDeliveryStatusToHub) {
483 MessageDeliveryStatus messageDeliveryStatus;
484 messageDeliveryStatus.messageSequenceNumber = 123;
485 messageDeliveryStatus.errorCode = ErrorCode::OK;
486
487 Status status = contextHub->sendMessageDeliveryStatusToHub(getHubId(), messageDeliveryStatus);
488 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
489 status.transactionError() == android::UNKNOWN_TRANSACTION) {
490 GTEST_SKIP() << "Not supported -> old API; or not implemented";
491 } else {
492 EXPECT_TRUE(status.isOk());
493 }
494}
495
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000496class TestEndpointCallback : public BnEndpointCallback {
497 public:
498 Status onEndpointStarted(const std::vector<EndpointInfo>& /* endpointInfos */) override {
499 return Status::ok();
500 }
501
502 Status onEndpointStopped(const std::vector<EndpointId>& /* endpointIds */,
503 Reason /* reason */) override {
504 return Status::ok();
505 }
506
507 Status onMessageReceived(int32_t /* sessionId */, const Message& message) override {
Matthew Sedam0ec290c2024-12-11 11:18:15 -0800508 {
509 std::unique_lock<std::mutex> lock(mMutex);
510 mMessages.push_back(message);
511 }
512 mCondVar.notify_one();
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000513 return Status::ok();
514 }
515
516 Status onMessageDeliveryStatusReceived(int32_t /* sessionId */,
517 const MessageDeliveryStatus& /* msgStatus */) override {
518 return Status::ok();
519 }
520
521 Status onEndpointSessionOpenRequest(
522 int32_t /* sessionId */, const EndpointId& /* destination */,
523 const EndpointId& /* initiator */,
524 const std::optional<String16>& /* serviceDescriptor */) override {
525 return Status::ok();
526 }
527
528 Status onCloseEndpointSession(int32_t /* sessionId */, Reason /* reason */) override {
529 return Status::ok();
530 }
531
532 Status onEndpointSessionOpenComplete(int32_t /* sessionId */) override {
Matthew Sedam0ec290c2024-12-11 11:18:15 -0800533 {
534 std::unique_lock<std::mutex> lock(mMutex);
535 mWasOnEndpointSessionOpenCompleteCalled = true;
536 }
537 mCondVar.notify_one();
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000538 return Status::ok();
539 }
540
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000541 bool wasOnEndpointSessionOpenCompleteCalled() {
542 return mWasOnEndpointSessionOpenCompleteCalled;
543 }
Matthew Sedam0ec290c2024-12-11 11:18:15 -0800544
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000545 void resetWasOnEndpointSessionOpenCompleteCalled() {
546 mWasOnEndpointSessionOpenCompleteCalled = false;
547 }
548
Matthew Sedam0ec290c2024-12-11 11:18:15 -0800549 std::mutex& getMutex() { return mMutex; }
550 std::condition_variable& getCondVar() { return mCondVar; }
551 std::vector<Message> getMessages() { return mMessages; }
552
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000553 private:
554 std::vector<Message> mMessages;
Matthew Sedam0ec290c2024-12-11 11:18:15 -0800555 std::mutex mMutex;
556 std::condition_variable mCondVar;
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000557 bool mWasOnEndpointSessionOpenCompleteCalled = false;
558};
559
Matthew Sedam41db0932025-01-02 11:17:46 -0800560TEST_P(ContextHubAidlWithTestMode, RegisterEndpoint) {
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000561 EndpointInfo endpointInfo;
562 endpointInfo.id.id = 1;
563 endpointInfo.id.hubId = 0xCAFECAFECAFECAFE;
564 endpointInfo.type = EndpointInfo::EndpointType::NATIVE;
565 endpointInfo.name = String16("Test host endpoint 1");
566 endpointInfo.version = 42;
567
568 Status status = contextHub->registerEndpoint(endpointInfo);
569 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
570 status.transactionError() == android::UNKNOWN_TRANSACTION) {
571 GTEST_SKIP() << "Not supported -> old API; or not implemented";
572 } else {
573 EXPECT_TRUE(status.isOk());
574 }
575}
576
Matthew Sedam41db0932025-01-02 11:17:46 -0800577TEST_P(ContextHubAidlWithTestMode, RegisterEndpointSameNameFailure) {
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000578 EndpointInfo endpointInfo;
579 endpointInfo.id.id = 2;
580 endpointInfo.id.hubId = 0xCAFECAFECAFECAFE;
581 endpointInfo.type = EndpointInfo::EndpointType::NATIVE;
582 endpointInfo.name = String16("Test host endpoint 2");
583 endpointInfo.version = 42;
584
585 EndpointInfo endpointInfo2;
586 endpointInfo2.id.id = 3;
587 endpointInfo2.id.hubId = 0xCAFECAFECAFECAFE;
588 endpointInfo2.type = EndpointInfo::EndpointType::NATIVE;
589 endpointInfo2.name = String16("Test host endpoint 2");
590 endpointInfo2.version = 42;
591
592 Status status = contextHub->registerEndpoint(endpointInfo);
593 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
594 status.transactionError() == android::UNKNOWN_TRANSACTION) {
595 GTEST_SKIP() << "Not supported -> old API; or not implemented";
596 } else {
597 EXPECT_TRUE(status.isOk());
598 }
599
600 EXPECT_FALSE(contextHub->registerEndpoint(endpointInfo2).isOk());
601}
602
Matthew Sedam41db0932025-01-02 11:17:46 -0800603TEST_P(ContextHubAidlWithTestMode, RegisterEndpointSameIdFailure) {
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000604 EndpointInfo endpointInfo;
605 endpointInfo.id.id = 4;
606 endpointInfo.id.hubId = 0xCAFECAFECAFECAFE;
607 endpointInfo.type = EndpointInfo::EndpointType::NATIVE;
608 endpointInfo.name = String16("Test host endpoint 4");
609 endpointInfo.version = 42;
610
611 EndpointInfo endpointInfo2;
612 endpointInfo2.id.id = 4;
613 endpointInfo2.id.hubId = 0xCAFECAFECAFECAFE;
614 endpointInfo2.type = EndpointInfo::EndpointType::NATIVE;
615 endpointInfo2.name = String16("Test host endpoint - same ID test");
616 endpointInfo2.version = 42;
617
618 Status status = contextHub->registerEndpoint(endpointInfo);
619 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
620 status.transactionError() == android::UNKNOWN_TRANSACTION) {
621 GTEST_SKIP() << "Not supported -> old API; or not implemented";
622 } else {
623 EXPECT_TRUE(status.isOk());
624 }
625
626 EXPECT_FALSE(contextHub->registerEndpoint(endpointInfo2).isOk());
627}
628
Matthew Sedam41db0932025-01-02 11:17:46 -0800629TEST_P(ContextHubAidlWithTestMode, UnregisterEndpoint) {
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000630 EndpointInfo endpointInfo;
631 endpointInfo.id.id = 6;
632 endpointInfo.id.hubId = 0xCAFECAFECAFECAFE;
633 endpointInfo.type = EndpointInfo::EndpointType::NATIVE;
634 endpointInfo.name = String16("Test host endpoint 6");
635 endpointInfo.version = 42;
636
637 Status status = contextHub->registerEndpoint(endpointInfo);
638 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
639 status.transactionError() == android::UNKNOWN_TRANSACTION) {
640 GTEST_SKIP() << "Not supported -> old API; or not implemented";
641 } else {
642 EXPECT_TRUE(status.isOk());
643 }
644
645 EXPECT_TRUE(contextHub->unregisterEndpoint(endpointInfo).isOk());
646}
647
Matthew Sedam41db0932025-01-02 11:17:46 -0800648TEST_P(ContextHubAidlWithTestMode, UnregisterEndpointNonexistent) {
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000649 EndpointInfo endpointInfo;
650 endpointInfo.id.id = 100;
651 endpointInfo.id.hubId = 0xCAFECAFECAFECAFE;
652 endpointInfo.type = EndpointInfo::EndpointType::NATIVE;
653 endpointInfo.name = String16("Test host endpoint 100");
654 endpointInfo.version = 42;
655
656 Status status = contextHub->unregisterEndpoint(endpointInfo);
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_FALSE(status.isOk());
662 }
663}
664
Matthew Sedam41db0932025-01-02 11:17:46 -0800665TEST_P(ContextHubAidlWithTestMode, RegisterEndpointCallback) {
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000666 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
Matthew Sedam41db0932025-01-02 11:17:46 -0800676TEST_P(ContextHubAidlWithTestMode, OpenEndpointSessionInvalidRange) {
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000677 auto cb = sp<TestEndpointCallback>::make();
678 Status status = contextHub->registerEndpointCallback(cb);
679 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
680 status.transactionError() == android::UNKNOWN_TRANSACTION) {
681 GTEST_SKIP() << "Not supported -> old API; or not implemented";
682 } else {
683 EXPECT_TRUE(status.isOk());
684 }
685
686 // Register the endpoint
687 EndpointInfo initiatorEndpoint;
688 initiatorEndpoint.id.id = 7;
689 initiatorEndpoint.id.hubId = 0xCAFECAFECAFECAFE;
690 initiatorEndpoint.type = EndpointInfo::EndpointType::NATIVE;
691 initiatorEndpoint.name = String16("Test host endpoint 7");
692 initiatorEndpoint.version = 42;
693 EXPECT_TRUE(contextHub->registerEndpoint(initiatorEndpoint).isOk());
694
695 // Find the destination, if it exists
696 std::vector<EndpointInfo> endpoints;
697 EXPECT_TRUE(contextHub->getEndpoints(&endpoints).isOk());
698 const EndpointInfo* destinationEndpoint = nullptr;
699 for (const EndpointInfo& endpoint : endpoints) {
700 for (const Service& service : endpoint.services) {
Arthur Ishiguro38712cf2024-12-13 11:40:47 -0800701 if (service.serviceDescriptor == kEchoServiceName) {
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000702 destinationEndpoint = &endpoint;
703 break;
704 }
705 }
706 }
707 if (destinationEndpoint == nullptr) {
708 return; // no echo service endpoint -> just return
709 }
710
711 // Request the range
712 constexpr int32_t requestedRange = 100;
Yifei Zhangcef8f662024-12-06 16:03:26 -0800713 std::array<int32_t, 2> range;
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000714 ASSERT_TRUE(contextHub->requestSessionIdRange(requestedRange, &range).isOk());
715 EXPECT_EQ(range.size(), 2);
716 EXPECT_GE(range[1] - range[0] + 1, requestedRange);
717
718 // Open the session
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000719 int32_t sessionId = range[1] + 10; // invalid
720 EXPECT_FALSE(contextHub
721 ->openEndpointSession(sessionId, destinationEndpoint->id,
722 initiatorEndpoint.id,
Arthur Ishiguro38712cf2024-12-13 11:40:47 -0800723 /* in_serviceDescriptor= */ kEchoServiceName)
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000724 .isOk());
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000725}
726
Matthew Sedam41db0932025-01-02 11:17:46 -0800727TEST_P(ContextHubAidlWithTestMode, OpenEndpointSessionAndSendMessageEchoesBack) {
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000728 auto cb = sp<TestEndpointCallback>::make();
729 Status status = contextHub->registerEndpointCallback(cb);
730 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
731 status.transactionError() == android::UNKNOWN_TRANSACTION) {
732 GTEST_SKIP() << "Not supported -> old API; or not implemented";
733 } else {
734 EXPECT_TRUE(status.isOk());
735 }
736
Matthew Sedam0ec290c2024-12-11 11:18:15 -0800737 std::unique_lock<std::mutex> lock(cb->getMutex());
738
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000739 // Register the endpoint
740 EndpointInfo initiatorEndpoint;
741 initiatorEndpoint.id.id = 8;
742 initiatorEndpoint.id.hubId = 0xCAFECAFECAFECAFE;
743 initiatorEndpoint.type = EndpointInfo::EndpointType::NATIVE;
744 initiatorEndpoint.name = String16("Test host endpoint 7");
745 initiatorEndpoint.version = 42;
746 EXPECT_TRUE(contextHub->registerEndpoint(initiatorEndpoint).isOk());
747
748 // Find the destination, if it exists
749 std::vector<EndpointInfo> endpoints;
750 EXPECT_TRUE(contextHub->getEndpoints(&endpoints).isOk());
751 const EndpointInfo* destinationEndpoint = nullptr;
752 for (const EndpointInfo& endpoint : endpoints) {
753 for (const Service& service : endpoint.services) {
Arthur Ishiguro38712cf2024-12-13 11:40:47 -0800754 if (service.serviceDescriptor == kEchoServiceName) {
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000755 destinationEndpoint = &endpoint;
756 break;
757 }
758 }
759 }
760 if (destinationEndpoint == nullptr) {
761 return; // no echo service endpoint -> just return
762 }
763
764 // Request the range
765 constexpr int32_t requestedRange = 100;
Yifei Zhangcef8f662024-12-06 16:03:26 -0800766 std::array<int32_t, 2> range;
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000767 ASSERT_TRUE(contextHub->requestSessionIdRange(requestedRange, &range).isOk());
768 EXPECT_EQ(range.size(), 2);
769 EXPECT_GE(range[1] - range[0] + 1, requestedRange);
770
771 // Open the session
772 cb->resetWasOnEndpointSessionOpenCompleteCalled();
773 int32_t sessionId = range[0];
774 ASSERT_TRUE(contextHub
775 ->openEndpointSession(sessionId, destinationEndpoint->id,
776 initiatorEndpoint.id,
Arthur Ishiguro38712cf2024-12-13 11:40:47 -0800777 /* in_serviceDescriptor= */ kEchoServiceName)
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000778 .isOk());
Matthew Sedam0ec290c2024-12-11 11:18:15 -0800779 cb->getCondVar().wait(lock);
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000780 EXPECT_TRUE(cb->wasOnEndpointSessionOpenCompleteCalled());
781
782 // Send the message
783 Message message;
784 message.flags = 0;
785 message.sequenceNumber = 0;
786 message.content.push_back(42);
787 ASSERT_TRUE(contextHub->sendMessageToEndpoint(sessionId, message).isOk());
788
789 // Check for echo
Matthew Sedam0ec290c2024-12-11 11:18:15 -0800790 cb->getCondVar().wait(lock);
Matthew Sedam92c2bd82024-11-11 19:52:30 +0000791 EXPECT_FALSE(cb->getMessages().empty());
792 EXPECT_EQ(cb->getMessages().back().content.back(), 42);
793}
794
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700795std::string PrintGeneratedTest(const testing::TestParamInfo<ContextHubAidl::ParamType>& info) {
796 return std::string("CONTEXT_HUB_ID_") + std::to_string(std::get<1>(info.param));
797}
798
799GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContextHubAidl);
800INSTANTIATE_TEST_SUITE_P(ContextHub, ContextHubAidl, testing::ValuesIn(generateContextHubMapping()),
801 PrintGeneratedTest);
802
Matthew Sedam41db0932025-01-02 11:17:46 -0800803GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContextHubAidlWithTestMode);
804INSTANTIATE_TEST_SUITE_P(ContextHub, ContextHubAidlWithTestMode,
805 testing::ValuesIn(generateContextHubMapping()), PrintGeneratedTest);
806
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700807GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContextHubTransactionTest);
808INSTANTIATE_TEST_SUITE_P(ContextHub, ContextHubTransactionTest,
809 testing::ValuesIn(generateContextHubMapping()), PrintGeneratedTest);
810
811int main(int argc, char** argv) {
812 ::testing::InitGoogleTest(&argc, argv);
Matthew Sedam41db0932025-01-02 11:17:46 -0800813 ProcessState::self()->setThreadPoolMaxThreadCount(2);
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700814 ProcessState::self()->startThreadPool();
815 return RUN_ALL_TESTS();
816}