1*ee3b7b62SAndroid Build Coastguard Worker /*
2*ee3b7b62SAndroid Build Coastguard Worker * Copyright (C) 2016 The Android Open Source Project
3*ee3b7b62SAndroid Build Coastguard Worker *
4*ee3b7b62SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*ee3b7b62SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*ee3b7b62SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*ee3b7b62SAndroid Build Coastguard Worker *
8*ee3b7b62SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*ee3b7b62SAndroid Build Coastguard Worker *
10*ee3b7b62SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*ee3b7b62SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*ee3b7b62SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ee3b7b62SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*ee3b7b62SAndroid Build Coastguard Worker * limitations under the License.
15*ee3b7b62SAndroid Build Coastguard Worker */
16*ee3b7b62SAndroid Build Coastguard Worker
17*ee3b7b62SAndroid Build Coastguard Worker #define LOG_TAG "hwservicemanager"
18*ee3b7b62SAndroid Build Coastguard Worker #include "HidlService.h"
19*ee3b7b62SAndroid Build Coastguard Worker
20*ee3b7b62SAndroid Build Coastguard Worker #include <android-base/logging.h>
21*ee3b7b62SAndroid Build Coastguard Worker #include <hidl/HidlTransportSupport.h>
22*ee3b7b62SAndroid Build Coastguard Worker #include <hwbinder/BpHwBinder.h>
23*ee3b7b62SAndroid Build Coastguard Worker #include <sstream>
24*ee3b7b62SAndroid Build Coastguard Worker
25*ee3b7b62SAndroid Build Coastguard Worker using ::android::hardware::interfacesEqual;
26*ee3b7b62SAndroid Build Coastguard Worker
27*ee3b7b62SAndroid Build Coastguard Worker namespace android {
28*ee3b7b62SAndroid Build Coastguard Worker namespace hidl {
29*ee3b7b62SAndroid Build Coastguard Worker namespace manager {
30*ee3b7b62SAndroid Build Coastguard Worker namespace implementation {
31*ee3b7b62SAndroid Build Coastguard Worker
32*ee3b7b62SAndroid Build Coastguard Worker static constexpr int kNoClientRepeatLimit = 2;
33*ee3b7b62SAndroid Build Coastguard Worker
HidlService(const std::string & interfaceName,const std::string & instanceName,const sp<IBase> & service,pid_t pid)34*ee3b7b62SAndroid Build Coastguard Worker HidlService::HidlService(
35*ee3b7b62SAndroid Build Coastguard Worker const std::string &interfaceName,
36*ee3b7b62SAndroid Build Coastguard Worker const std::string &instanceName,
37*ee3b7b62SAndroid Build Coastguard Worker const sp<IBase> &service,
38*ee3b7b62SAndroid Build Coastguard Worker pid_t pid)
39*ee3b7b62SAndroid Build Coastguard Worker : mInterfaceName(interfaceName),
40*ee3b7b62SAndroid Build Coastguard Worker mInstanceName(instanceName),
41*ee3b7b62SAndroid Build Coastguard Worker mService(service),
42*ee3b7b62SAndroid Build Coastguard Worker mPid(pid)
43*ee3b7b62SAndroid Build Coastguard Worker {}
44*ee3b7b62SAndroid Build Coastguard Worker
getService() const45*ee3b7b62SAndroid Build Coastguard Worker sp<IBase> HidlService::getService() const {
46*ee3b7b62SAndroid Build Coastguard Worker return mService;
47*ee3b7b62SAndroid Build Coastguard Worker }
setService(sp<IBase> service,pid_t pid)48*ee3b7b62SAndroid Build Coastguard Worker void HidlService::setService(sp<IBase> service, pid_t pid) {
49*ee3b7b62SAndroid Build Coastguard Worker mService = service;
50*ee3b7b62SAndroid Build Coastguard Worker mPid = pid;
51*ee3b7b62SAndroid Build Coastguard Worker
52*ee3b7b62SAndroid Build Coastguard Worker mClientCallbacks.clear();
53*ee3b7b62SAndroid Build Coastguard Worker mHasClients = false;
54*ee3b7b62SAndroid Build Coastguard Worker mGuaranteeClient = false;
55*ee3b7b62SAndroid Build Coastguard Worker mNoClientsCounter = 0;
56*ee3b7b62SAndroid Build Coastguard Worker
57*ee3b7b62SAndroid Build Coastguard Worker sendRegistrationNotifications();
58*ee3b7b62SAndroid Build Coastguard Worker }
59*ee3b7b62SAndroid Build Coastguard Worker
getDebugPid() const60*ee3b7b62SAndroid Build Coastguard Worker pid_t HidlService::getDebugPid() const {
61*ee3b7b62SAndroid Build Coastguard Worker return mPid;
62*ee3b7b62SAndroid Build Coastguard Worker }
getInterfaceName() const63*ee3b7b62SAndroid Build Coastguard Worker const std::string &HidlService::getInterfaceName() const {
64*ee3b7b62SAndroid Build Coastguard Worker return mInterfaceName;
65*ee3b7b62SAndroid Build Coastguard Worker }
getInstanceName() const66*ee3b7b62SAndroid Build Coastguard Worker const std::string &HidlService::getInstanceName() const {
67*ee3b7b62SAndroid Build Coastguard Worker return mInstanceName;
68*ee3b7b62SAndroid Build Coastguard Worker }
69*ee3b7b62SAndroid Build Coastguard Worker
addListener(const sp<IServiceNotification> & listener)70*ee3b7b62SAndroid Build Coastguard Worker void HidlService::addListener(const sp<IServiceNotification> &listener) {
71*ee3b7b62SAndroid Build Coastguard Worker if (mService != nullptr) {
72*ee3b7b62SAndroid Build Coastguard Worker auto ret = listener->onRegistration(
73*ee3b7b62SAndroid Build Coastguard Worker mInterfaceName, mInstanceName, true /* preexisting */);
74*ee3b7b62SAndroid Build Coastguard Worker if (!ret.isOk()) {
75*ee3b7b62SAndroid Build Coastguard Worker LOG(ERROR) << "Not adding listener for " << mInterfaceName << "/"
76*ee3b7b62SAndroid Build Coastguard Worker << mInstanceName << ": transport error when sending "
77*ee3b7b62SAndroid Build Coastguard Worker << "notification for already registered instance.";
78*ee3b7b62SAndroid Build Coastguard Worker return;
79*ee3b7b62SAndroid Build Coastguard Worker }
80*ee3b7b62SAndroid Build Coastguard Worker }
81*ee3b7b62SAndroid Build Coastguard Worker mListeners.push_back(listener);
82*ee3b7b62SAndroid Build Coastguard Worker }
83*ee3b7b62SAndroid Build Coastguard Worker
removeListener(const wp<IBase> & listener)84*ee3b7b62SAndroid Build Coastguard Worker bool HidlService::removeListener(const wp<IBase>& listener) {
85*ee3b7b62SAndroid Build Coastguard Worker bool found = false;
86*ee3b7b62SAndroid Build Coastguard Worker
87*ee3b7b62SAndroid Build Coastguard Worker for (auto it = mListeners.begin(); it != mListeners.end();) {
88*ee3b7b62SAndroid Build Coastguard Worker if (interfacesEqual(*it, listener.promote())) {
89*ee3b7b62SAndroid Build Coastguard Worker it = mListeners.erase(it);
90*ee3b7b62SAndroid Build Coastguard Worker found = true;
91*ee3b7b62SAndroid Build Coastguard Worker } else {
92*ee3b7b62SAndroid Build Coastguard Worker ++it;
93*ee3b7b62SAndroid Build Coastguard Worker }
94*ee3b7b62SAndroid Build Coastguard Worker }
95*ee3b7b62SAndroid Build Coastguard Worker
96*ee3b7b62SAndroid Build Coastguard Worker return found;
97*ee3b7b62SAndroid Build Coastguard Worker }
98*ee3b7b62SAndroid Build Coastguard Worker
registerPassthroughClient(pid_t pid)99*ee3b7b62SAndroid Build Coastguard Worker void HidlService::registerPassthroughClient(pid_t pid) {
100*ee3b7b62SAndroid Build Coastguard Worker mPassthroughClients.insert(pid);
101*ee3b7b62SAndroid Build Coastguard Worker }
102*ee3b7b62SAndroid Build Coastguard Worker
getPassthroughClients() const103*ee3b7b62SAndroid Build Coastguard Worker const std::set<pid_t> &HidlService::getPassthroughClients() const {
104*ee3b7b62SAndroid Build Coastguard Worker return mPassthroughClients;
105*ee3b7b62SAndroid Build Coastguard Worker }
106*ee3b7b62SAndroid Build Coastguard Worker
addClientCallback(const sp<IClientCallback> & callback,size_t knownClientCount)107*ee3b7b62SAndroid Build Coastguard Worker void HidlService::addClientCallback(const sp<IClientCallback>& callback, size_t knownClientCount) {
108*ee3b7b62SAndroid Build Coastguard Worker if (mHasClients) {
109*ee3b7b62SAndroid Build Coastguard Worker // we have this kernel feature, so make sure we're in an updated state
110*ee3b7b62SAndroid Build Coastguard Worker forceHandleClientCallbacks(false /*onInterval*/, knownClientCount);
111*ee3b7b62SAndroid Build Coastguard Worker }
112*ee3b7b62SAndroid Build Coastguard Worker
113*ee3b7b62SAndroid Build Coastguard Worker if (mHasClients) {
114*ee3b7b62SAndroid Build Coastguard Worker // make sure this callback is in the same state as all of the rest
115*ee3b7b62SAndroid Build Coastguard Worker sendClientCallbackNotification(callback, true /*hasClients*/);
116*ee3b7b62SAndroid Build Coastguard Worker }
117*ee3b7b62SAndroid Build Coastguard Worker
118*ee3b7b62SAndroid Build Coastguard Worker mClientCallbacks.push_back(callback);
119*ee3b7b62SAndroid Build Coastguard Worker }
120*ee3b7b62SAndroid Build Coastguard Worker
removeClientCallback(const sp<IClientCallback> & callback)121*ee3b7b62SAndroid Build Coastguard Worker bool HidlService::removeClientCallback(const sp<IClientCallback>& callback) {
122*ee3b7b62SAndroid Build Coastguard Worker bool found = false;
123*ee3b7b62SAndroid Build Coastguard Worker
124*ee3b7b62SAndroid Build Coastguard Worker for (auto it = mClientCallbacks.begin(); it != mClientCallbacks.end();) {
125*ee3b7b62SAndroid Build Coastguard Worker if (interfacesEqual(*it, callback)) {
126*ee3b7b62SAndroid Build Coastguard Worker it = mClientCallbacks.erase(it);
127*ee3b7b62SAndroid Build Coastguard Worker found = true;
128*ee3b7b62SAndroid Build Coastguard Worker } else {
129*ee3b7b62SAndroid Build Coastguard Worker ++it;
130*ee3b7b62SAndroid Build Coastguard Worker }
131*ee3b7b62SAndroid Build Coastguard Worker }
132*ee3b7b62SAndroid Build Coastguard Worker
133*ee3b7b62SAndroid Build Coastguard Worker return found;
134*ee3b7b62SAndroid Build Coastguard Worker }
135*ee3b7b62SAndroid Build Coastguard Worker
handleClientCallbacks(bool isCalledOnInterval,size_t knownClientCount)136*ee3b7b62SAndroid Build Coastguard Worker bool HidlService::handleClientCallbacks(bool isCalledOnInterval, size_t knownClientCount) {
137*ee3b7b62SAndroid Build Coastguard Worker if (!mClientCallbacks.empty()) {
138*ee3b7b62SAndroid Build Coastguard Worker return forceHandleClientCallbacks(isCalledOnInterval, knownClientCount);
139*ee3b7b62SAndroid Build Coastguard Worker }
140*ee3b7b62SAndroid Build Coastguard Worker
141*ee3b7b62SAndroid Build Coastguard Worker return false;
142*ee3b7b62SAndroid Build Coastguard Worker }
143*ee3b7b62SAndroid Build Coastguard Worker
forceHandleClientCallbacks(bool isCalledOnInterval,size_t knownClientCount)144*ee3b7b62SAndroid Build Coastguard Worker bool HidlService::forceHandleClientCallbacks(bool isCalledOnInterval, size_t knownClientCount) {
145*ee3b7b62SAndroid Build Coastguard Worker ssize_t count = getNodeStrongRefCount();
146*ee3b7b62SAndroid Build Coastguard Worker
147*ee3b7b62SAndroid Build Coastguard Worker // binder driver doesn't support this feature
148*ee3b7b62SAndroid Build Coastguard Worker if (count < 0) return false;
149*ee3b7b62SAndroid Build Coastguard Worker
150*ee3b7b62SAndroid Build Coastguard Worker bool hasClients = (size_t)count > knownClientCount;
151*ee3b7b62SAndroid Build Coastguard Worker
152*ee3b7b62SAndroid Build Coastguard Worker if (mGuaranteeClient) {
153*ee3b7b62SAndroid Build Coastguard Worker // we have no record of this client
154*ee3b7b62SAndroid Build Coastguard Worker if (!mHasClients && !hasClients) {
155*ee3b7b62SAndroid Build Coastguard Worker sendClientCallbackNotifications(true);
156*ee3b7b62SAndroid Build Coastguard Worker }
157*ee3b7b62SAndroid Build Coastguard Worker
158*ee3b7b62SAndroid Build Coastguard Worker // guarantee is temporary
159*ee3b7b62SAndroid Build Coastguard Worker mGuaranteeClient = false;
160*ee3b7b62SAndroid Build Coastguard Worker }
161*ee3b7b62SAndroid Build Coastguard Worker
162*ee3b7b62SAndroid Build Coastguard Worker if (hasClients && !mHasClients) {
163*ee3b7b62SAndroid Build Coastguard Worker // client was retrieved in some other way
164*ee3b7b62SAndroid Build Coastguard Worker sendClientCallbackNotifications(true);
165*ee3b7b62SAndroid Build Coastguard Worker }
166*ee3b7b62SAndroid Build Coastguard Worker
167*ee3b7b62SAndroid Build Coastguard Worker // there are no more clients, but the callback has not been called yet
168*ee3b7b62SAndroid Build Coastguard Worker if (!hasClients && mHasClients && isCalledOnInterval) {
169*ee3b7b62SAndroid Build Coastguard Worker mNoClientsCounter++;
170*ee3b7b62SAndroid Build Coastguard Worker
171*ee3b7b62SAndroid Build Coastguard Worker if (mNoClientsCounter >= kNoClientRepeatLimit) {
172*ee3b7b62SAndroid Build Coastguard Worker sendClientCallbackNotifications(false);
173*ee3b7b62SAndroid Build Coastguard Worker }
174*ee3b7b62SAndroid Build Coastguard Worker }
175*ee3b7b62SAndroid Build Coastguard Worker
176*ee3b7b62SAndroid Build Coastguard Worker return mHasClients;
177*ee3b7b62SAndroid Build Coastguard Worker }
178*ee3b7b62SAndroid Build Coastguard Worker
guaranteeClient()179*ee3b7b62SAndroid Build Coastguard Worker void HidlService::guaranteeClient() {
180*ee3b7b62SAndroid Build Coastguard Worker mGuaranteeClient = true;
181*ee3b7b62SAndroid Build Coastguard Worker }
182*ee3b7b62SAndroid Build Coastguard Worker
string() const183*ee3b7b62SAndroid Build Coastguard Worker std::string HidlService::string() const {
184*ee3b7b62SAndroid Build Coastguard Worker std::stringstream ss;
185*ee3b7b62SAndroid Build Coastguard Worker ss << mInterfaceName << "/" << mInstanceName;
186*ee3b7b62SAndroid Build Coastguard Worker return ss.str();
187*ee3b7b62SAndroid Build Coastguard Worker }
188*ee3b7b62SAndroid Build Coastguard Worker
getNodeStrongRefCount()189*ee3b7b62SAndroid Build Coastguard Worker ssize_t HidlService::getNodeStrongRefCount() {
190*ee3b7b62SAndroid Build Coastguard Worker using ::android::hardware::toBinder;
191*ee3b7b62SAndroid Build Coastguard Worker using ::android::hardware::BpHwBinder;
192*ee3b7b62SAndroid Build Coastguard Worker using ::android::hardware::IBinder;
193*ee3b7b62SAndroid Build Coastguard Worker
194*ee3b7b62SAndroid Build Coastguard Worker if (mService == nullptr) return -1;
195*ee3b7b62SAndroid Build Coastguard Worker
196*ee3b7b62SAndroid Build Coastguard Worker // this justifies the bp cast below, no in-process HALs need this
197*ee3b7b62SAndroid Build Coastguard Worker if (!mService->isRemote()) return -1;
198*ee3b7b62SAndroid Build Coastguard Worker
199*ee3b7b62SAndroid Build Coastguard Worker sp<IBinder> binder = toBinder(mService);
200*ee3b7b62SAndroid Build Coastguard Worker if (binder == nullptr) return -1;
201*ee3b7b62SAndroid Build Coastguard Worker
202*ee3b7b62SAndroid Build Coastguard Worker sp<BpHwBinder> bpBinder = static_cast<BpHwBinder*>(binder.get());
203*ee3b7b62SAndroid Build Coastguard Worker return bpBinder->getNodeStrongRefCount();
204*ee3b7b62SAndroid Build Coastguard Worker }
205*ee3b7b62SAndroid Build Coastguard Worker
sendRegistrationNotifications()206*ee3b7b62SAndroid Build Coastguard Worker void HidlService::sendRegistrationNotifications() {
207*ee3b7b62SAndroid Build Coastguard Worker if (mListeners.size() == 0 || mService == nullptr) {
208*ee3b7b62SAndroid Build Coastguard Worker return;
209*ee3b7b62SAndroid Build Coastguard Worker }
210*ee3b7b62SAndroid Build Coastguard Worker
211*ee3b7b62SAndroid Build Coastguard Worker hidl_string iface = mInterfaceName;
212*ee3b7b62SAndroid Build Coastguard Worker hidl_string name = mInstanceName;
213*ee3b7b62SAndroid Build Coastguard Worker
214*ee3b7b62SAndroid Build Coastguard Worker for (auto it = mListeners.begin(); it != mListeners.end();) {
215*ee3b7b62SAndroid Build Coastguard Worker auto ret = (*it)->onRegistration(iface, name, false /* preexisting */);
216*ee3b7b62SAndroid Build Coastguard Worker if (ret.isOk()) {
217*ee3b7b62SAndroid Build Coastguard Worker ++it;
218*ee3b7b62SAndroid Build Coastguard Worker } else {
219*ee3b7b62SAndroid Build Coastguard Worker LOG(ERROR) << "Dropping registration callback for " << iface << "/" << name
220*ee3b7b62SAndroid Build Coastguard Worker << ": transport error.";
221*ee3b7b62SAndroid Build Coastguard Worker it = mListeners.erase(it);
222*ee3b7b62SAndroid Build Coastguard Worker }
223*ee3b7b62SAndroid Build Coastguard Worker }
224*ee3b7b62SAndroid Build Coastguard Worker }
225*ee3b7b62SAndroid Build Coastguard Worker
sendClientCallbackNotifications(bool hasClients)226*ee3b7b62SAndroid Build Coastguard Worker void HidlService::sendClientCallbackNotifications(bool hasClients) {
227*ee3b7b62SAndroid Build Coastguard Worker CHECK(hasClients != mHasClients) << "Record shows: " << mHasClients
228*ee3b7b62SAndroid Build Coastguard Worker << " so we can't tell clients again that we have client: " << hasClients;
229*ee3b7b62SAndroid Build Coastguard Worker
230*ee3b7b62SAndroid Build Coastguard Worker LOG(INFO) << "Notifying " << string() << " they have clients: " << hasClients;
231*ee3b7b62SAndroid Build Coastguard Worker
232*ee3b7b62SAndroid Build Coastguard Worker for (const auto& cb : mClientCallbacks) {
233*ee3b7b62SAndroid Build Coastguard Worker sendClientCallbackNotification(cb, hasClients);
234*ee3b7b62SAndroid Build Coastguard Worker }
235*ee3b7b62SAndroid Build Coastguard Worker
236*ee3b7b62SAndroid Build Coastguard Worker mNoClientsCounter = 0;
237*ee3b7b62SAndroid Build Coastguard Worker mHasClients = hasClients;
238*ee3b7b62SAndroid Build Coastguard Worker }
239*ee3b7b62SAndroid Build Coastguard Worker
sendClientCallbackNotification(const sp<IClientCallback> & callback,bool hasClients)240*ee3b7b62SAndroid Build Coastguard Worker void HidlService::sendClientCallbackNotification(const sp<IClientCallback>& callback, bool hasClients) {
241*ee3b7b62SAndroid Build Coastguard Worker Return<void> ret = callback->onClients(getService(), hasClients);
242*ee3b7b62SAndroid Build Coastguard Worker if (!ret.isOk()) {
243*ee3b7b62SAndroid Build Coastguard Worker LOG(WARNING) << "onClients callback failed for " << string() << ": " << ret.description();
244*ee3b7b62SAndroid Build Coastguard Worker }
245*ee3b7b62SAndroid Build Coastguard Worker }
246*ee3b7b62SAndroid Build Coastguard Worker
247*ee3b7b62SAndroid Build Coastguard Worker
248*ee3b7b62SAndroid Build Coastguard Worker } // namespace implementation
249*ee3b7b62SAndroid Build Coastguard Worker } // namespace manager
250*ee3b7b62SAndroid Build Coastguard Worker } // namespace hidl
251*ee3b7b62SAndroid Build Coastguard Worker } // namespace android
252