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