Support get multiple ipv4/ipv6 addresses in `apf_utils`

Test: atest NetworkStaticLibHostPythonTests
Change-Id: I806696437acf905c049762d59a46c866ff0584ef
diff --git a/staticlibs/tests/unit/host/python/apf_utils_test.py b/staticlibs/tests/unit/host/python/apf_utils_test.py
index 96b967b..2885460 100644
--- a/staticlibs/tests/unit/host/python/apf_utils_test.py
+++ b/staticlibs/tests/unit/host/python/apf_utils_test.py
@@ -25,8 +25,8 @@
     get_apf_capabilities,
     get_apf_counter,
     get_apf_counters_from_dumpsys,
-    get_ipv4_address,
-    get_ipv6_address,
+    get_ipv4_addresses,
+    get_ipv6_addresses,
     get_hardware_address,
     is_send_raw_packet_downstream_supported,
     send_raw_packet_downstream,
@@ -114,44 +114,53 @@
       get_hardware_address(self.mock_ad, "wlan0")
 
   @patch("net_tests_utils.host.python.adb_utils.adb_shell")
-  def test_get_ipv4_address_success(
+  def test_get_ipv4_addresses_success(
       self, mock_adb_shell: MagicMock
   ) -> None:
     mock_adb_shell.return_value = """
 54: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
-inet 192.168.195.162/24 brd 192.168.195.255 scope global wlan0
-valid_lft forever preferred_lft forever
+    inet 192.168.195.162/24 brd 192.168.195.255 scope global wlan0
+       valid_lft forever preferred_lft forever
+    inet 192.168.200.1/24 brd 192.168.200.255 scope global wlan0
+       valid_lft forever preferred_lft forever
 """
-    ip_address = get_ipv4_address(self.mock_ad, "wlan0")
-    asserts.assert_equal(ip_address, "192.168.195.162")
+    ip_addresses = get_ipv4_addresses(self.mock_ad, "wlan0")
+    asserts.assert_equal(ip_addresses, ["192.168.195.162", "192.168.200.1"])
 
   @patch("net_tests_utils.host.python.adb_utils.adb_shell")
-  def test_get_ipv4_address_not_found(
+  def test_get_ipv4_addresses_not_found(
       self, mock_adb_shell: MagicMock
   ) -> None:
-     mock_adb_shell.return_value = ""
-     with asserts.assert_raises(PatternNotFoundException):
-       get_ipv4_address(self.mock_ad, "wlan0")
+    mock_adb_shell.return_value = ""
+    ip_addresses = get_ipv4_addresses(self.mock_ad, "wlan0")
+    asserts.assert_equal(ip_addresses, [])
 
   @patch("net_tests_utils.host.python.adb_utils.adb_shell")
-  def test_get_ipv6_address_success(
+  def test_get_ipv6_addresses_success(
       self, mock_adb_shell: MagicMock
   ) -> None:
     mock_adb_shell.return_value = """
 54: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
-inet6 fe80::10a3:5dff:fe52:de32/64 scope link
-valid_lft forever preferred_lft forever
+    inet6 fe80::10a3:5dff:fe52:de32/64 scope link
+        valid_lft forever preferred_lft forever
+    inet6 2001:b400:e53f:164e:9c1e:780e:d1:4658/64 scope global dynamic mngtmpaddr noprefixroute
+        valid_lft 6995sec preferred_lft 6995sec
+    inet6 fe80::3aff:2199:2d8e:20d1/64 scope link noprefixroute
+        valid_lft forever preferred_lft forever
 """
-    ip_address = get_ipv6_address(self.mock_ad, "wlan0")
-    asserts.assert_equal(ip_address, "fe80::10a3:5dff:fe52:de32")
+    ip_addresses = get_ipv6_addresses(self.mock_ad, "wlan0")
+    asserts.assert_equal(ip_addresses,
+                         ["fe80::10a3:5dff:fe52:de32",
+                          "2001:b400:e53f:164e:9c1e:780e:d1:4658",
+                          "fe80::3aff:2199:2d8e:20d1"])
 
   @patch("net_tests_utils.host.python.adb_utils.adb_shell")
   def test_get_ipv6_address_not_found(
           self, mock_adb_shell: MagicMock
   ) -> None:
-      mock_adb_shell.return_value = ""
-      with asserts.assert_raises(PatternNotFoundException):
-          get_ipv6_address(self.mock_ad, "wlan0")
+    mock_adb_shell.return_value = ""
+    ip_addresses = get_ipv6_addresses(self.mock_ad, "wlan0")
+    asserts.assert_equal(ip_addresses, [])
 
   @patch("net_tests_utils.host.python.adb_utils.adb_shell")
   def test_send_raw_packet_downstream_success(
diff --git a/staticlibs/testutils/host/python/apf_utils.py b/staticlibs/testutils/host/python/apf_utils.py
index b312bcf..e84ba3e 100644
--- a/staticlibs/testutils/host/python/apf_utils.py
+++ b/staticlibs/testutils/host/python/apf_utils.py
@@ -83,14 +83,13 @@
   ad.log.debug("Getting apf counters: " + str(result))
   return result
 
-def get_ipv4_address(
+def get_ipv4_addresses(
     ad: android_device.AndroidDevice, iface_name: str
-) -> str:
-  """Retrieves the IPv4 address of a given interface on an Android device.
+) -> list[str]:
+  """Retrieves the IPv4 addresses of a given interface on an Android device.
 
   This function executes an ADB shell command (`ip -4 address show`) to get the
   network interface information and extracts the IPv4 address from the output.
-  If devices has multiple IPv4 addresses, return the first one.
   If devices have no IPv4 address, raise PatternNotFoundException.
 
   Args:
@@ -98,35 +97,31 @@
       iface_name: The name of the network interface (e.g., "wlan0").
 
   Returns:
-      The IPv4 address of the interface as a string.
-
-  Raises:
-      PatternNotFoundException: If the IPv4 address is not found in the command
-      output.
+      The IPv4 addresses of the interface as a list of string.
+      Return empty list if no IPv4 address.
   """
   # output format:
   # 54: wlan2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
-  # inet 192.168.195.162/24 brd 192.168.195.255 scope global wlan2
-  # valid_lft forever preferred_lft forever
+  #     inet 192.168.195.162/24 brd 192.168.195.255 scope global wlan2
+  #         valid_lft forever preferred_lft forever
+  #     inet 192.168.1.1/24 brd 192.168.1.255 scope global wlan2
+  #         valid_lft forever preferred_lft forever
   output = adb_utils.adb_shell(ad, f"ip -4 address show {iface_name}")
   pattern = r"inet\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\/\d+"
-  match = re.search(pattern, output)
+  matches = re.findall(pattern, output)
 
-  if match:
-    return match.group(1)  # Extract the IPv4 address string.
+  if matches:
+    return matches
   else:
-    raise PatternNotFoundException(
-      "Cannot get hardware address for " + iface_name
-    )
+    return []
 
-def get_ipv6_address(
+def get_ipv6_addresses(
     ad: android_device.AndroidDevice, iface_name: str
-) -> str:
-  """Retrieves the IPv6 address of a given interface on an Android device.
+) -> list[str]:
+  """Retrieves the IPv6 addresses of a given interface on an Android device.
 
   This function executes an ADB shell command (`ip -6 address show`) to get the
   network interface information and extracts the IPv6 address from the output.
-  If devices has multiple IPv6 addresses, return the first one.
   If devices have no IPv6 address, raise PatternNotFoundException.
 
   Args:
@@ -134,29 +129,23 @@
       iface_name: The name of the network interface (e.g., "wlan0").
 
   Returns:
-      The IPv6 address of the interface as a string.
-
-  Raises:
-      PatternNotFoundException: If the IPv6 address is not found in the command
-      output.
+      The IPv6 addresses of the interface as a list of string.
+      Return empty list if no IPv6 address.
   """
   # output format
   # 54: wlan2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
-  # inet6 fe80::10a3:5dff:fe52:de32/64 scope link
-  # valid_lft forever preferred_lft forever
+  #     inet6 fe80::10a3:5dff:fe52:de32/64 scope link
+  #         valid_lft forever preferred_lft forever
+  #     inet6 fe80::1233:aadb:3d32:1234/64 scope link
+  #         valid_lft forever preferred_lft forever
   output = adb_utils.adb_shell(ad, f"ip -6 address show {iface_name}")
-  if output is "":
-    raise PatternNotFoundException(
-      "Cannot get ipv6 address for " + iface_name
-    )
   pattern = r"inet6\s+([0-9a-fA-F:]+)\/\d+"
-  match = re.search(pattern, output)
-  if match:
-    return match.group(1)  # Extract the IPv6 address string.
+  matches = re.findall(pattern, output)
+
+  if matches:
+    return matches
   else:
-    raise PatternNotFoundException(
-      "Cannot get IPv6 address for " + iface_name
-    )
+    return []
 
 def get_hardware_address(
     ad: android_device.AndroidDevice, iface_name: str