Make uid related tests compatible with Android Q

To be compatible with VPN isolation feature, DnsResolver has
different behavior fchown'ing when query socket.

sdk version >= (R+), fchown to apps' uid, otherwise fchown to AID_DNS

Make relevant tests compatible with it.

Test: atest
Bug: 161509097
Change-Id: I1c0bb4b9f35eaae32977a51c2d0a968092095cd0
diff --git a/DnsResolver.cpp b/DnsResolver.cpp
index 9c569c0..5068aef 100644
--- a/DnsResolver.cpp
+++ b/DnsResolver.cpp
@@ -17,26 +17,20 @@
 #include "DnsResolver.h"
 
 #include <android-base/logging.h>
-#include <android-base/properties.h>
 
 #include "DnsProxyListener.h"
 #include "DnsResolverService.h"
 #include "netd_resolv/resolv.h"
 #include "res_debug.h"
+#include "util.h"
 
 bool resolv_init(const ResolverNetdCallbacks* callbacks) {
     android::base::InitLogging(/*argv=*/nullptr);
     android::base::SetDefaultTag("libnetd_resolv");
     LOG(INFO) << __func__ << ": Initializing resolver";
     resolv_set_log_severity(android::base::WARNING);
-
-    uint64_t buildVersionSdk = android::base::GetUintProperty<uint64_t>("ro.build.version.sdk", 0);
-    uint64_t buildVersionPreviewSdk =
-            android::base::GetUintProperty<uint64_t>("ro.build.version.preview_sdk", 0);
-    uint64_t firstApiLevel =
-            android::base::GetUintProperty<uint64_t>("ro.product.first_api_level", 0);
     using android::net::gApiLevel;
-    gApiLevel = std::max(buildVersionSdk + !!buildVersionPreviewSdk, firstApiLevel);
+    gApiLevel = getApiLevel();
     using android::net::gResNetdCallbacks;
     gResNetdCallbacks.check_calling_permission = callbacks->check_calling_permission;
     gResNetdCallbacks.get_network_context = callbacks->get_network_context;
diff --git a/tests/resolv_integration_test.cpp b/tests/resolv_integration_test.cpp
index 716dc71..2c1dc9d 100644
--- a/tests/resolv_integration_test.cpp
+++ b/tests/resolv_integration_test.cpp
@@ -58,6 +58,7 @@
 #include <aidl/android/net/IDnsResolver.h>
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
+#include <util.h>  // getApiLevel
 #include "NetdClient.h"
 #include "ResolverStats.h"
 #include "netid_client.h"  // NETID_UNSET
@@ -161,6 +162,8 @@
     std::string mStoredValue;
 };
 
