blob: c1cc07cf51a961adeab622f8605f374f1d1f7db5 [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>
23#include <android/hardware/contexthub/IContextHub.h>
24#include <android/hardware/contexthub/IContextHubCallback.h>
25#include <binder/IServiceManager.h>
26#include <binder/ProcessState.h>
27#include <log/log.h>
28
29#include <cinttypes>
30#include <future>
31
32using ::android::ProcessState;
33using ::android::sp;
34using ::android::String16;
35using ::android::binder::Status;
36using ::android::hardware::contexthub::AsyncEventType;
37using ::android::hardware::contexthub::ContextHubInfo;
38using ::android::hardware::contexthub::ContextHubMessage;
Arthur Ishiguro065a9a52021-11-19 00:24:45 +000039using ::android::hardware::contexthub::HostEndpointInfo;
Arthur Ishiguro4e916c32021-08-12 12:47:03 -070040using ::android::hardware::contexthub::IContextHub;
41using ::android::hardware::contexthub::IContextHubCallbackDefault;
42using ::android::hardware::contexthub::NanoappBinary;
43using ::android::hardware::contexthub::NanoappInfo;
Arthur Ishiguro08103072021-12-09 18:30:49 +000044using ::android::hardware::contexthub::NanoappRpcService;
Anthony Stange7fba1002023-03-02 21:45:20 +000045using ::android::hardware::contexthub::NanSessionRequest;
46using ::android::hardware::contexthub::NanSessionStateUpdate;
Arthur Ishiguro4e916c32021-08-12 12:47:03 -070047using ::android::hardware::contexthub::Setting;
48using ::android::hardware::contexthub::vts_utils::kNonExistentAppId;
49using ::android::hardware::contexthub::vts_utils::waitForCallback;
50
51class ContextHubAidl : public testing::TestWithParam<std::tuple<std::string, int32_t>> {
52 public:
53 virtual void SetUp() override {
54 contextHub = android::waitForDeclaredService<IContextHub>(
55 String16(std::get<0>(GetParam()).c_str()));
56 ASSERT_NE(contextHub, nullptr);
57 }
58
59 uint32_t getHubId() { return std::get<1>(GetParam()); }
60
61 void testSettingChanged(Setting setting);
62
63 sp<IContextHub> contextHub;
64};
65
66TEST_P(ContextHubAidl, TestGetHubs) {
67 std::vector<ContextHubInfo> hubs;
68 ASSERT_TRUE(contextHub->getContextHubs(&hubs).isOk());
69
70 ALOGD("System reports %zu hubs", hubs.size());
71
72 for (const ContextHubInfo& hub : hubs) {
73 ALOGD("Checking hub ID %" PRIu32, hub.id);
74
75 EXPECT_GT(hub.name.size(), 0);
76 EXPECT_GT(hub.vendor.size(), 0);
77 EXPECT_GT(hub.toolchain.size(), 0);
78 EXPECT_GT(hub.peakMips, 0);
79 EXPECT_GT(hub.chrePlatformId, 0);
80 EXPECT_GT(hub.chreApiMajorVersion, 0);
Arthur Ishiguro6471f612021-10-28 21:59:55 +000081 EXPECT_GE(hub.chreApiMinorVersion, 0);
82 EXPECT_GE(hub.chrePatchVersion, 0);
Arthur Ishiguro4e916c32021-08-12 12:47:03 -070083
84 // Minimum 128 byte MTU as required by CHRE API v1.0
85 EXPECT_GE(hub.maxSupportedMessageLengthBytes, UINT32_C(128));
86 }
87}
88
Matthew Sedamc8ce4d52023-01-09 20:18:21 +000089TEST_P(ContextHubAidl, TestEnableTestMode) {
90 Status status = contextHub->setTestMode(true);
91 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
92 status.transactionError() == android::UNKNOWN_TRANSACTION) {
Matthew Sedam121b6d62023-01-19 19:04:53 +000093 GTEST_SKIP() << "Not supported -> old API; or not implemented";
94 } else {
95 ASSERT_TRUE(status.isOk());
Matthew Sedamc8ce4d52023-01-09 20:18:21 +000096 }
Matthew Sedamc8ce4d52023-01-09 20:18:21 +000097}
98
99TEST_P(ContextHubAidl, TestDisableTestMode) {
100 Status status = contextHub->setTestMode(false);
101 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
102 status.transactionError() == android::UNKNOWN_TRANSACTION) {
Matthew Sedam121b6d62023-01-19 19:04:53 +0000103 GTEST_SKIP() << "Not supported -> old API; or not implemented";
104 } else {
105 ASSERT_TRUE(status.isOk());
Matthew Sedamc8ce4d52023-01-09 20:18:21 +0000106 }
Matthew Sedamc8ce4d52023-01-09 20:18:21 +0000107}
108
Arthur Ishiguroe6b540d2021-10-29 16:01:35 +0000109class EmptyContextHubCallback : public android::hardware::contexthub::BnContextHubCallback {
110 public:
111 Status handleNanoappInfo(const std::vector<NanoappInfo>& /* appInfo */) override {
112 return Status::ok();
113 }
114
115 Status handleContextHubMessage(const ContextHubMessage& /* msg */,
116 const std::vector<String16>& /* msgContentPerms */) override {
117 return Status::ok();
118 }
119
120 Status handleContextHubAsyncEvent(AsyncEventType /* evt */) override { return Status::ok(); }
121
122 Status handleTransactionResult(int32_t /* transactionId */, bool /* success */) override {
123 return Status::ok();
124 }
Anthony Stange7344af92022-12-22 14:21:31 +0000125
Anthony Stange7fba1002023-03-02 21:45:20 +0000126 Status handleNanSessionRequest(const NanSessionRequest& /* request */) override {
127 return Status::ok();
128 }
Arthur Ishiguroe6b540d2021-10-29 16:01:35 +0000129};
130
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700131TEST_P(ContextHubAidl, TestRegisterCallback) {
Arthur Ishiguroe6b540d2021-10-29 16:01:35 +0000132 sp<EmptyContextHubCallback> cb = sp<EmptyContextHubCallback>::make();
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000133 ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb).isOk());
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700134}
135
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700136// Helper callback that puts the async appInfo callback data into a promise
137class QueryAppsCallback : public android::hardware::contexthub::BnContextHubCallback {
138 public:
139 Status handleNanoappInfo(const std::vector<NanoappInfo>& appInfo) override {
140 ALOGD("Got app info callback with %zu apps", appInfo.size());
141 promise.set_value(appInfo);
142 return Status::ok();
143 }
144
145 Status handleContextHubMessage(const ContextHubMessage& /* msg */,
146 const std::vector<String16>& /* msgContentPerms */) override {
147 return Status::ok();
148 }
149
150 Status handleContextHubAsyncEvent(AsyncEventType /* evt */) override { return Status::ok(); }
151
152 Status handleTransactionResult(int32_t /* transactionId */, bool /* success */) override {
153 return Status::ok();
154 }
155
Anthony Stange7fba1002023-03-02 21:45:20 +0000156 Status handleNanSessionRequest(const NanSessionRequest& /* request */) override {
157 return Status::ok();
158 }
Anthony Stange7344af92022-12-22 14:21:31 +0000159
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700160 std::promise<std::vector<NanoappInfo>> promise;
161};
162
163// Calls queryApps() and checks the returned metadata
164TEST_P(ContextHubAidl, TestQueryApps) {
165 sp<QueryAppsCallback> cb = sp<QueryAppsCallback>::make();
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000166 ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb).isOk());
167 ASSERT_TRUE(contextHub->queryNanoapps(getHubId()).isOk());
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700168
169 std::vector<NanoappInfo> appInfoList;
170 ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &appInfoList));
171 for (const NanoappInfo& appInfo : appInfoList) {
172 EXPECT_NE(appInfo.nanoappId, UINT64_C(0));
173 EXPECT_NE(appInfo.nanoappId, kNonExistentAppId);
Arthur Ishiguro08103072021-12-09 18:30:49 +0000174
175 // Verify services are unique.
176 std::set<uint64_t> existingServiceIds;
177 for (const NanoappRpcService& rpcService : appInfo.rpcServices) {
178 EXPECT_NE(rpcService.id, UINT64_C(0));
179 EXPECT_EQ(existingServiceIds.count(rpcService.id), 0);
180 existingServiceIds.insert(rpcService.id);
181 }
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700182 }
183}
184
Matthew Sedamd70f84d2023-03-06 18:34:24 +0000185// Calls getPreloadedNanoappsIds() and verifies there are preloaded nanoapps
186TEST_P(ContextHubAidl, TestGetPreloadedNanoappIds) {
Arthur Ishigurofd5e65c2022-11-08 16:49:47 +0000187 std::vector<int64_t> preloadedNanoappIds;
Matthew Sedamd70f84d2023-03-06 18:34:24 +0000188 Status status = contextHub->getPreloadedNanoappIds(getHubId(), &preloadedNanoappIds);
Arthur Ishigurofd5e65c2022-11-08 16:49:47 +0000189 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
190 status.transactionError() == android::UNKNOWN_TRANSACTION) {
Matthew Sedam121b6d62023-01-19 19:04:53 +0000191 GTEST_SKIP() << "Not supported -> old API; or not implemented";
192 } else {
193 ASSERT_TRUE(status.isOk());
Arthur Ishigurofd5e65c2022-11-08 16:49:47 +0000194 }
Arthur Ishigurofd5e65c2022-11-08 16:49:47 +0000195}
196
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700197// Helper callback that puts the TransactionResult for the expectedTransactionId into a
198// promise
199class TransactionResultCallback : public android::hardware::contexthub::BnContextHubCallback {
200 public:
201 Status handleNanoappInfo(const std::vector<NanoappInfo>& /* appInfo */) override {
202 return Status::ok();
203 }
204
205 Status handleContextHubMessage(const ContextHubMessage& /* msg */,
206 const std::vector<String16>& /* msgContentPerms */) override {
207 return Status::ok();
208 }
209
210 Status handleContextHubAsyncEvent(AsyncEventType /* evt */) override { return Status::ok(); }
211
212 Status handleTransactionResult(int32_t transactionId, bool success) override {
213 ALOGD("Got transaction result callback for transactionId %" PRIu32 " (expecting %" PRIu32
214 ") with success %d",
215 transactionId, expectedTransactionId, success);
216 if (transactionId == expectedTransactionId) {
217 promise.set_value(success);
218 }
219 return Status::ok();
220 }
221
Anthony Stange7fba1002023-03-02 21:45:20 +0000222 Status handleNanSessionRequest(const NanSessionRequest& /* request */) override {
223 return Status::ok();
224 }
Anthony Stange7344af92022-12-22 14:21:31 +0000225
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700226 uint32_t expectedTransactionId = 0;
227 std::promise<bool> promise;
228};
229
230// Parameterized fixture that sets the callback to TransactionResultCallback
231class ContextHubTransactionTest : public ContextHubAidl {
232 public:
233 virtual void SetUp() override {
234 ContextHubAidl::SetUp();
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000235 ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb).isOk());
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700236 }
237
238 sp<TransactionResultCallback> cb = sp<TransactionResultCallback>::make();
239};
240
241TEST_P(ContextHubTransactionTest, TestSendMessageToNonExistentNanoapp) {
242 ContextHubMessage message;
243 message.nanoappId = kNonExistentAppId;
244 message.messageType = 1;
245 message.messageBody.resize(4);
246 std::fill(message.messageBody.begin(), message.messageBody.end(), 0);
247
248 ALOGD("Sending message to non-existent nanoapp");
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000249 ASSERT_TRUE(contextHub->sendMessageToHub(getHubId(), message).isOk());
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700250}
251
252TEST_P(ContextHubTransactionTest, TestLoadEmptyNanoapp) {
253 cb->expectedTransactionId = 0123;
254 NanoappBinary emptyApp;
255
256 emptyApp.nanoappId = kNonExistentAppId;
257 emptyApp.nanoappVersion = 1;
258 emptyApp.flags = 0;
259 emptyApp.targetChreApiMajorVersion = 1;
260 emptyApp.targetChreApiMinorVersion = 0;
261
262 ALOGD("Loading empty nanoapp");
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000263 bool success = contextHub->loadNanoapp(getHubId(), emptyApp, cb->expectedTransactionId).isOk();
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700264 if (success) {
265 bool transactionSuccess;
266 ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
267 ASSERT_FALSE(transactionSuccess);
268 }
269}
270
271TEST_P(ContextHubTransactionTest, TestUnloadNonexistentNanoapp) {
272 cb->expectedTransactionId = 1234;
273
274 ALOGD("Unloading nonexistent nanoapp");
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000275 bool success =
276 contextHub->unloadNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId)
277 .isOk();
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700278 if (success) {
279 bool transactionSuccess;
280 ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
281 ASSERT_FALSE(transactionSuccess);
282 }
283}
284
285TEST_P(ContextHubTransactionTest, TestEnableNonexistentNanoapp) {
286 cb->expectedTransactionId = 2345;
287
288 ALOGD("Enabling nonexistent nanoapp");
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000289 bool success =
290 contextHub->enableNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId)
291 .isOk();
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700292 if (success) {
293 bool transactionSuccess;
294 ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
295 ASSERT_FALSE(transactionSuccess);
296 }
297}
298
299TEST_P(ContextHubTransactionTest, TestDisableNonexistentNanoapp) {
300 cb->expectedTransactionId = 3456;
301
302 ALOGD("Disabling nonexistent nanoapp");
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000303 bool success =
304 contextHub->disableNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId)
305 .isOk();
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700306 if (success) {
307 bool transactionSuccess;
308 ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
309 ASSERT_FALSE(transactionSuccess);
310 }
311}
312
313void ContextHubAidl::testSettingChanged(Setting setting) {
314 // In VTS, we only test that sending the values doesn't cause things to blow up - GTS tests
315 // verify the expected E2E behavior in CHRE
Arthur Ishiguroe6b540d2021-10-29 16:01:35 +0000316 sp<EmptyContextHubCallback> cb = sp<EmptyContextHubCallback>::make();
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000317 ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb).isOk());
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700318
319 ASSERT_TRUE(contextHub->onSettingChanged(setting, true /* enabled */).isOk());
320 ASSERT_TRUE(contextHub->onSettingChanged(setting, false /* enabled */).isOk());
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700321}
322
323TEST_P(ContextHubAidl, TestOnLocationSettingChanged) {
324 testSettingChanged(Setting::LOCATION);
325}
326
327TEST_P(ContextHubAidl, TestOnWifiMainSettingChanged) {
328 testSettingChanged(Setting::WIFI_MAIN);
329}
330
331TEST_P(ContextHubAidl, TestOnWifiScanningSettingChanged) {
332 testSettingChanged(Setting::WIFI_SCANNING);
333}
334
335TEST_P(ContextHubAidl, TestOnAirplaneModeSettingChanged) {
336 testSettingChanged(Setting::AIRPLANE_MODE);
337}
338
339TEST_P(ContextHubAidl, TestOnMicrophoneSettingChanged) {
340 testSettingChanged(Setting::MICROPHONE);
341}
342
Anthonya6b65002022-01-20 20:49:10 +0000343TEST_P(ContextHubAidl, TestOnBtMainSettingChanged) {
344 testSettingChanged(Setting::BT_MAIN);
345}
346
347TEST_P(ContextHubAidl, TestOnBtScanningSettingChanged) {
348 testSettingChanged(Setting::BT_SCANNING);
349}
350
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700351std::vector<std::tuple<std::string, int32_t>> generateContextHubMapping() {
352 std::vector<std::tuple<std::string, int32_t>> tuples;
353 auto contextHubAidlNames = android::getAidlHalInstanceNames(IContextHub::descriptor);
354 std::vector<ContextHubInfo> contextHubInfos;
355
356 for (int i = 0; i < contextHubAidlNames.size(); i++) {
357 auto contextHubName = contextHubAidlNames[i].c_str();
358 auto contextHub = android::waitForDeclaredService<IContextHub>(String16(contextHubName));
359 if (contextHub->getContextHubs(&contextHubInfos).isOk()) {
360 for (auto& info : contextHubInfos) {
361 tuples.push_back(std::make_tuple(contextHubName, info.id));
362 }
363 }
364 }
365
366 return tuples;
367}
368
Arthur Ishiguro065a9a52021-11-19 00:24:45 +0000369TEST_P(ContextHubAidl, TestHostConnection) {
370 constexpr char16_t kHostEndpointId = 1;
371 HostEndpointInfo hostEndpointInfo;
Arthur Ishiguro16f40622023-02-10 18:11:12 +0000372 hostEndpointInfo.type = HostEndpointInfo::Type::NATIVE;
Arthur Ishiguro065a9a52021-11-19 00:24:45 +0000373 hostEndpointInfo.hostEndpointId = kHostEndpointId;
374
375 ASSERT_TRUE(contextHub->onHostEndpointConnected(hostEndpointInfo).isOk());
376 ASSERT_TRUE(contextHub->onHostEndpointDisconnected(kHostEndpointId).isOk());
377}
378
379TEST_P(ContextHubAidl, TestInvalidHostConnection) {
380 constexpr char16_t kHostEndpointId = 1;
381
Arthur Ishiguro5dba9212022-02-01 17:03:32 +0000382 ASSERT_TRUE(contextHub->onHostEndpointDisconnected(kHostEndpointId).isOk());
Arthur Ishiguro065a9a52021-11-19 00:24:45 +0000383}
384
Anthony Stange7344af92022-12-22 14:21:31 +0000385TEST_P(ContextHubAidl, TestNanSessionStateChange) {
Anthony Stange7fba1002023-03-02 21:45:20 +0000386 NanSessionStateUpdate update;
387 update.state = true;
Rocky Fang78140982023-06-16 00:42:41 +0000388 Status status = contextHub->onNanSessionStateChanged(update);
389 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
390 status.transactionError() == android::UNKNOWN_TRANSACTION) {
391 GTEST_SKIP() << "Not supported -> old API; or not implemented";
392 } else {
393 ASSERT_TRUE(status.isOk());
394 update.state = false;
395 ASSERT_TRUE(contextHub->onNanSessionStateChanged(update).isOk());
396 }
Anthony Stange7344af92022-12-22 14:21:31 +0000397}
398
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700399std::string PrintGeneratedTest(const testing::TestParamInfo<ContextHubAidl::ParamType>& info) {
400 return std::string("CONTEXT_HUB_ID_") + std::to_string(std::get<1>(info.param));
401}
402
403GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContextHubAidl);
404INSTANTIATE_TEST_SUITE_P(ContextHub, ContextHubAidl, testing::ValuesIn(generateContextHubMapping()),
405 PrintGeneratedTest);
406
407GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContextHubTransactionTest);
408INSTANTIATE_TEST_SUITE_P(ContextHub, ContextHubTransactionTest,
409 testing::ValuesIn(generateContextHubMapping()), PrintGeneratedTest);
410
411int main(int argc, char** argv) {
412 ::testing::InitGoogleTest(&argc, argv);
413 ProcessState::self()->setThreadPoolMaxThreadCount(1);
414 ProcessState::self()->startThreadPool();
415 return RUN_ALL_TESTS();
416}