• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 "chre_host/hal_client.h"
17 #include "chre_host/hal_error.h"
18 
19 #include <unordered_set>
20 
21 #include "gmock/gmock.h"
22 #include "gtest/gtest.h"
23 
24 #include <aidl/android/hardware/contexthub/IContextHub.h>
25 
26 namespace android::chre {
27 
28 namespace {
29 using ::aidl::android::hardware::contexthub::ContextHubMessage;
30 using ::aidl::android::hardware::contexthub::HostEndpointInfo;
31 using ::aidl::android::hardware::contexthub::IContextHub;
32 using ::aidl::android::hardware::contexthub::IContextHubCallbackDefault;
33 using ::aidl::android::hardware::contexthub::IContextHubDefault;
34 
35 using ::ndk::ScopedAStatus;
36 
37 using ::testing::_;
38 using ::testing::ByMove;
39 using ::testing::Field;
40 using ::testing::IsEmpty;
41 using ::testing::Return;
42 using ::testing::UnorderedElementsAre;
43 
44 using HostEndpointId = char16_t;
45 constexpr HostEndpointId kEndpointId = 0x10;
46 
47 class HalClientForTest : public HalClient {
48  public:
HalClientForTest(const std::shared_ptr<IContextHub> & contextHub,const std::vector<HostEndpointId> & connectedEndpoints,const std::shared_ptr<IContextHubCallback> & callback=ndk::SharedRefBase::make<IContextHubCallbackDefault> ())49   HalClientForTest(const std::shared_ptr<IContextHub> &contextHub,
50                    const std::vector<HostEndpointId> &connectedEndpoints,
51                    const std::shared_ptr<IContextHubCallback> &callback =
52                        ndk::SharedRefBase::make<IContextHubCallbackDefault>())
53       : HalClient(callback) {
54     mContextHub = contextHub;
55     mIsHalConnected = contextHub != nullptr;
56     for (const HostEndpointId &endpointId : connectedEndpoints) {
57       mConnectedEndpoints[endpointId] = {.hostEndpointId = endpointId};
58     }
59   }
60 
getConnectedEndpointIds()61   std::unordered_set<HostEndpointId> getConnectedEndpointIds() {
62     std::unordered_set<HostEndpointId> result{};
63     for (const auto &[endpointId, unusedEndpointInfo] : mConnectedEndpoints) {
64       result.insert(endpointId);
65     }
66     return result;
67   }
68 
getClientCallback()69   HalClientCallback *getClientCallback() {
70     return mCallback.get();
71   }
72 };
73 
74 class MockContextHub : public IContextHubDefault {
75  public:
76   MOCK_METHOD(ScopedAStatus, onHostEndpointConnected,
77               (const HostEndpointInfo &info), (override));
78   MOCK_METHOD(ScopedAStatus, onHostEndpointDisconnected,
79               (HostEndpointId endpointId), (override));
80   MOCK_METHOD(ScopedAStatus, queryNanoapps, (int32_t icontextHubId),
81               (override));
82   MOCK_METHOD(ScopedAStatus, sendMessageToHub,
83               (int32_t contextHubId, const ContextHubMessage &message),
84               (override));
85 };
86 
87 }  // namespace
88 
TEST(HalClientTest,EndpointConnectionBasic)89 TEST(HalClientTest, EndpointConnectionBasic) {
90   auto mockContextHub = ndk::SharedRefBase::make<MockContextHub>();
91   const HostEndpointInfo kInfo = {
92       .hostEndpointId = kEndpointId,
93       .type = HostEndpointInfo::Type::NATIVE,
94       .packageName = "HalClientTest",
95       .attributionTag{},
96   };
97 
98   auto halClient = std::make_unique<HalClientForTest>(
99       mockContextHub, std::vector<HostEndpointId>{});
100   EXPECT_THAT(halClient->getConnectedEndpointIds(), IsEmpty());
101 
102   EXPECT_CALL(*mockContextHub,
103               onHostEndpointConnected(
104                   Field(&HostEndpointInfo::hostEndpointId, kEndpointId)))
105       .WillOnce(Return(ScopedAStatus::ok()));
106 
107   halClient->connectEndpoint(kInfo);
108   EXPECT_THAT(halClient->getConnectedEndpointIds(),
109               UnorderedElementsAre(kEndpointId));
110 }
111 
TEST(HalClientTest,EndpointConnectionMultipleRequests)112 TEST(HalClientTest, EndpointConnectionMultipleRequests) {
113   auto mockContextHub = ndk::SharedRefBase::make<MockContextHub>();
114   const HostEndpointInfo kInfo = {
115       .hostEndpointId = kEndpointId,
116       .type = HostEndpointInfo::Type::NATIVE,
117       .packageName = "HalClientTest",
118       .attributionTag{},
119   };
120 
121   auto halClient = std::make_unique<HalClientForTest>(
122       mockContextHub, std::vector<HostEndpointId>{});
123   EXPECT_THAT(halClient->getConnectedEndpointIds(), IsEmpty());
124 
125   // multiple requests are tolerated
126   EXPECT_CALL(*mockContextHub,
127               onHostEndpointConnected(
128                   Field(&HostEndpointInfo::hostEndpointId, kEndpointId)))
129       .WillOnce(Return(ScopedAStatus::ok()))
130       .WillOnce(Return(ScopedAStatus::ok()));
131 
132   halClient->connectEndpoint(kInfo);
133   halClient->connectEndpoint(kInfo);
134 
135   EXPECT_THAT(halClient->getConnectedEndpointIds(),
136               UnorderedElementsAre(kEndpointId));
137 }
138 
TEST(HalClientTest,EndpointDisconnectionBasic)139 TEST(HalClientTest, EndpointDisconnectionBasic) {
140   auto mockContextHub = ndk::SharedRefBase::make<MockContextHub>();
141   auto halClient = std::make_unique<HalClientForTest>(
142       mockContextHub, std::vector<HostEndpointId>{kEndpointId});
143 
144   EXPECT_THAT(halClient->getConnectedEndpointIds(),
145               UnorderedElementsAre(kEndpointId));
146 
147   EXPECT_CALL(*mockContextHub, onHostEndpointDisconnected(kEndpointId))
148       .WillOnce(Return(ScopedAStatus::ok()));
149   halClient->disconnectEndpoint(kEndpointId);
150 
151   EXPECT_THAT(halClient->getConnectedEndpointIds(), IsEmpty());
152 }
153 
TEST(HalClientTest,EndpointDisconnectionMultipleRequest)154 TEST(HalClientTest, EndpointDisconnectionMultipleRequest) {
155   auto mockContextHub = ndk::SharedRefBase::make<MockContextHub>();
156   auto halClient = std::make_unique<HalClientForTest>(
157       mockContextHub, std::vector<HostEndpointId>{kEndpointId});
158   EXPECT_THAT(halClient->getConnectedEndpointIds(),
159               UnorderedElementsAre(kEndpointId));
160 
161   EXPECT_CALL(*mockContextHub, onHostEndpointDisconnected(kEndpointId))
162       .WillOnce(Return(ScopedAStatus::ok()))
163       .WillOnce(Return(ScopedAStatus::ok()));
164 
165   halClient->disconnectEndpoint(kEndpointId);
166   halClient->disconnectEndpoint(kEndpointId);
167 
168   EXPECT_THAT(halClient->getConnectedEndpointIds(), IsEmpty());
169 }
170 
TEST(HalClientTest,SendMessageBasic)171 TEST(HalClientTest, SendMessageBasic) {
172   auto mockContextHub = ndk::SharedRefBase::make<MockContextHub>();
173   const ContextHubMessage contextHubMessage = {
174       .nanoappId = 0xbeef,
175       .hostEndPoint = kEndpointId,
176       .messageBody = {},
177       .permissions = {},
178   };
179   auto halClient = std::make_unique<HalClientForTest>(
180       mockContextHub, std::vector<HostEndpointId>{kEndpointId});
181 
182   EXPECT_CALL(*mockContextHub, sendMessageToHub(_, _))
183       .WillOnce(Return(ScopedAStatus::ok()));
184   halClient->sendMessage(contextHubMessage);
185 }
186 
TEST(HalClientTest,QueryNanoapp)187 TEST(HalClientTest, QueryNanoapp) {
188   auto mockContextHub = ndk::SharedRefBase::make<MockContextHub>();
189   auto halClient = std::make_unique<HalClientForTest>(
190       mockContextHub, std::vector<HostEndpointId>{});
191 
192   EXPECT_CALL(*mockContextHub, queryNanoapps(HalClient::kDefaultContextHubId));
193   halClient->queryNanoapps();
194 }
195 
TEST(HalClientTest,HandleChreRestart)196 TEST(HalClientTest, HandleChreRestart) {
197   auto mockContextHub = ndk::SharedRefBase::make<MockContextHub>();
198 
199   auto halClient = std::make_unique<HalClientForTest>(
200       mockContextHub,
201       std::vector<HostEndpointId>{kEndpointId, kEndpointId + 1});
202 
203   EXPECT_CALL(*mockContextHub, onHostEndpointConnected(
204                                    Field(&HostEndpointInfo::hostEndpointId, _)))
205       .WillOnce(Return(ScopedAStatus::ok()))
206       .WillOnce(Return(ScopedAStatus::ok()));
207 
208   halClient->getClientCallback()->handleContextHubAsyncEvent(
209       AsyncEventType::RESTARTED);
210   EXPECT_THAT(halClient->getConnectedEndpointIds(),
211               UnorderedElementsAre(kEndpointId, kEndpointId + 1));
212 }
213 
TEST(HalClientTest,IsConnected)214 TEST(HalClientTest, IsConnected) {
215   auto mockContextHub = ndk::SharedRefBase::make<MockContextHub>();
216 
217   auto halClient = std::make_unique<HalClientForTest>(
218       mockContextHub,
219       std::vector<HostEndpointId>{kEndpointId, kEndpointId + 1});
220 
221   EXPECT_THAT(halClient->isConnected(), true);
222 }
223 }  // namespace android::chre
224