blob: f7ff73d477ff6afc977e2e7465c27cb754461c63 [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;
Arthur Ishiguro4e916c32021-08-12 12:47:03 -070045using ::android::hardware::contexthub::Setting;
46using ::android::hardware::contexthub::vts_utils::kNonExistentAppId;
47using ::android::hardware::contexthub::vts_utils::waitForCallback;
48
49class ContextHubAidl : public testing::TestWithParam<std::tuple<std::string, int32_t>> {
50 public:
51 virtual void SetUp() override {
52 contextHub = android::waitForDeclaredService<IContextHub>(
53 String16(std::get<0>(GetParam()).c_str()));
54 ASSERT_NE(contextHub, nullptr);
55 }
56
57 uint32_t getHubId() { return std::get<1>(GetParam()); }
58
59 void testSettingChanged(Setting setting);
60
61 sp<IContextHub> contextHub;
62};
63
64TEST_P(ContextHubAidl, TestGetHubs) {
65 std::vector<ContextHubInfo> hubs;
66 ASSERT_TRUE(contextHub->getContextHubs(&hubs).isOk());
67
68 ALOGD("System reports %zu hubs", hubs.size());
69
70 for (const ContextHubInfo& hub : hubs) {
71 ALOGD("Checking hub ID %" PRIu32, hub.id);
72
73 EXPECT_GT(hub.name.size(), 0);
74 EXPECT_GT(hub.vendor.size(), 0);
75 EXPECT_GT(hub.toolchain.size(), 0);
76 EXPECT_GT(hub.peakMips, 0);
77 EXPECT_GT(hub.chrePlatformId, 0);
78 EXPECT_GT(hub.chreApiMajorVersion, 0);
Arthur Ishiguro6471f612021-10-28 21:59:55 +000079 EXPECT_GE(hub.chreApiMinorVersion, 0);
80 EXPECT_GE(hub.chrePatchVersion, 0);
Arthur Ishiguro4e916c32021-08-12 12:47:03 -070081
82 // Minimum 128 byte MTU as required by CHRE API v1.0
83 EXPECT_GE(hub.maxSupportedMessageLengthBytes, UINT32_C(128));
84 }
85}
86
Matthew Sedamc8ce4d52023-01-09 20:18:21 +000087TEST_P(ContextHubAidl, TestEnableTestMode) {
88 Status status = contextHub->setTestMode(true);
89 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
90 status.transactionError() == android::UNKNOWN_TRANSACTION) {
91 return; // not supported -> old API; or not implemented
92 }
93
94 ASSERT_TRUE(status.isOk());
95}
96
97TEST_P(ContextHubAidl, TestDisableTestMode) {
98 Status status = contextHub->setTestMode(false);
99 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
100 status.transactionError() == android::UNKNOWN_TRANSACTION) {
101 return; // not supported -> old API; or not implemented
102 }
103
104 ASSERT_TRUE(status.isOk());
105}
106
Arthur Ishiguroe6b540d2021-10-29 16:01:35 +0000107class EmptyContextHubCallback : public android::hardware::contexthub::BnContextHubCallback {
108 public:
109 Status handleNanoappInfo(const std::vector<NanoappInfo>& /* appInfo */) override {
110 return Status::ok();
111 }
112
113 Status handleContextHubMessage(const ContextHubMessage& /* msg */,
114 const std::vector<String16>& /* msgContentPerms */) override {
115 return Status::ok();
116 }
117
118 Status handleContextHubAsyncEvent(AsyncEventType /* evt */) override { return Status::ok(); }
119
120 Status handleTransactionResult(int32_t /* transactionId */, bool /* success */) override {
121 return Status::ok();
122 }
Anthony Stange7344af92022-12-22 14:21:31 +0000123
124 Status handleNanSessionRequest(bool /* enable */) override { return Status::ok(); }
Arthur Ishiguroe6b540d2021-10-29 16:01:35 +0000125};
126
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700127TEST_P(ContextHubAidl, TestRegisterCallback) {
Arthur Ishiguroe6b540d2021-10-29 16:01:35 +0000128 sp<EmptyContextHubCallback> cb = sp<EmptyContextHubCallback>::make();
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000129 ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb).isOk());
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700130}
131
132TEST_P(ContextHubAidl, TestRegisterNullCallback) {
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000133 ASSERT_TRUE(contextHub->registerCallback(getHubId(), nullptr).isOk());
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700134}
135
136// 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 Stange7344af92022-12-22 14:21:31 +0000156 Status handleNanSessionRequest(bool /* enable */) override { return Status::ok(); }
157
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700158 std::promise<std::vector<NanoappInfo>> promise;
159};
160
161// Calls queryApps() and checks the returned metadata
162TEST_P(ContextHubAidl, TestQueryApps) {
163 sp<QueryAppsCallback> cb = sp<QueryAppsCallback>::make();
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000164 ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb).isOk());
165 ASSERT_TRUE(contextHub->queryNanoapps(getHubId()).isOk());
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700166
167 std::vector<NanoappInfo> appInfoList;
168 ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &appInfoList));
169 for (const NanoappInfo& appInfo : appInfoList) {
170 EXPECT_NE(appInfo.nanoappId, UINT64_C(0));
171 EXPECT_NE(appInfo.nanoappId, kNonExistentAppId);
Arthur Ishiguro08103072021-12-09 18:30:49 +0000172
173 // Verify services are unique.
174 std::set<uint64_t> existingServiceIds;
175 for (const NanoappRpcService& rpcService : appInfo.rpcServices) {
176 EXPECT_NE(rpcService.id, UINT64_C(0));
177 EXPECT_EQ(existingServiceIds.count(rpcService.id), 0);
178 existingServiceIds.insert(rpcService.id);
179 }
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700180 }
181}
182
Arthur Ishigurofd5e65c2022-11-08 16:49:47 +0000183// Calls getPreloadedNanoapps() and verifies there are preloaded nanoapps
184TEST_P(ContextHubAidl, TestGetPreloadedNanoapps) {
185 std::vector<int64_t> preloadedNanoappIds;
186 Status status = contextHub->getPreloadedNanoappIds(&preloadedNanoappIds);
187 if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
188 status.transactionError() == android::UNKNOWN_TRANSACTION) {
189 return; // not supported -> old API; or not implemented
190 }
191
192 ASSERT_TRUE(status.isOk());
193 ASSERT_FALSE(preloadedNanoappIds.empty());
194}
195
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700196// Helper callback that puts the TransactionResult for the expectedTransactionId into a
197// promise
198class TransactionResultCallback : public android::hardware::contexthub::BnContextHubCallback {
199 public:
200 Status handleNanoappInfo(const std::vector<NanoappInfo>& /* appInfo */) override {
201 return Status::ok();
202 }
203
204 Status handleContextHubMessage(const ContextHubMessage& /* msg */,
205 const std::vector<String16>& /* msgContentPerms */) override {
206 return Status::ok();
207 }
208
209 Status handleContextHubAsyncEvent(AsyncEventType /* evt */) override { return Status::ok(); }
210
211 Status handleTransactionResult(int32_t transactionId, bool success) override {
212 ALOGD("Got transaction result callback for transactionId %" PRIu32 " (expecting %" PRIu32
213 ") with success %d",
214 transactionId, expectedTransactionId, success);
215 if (transactionId == expectedTransactionId) {
216 promise.set_value(success);
217 }
218 return Status::ok();
219 }
220
Anthony Stange7344af92022-12-22 14:21:31 +0000221 Status handleNanSessionRequest(bool /* enable */) override { return Status::ok(); }
222
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700223 uint32_t expectedTransactionId = 0;
224 std::promise<bool> promise;
225};
226
227// Parameterized fixture that sets the callback to TransactionResultCallback
228class ContextHubTransactionTest : public ContextHubAidl {
229 public:
230 virtual void SetUp() override {
231 ContextHubAidl::SetUp();
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000232 ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb).isOk());
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700233 }
234
235 sp<TransactionResultCallback> cb = sp<TransactionResultCallback>::make();
236};
237
238TEST_P(ContextHubTransactionTest, TestSendMessageToNonExistentNanoapp) {
239 ContextHubMessage message;
240 message.nanoappId = kNonExistentAppId;
241 message.messageType = 1;
242 message.messageBody.resize(4);
243 std::fill(message.messageBody.begin(), message.messageBody.end(), 0);
244
245 ALOGD("Sending message to non-existent nanoapp");
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000246 ASSERT_TRUE(contextHub->sendMessageToHub(getHubId(), message).isOk());
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700247}
248
249TEST_P(ContextHubTransactionTest, TestLoadEmptyNanoapp) {
250 cb->expectedTransactionId = 0123;
251 NanoappBinary emptyApp;
252
253 emptyApp.nanoappId = kNonExistentAppId;
254 emptyApp.nanoappVersion = 1;
255 emptyApp.flags = 0;
256 emptyApp.targetChreApiMajorVersion = 1;
257 emptyApp.targetChreApiMinorVersion = 0;
258
259 ALOGD("Loading empty nanoapp");
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000260 bool success = contextHub->loadNanoapp(getHubId(), emptyApp, cb->expectedTransactionId).isOk();
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700261 if (success) {
262 bool transactionSuccess;
263 ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
264 ASSERT_FALSE(transactionSuccess);
265 }
266}
267
268TEST_P(ContextHubTransactionTest, TestUnloadNonexistentNanoapp) {
269 cb->expectedTransactionId = 1234;
270
271 ALOGD("Unloading nonexistent nanoapp");
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000272 bool success =
273 contextHub->unloadNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId)
274 .isOk();
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700275 if (success) {
276 bool transactionSuccess;
277 ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
278 ASSERT_FALSE(transactionSuccess);
279 }
280}
281
282TEST_P(ContextHubTransactionTest, TestEnableNonexistentNanoapp) {
283 cb->expectedTransactionId = 2345;
284
285 ALOGD("Enabling nonexistent nanoapp");
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000286 bool success =
287 contextHub->enableNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId)
288 .isOk();
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700289 if (success) {
290 bool transactionSuccess;
291 ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
292 ASSERT_FALSE(transactionSuccess);
293 }
294}
295
296TEST_P(ContextHubTransactionTest, TestDisableNonexistentNanoapp) {
297 cb->expectedTransactionId = 3456;
298
299 ALOGD("Disabling nonexistent nanoapp");
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000300 bool success =
301 contextHub->disableNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId)
302 .isOk();
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700303 if (success) {
304 bool transactionSuccess;
305 ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
306 ASSERT_FALSE(transactionSuccess);
307 }
308}
309
310void ContextHubAidl::testSettingChanged(Setting setting) {
311 // In VTS, we only test that sending the values doesn't cause things to blow up - GTS tests
312 // verify the expected E2E behavior in CHRE
Arthur Ishiguroe6b540d2021-10-29 16:01:35 +0000313 sp<EmptyContextHubCallback> cb = sp<EmptyContextHubCallback>::make();
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000314 ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb).isOk());
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700315
316 ASSERT_TRUE(contextHub->onSettingChanged(setting, true /* enabled */).isOk());
317 ASSERT_TRUE(contextHub->onSettingChanged(setting, false /* enabled */).isOk());
318
Arthur Ishiguro070f47d2022-01-06 22:42:10 +0000319 ASSERT_TRUE(contextHub->registerCallback(getHubId(), nullptr).isOk());
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700320}
321
322TEST_P(ContextHubAidl, TestOnLocationSettingChanged) {
323 testSettingChanged(Setting::LOCATION);
324}
325
326TEST_P(ContextHubAidl, TestOnWifiMainSettingChanged) {
327 testSettingChanged(Setting::WIFI_MAIN);
328}
329
330TEST_P(ContextHubAidl, TestOnWifiScanningSettingChanged) {
331 testSettingChanged(Setting::WIFI_SCANNING);
332}
333
334TEST_P(ContextHubAidl, TestOnAirplaneModeSettingChanged) {
335 testSettingChanged(Setting::AIRPLANE_MODE);
336}
337
338TEST_P(ContextHubAidl, TestOnMicrophoneSettingChanged) {
339 testSettingChanged(Setting::MICROPHONE);
340}
341
Anthonya6b65002022-01-20 20:49:10 +0000342TEST_P(ContextHubAidl, TestOnBtMainSettingChanged) {
343 testSettingChanged(Setting::BT_MAIN);
344}
345
346TEST_P(ContextHubAidl, TestOnBtScanningSettingChanged) {
347 testSettingChanged(Setting::BT_SCANNING);
348}
349
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700350std::vector<std::tuple<std::string, int32_t>> generateContextHubMapping() {
351 std::vector<std::tuple<std::string, int32_t>> tuples;
352 auto contextHubAidlNames = android::getAidlHalInstanceNames(IContextHub::descriptor);
353 std::vector<ContextHubInfo> contextHubInfos;
354
355 for (int i = 0; i < contextHubAidlNames.size(); i++) {
356 auto contextHubName = contextHubAidlNames[i].c_str();
357 auto contextHub = android::waitForDeclaredService<IContextHub>(String16(contextHubName));
358 if (contextHub->getContextHubs(&contextHubInfos).isOk()) {
359 for (auto& info : contextHubInfos) {
360 tuples.push_back(std::make_tuple(contextHubName, info.id));
361 }
362 }
363 }
364
365 return tuples;
366}
367
Arthur Ishiguro065a9a52021-11-19 00:24:45 +0000368TEST_P(ContextHubAidl, TestHostConnection) {
369 constexpr char16_t kHostEndpointId = 1;
370 HostEndpointInfo hostEndpointInfo;
371 hostEndpointInfo.hostEndpointId = kHostEndpointId;
372
373 ASSERT_TRUE(contextHub->onHostEndpointConnected(hostEndpointInfo).isOk());
374 ASSERT_TRUE(contextHub->onHostEndpointDisconnected(kHostEndpointId).isOk());
375}
376
377TEST_P(ContextHubAidl, TestInvalidHostConnection) {
378 constexpr char16_t kHostEndpointId = 1;
379
Arthur Ishiguro5dba9212022-02-01 17:03:32 +0000380 ASSERT_TRUE(contextHub->onHostEndpointDisconnected(kHostEndpointId).isOk());
Arthur Ishiguro065a9a52021-11-19 00:24:45 +0000381}
382
Anthony Stange7344af92022-12-22 14:21:31 +0000383TEST_P(ContextHubAidl, TestNanSessionStateChange) {
384 ASSERT_TRUE(contextHub->onNanSessionStateChanged(true /*state*/).isOk());
385 ASSERT_TRUE(contextHub->onNanSessionStateChanged(false /*state*/).isOk());
386}
387
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700388std::string PrintGeneratedTest(const testing::TestParamInfo<ContextHubAidl::ParamType>& info) {
389 return std::string("CONTEXT_HUB_ID_") + std::to_string(std::get<1>(info.param));
390}
391
392GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContextHubAidl);
393INSTANTIATE_TEST_SUITE_P(ContextHub, ContextHubAidl, testing::ValuesIn(generateContextHubMapping()),
394 PrintGeneratedTest);
395
396GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContextHubTransactionTest);
397INSTANTIATE_TEST_SUITE_P(ContextHub, ContextHubTransactionTest,
398 testing::ValuesIn(generateContextHubMapping()), PrintGeneratedTest);
399
400int main(int argc, char** argv) {
401 ::testing::InitGoogleTest(&argc, argv);
402 ProcessState::self()->setThreadPoolMaxThreadCount(1);
403 ProcessState::self()->startThreadPool();
404 return RUN_ALL_TESTS();
405}