+const bool isAtLeastR = (getApiLevel() >= 30);
+
 }  // namespace
 
 class ResolverTest : public ::testing::Test {
@@ -4119,17 +4122,24 @@
     EXPECT_TRUE(fd1 != -1);
     EXPECT_TRUE(fd2 != -1);
 
-    uint8_t buf[MAXPACKET] = {};
+    uint8_t buf1[MAXPACKET] = {};
+    uint8_t buf2[MAXPACKET] = {};
     int rcode;
-    int res = getAsyncResponse(fd2, &rcode, buf, MAXPACKET);
-    EXPECT_EQ(-ECONNREFUSED, res);
-
-    memset(buf, 0, MAXPACKET);
-    res = getAsyncResponse(fd1, &rcode, buf, MAXPACKET);
-    EXPECT_EQ(-ECONNREFUSED, res);
-
-    ExpectDnsEvent(INetdEventListener::EVENT_RES_NSEND, EAI_SYSTEM, "howdy.example.com", {});
-    ExpectDnsEvent(INetdEventListener::EVENT_RES_NSEND, EAI_SYSTEM, "howdy.example.com", {});
+    int res2 = getAsyncResponse(fd2, &rcode, buf2, MAXPACKET);
+    int res1 = getAsyncResponse(fd1, &rcode, buf1, MAXPACKET);
+    // If API level >= 30 (R+), these queries should be blocked.
+    if (isAtLeastR) {
+        EXPECT_EQ(res2, -ECONNREFUSED);
+        EXPECT_EQ(res1, -ECONNREFUSED);
+        ExpectDnsEvent(INetdEventListener::EVENT_RES_NSEND, EAI_SYSTEM, "howdy.example.com", {});
+        ExpectDnsEvent(INetdEventListener::EVENT_RES_NSEND, EAI_SYSTEM, "howdy.example.com", {});
+    } else {
+        EXPECT_GT(res2, 0);
+        EXPECT_EQ("::1.2.3.4", toString(buf2, res2, AF_INET6));
+        EXPECT_GT(res1, 0);
+        EXPECT_EQ("1.2.3.4", toString(buf1, res1, AF_INET));
+        // To avoid flaky test, do not evaluate DnsEvent since event order is not guaranteed.
+    }
 }
 
 TEST_F(ResolverTest, EnforceDnsUid) {
@@ -4155,23 +4165,31 @@
     ASSERT_TRUE(mDnsClient.resolvService()->setResolverConfiguration(parcel).isOk());
 
     uint8_t buf[MAXPACKET] = {};
+    uint8_t buf2[MAXPACKET] = {};
     int rcode;
     {
         ScopeBlockedUIDRule scopeBlockUidRule(netdService, TEST_UID);
         // Dns Queries should be blocked
-        int fd1 = resNetworkQuery(TEST_NETID, host_name, ns_c_in, ns_t_a, 0);
-        int fd2 = resNetworkQuery(TEST_NETID, host_name, ns_c_in, ns_t_aaaa, 0);
+        const int fd1 = resNetworkQuery(TEST_NETID, host_name, ns_c_in, ns_t_a, 0);
+        const int fd2 = resNetworkQuery(TEST_NETID, host_name, ns_c_in, ns_t_aaaa, 0);
         EXPECT_TRUE(fd1 != -1);
         EXPECT_TRUE(fd2 != -1);
 
-        int res = getAsyncResponse(fd2, &rcode, buf, MAXPACKET);
-        EXPECT_EQ(-ECONNREFUSED, res);
-
-        memset(buf, 0, MAXPACKET);
-        res = getAsyncResponse(fd1, &rcode, buf, MAXPACKET);
-        EXPECT_EQ(-ECONNREFUSED, res);
+        const int res2 = getAsyncResponse(fd2, &rcode, buf2, MAXPACKET);
+        const int res1 = getAsyncResponse(fd1, &rcode, buf, MAXPACKET);
+        // If API level >= 30 (R+), the query should be blocked.
+        if (isAtLeastR) {
+            EXPECT_EQ(res2, -ECONNREFUSED);
+            EXPECT_EQ(res1, -ECONNREFUSED);
+        } else {
+            EXPECT_GT(res2, 0);
+            EXPECT_EQ("::1.2.3.4", toString(buf2, res2, AF_INET6));
+            EXPECT_GT(res1, 0);
+            EXPECT_EQ("1.2.3.4", toString(buf, res1, AF_INET));
+        }
     }
 
+    memset(buf, 0, MAXPACKET);
     parcel.resolverOptions.enforceDnsUid = true;
     ASSERT_TRUE(mDnsClient.resolvService()->setResolverConfiguration(parcel).isOk());
     {
@@ -5167,16 +5185,23 @@
         for (int i = 0; i < 10; i++) {
             std::string hostName = fmt::format("blocked{}.com", i);
             const addrinfo hints = {.ai_family = AF_INET, .ai_socktype = SOCK_DGRAM};
-            EXPECT_EQ(safe_getaddrinfo(hostName.c_str(), nullptr, &hints), nullptr);
+            // The query result between R+ and Q would be different, but we don't really care
+            // about the result here because this test is only used to ensure blocked uid rule
+            // won't cause bad servers.
+            safe_getaddrinfo(hostName.c_str(), nullptr, &hints);
         }
     }
-    // Since all query packets are blocked, we should not see any stats of them.
-    const std::vector<NameserverStats> expectedEmptyDnsStats = {
-            NameserverStats(listen_addr1),
+    ResolverParamsParcel setupParams = DnsResponderClient::GetDefaultResolverParamsParcel();
+    // If api level >= 30 (R+), expect all query packets to be blocked, hence we should not see any
+    // of their stats show up. Otherwise, all queries should succeed.
+    const std::vector<NameserverStats> expectedDnsStats = {
+            NameserverStats(listen_addr1).setSuccesses(isAtLeastR ? 0 : setupParams.maxSamples),
             NameserverStats(listen_addr2),
     };
-    expectStatsEqualTo(expectedEmptyDnsStats);
-    EXPECT_EQ(dns1.queries().size(), 0U);
+    expectStatsEqualTo(expectedDnsStats);
+    // If api level >= 30 (R+), expect server won't receive any queries,
+    // otherwise expect 20 == 10 * (setupParams.domains.size() + 1) queries.
+    EXPECT_EQ(dns1.queries().size(), isAtLeastR ? 0U : 10 * (setupParams.domains.size() + 1));
     EXPECT_EQ(dns2.queries().size(), 0U);
 }
 
diff --git a/util.h b/util.h
index d13a032..38f09b8 100644
--- a/util.h
+++ b/util.h
@@ -21,9 +21,29 @@
 
 #include <netinet/in.h>
 
+#include <android-base/properties.h>
+
 socklen_t sockaddrSize(const sockaddr* sa);
 socklen_t sockaddrSize(const sockaddr_storage& ss);
 
 // TODO: getExperimentFlagString
 // TODO: Migrate it to DnsResolverExperiments.cpp
 int getExperimentFlagInt(const std::string& flagName, int defaultValue);
+
+// When sdk X release branch is created, aosp's sdk version would still be X-1,
+// internal would be X. Also there might be some different setting between real devices and
+// CF. Below is the example for the sdk related properties in later R development stage. (internal
+// should be cosidered as S and aosp should be considered as R.)
+// R version is 30,                          rvc-dev  aosp(CF)  aosp(non-CF)  internal
+// ro.build.version.sdk:                     [30]     [29]      [29]          [30]
+// Note that, ro.product.first_api_level is device specific - so the value might be various.
+// ro.product.first_api_level:               [26-30]  [31]      [28]          [26-30]
+// ro.build.version.preview_sdk:             [0]      [1]       [1]           [1]
+inline uint64_t getApiLevel() {
+    uint64_t buildVersionSdk = android::base::GetUintProperty<uint64_t>("ro.build.version.sdk", 0);
+    uint64_t buildVersionPreviewSdk =
+            android::base::GetUintProperty<uint64_t>("ro.build.version.preview_sdk", 0);
+    uint64_t firstApiLevel =
+            android::base::GetUintProperty<uint64_t>("ro.product.first_api_level", 0);
+    return std::max(buildVersionSdk + !!buildVersionPreviewSdk, firstApiLevel);
+}