xref: /aosp_15_r20/system/hwservicemanager/HidlService.cpp (revision ee3b7b6295061e544d3520b965ea91a90424af41)
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