123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- /*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #define LOG_TAG "hwservicemanager"
- #include "HidlService.h"
- #include <android-base/logging.h>
- #include <hidl/HidlTransportSupport.h>
- #include <hwbinder/BpHwBinder.h>
- #include <sstream>
- using ::android::hardware::interfacesEqual;
- namespace android {
- namespace hidl {
- namespace manager {
- namespace implementation {
- static constexpr int kNoClientRepeatLimit = 2;
- HidlService::HidlService(
- const std::string &interfaceName,
- const std::string &instanceName,
- const sp<IBase> &service,
- pid_t pid)
- : mInterfaceName(interfaceName),
- mInstanceName(instanceName),
- mService(service),
- mPid(pid)
- {}
- sp<IBase> HidlService::getService() const {
- return mService;
- }
- void HidlService::setService(sp<IBase> service, pid_t pid) {
- mService = service;
- mPid = pid;
- mClientCallbacks.clear();
- mHasClients = false;
- mGuaranteeClient = false;
- mNoClientsCounter = 0;
- sendRegistrationNotifications();
- }
- pid_t HidlService::getDebugPid() const {
- return mPid;
- }
- const std::string &HidlService::getInterfaceName() const {
- return mInterfaceName;
- }
- const std::string &HidlService::getInstanceName() const {
- return mInstanceName;
- }
- void HidlService::addListener(const sp<IServiceNotification> &listener) {
- if (mService != nullptr) {
- auto ret = listener->onRegistration(
- mInterfaceName, mInstanceName, true /* preexisting */);
- if (!ret.isOk()) {
- LOG(ERROR) << "Not adding listener for " << mInterfaceName << "/"
- << mInstanceName << ": transport error when sending "
- << "notification for already registered instance.";
- return;
- }
- }
- mListeners.push_back(listener);
- }
- bool HidlService::removeListener(const wp<IBase>& listener) {
- bool found = false;
- for (auto it = mListeners.begin(); it != mListeners.end();) {
- if (interfacesEqual(*it, listener.promote())) {
- it = mListeners.erase(it);
- found = true;
- } else {
- ++it;
- }
- }
- return found;
- }
- void HidlService::registerPassthroughClient(pid_t pid) {
- mPassthroughClients.insert(pid);
- }
- const std::set<pid_t> &HidlService::getPassthroughClients() const {
- return mPassthroughClients;
- }
- void HidlService::addClientCallback(const sp<IClientCallback>& callback) {
- if (mHasClients) {
- // we have this kernel feature, so make sure we're in an updated state
- forceHandleClientCallbacks(false /*onInterval*/);
- }
- if (mHasClients) {
- // make sure this callback is in the same state as all of the rest
- sendClientCallbackNotification(callback, true /*hasClients*/);
- }
- mClientCallbacks.push_back(callback);
- }
- bool HidlService::removeClientCallback(const sp<IClientCallback>& callback) {
- bool found = false;
- for (auto it = mClientCallbacks.begin(); it != mClientCallbacks.end();) {
- if (interfacesEqual(*it, callback)) {
- it = mClientCallbacks.erase(it);
- found = true;
- } else {
- ++it;
- }
- }
- return found;
- }
- ssize_t HidlService::handleClientCallbacks(bool isCalledOnInterval) {
- if (!mClientCallbacks.empty()) {
- return forceHandleClientCallbacks(isCalledOnInterval);
- }
- return -1;
- }
- ssize_t HidlService::forceHandleClientCallbacks(bool isCalledOnInterval) {
- ssize_t count = getNodeStrongRefCount();
- // binder driver doesn't support this feature
- if (count == -1) return count;
- bool hasClients = count > 1; // this process holds a strong count
- if (mGuaranteeClient) {
- // we have no record of this client
- if (!mHasClients && !hasClients) {
- sendClientCallbackNotifications(true);
- }
- // guarantee is temporary
- mGuaranteeClient = false;
- }
- if (hasClients && !mHasClients) {
- // client was retrieved in some other way
- sendClientCallbackNotifications(true);
- }
- // there are no more clients, but the callback has not been called yet
- if (!hasClients && mHasClients && isCalledOnInterval) {
- mNoClientsCounter++;
- if (mNoClientsCounter >= kNoClientRepeatLimit) {
- sendClientCallbackNotifications(false);
- }
- }
- return count;
- }
- void HidlService::guaranteeClient() {
- mGuaranteeClient = true;
- }
- std::string HidlService::string() const {
- std::stringstream ss;
- ss << mInterfaceName << "/" << mInstanceName;
- return ss.str();
- }
- ssize_t HidlService::getNodeStrongRefCount() {
- using ::android::hardware::toBinder;
- using ::android::hardware::BpHwBinder;
- using ::android::hardware::IBinder;
- if (mService == nullptr) return -1;
- // this justifies the bp cast below, no in-process HALs need this
- if (!mService->isRemote()) return -1;
- sp<IBinder> binder = toBinder(mService);
- if (binder == nullptr) return -1;
- sp<BpHwBinder> bpBinder = static_cast<BpHwBinder*>(binder.get());
- return bpBinder->getNodeStrongRefCount();
- }
- void HidlService::sendRegistrationNotifications() {
- if (mListeners.size() == 0 || mService == nullptr) {
- return;
- }
- hidl_string iface = mInterfaceName;
- hidl_string name = mInstanceName;
- for (auto it = mListeners.begin(); it != mListeners.end();) {
- auto ret = (*it)->onRegistration(iface, name, false /* preexisting */);
- if (ret.isOk()) {
- ++it;
- } else {
- LOG(ERROR) << "Dropping registration callback for " << iface << "/" << name
- << ": transport error.";
- it = mListeners.erase(it);
- }
- }
- }
- void HidlService::sendClientCallbackNotifications(bool hasClients) {
- CHECK(hasClients != mHasClients) << "Record shows: " << mHasClients
- << " so we can't tell clients again that we have client: " << hasClients;
- LOG(INFO) << "Notifying " << string() << " they have clients: " << hasClients;
- for (const auto& cb : mClientCallbacks) {
- sendClientCallbackNotification(cb, hasClients);
- }
- mNoClientsCounter = 0;
- mHasClients = hasClients;
- }
- void HidlService::sendClientCallbackNotification(const sp<IClientCallback>& callback, bool hasClients) {
- Return<void> ret = callback->onClients(getService(), hasClients);
- if (!ret.isOk()) {
- LOG(WARNING) << "onClients callback failed for " << string() << ": " << ret.description();
- }
- }
- } // namespace implementation
- } // namespace manager
- } // namespace hidl
- } // namespace android
|