1 /*
2 * Copyright (C) 2019 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
17 #include <HidlService.h>
18
19 #include <android/hidl/manager/1.2/IClientCallback.h>
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22
23 using ::android::hardware::Return;
24 using ::android::hardware::Void;
25 using ::android::hidl::base::V1_0::IBase;
26 using ::android::hidl::manager::implementation::HidlService;
27 using ::android::hidl::manager::V1_2::IClientCallback;
28 using ::android::sp;
29 using ::testing::ElementsAre;
30 using ::testing::Invoke;
31 using ::testing::NiceMock;
32
33 class RecordingClientCallback : public IClientCallback {
34 public:
onClients(const sp<IBase> &,bool clients)35 Return<void> onClients(const sp<IBase>& /*base*/, bool clients) override {
36 stream.push_back(clients);
37 return Void();
38 }
39
40 std::vector<bool> stream;
41 };
42
43 class MockHidlService : public HidlService {
44 public:
MockHidlService()45 MockHidlService() : HidlService("fqname", "instance") {}
46 MOCK_METHOD0(getNodeStrongRefCount, ssize_t());
47 };
48
49 class HidlServiceLazyTest : public ::testing::Test {
50 public:
51 // Note that this should include one count for hwservicemanager. A count of
52 // 1 indicates that hwservicemanager is the only process holding the service.
setReportedClientCount(ssize_t count)53 void setReportedClientCount(ssize_t count) {
54 mState.mInjectedReportCount = count;
55 }
56
57 // Essentially, the number of times the kernel API would be called
getNumTimesReported()58 size_t getNumTimesReported() {
59 return mState.mInjectedTimes;
60 }
61
makeService()62 std::unique_ptr<HidlService> makeService() {
63 auto service = std::make_unique<NiceMock<MockHidlService>>();
64 ON_CALL(*service, getNodeStrongRefCount()).WillByDefault(Invoke([&]() {
65 mState.mInjectedTimes++;
66 return mState.mInjectedReportCount;
67 }));
68 return service;
69 }
70
71 protected:
SetUp()72 void SetUp() override {
73 mState = TestState();
74 }
75
76 struct TestState {
77 ssize_t mInjectedReportCount = -1;
78 size_t mInjectedTimes = 0;
79 } mState;
80 };
81
TEST_F(HidlServiceLazyTest,NoChange)82 TEST_F(HidlServiceLazyTest, NoChange) {
83 sp<RecordingClientCallback> cb = new RecordingClientCallback;
84
85 std::unique_ptr<HidlService> service = makeService();
86 service->addClientCallback(cb, 1 /*knownClients*/);
87
88 setReportedClientCount(1);
89
90 for (size_t i = 0; i < 100; i++) {
91 service->handleClientCallbacks(true /*onInterval*/, 1 /*knownClients*/);
92 }
93
94 ASSERT_THAT(cb->stream, ElementsAre());
95 }
96
TEST_F(HidlServiceLazyTest,NoChangeWithKnownClients)97 TEST_F(HidlServiceLazyTest, NoChangeWithKnownClients) {
98 sp<RecordingClientCallback> cb = new RecordingClientCallback;
99
100 std::unique_ptr<HidlService> service = makeService();
101 service->addClientCallback(cb, 2 /*knownClients*/);
102
103 setReportedClientCount(2);
104
105 for (size_t i = 0; i < 100; i++) {
106 service->handleClientCallbacks(true /*onInterval*/, 2 /*knownClients*/);
107 }
108
109 ASSERT_THAT(cb->stream, ElementsAre());
110 }
111
TEST_F(HidlServiceLazyTest,GetAndDrop)112 TEST_F(HidlServiceLazyTest, GetAndDrop) {
113 sp<RecordingClientCallback> cb = new RecordingClientCallback;
114
115 std::unique_ptr<HidlService> service = makeService();
116 service->addClientCallback(cb, 1 /*knownClients*/);
117
118 // some other process has the service
119 setReportedClientCount(2);
120 service->handleClientCallbacks(true /*onInterval*/, 1 /*knownClients*/);
121
122 ASSERT_THAT(cb->stream, ElementsAre(true));
123
124 // just hwservicemanager has the service
125 setReportedClientCount(1);
126 service->handleClientCallbacks(true /*onInterval*/, 1 /*knownClients*/);
127
128 ASSERT_THAT(cb->stream, ElementsAre(true));
129 service->handleClientCallbacks(true /*onInterval*/, 1 /*knownClients*/);
130
131 ASSERT_THAT(cb->stream, ElementsAre(true, false)); // reported only after two intervals
132 }
133
TEST_F(HidlServiceLazyTest,GetGuarantee)134 TEST_F(HidlServiceLazyTest, GetGuarantee) {
135 sp<RecordingClientCallback> cb = new RecordingClientCallback;
136
137 std::unique_ptr<HidlService> service = makeService();
138 service->addClientCallback(cb, 1 /*knownClients*/);
139
140 service->guaranteeClient();
141
142 setReportedClientCount(1);
143 service->handleClientCallbacks(false /*onInterval*/, 1 /*knownClients*/);
144 ASSERT_THAT(cb->stream, ElementsAre(true));
145
146 service->handleClientCallbacks(true /*onInterval*/, 1 /*knownClients*/);
147 ASSERT_THAT(cb->stream, ElementsAre(true));
148
149 service->handleClientCallbacks(true /*onInterval*/, 1 /*knownClients*/);
150 ASSERT_THAT(cb->stream, ElementsAre(true, false)); // reported only after two intervals
151 }
152
TEST_F(HidlServiceLazyTest,ManyUpdatesOffInterval)153 TEST_F(HidlServiceLazyTest, ManyUpdatesOffInterval) {
154 sp<RecordingClientCallback> cb = new RecordingClientCallback;
155
156 std::unique_ptr<HidlService> service = makeService();
157 service->addClientCallback(cb, 1 /*knownClients*/);
158
159 // Clients can appear and dissappear as many times as necessary, but they are only considered
160 // dropped when the fixed interval stops.
161 for (size_t i = 0; i < 100; i++) {
162 setReportedClientCount(2);
163 service->handleClientCallbacks(false /*onInterval*/, 1 /*knownClients*/);
164 setReportedClientCount(1);
165 service->handleClientCallbacks(false /*onInterval*/, 1 /*knownClients*/);
166 }
167
168 ASSERT_THAT(cb->stream, ElementsAre(true));
169
170 service->handleClientCallbacks(true /*onInterval*/, 1 /*knownClients*/);
171 ASSERT_THAT(cb->stream, ElementsAre(true));
172
173 service->handleClientCallbacks(true /*onInterval*/, 1 /*knownClients*/);
174 ASSERT_THAT(cb->stream, ElementsAre(true, false)); // reported only after two intervals
175 }
176
TEST_F(HidlServiceLazyTest,AcquisitionAfterGuarantee)177 TEST_F(HidlServiceLazyTest, AcquisitionAfterGuarantee) {
178 sp<RecordingClientCallback> cb = new RecordingClientCallback;
179
180 std::unique_ptr<HidlService> service = makeService();
181 service->addClientCallback(cb, 1 /*knownClients*/);
182
183 setReportedClientCount(2);
184 service->handleClientCallbacks(false /*onInterval*/, 1 /*knownClients*/);
185 ASSERT_THAT(cb->stream, ElementsAre(true));
186
187 setReportedClientCount(1);
188 service->guaranteeClient();
189
190 service->handleClientCallbacks(false /*onInterval*/, 1 /*knownClients*/);
191 ASSERT_THAT(cb->stream, ElementsAre(true));
192
193 service->handleClientCallbacks(true /*onInterval*/, 1 /*knownClients*/);
194 ASSERT_THAT(cb->stream, ElementsAre(true));
195
196 service->handleClientCallbacks(true /*onInterval*/, 1 /*knownClients*/);
197 ASSERT_THAT(cb->stream, ElementsAre(true, false)); // reported only after two intervals
198 }
199
TEST_F(HidlServiceLazyTest,NotificationSentForNewClientCallback)200 TEST_F(HidlServiceLazyTest, NotificationSentForNewClientCallback) {
201 sp<RecordingClientCallback> cb = new RecordingClientCallback;
202
203 std::unique_ptr<HidlService> service = makeService();
204 service->addClientCallback(cb, 1 /*knownClients*/);
205
206 setReportedClientCount(2);
207 service->handleClientCallbacks(false /*onInterval*/, 1 /*knownClients*/);
208 ASSERT_THAT(cb->stream, ElementsAre(true));
209
210 sp<RecordingClientCallback> laterCb = new RecordingClientCallback;
211 service->addClientCallback(laterCb, 1 /*knownClients*/);
212
213 ASSERT_THAT(cb->stream, ElementsAre(true));
214 ASSERT_THAT(laterCb->stream, ElementsAre(true));
215
216 setReportedClientCount(1);
217
218 service->handleClientCallbacks(true /*onInterval*/, 1 /*knownClients*/);
219 ASSERT_THAT(cb->stream, ElementsAre(true));
220 ASSERT_THAT(laterCb->stream, ElementsAre(true));
221
222 service->handleClientCallbacks(true /*onInterval*/, 1 /*knownClients*/);
223 ASSERT_THAT(cb->stream, ElementsAre(true, false)); // reported only after two intervals
224 ASSERT_THAT(laterCb->stream, ElementsAre(true, false)); // reported only after two intervals
225 }
226
TEST_F(HidlServiceLazyTest,ClientWithoutLazy)227 TEST_F(HidlServiceLazyTest, ClientWithoutLazy) {
228 std::unique_ptr<HidlService> service = makeService();
229
230 setReportedClientCount(2);
231 service->handleClientCallbacks(false /*onInterval*/, 1 /*knownClients*/);
232
233 // kernel API should not be called
234 EXPECT_EQ(0u, getNumTimesReported());
235 }
236