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: 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: 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. 53 void setReportedClientCount(ssize_t count) { 54 mState.mInjectedReportCount = count; 55 } 56 57 // Essentially, the number of times the kernel API would be called 58 size_t getNumTimesReported() { 59 return mState.mInjectedTimes; 60 } 61 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: 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 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 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 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 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 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 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 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 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