blob: 1b2dc2929061de29ea6567ff40f4c4d235399461 [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;
44using ::android::hardware::contexthub::Setting;
45using ::android::hardware::contexthub::vts_utils::kNonExistentAppId;
46using ::android::hardware::contexthub::vts_utils::waitForCallback;
47
48class ContextHubAidl : public testing::TestWithParam<std::tuple<std::string, int32_t>> {
49 public:
50 virtual void SetUp() override {
51 contextHub = android::waitForDeclaredService<IContextHub>(
52 String16(std::get<0>(GetParam()).c_str()));
53 ASSERT_NE(contextHub, nullptr);
54 }
55
56 uint32_t getHubId() { return std::get<1>(GetParam()); }
57
58 void testSettingChanged(Setting setting);
59
60 sp<IContextHub> contextHub;
61};
62
63TEST_P(ContextHubAidl, TestGetHubs) {
64 std::vector<ContextHubInfo> hubs;
65 ASSERT_TRUE(contextHub->getContextHubs(&hubs).isOk());
66
67 ALOGD("System reports %zu hubs", hubs.size());
68
69 for (const ContextHubInfo& hub : hubs) {
70 ALOGD("Checking hub ID %" PRIu32, hub.id);
71
72 EXPECT_GT(hub.name.size(), 0);
73 EXPECT_GT(hub.vendor.size(), 0);
74 EXPECT_GT(hub.toolchain.size(), 0);
75 EXPECT_GT(hub.peakMips, 0);
76 EXPECT_GT(hub.chrePlatformId, 0);
77 EXPECT_GT(hub.chreApiMajorVersion, 0);
Arthur Ishiguro6471f612021-10-28 21:59:55 +000078 EXPECT_GE(hub.chreApiMinorVersion, 0);
79 EXPECT_GE(hub.chrePatchVersion, 0);
Arthur Ishiguro4e916c32021-08-12 12:47:03 -070080
81 // Minimum 128 byte MTU as required by CHRE API v1.0
82 EXPECT_GE(hub.maxSupportedMessageLengthBytes, UINT32_C(128));
83 }
84}
85
Arthur Ishiguroe6b540d2021-10-29 16:01:35 +000086class EmptyContextHubCallback : public android::hardware::contexthub::BnContextHubCallback {
87 public:
88 Status handleNanoappInfo(const std::vector<NanoappInfo>& /* appInfo */) override {
89 return Status::ok();
90 }
91
92 Status handleContextHubMessage(const ContextHubMessage& /* msg */,
93 const std::vector<String16>& /* msgContentPerms */) override {
94 return Status::ok();
95 }
96
97 Status handleContextHubAsyncEvent(AsyncEventType /* evt */) override { return Status::ok(); }
98
99 Status handleTransactionResult(int32_t /* transactionId */, bool /* success */) override {
100 return Status::ok();
101 }
102};
103
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700104TEST_P(ContextHubAidl, TestRegisterCallback) {
105 bool success;
Arthur Ishiguroe6b540d2021-10-29 16:01:35 +0000106 sp<EmptyContextHubCallback> cb = sp<EmptyContextHubCallback>::make();
107 ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb, &success).isOk());
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700108 ASSERT_TRUE(success);
109}
110
111TEST_P(ContextHubAidl, TestRegisterNullCallback) {
112 bool success;
113 ASSERT_TRUE(contextHub->registerCallback(getHubId(), nullptr, &success).isOk());
114}
115
116// Helper callback that puts the async appInfo callback data into a promise
117class QueryAppsCallback : public android::hardware::contexthub::BnContextHubCallback {
118 public:
119 Status handleNanoappInfo(const std::vector<NanoappInfo>& appInfo) override {
120 ALOGD("Got app info callback with %zu apps", appInfo.size());
121 promise.set_value(appInfo);
122 return Status::ok();
123 }
124
125 Status handleContextHubMessage(const ContextHubMessage& /* msg */,
126 const std::vector<String16>& /* msgContentPerms */) override {
127 return Status::ok();
128 }
129
130 Status handleContextHubAsyncEvent(AsyncEventType /* evt */) override { return Status::ok(); }
131
132 Status handleTransactionResult(int32_t /* transactionId */, bool /* success */) override {
133 return Status::ok();
134 }
135
136 std::promise<std::vector<NanoappInfo>> promise;
137};
138
139// Calls queryApps() and checks the returned metadata
140TEST_P(ContextHubAidl, TestQueryApps) {
141 sp<QueryAppsCallback> cb = sp<QueryAppsCallback>::make();
142 bool success;
143 ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb, &success).isOk());
144 ASSERT_TRUE(success);
145
146 ASSERT_TRUE(contextHub->queryNanoapps(getHubId(), &success).isOk());
147 ASSERT_TRUE(success);
148
149 std::vector<NanoappInfo> appInfoList;
150 ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &appInfoList));
151 for (const NanoappInfo& appInfo : appInfoList) {
152 EXPECT_NE(appInfo.nanoappId, UINT64_C(0));
153 EXPECT_NE(appInfo.nanoappId, kNonExistentAppId);
154 }
155}
156
157// Helper callback that puts the TransactionResult for the expectedTransactionId into a
158// promise
159class TransactionResultCallback : public android::hardware::contexthub::BnContextHubCallback {
160 public:
161 Status handleNanoappInfo(const std::vector<NanoappInfo>& /* appInfo */) override {
162 return Status::ok();
163 }
164
165 Status handleContextHubMessage(const ContextHubMessage& /* msg */,
166 const std::vector<String16>& /* msgContentPerms */) override {
167 return Status::ok();
168 }
169
170 Status handleContextHubAsyncEvent(AsyncEventType /* evt */) override { return Status::ok(); }
171
172 Status handleTransactionResult(int32_t transactionId, bool success) override {
173 ALOGD("Got transaction result callback for transactionId %" PRIu32 " (expecting %" PRIu32
174 ") with success %d",
175 transactionId, expectedTransactionId, success);
176 if (transactionId == expectedTransactionId) {
177 promise.set_value(success);
178 }
179 return Status::ok();
180 }
181
182 uint32_t expectedTransactionId = 0;
183 std::promise<bool> promise;
184};
185
186// Parameterized fixture that sets the callback to TransactionResultCallback
187class ContextHubTransactionTest : public ContextHubAidl {
188 public:
189 virtual void SetUp() override {
190 ContextHubAidl::SetUp();
191 bool success;
192 ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb, &success).isOk());
193 ASSERT_TRUE(success);
194 }
195
196 sp<TransactionResultCallback> cb = sp<TransactionResultCallback>::make();
197};
198
199TEST_P(ContextHubTransactionTest, TestSendMessageToNonExistentNanoapp) {
200 ContextHubMessage message;
201 message.nanoappId = kNonExistentAppId;
202 message.messageType = 1;
203 message.messageBody.resize(4);
204 std::fill(message.messageBody.begin(), message.messageBody.end(), 0);
205
206 ALOGD("Sending message to non-existent nanoapp");
207 bool success;
208 ASSERT_TRUE(contextHub->sendMessageToHub(getHubId(), message, &success).isOk());
209 ASSERT_TRUE(success);
210}
211
212TEST_P(ContextHubTransactionTest, TestLoadEmptyNanoapp) {
213 cb->expectedTransactionId = 0123;
214 NanoappBinary emptyApp;
215
216 emptyApp.nanoappId = kNonExistentAppId;
217 emptyApp.nanoappVersion = 1;
218 emptyApp.flags = 0;
219 emptyApp.targetChreApiMajorVersion = 1;
220 emptyApp.targetChreApiMinorVersion = 0;
221
222 ALOGD("Loading empty nanoapp");
223 bool success;
224 ASSERT_TRUE(contextHub->loadNanoapp(getHubId(), emptyApp, cb->expectedTransactionId, &success)
225 .isOk());
226 if (success) {
227 bool transactionSuccess;
228 ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
229 ASSERT_FALSE(transactionSuccess);
230 }
231}
232
233TEST_P(ContextHubTransactionTest, TestUnloadNonexistentNanoapp) {
234 cb->expectedTransactionId = 1234;
235
236 ALOGD("Unloading nonexistent nanoapp");
237 bool success;
238 ASSERT_TRUE(contextHub
239 ->unloadNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId,
240 &success)
241 .isOk());
242 if (success) {
243 bool transactionSuccess;
244 ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
245 ASSERT_FALSE(transactionSuccess);
246 }
247}
248
249TEST_P(ContextHubTransactionTest, TestEnableNonexistentNanoapp) {
250 cb->expectedTransactionId = 2345;
251
252 ALOGD("Enabling nonexistent nanoapp");
253 bool success;
254 ASSERT_TRUE(contextHub
255 ->enableNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId,
256 &success)
257 .isOk());
258 if (success) {
259 bool transactionSuccess;
260 ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
261 ASSERT_FALSE(transactionSuccess);
262 }
263}
264
265TEST_P(ContextHubTransactionTest, TestDisableNonexistentNanoapp) {
266 cb->expectedTransactionId = 3456;
267
268 ALOGD("Disabling nonexistent nanoapp");
269 bool success;
270 ASSERT_TRUE(contextHub
271 ->disableNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId,
272 &success)
273 .isOk());
274 if (success) {
275 bool transactionSuccess;
276 ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
277 ASSERT_FALSE(transactionSuccess);
278 }
279}
280
281void ContextHubAidl::testSettingChanged(Setting setting) {
282 // In VTS, we only test that sending the values doesn't cause things to blow up - GTS tests
283 // verify the expected E2E behavior in CHRE
284 bool success;
Arthur Ishiguroe6b540d2021-10-29 16:01:35 +0000285 sp<EmptyContextHubCallback> cb = sp<EmptyContextHubCallback>::make();
286 ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb, &success).isOk());
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700287 ASSERT_TRUE(success);
288
289 ASSERT_TRUE(contextHub->onSettingChanged(setting, true /* enabled */).isOk());
290 ASSERT_TRUE(contextHub->onSettingChanged(setting, false /* enabled */).isOk());
291
292 ASSERT_TRUE(contextHub->registerCallback(getHubId(), nullptr, &success).isOk());
293 ASSERT_TRUE(success);
294}
295
296TEST_P(ContextHubAidl, TestOnLocationSettingChanged) {
297 testSettingChanged(Setting::LOCATION);
298}
299
300TEST_P(ContextHubAidl, TestOnWifiMainSettingChanged) {
301 testSettingChanged(Setting::WIFI_MAIN);
302}
303
304TEST_P(ContextHubAidl, TestOnWifiScanningSettingChanged) {
305 testSettingChanged(Setting::WIFI_SCANNING);
306}
307
308TEST_P(ContextHubAidl, TestOnAirplaneModeSettingChanged) {
309 testSettingChanged(Setting::AIRPLANE_MODE);
310}
311
312TEST_P(ContextHubAidl, TestOnMicrophoneSettingChanged) {
313 testSettingChanged(Setting::MICROPHONE);
314}
315
316std::vector<std::tuple<std::string, int32_t>> generateContextHubMapping() {
317 std::vector<std::tuple<std::string, int32_t>> tuples;
318 auto contextHubAidlNames = android::getAidlHalInstanceNames(IContextHub::descriptor);
319 std::vector<ContextHubInfo> contextHubInfos;
320
321 for (int i = 0; i < contextHubAidlNames.size(); i++) {
322 auto contextHubName = contextHubAidlNames[i].c_str();
323 auto contextHub = android::waitForDeclaredService<IContextHub>(String16(contextHubName));
324 if (contextHub->getContextHubs(&contextHubInfos).isOk()) {
325 for (auto& info : contextHubInfos) {
326 tuples.push_back(std::make_tuple(contextHubName, info.id));
327 }
328 }
329 }
330
331 return tuples;
332}
333
Arthur Ishiguro065a9a52021-11-19 00:24:45 +0000334TEST_P(ContextHubAidl, TestHostConnection) {
335 constexpr char16_t kHostEndpointId = 1;
336 HostEndpointInfo hostEndpointInfo;
337 hostEndpointInfo.hostEndpointId = kHostEndpointId;
338
339 ASSERT_TRUE(contextHub->onHostEndpointConnected(hostEndpointInfo).isOk());
340 ASSERT_TRUE(contextHub->onHostEndpointDisconnected(kHostEndpointId).isOk());
341}
342
343TEST_P(ContextHubAidl, TestInvalidHostConnection) {
344 constexpr char16_t kHostEndpointId = 1;
345
346 Status status = contextHub->onHostEndpointDisconnected(kHostEndpointId);
347 ASSERT_EQ(status.exceptionCode(), android::binder::Status::EX_ILLEGAL_ARGUMENT);
348}
349
Arthur Ishiguro4e916c32021-08-12 12:47:03 -0700350std::string PrintGeneratedTest(const testing::TestParamInfo<ContextHubAidl::ParamType>& info) {
351 return std::string("CONTEXT_HUB_ID_") + std::to_string(std::get<1>(info.param));
352}
353
354GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContextHubAidl);
355INSTANTIATE_TEST_SUITE_P(ContextHub, ContextHubAidl, testing::ValuesIn(generateContextHubMapping()),
356 PrintGeneratedTest);
357
358GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContextHubTransactionTest);
359INSTANTIATE_TEST_SUITE_P(ContextHub, ContextHubTransactionTest,
360 testing::ValuesIn(generateContextHubMapping()), PrintGeneratedTest);
361
362int main(int argc, char** argv) {
363 ::testing::InitGoogleTest(&argc, argv);
364 ProcessState::self()->setThreadPoolMaxThreadCount(1);
365 ProcessState::self()->startThreadPool();
366 return RUN_ALL_TESTS();
367}