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