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
getInstance()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
getListeners() const38 ResolverEventReporter::ListenerSet ResolverEventReporter::getListeners() const {
39 return getListenersImpl();
40 }
41
getUnsolEventListeners() const42 ResolverEventReporter::UnsolEventListenerSet ResolverEventReporter::getUnsolEventListeners() const {
43 return getUnsolEventListenersImpl();
44 }
45
addListener(const std::shared_ptr<INetdEventListener> & listener)46 int ResolverEventReporter::addListener(const std::shared_ptr<INetdEventListener>& listener) {
47 return addListenerImpl(listener);
48 }
49
addUnsolEventListener(const std::shared_ptr<IDnsResolverUnsolicitedEventListener> & listener)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.
addDefaultListener()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
handleBinderDied(const void * who)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
handleUnsolEventBinderDied(const void * who)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
getListenersImpl() const97 ResolverEventReporter::ListenerSet ResolverEventReporter::getListenersImpl() const {
98 std::lock_guard lock(mMutex);
99 return mListeners;
100 }
101
getUnsolEventListenersImpl() const102 ResolverEventReporter::UnsolEventListenerSet ResolverEventReporter::getUnsolEventListenersImpl()
103 const {
104 std::lock_guard lock(mMutex);
105 return mUnsolEventListeners;
106 }
107
addListenerImpl(const std::shared_ptr<INetdEventListener> & listener)108 int ResolverEventReporter::addListenerImpl(const std::shared_ptr<INetdEventListener>& listener) {
109 std::lock_guard lock(mMutex);
110 return addListenerImplLocked(listener);
111 }
112
addListenerImplLocked(const std::shared_ptr<INetdEventListener> & listener)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
addUnsolEventListenerImpl(const std::shared_ptr<IDnsResolverUnsolicitedEventListener> & listener)158 int ResolverEventReporter::addUnsolEventListenerImpl(
159 const std::shared_ptr<IDnsResolverUnsolicitedEventListener>& listener) {
160 std::lock_guard lock(mMutex);
161 return addUnsolEventListenerImplLocked(listener);
162 }
163
addUnsolEventListenerImplLocked(const std::shared_ptr<IDnsResolverUnsolicitedEventListener> & listener)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