Provide a way to disable socket() and DNS lookups in libnetd_client.

This is a Client-only solution.
  - Add to NetdClient a per-process std::atomic_boolean
    similar to netIdForProcess and netIdForResolv.
  - The boolean says whether the process should be
    allowed Internet connectivity.
  - Add an @hide method to NetUtils.java to set the boolean;
    call it from the initialization code of the new
    process just after forking from zygote.
  - Make netdClientSocket and dnsOpenProxy check the
    boolean. If the boolean is false, return EPERM from
    socket calls.

Bug: 150028556
Test: atest netd_integration_test
Test: atest CtsAppSecurityHostTestCases:UseProcessTest
Change-Id: Ic697afd284ba250e56bd9492241452762da15770
diff --git a/tests/netd_client_test.cpp b/tests/netd_client_test.cpp
new file mode 100644
index 0000000..c8af408
--- /dev/null
+++ b/tests/netd_client_test.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <netdb.h>
+#include <netinet/in.h>
+#include <poll.h> /* poll */
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include <android-base/unique_fd.h>
+#include <gtest/gtest.h>
+
+#include "NetdClient.h"
+
+#define SKIP_IF_NO_NETWORK_CONNECTIVITY                                    \
+    do {                                                                   \
+        if (!checkNetworkConnectivity()) {                                 \
+            GTEST_LOG_(INFO) << "Skip. Required Network Connectivity. \n"; \
+            return;                                                        \
+        }                                                                  \
+    } while (0)
+
+namespace {
+
+constexpr char TEST_DOMAIN[] = "www.google.com";
+
+bool checkNetworkConnectivity() {
+    android::base::unique_fd sock(socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP));
+    if (sock == -1) return false;
+    static const sockaddr_in6 server6 = {
+            .sin6_family = AF_INET6,
+            .sin6_addr.s6_addr = {// 2000::
+                                  0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
+    int ret = connect(sock, reinterpret_cast<const sockaddr*>(&server6), sizeof(server6));
+    if (ret == 0) return true;
+    sock.reset(socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP));
+    if (sock == -1) return false;
+    static const sockaddr_in server4 = {
+            .sin_family = AF_INET,
+            .sin_addr.s_addr = __constant_htonl(0x08080808L)  // 8.8.8.8
+    };
+    ret = connect(sock, reinterpret_cast<const sockaddr*>(&server4), sizeof(server4));
+    return !ret;
+}
+
+void expectHasNetworking() {
+    // Socket
+    android::base::unique_fd ipv4(socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0)),
+            ipv6(socket(AF_INET6, SOCK_STREAM | SOCK_CLOEXEC, 0));
+    EXPECT_LE(3, ipv4);
+    EXPECT_LE(3, ipv6);
+
+    // DNS
+    addrinfo* result = nullptr;
+    errno = 0;
+    const addrinfo hints = {
+            .ai_family = AF_UNSPEC,
+            .ai_socktype = SOCK_DGRAM,
+    };
+    EXPECT_EQ(0, getaddrinfo(TEST_DOMAIN, nullptr, &hints, &result));
+    EXPECT_EQ(0, errno);
+    freeaddrinfo(result);
+}
+
+void expectNoNetworking() {
+    // Socket
+    android::base::unique_fd unixSocket(socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0));
+    EXPECT_LE(3, unixSocket);
+    android::base::unique_fd ipv4(socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0));
+    EXPECT_EQ(-1, ipv4);
+    EXPECT_EQ(EPERM, errno);
+    android::base::unique_fd ipv6(socket(AF_INET6, SOCK_STREAM | SOCK_CLOEXEC, 0));
+    EXPECT_EQ(-1, ipv6);
+    EXPECT_EQ(EPERM, errno);
+
+    // DNS
+    addrinfo* result = nullptr;
+    errno = 0;
+    const addrinfo hints = {
+            .ai_family = AF_UNSPEC,
+            .ai_socktype = SOCK_DGRAM,
+    };
+    EXPECT_EQ(EAI_NODATA, getaddrinfo(TEST_DOMAIN, nullptr, &hints, &result));
+    EXPECT_EQ(EPERM, errno);
+    freeaddrinfo(result);
+}
+
+}  // namespace
+
+TEST(NetdClientIntegrationTest, setAllowNetworkingForProcess) {
+    SKIP_IF_NO_NETWORK_CONNECTIVITY;
+    // At the beginning, we should be able to use socket since the default setting is allowing.
+    expectHasNetworking();
+    // Disable
+    setAllowNetworkingForProcess(false);
+    expectNoNetworking();
+    // Reset
+    setAllowNetworkingForProcess(true);
+    expectHasNetworking();
+}