1 /* 2 * Copyright (C) 2018 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 #define LOG_TAG "resolv" 17 18 #include "ResolverEventReporter.h" 19 20 #include <android-base/logging.h> 21 #include <android/binder_manager.h> 22 23 using aidl::android::net::metrics::INetdEventListener; 24 using aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener; 25 26 ResolverEventReporter& ResolverEventReporter::getInstance() { 27 // It should be initialized only once. 28 static ResolverEventReporter instance; 29 30 // Add framework metrics listener. Because the binder service "netd_listener" may be launched 31 // later than Netd, try to get binder handler in every instance query if any. The framework 32 // metrics listener should be added only once if it has been already added successfully. 33 instance.addDefaultListener(); 34 35 return instance; 36 } 37 38 ResolverEventReporter::ListenerSet ResolverEventReporter::getListeners() const { 39 return getListenersImpl(); 40 } 41 42 ResolverEventReporter::UnsolEventListenerSet ResolverEventReporter::getUnsolEventListeners() const { 43 return getUnsolEventListenersImpl(); 44 } 45 46 int ResolverEventReporter::addListener(const std::shared_ptr<INetdEventListener>& listener) { 47 return addListenerImpl(listener); 48 } 49 50 int ResolverEventReporter::addUnsolEventListener( 51 const std::shared_ptr<IDnsResolverUnsolicitedEventListener>& listener) { 52 return addUnsolEventListenerImpl(listener); 53 } 54 55 // TODO: Consider registering metrics listener from framework and remove this function. 56 // Currently, the framework listener "netd_listener" is shared by netd and libnetd_resolv. 57 // Consider breaking it into two listeners. Once it has done, may let framework register 58 // the listener proactively. 59 void ResolverEventReporter::addDefaultListener() { 60 std::lock_guard lock(mMutex); 61 62 static bool added = false; 63 if (added) return; 64 65 // Use the non-blocking call AServiceManager_checkService in order not to delay DNS 66 // lookup threads when the netd_listener service is not ready. 67 ndk::SpAIBinder binder = ndk::SpAIBinder(AServiceManager_checkService("netd_listener")); 68 std::shared_ptr<INetdEventListener> listener = INetdEventListener::fromBinder(binder); 69 70 if (listener == nullptr) return; 71 72 if (!addListenerImplLocked(listener)) added = true; 73 } 74 75 void ResolverEventReporter::handleBinderDied(const void* who) { 76 std::lock_guard lock(mMutex); 77 78 // Use the raw binder pointer address to be the identification of dead binder. Treat "who" 79 // which passes the raw address of dead binder as an identification only. 80 auto found = std::find_if(mListeners.begin(), mListeners.end(), 81 [=](const auto& it) { return static_cast<void*>(it.get()) == who; }); 82 83 if (found != mListeners.end()) mListeners.erase(found); 84 } 85 86 void ResolverEventReporter::handleUnsolEventBinderDied(const void* who) { 87 std::lock_guard lock(mMutex); 88 89 // Use the raw binder pointer address to be the identification of dead binder. Treat "who" 90 // which passes the raw address of dead binder as an identification only. 91 auto found = std::find_if(mUnsolEventListeners.begin(), mUnsolEventListeners.end(), 92 [=](const auto& it) { return static_cast<void*>(it.get()) == who; }); 93 94 if (found != mUnsolEventListeners.end()) mUnsolEventListeners.erase(found); 95 } 96 97 ResolverEventReporter::ListenerSet ResolverEventReporter::getListenersImpl() const { 98 std::lock_guard lock(mMutex); 99 return mListeners; 100 } 101 102 ResolverEventReporter::UnsolEventListenerSet ResolverEventReporter::getUnsolEventListenersImpl() 103 const { 104 std::lock_guard lock(mMutex); 105 return mUnsolEventListeners; 106 } 107 108 int ResolverEventReporter::addListenerImpl(const std::shared_ptr<INetdEventListener>& listener) { 109 std::lock_guard lock(mMutex); 110 return addListenerImplLocked(listener); 111 } 112 113 int ResolverEventReporter::addListenerImplLocked( 114 const std::shared_ptr<INetdEventListener>& listener) { 115 if (listener == nullptr) { 116 LOG(ERROR) << "The listener should not be null"; 117 return -EINVAL; 118 } 119 120 for (const auto& it : mListeners) { 121 if (it->asBinder().get() == listener->asBinder().get()) { 122 LOG(WARNING) << "The listener was already subscribed"; 123 return -EEXIST; 124 } 125 } 126 127 static AIBinder_DeathRecipient* deathRecipient = nullptr; 128 if (deathRecipient == nullptr) { 129 // The AIBinder_DeathRecipient object is used to manage all death recipients for multiple 130 // binder objects. It doesn't released because there should have at least one binder object 131 // from framework. 132 // TODO: Considering to remove death recipient for the binder object from framework because 133 // it doesn't need death recipient actually. 134 deathRecipient = AIBinder_DeathRecipient_new([](void* cookie) { 135 ResolverEventReporter::getInstance().handleBinderDied(cookie); 136 }); 137 } 138 139 // Pass the raw binder pointer address to be the cookie of the death recipient. While the death 140 // notification is fired, the cookie is used for identifying which binder was died. Because 141 // the NDK binder doesn't pass dead binder pointer to binder death handler, the binder death 142 // handler can't know who was died via wp<IBinder>. The reason for wp<IBinder> is not passed 143 // is that NDK binder can't transform a wp<IBinder> to a wp<AIBinder> in some cases. 144 // See more information in b/128712772. 145 auto binder = listener->asBinder().get(); 146 auto cookie = static_cast<void*>(listener.get()); // Used for dead binder identification. 147 binder_status_t status = AIBinder_linkToDeath(binder, deathRecipient, cookie); 148 149 if (STATUS_OK != status) { 150 LOG(ERROR) << "Failed to register death notification for INetdEventListener"; 151 return -EAGAIN; 152 } 153 154 mListeners.insert(listener); 155 return 0; 156 } 157 158 int ResolverEventReporter::addUnsolEventListenerImpl( 159 const std::shared_ptr<IDnsResolverUnsolicitedEventListener>& listener) { 160 std::lock_guard lock(mMutex); 161 return addUnsolEventListenerImplLocked(listener); 162 } 163 164 int ResolverEventReporter::addUnsolEventListenerImplLocked( 165 const std::shared_ptr<IDnsResolverUnsolicitedEventListener>& listener) { 166 if (listener == nullptr) { 167 LOG(ERROR) << "The unsolicited event listener should not be null"; 168 return -EINVAL; 169 } 170 171 for (const auto& it : mUnsolEventListeners) { 172 if (it->asBinder().get() == listener->asBinder().get()) { 173 LOG(WARNING) << "The unsolicited event listener was already subscribed"; 174 return -EEXIST; 175 } 176 } 177 178 static AIBinder_DeathRecipient* deathRecipient = nullptr; 179 if (deathRecipient == nullptr) { 180 // The AIBinder_DeathRecipient object is used to manage all death recipients for multiple 181 // binder objects. It doesn't released because there should have at least one binder object 182 // from framework. 183 // TODO: Considering to remove death recipient for the binder object from framework because 184 // it doesn't need death recipient actually. 185 deathRecipient = AIBinder_DeathRecipient_new([](void* cookie) { 186 ResolverEventReporter::getInstance().handleUnsolEventBinderDied(cookie); 187 }); 188 } 189 190 // Pass the raw binder pointer address to be the cookie of the death recipient. While the death 191 // notification is fired, the cookie is used for identifying which binder was died. Because 192 // the NDK binder doesn't pass dead binder pointer to binder death handler, the binder death 193 // handler can't know who was died via wp<IBinder>. The reason for wp<IBinder> is not passed 194 // is that NDK binder can't transform a wp<IBinder> to a wp<AIBinder> in some cases. 195 // See more information in b/128712772. 196 auto binder = listener->asBinder().get(); 197 auto cookie = static_cast<void*>(listener.get()); // Used for dead binder identification. 198 binder_status_t status = AIBinder_linkToDeath(binder, deathRecipient, cookie); 199 200 if (STATUS_OK != status) { 201 LOG(ERROR) 202 << "Failed to register death notification for IDnsResolverUnsolicitedEventListener"; 203 return -EAGAIN; 204 } 205 206 mUnsolEventListeners.insert(listener); 207 return 0; 208 } 209