Fallback to IPv6 when IPv4 is not available in adb

Test: manual - make sure it works in both IPv4/IPv6 env.
BUG: 31537253
Change-Id: Ica492bff34a8c0441516a213d0e8b78fcdfd3282
Signed-off-by: Tao Wu <lepton@google.com>
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index ded8214..ad9b9fd 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -598,7 +598,10 @@
 }
 
 inline int network_loopback_server(int port, int type, std::string* error) {
-  return _fd_set_error_str(socket_loopback_server(port, type), error);
+  int fd = socket_loopback_server(port, type);
+  if (fd < 0 && errno == EAFNOSUPPORT)
+      return _fd_set_error_str(socket_loopback_server6(port, type), error);
+  return _fd_set_error_str(fd, error);
 }
 
 inline int network_inaddr_any_server(int port, int type, std::string* error) {
diff --git a/include/cutils/sockets.h b/include/cutils/sockets.h
index a93c8ea..b9c22c1 100644
--- a/include/cutils/sockets.h
+++ b/include/cutils/sockets.h
@@ -89,6 +89,7 @@
 int socket_network_client_timeout(const char* host, int port, int type,
                                   int timeout, int* getaddrinfo_error);
 int socket_loopback_server(int port, int type);
+int socket_loopback_server6(int port, int type);
 int socket_local_server(const char* name, int namespaceId, int type);
 int socket_local_server_bind(int s, const char* name, int namespaceId);
 int socket_local_client_connect(int fd, const char *name, int namespaceId,
diff --git a/libcutils/socket_loopback_server_unix.c b/libcutils/socket_loopback_server_unix.c
index b600e34..7b92fd6 100644
--- a/libcutils/socket_loopback_server_unix.c
+++ b/libcutils/socket_loopback_server_unix.c
@@ -31,24 +31,18 @@
 
 #include <cutils/sockets.h>
 
-/* open listen() port on loopback interface */
-int socket_loopback_server(int port, int type)
+static int _socket_loopback_server(int family, int type, struct sockaddr * addr, size_t size)
 {
-    struct sockaddr_in addr;
     int s, n;
 
-    memset(&addr, 0, sizeof(addr));
-    addr.sin_family = AF_INET;
-    addr.sin_port = htons(port);
-    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-
-    s = socket(AF_INET, type, 0);
-    if(s < 0) return -1;
+    s = socket(family, type, 0);
+    if(s < 0)
+        return -1;
 
     n = 1;
     setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *) &n, sizeof(n));
 
-    if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+    if(bind(s, addr, size) < 0) {
         close(s);
         return -1;
     }
@@ -60,10 +54,35 @@
 
         if (ret < 0) {
             close(s);
-            return -1; 
+            return -1;
         }
     }
 
     return s;
 }
 
+/* open listen() port on loopback IPv6 interface */
+int socket_loopback_server6(int port, int type)
+{
+    struct sockaddr_in6 addr;
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sin6_family = AF_INET6;
+    addr.sin6_port = htons(port);
+    addr.sin6_addr = in6addr_loopback;
+
+    return _socket_loopback_server(AF_INET6, type, (struct sockaddr *) &addr, sizeof(addr));
+}
+
+/* open listen() port on loopback interface */
+int socket_loopback_server(int port, int type)
+{
+    struct sockaddr_in addr;
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons(port);
+    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+    return _socket_loopback_server(AF_INET, type, (struct sockaddr *) &addr, sizeof(addr));
+}