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