Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1703c96e authored by Paul Hu's avatar Paul Hu Committed by Automerger Merge Worker
Browse files

Merge "[DRUEL05] Implement unsolicited dns health event" am: 79215996 am: 3014137d

Original change: https://android-review.googlesource.com/c/platform/packages/modules/DnsResolver/+/1533172

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: Ifa5440cb872e264f8c7b9d47c579130dcf4d7b1b
parents 8c11f22e 3014137d
Loading
Loading
Loading
Loading
+31 −2
Original line number Original line Diff line number Diff line
@@ -62,6 +62,8 @@
#include "stats.pb.h"
#include "stats.pb.h"


using aidl::android::net::metrics::INetdEventListener;
using aidl::android::net::metrics::INetdEventListener;
using aidl::android::net::resolv::aidl::DnsHealthEventParcel;
using aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener;
using android::net::NetworkDnsEventReported;
using android::net::NetworkDnsEventReported;


namespace android {
namespace android {
@@ -347,16 +349,43 @@ void reportDnsEvent(int eventType, const android_net_context& netContext, int la
    maybeLogQuery(eventType, netContext, event, query_name, ip_addrs);
    maybeLogQuery(eventType, netContext, event, query_name, ip_addrs);


    const auto& listeners = ResolverEventReporter::getInstance().getListeners();
    const auto& listeners = ResolverEventReporter::getInstance().getListeners();
    if (listeners.size() == 0) {
    if (listeners.empty()) {
        LOG(ERROR) << __func__
        LOG(ERROR) << __func__
                   << ": DNS event not sent since no INetdEventListener receiver is available.";
                   << ": DNS event not sent since no INetdEventListener receiver is available.";
        return;
    }
    }
    const int latencyMs = latencyUs / 1000;
    const int latencyMs = latencyUs / 1000;
    for (const auto& it : listeners) {
    for (const auto& it : listeners) {
        it->onDnsEvent(netContext.dns_netid, eventType, returnCode, latencyMs, query_name, ip_addrs,
        it->onDnsEvent(netContext.dns_netid, eventType, returnCode, latencyMs, query_name, ip_addrs,
                       total_ip_addr_count, netContext.uid);
                       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) {
bool onlyIPv4Answers(const addrinfo* res) {
+15 −0
Original line number Original line Diff line number Diff line
@@ -95,6 +95,7 @@ using aidl::android::net::IDnsResolver;
using aidl::android::net::INetd;
using aidl::android::net::INetd;
using aidl::android::net::ResolverParamsParcel;
using aidl::android::net::ResolverParamsParcel;
using aidl::android::net::metrics::INetdEventListener;
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::IDnsResolverUnsolicitedEventListener;
using aidl::android::net::resolv::aidl::Nat64PrefixEventParcel;
using aidl::android::net::resolv::aidl::Nat64PrefixEventParcel;
using aidl::android::net::resolv::aidl::PrivateDnsValidationEventParcel;
using aidl::android::net::resolv::aidl::PrivateDnsValidationEventParcel;
@@ -292,6 +293,20 @@ class ResolverTest : public ::testing::Test {
            if (dnsEvent.value() == expect) break;
            if (dnsEvent.value() == expect) break;
            LOG(INFO) << "Skip unexpected DnsEvent: " << dnsEvent.value();
            LOG(INFO) << "Skip unexpected DnsEvent: " << dnsEvent.value();
        } while (true);
        } 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 };
    enum class StatsCmp { LE, EQ };
+25 −3
Original line number Original line Diff line number Diff line
@@ -23,18 +23,21 @@


namespace android::net::resolv::aidl {
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::IDnsResolverUnsolicitedEventListener;
using ::aidl::android::net::resolv::aidl::Nat64PrefixEventParcel;
using ::aidl::android::net::resolv::aidl::Nat64PrefixEventParcel;
using ::aidl::android::net::resolv::aidl::PrivateDnsValidationEventParcel;
using ::aidl::android::net::resolv::aidl::PrivateDnsValidationEventParcel;
using android::base::Error;
using android::base::Result;
using android::base::ScopedLockAssertion;
using android::base::ScopedLockAssertion;
using std::chrono::milliseconds;
using std::chrono::milliseconds;


constexpr milliseconds kEventTimeoutMs{5000};
constexpr milliseconds kEventTimeoutMs{5000};
constexpr milliseconds kRetryIntervalMs{20};
constexpr milliseconds kRetryIntervalMs{20};


::ndk::ScopedAStatus UnsolicitedEventListener::onDnsHealthEvent(
::ndk::ScopedAStatus UnsolicitedEventListener::onDnsHealthEvent(const DnsHealthEventParcel& event) {
        const ::aidl::android::net::resolv::aidl::DnsHealthEventParcel&) {
    std::lock_guard lock(mMutex);
    // default no-op
    if (event.netId == mNetId) mDnsHealthResultRecords.push(event.healthResult);
    return ::ndk::ScopedAStatus::ok();
    return ::ndk::ScopedAStatus::ok();
}
}


@@ -105,4 +108,23 @@ bool UnsolicitedEventListener::waitForNat64Prefix(int operation, const milliseco
    return false;
    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
}  // namespace android::net::resolv::aidl
+10 −0
Original line number Original line Diff line number Diff line
@@ -23,6 +23,7 @@
#include <utility>
#include <utility>


#include <aidl/android/net/resolv/aidl/BnDnsResolverUnsolicitedEventListener.h>
#include <aidl/android/net/resolv/aidl/BnDnsResolverUnsolicitedEventListener.h>
#include <android-base/result.h>
#include <android-base/thread_annotations.h>
#include <android-base/thread_annotations.h>


namespace android::net::resolv::aidl {
namespace android::net::resolv::aidl {
@@ -48,6 +49,9 @@ class UnsolicitedEventListener
    bool waitForNat64Prefix(int operation, const std::chrono::milliseconds& timeout)
    bool waitForNat64Prefix(int operation, const std::chrono::milliseconds& timeout)
            EXCLUDES(mMutex);
            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.
    // Return true if a validation result for |serverAddr| is found; otherwise, return false.
    bool findValidationRecord(const std::string& serverAddr) const EXCLUDES(mMutex) {
    bool findValidationRecord(const std::string& serverAddr) const EXCLUDES(mMutex) {
        std::lock_guard lock(mMutex);
        std::lock_guard lock(mMutex);
@@ -64,6 +68,9 @@ class UnsolicitedEventListener
        std::lock_guard lock(mMutex);
        std::lock_guard lock(mMutex);
        mValidationRecords.clear();
        mValidationRecords.clear();
        mUnexpectedNat64PrefixUpdates = 0;
        mUnexpectedNat64PrefixUpdates = 0;

        std::queue<int> emptyQueue;
        std::swap(mDnsHealthResultRecords, emptyQueue);
    }
    }


  private:
  private:
@@ -89,6 +96,9 @@ class UnsolicitedEventListener
    // resort to timeouts that make the tests slower and flakier.
    // resort to timeouts that make the tests slower and flakier.
    int mUnexpectedNat64PrefixUpdates GUARDED_BY(mMutex);
    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;
    mutable std::mutex mMutex;
    std::condition_variable mCv;
    std::condition_variable mCv;
};
};