Loading DnsProxyListener.cpp +31 −2 Original line number Diff line number Diff line Loading @@ -62,6 +62,8 @@ #include "stats.pb.h" using aidl::android::net::metrics::INetdEventListener; using aidl::android::net::resolv::aidl::DnsHealthEventParcel; using aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener; using android::net::NetworkDnsEventReported; namespace android { Loading Loading @@ -347,16 +349,43 @@ void reportDnsEvent(int eventType, const android_net_context& netContext, int la maybeLogQuery(eventType, netContext, event, query_name, ip_addrs); const auto& listeners = ResolverEventReporter::getInstance().getListeners(); if (listeners.size() == 0) { if (listeners.empty()) { LOG(ERROR) << __func__ << ": DNS event not sent since no INetdEventListener receiver is available."; return; } const int latencyMs = latencyUs / 1000; for (const auto& it : listeners) { it->onDnsEvent(netContext.dns_netid, eventType, returnCode, latencyMs, query_name, ip_addrs, total_ip_addr_count, netContext.uid); } const auto& unsolEventListeners = ResolverEventReporter::getInstance().getUnsolEventListeners(); if (returnCode == NETD_RESOLV_TIMEOUT) { const DnsHealthEventParcel dnsHealthEvent = { .netId = static_cast<int32_t>(netContext.dns_netid), .healthResult = IDnsResolverUnsolicitedEventListener::DNS_HEALTH_RESULT_TIMEOUT, }; for (const auto& it : unsolEventListeners) { it->onDnsHealthEvent(dnsHealthEvent); } } else if (returnCode == NOERROR) { DnsHealthEventParcel dnsHealthEvent = { .netId = static_cast<int32_t>(netContext.dns_netid), .healthResult = IDnsResolverUnsolicitedEventListener::DNS_HEALTH_RESULT_OK, }; for (const auto& query : event.dns_query_events().dns_query_event()) { if (query.cache_hit() != CS_FOUND && query.rcode() == NS_R_NO_ERROR) { dnsHealthEvent.successRttMicros.push_back(query.latency_micros()); } } if (!dnsHealthEvent.successRttMicros.empty()) { for (const auto& it : unsolEventListeners) { it->onDnsHealthEvent(dnsHealthEvent); } } } } bool onlyIPv4Answers(const addrinfo* res) { Loading tests/resolv_integration_test.cpp +15 −0 Original line number Diff line number Diff line Loading @@ -95,6 +95,7 @@ using aidl::android::net::IDnsResolver; using aidl::android::net::INetd; using aidl::android::net::ResolverParamsParcel; using aidl::android::net::metrics::INetdEventListener; using aidl::android::net::resolv::aidl::DnsHealthEventParcel; using aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener; using aidl::android::net::resolv::aidl::Nat64PrefixEventParcel; using aidl::android::net::resolv::aidl::PrivateDnsValidationEventParcel; Loading Loading @@ -292,6 +293,20 @@ class ResolverTest : public ::testing::Test { if (dnsEvent.value() == expect) break; LOG(INFO) << "Skip unexpected DnsEvent: " << dnsEvent.value(); } while (true); while (returnCode == 0 || returnCode == RCODE_TIMEOUT) { // Blocking call until timeout. Result<int> result = sUnsolicitedEventListener->popDnsHealthResult(); ASSERT_TRUE(result.ok()) << "Expected dns health result is " << returnCode; if ((returnCode == 0 && result.value() == IDnsResolverUnsolicitedEventListener::DNS_HEALTH_RESULT_OK) || (returnCode == RCODE_TIMEOUT && result.value() == IDnsResolverUnsolicitedEventListener::DNS_HEALTH_RESULT_TIMEOUT)) { break; } LOG(INFO) << "Skip unexpected dns health result:" << result.value(); } } enum class StatsCmp { LE, EQ }; Loading tests/unsolicited_listener/unsolicited_event_listener.cpp +25 −3 Original line number Diff line number Diff line Loading @@ -23,18 +23,21 @@ namespace android::net::resolv::aidl { using ::aidl::android::net::resolv::aidl::DnsHealthEventParcel; using ::aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener; using ::aidl::android::net::resolv::aidl::Nat64PrefixEventParcel; using ::aidl::android::net::resolv::aidl::PrivateDnsValidationEventParcel; using android::base::Error; using android::base::Result; using android::base::ScopedLockAssertion; using std::chrono::milliseconds; constexpr milliseconds kEventTimeoutMs{5000}; constexpr milliseconds kRetryIntervalMs{20}; ::ndk::ScopedAStatus UnsolicitedEventListener::onDnsHealthEvent( const ::aidl::android::net::resolv::aidl::DnsHealthEventParcel&) { // default no-op ::ndk::ScopedAStatus UnsolicitedEventListener::onDnsHealthEvent(const DnsHealthEventParcel& event) { std::lock_guard lock(mMutex); if (event.netId == mNetId) mDnsHealthResultRecords.push(event.healthResult); return ::ndk::ScopedAStatus::ok(); } Loading Loading @@ -105,4 +108,23 @@ bool UnsolicitedEventListener::waitForNat64Prefix(int operation, const milliseco return false; } Result<int> UnsolicitedEventListener::popDnsHealthResult() { // Wait until the queue is not empty or timeout. android::base::Timer t; while (t.duration() < milliseconds{1000}) { { std::lock_guard lock(mMutex); if (!mDnsHealthResultRecords.empty()) break; } std::this_thread::sleep_for(kRetryIntervalMs); } std::lock_guard lock(mMutex); if (mDnsHealthResultRecords.empty()) return Error() << "Dns health result record is empty"; auto ret = mDnsHealthResultRecords.front(); mDnsHealthResultRecords.pop(); return ret; } } // namespace android::net::resolv::aidl tests/unsolicited_listener/unsolicited_event_listener.h +10 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <utility> #include <aidl/android/net/resolv/aidl/BnDnsResolverUnsolicitedEventListener.h> #include <android-base/result.h> #include <android-base/thread_annotations.h> namespace android::net::resolv::aidl { Loading @@ -48,6 +49,9 @@ class UnsolicitedEventListener bool waitForNat64Prefix(int operation, const std::chrono::milliseconds& timeout) EXCLUDES(mMutex); // Pop up last receiving dns health result. android::base::Result<int> popDnsHealthResult() EXCLUDES(mMutex); // Return true if a validation result for |serverAddr| is found; otherwise, return false. bool findValidationRecord(const std::string& serverAddr) const EXCLUDES(mMutex) { std::lock_guard lock(mMutex); Loading @@ -64,6 +68,9 @@ class UnsolicitedEventListener std::lock_guard lock(mMutex); mValidationRecords.clear(); mUnexpectedNat64PrefixUpdates = 0; std::queue<int> emptyQueue; std::swap(mDnsHealthResultRecords, emptyQueue); } private: Loading @@ -89,6 +96,9 @@ class UnsolicitedEventListener // resort to timeouts that make the tests slower and flakier. int mUnexpectedNat64PrefixUpdates GUARDED_BY(mMutex); // Used to store the dns health result from onDnsHealthEvent(). std::queue<int> mDnsHealthResultRecords GUARDED_BY(mMutex); mutable std::mutex mMutex; std::condition_variable mCv; }; Loading Loading
DnsProxyListener.cpp +31 −2 Original line number Diff line number Diff line Loading @@ -62,6 +62,8 @@ #include "stats.pb.h" using aidl::android::net::metrics::INetdEventListener; using aidl::android::net::resolv::aidl::DnsHealthEventParcel; using aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener; using android::net::NetworkDnsEventReported; namespace android { Loading Loading @@ -347,16 +349,43 @@ void reportDnsEvent(int eventType, const android_net_context& netContext, int la maybeLogQuery(eventType, netContext, event, query_name, ip_addrs); const auto& listeners = ResolverEventReporter::getInstance().getListeners(); if (listeners.size() == 0) { if (listeners.empty()) { LOG(ERROR) << __func__ << ": DNS event not sent since no INetdEventListener receiver is available."; return; } const int latencyMs = latencyUs / 1000; for (const auto& it : listeners) { it->onDnsEvent(netContext.dns_netid, eventType, returnCode, latencyMs, query_name, ip_addrs, total_ip_addr_count, netContext.uid); } const auto& unsolEventListeners = ResolverEventReporter::getInstance().getUnsolEventListeners(); if (returnCode == NETD_RESOLV_TIMEOUT) { const DnsHealthEventParcel dnsHealthEvent = { .netId = static_cast<int32_t>(netContext.dns_netid), .healthResult = IDnsResolverUnsolicitedEventListener::DNS_HEALTH_RESULT_TIMEOUT, }; for (const auto& it : unsolEventListeners) { it->onDnsHealthEvent(dnsHealthEvent); } } else if (returnCode == NOERROR) { DnsHealthEventParcel dnsHealthEvent = { .netId = static_cast<int32_t>(netContext.dns_netid), .healthResult = IDnsResolverUnsolicitedEventListener::DNS_HEALTH_RESULT_OK, }; for (const auto& query : event.dns_query_events().dns_query_event()) { if (query.cache_hit() != CS_FOUND && query.rcode() == NS_R_NO_ERROR) { dnsHealthEvent.successRttMicros.push_back(query.latency_micros()); } } if (!dnsHealthEvent.successRttMicros.empty()) { for (const auto& it : unsolEventListeners) { it->onDnsHealthEvent(dnsHealthEvent); } } } } bool onlyIPv4Answers(const addrinfo* res) { Loading
tests/resolv_integration_test.cpp +15 −0 Original line number Diff line number Diff line Loading @@ -95,6 +95,7 @@ using aidl::android::net::IDnsResolver; using aidl::android::net::INetd; using aidl::android::net::ResolverParamsParcel; using aidl::android::net::metrics::INetdEventListener; using aidl::android::net::resolv::aidl::DnsHealthEventParcel; using aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener; using aidl::android::net::resolv::aidl::Nat64PrefixEventParcel; using aidl::android::net::resolv::aidl::PrivateDnsValidationEventParcel; Loading Loading @@ -292,6 +293,20 @@ class ResolverTest : public ::testing::Test { if (dnsEvent.value() == expect) break; LOG(INFO) << "Skip unexpected DnsEvent: " << dnsEvent.value(); } while (true); while (returnCode == 0 || returnCode == RCODE_TIMEOUT) { // Blocking call until timeout. Result<int> result = sUnsolicitedEventListener->popDnsHealthResult(); ASSERT_TRUE(result.ok()) << "Expected dns health result is " << returnCode; if ((returnCode == 0 && result.value() == IDnsResolverUnsolicitedEventListener::DNS_HEALTH_RESULT_OK) || (returnCode == RCODE_TIMEOUT && result.value() == IDnsResolverUnsolicitedEventListener::DNS_HEALTH_RESULT_TIMEOUT)) { break; } LOG(INFO) << "Skip unexpected dns health result:" << result.value(); } } enum class StatsCmp { LE, EQ }; Loading
tests/unsolicited_listener/unsolicited_event_listener.cpp +25 −3 Original line number Diff line number Diff line Loading @@ -23,18 +23,21 @@ namespace android::net::resolv::aidl { using ::aidl::android::net::resolv::aidl::DnsHealthEventParcel; using ::aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener; using ::aidl::android::net::resolv::aidl::Nat64PrefixEventParcel; using ::aidl::android::net::resolv::aidl::PrivateDnsValidationEventParcel; using android::base::Error; using android::base::Result; using android::base::ScopedLockAssertion; using std::chrono::milliseconds; constexpr milliseconds kEventTimeoutMs{5000}; constexpr milliseconds kRetryIntervalMs{20}; ::ndk::ScopedAStatus UnsolicitedEventListener::onDnsHealthEvent( const ::aidl::android::net::resolv::aidl::DnsHealthEventParcel&) { // default no-op ::ndk::ScopedAStatus UnsolicitedEventListener::onDnsHealthEvent(const DnsHealthEventParcel& event) { std::lock_guard lock(mMutex); if (event.netId == mNetId) mDnsHealthResultRecords.push(event.healthResult); return ::ndk::ScopedAStatus::ok(); } Loading Loading @@ -105,4 +108,23 @@ bool UnsolicitedEventListener::waitForNat64Prefix(int operation, const milliseco return false; } Result<int> UnsolicitedEventListener::popDnsHealthResult() { // Wait until the queue is not empty or timeout. android::base::Timer t; while (t.duration() < milliseconds{1000}) { { std::lock_guard lock(mMutex); if (!mDnsHealthResultRecords.empty()) break; } std::this_thread::sleep_for(kRetryIntervalMs); } std::lock_guard lock(mMutex); if (mDnsHealthResultRecords.empty()) return Error() << "Dns health result record is empty"; auto ret = mDnsHealthResultRecords.front(); mDnsHealthResultRecords.pop(); return ret; } } // namespace android::net::resolv::aidl
tests/unsolicited_listener/unsolicited_event_listener.h +10 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <utility> #include <aidl/android/net/resolv/aidl/BnDnsResolverUnsolicitedEventListener.h> #include <android-base/result.h> #include <android-base/thread_annotations.h> namespace android::net::resolv::aidl { Loading @@ -48,6 +49,9 @@ class UnsolicitedEventListener bool waitForNat64Prefix(int operation, const std::chrono::milliseconds& timeout) EXCLUDES(mMutex); // Pop up last receiving dns health result. android::base::Result<int> popDnsHealthResult() EXCLUDES(mMutex); // Return true if a validation result for |serverAddr| is found; otherwise, return false. bool findValidationRecord(const std::string& serverAddr) const EXCLUDES(mMutex) { std::lock_guard lock(mMutex); Loading @@ -64,6 +68,9 @@ class UnsolicitedEventListener std::lock_guard lock(mMutex); mValidationRecords.clear(); mUnexpectedNat64PrefixUpdates = 0; std::queue<int> emptyQueue; std::swap(mDnsHealthResultRecords, emptyQueue); } private: Loading @@ -89,6 +96,9 @@ class UnsolicitedEventListener // resort to timeouts that make the tests slower and flakier. int mUnexpectedNat64PrefixUpdates GUARDED_BY(mMutex); // Used to store the dns health result from onDnsHealthEvent(). std::queue<int> mDnsHealthResultRecords GUARDED_BY(mMutex); mutable std::mutex mMutex; std::condition_variable mCv; }; Loading