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