adb: support forwarding TCP port 0.

This CL adds support to forward or reverse TCP port 0 to allow the
system to automatically select an open port. The resolved port number
will be printed to stdout:
  $ adb forward tcp:0 tcp:8000
  12345
  $ adb reverse tcp:0 tcp:9000
  23456
This allows testing to be more robust by not hardcoding TCP ports which
may already be in use.

Forwarding port 0 is a host-only change and will work with any device,
but reversing port 0 requires the device to be updated with a new adbd
binary.

This CL also does a little bit of cleanup such as moving the alistener
class out of adb.h, and adds some error checking and additional tests.

Bug: 28051746
Test: python -m unittest discover
Test: adb_test
Test: `adb forward` and `adb reverse` with tcp:0
Change-Id: Icaa87346685b403ab5da7f0e6aa186aa091da572
diff --git a/adb/adb_utils_test.cpp b/adb/adb_utils_test.cpp
index f1ebaa1..aabc5d7 100644
--- a/adb/adb_utils_test.cpp
+++ b/adb/adb_utils_test.cpp
@@ -149,3 +149,24 @@
   ASSERT_EQ(0, adb_close(fd));
 }
 #endif
+
+TEST(adb_utils, test_forward_targets_are_valid) {
+    std::string error;
+
+    // Source port can be >= 0.
+    EXPECT_FALSE(forward_targets_are_valid("tcp:-1", "tcp:9000", &error));
+    EXPECT_TRUE(forward_targets_are_valid("tcp:0", "tcp:9000", &error));
+    EXPECT_TRUE(forward_targets_are_valid("tcp:8000", "tcp:9000", &error));
+
+    // Destination port must be >0.
+    EXPECT_FALSE(forward_targets_are_valid("tcp:8000", "tcp:-1", &error));
+    EXPECT_FALSE(forward_targets_are_valid("tcp:8000", "tcp:0", &error));
+
+    // Port must be a number.
+    EXPECT_FALSE(forward_targets_are_valid("tcp:", "tcp:9000", &error));
+    EXPECT_FALSE(forward_targets_are_valid("tcp:a", "tcp:9000", &error));
+    EXPECT_FALSE(forward_targets_are_valid("tcp:22x", "tcp:9000", &error));
+    EXPECT_FALSE(forward_targets_are_valid("tcp:8000", "tcp:", &error));
+    EXPECT_FALSE(forward_targets_are_valid("tcp:8000", "tcp:a", &error));
+    EXPECT_FALSE(forward_targets_are_valid("tcp:8000", "tcp:22x", &error));
+}