CompletableFuture can only be completed once

Also, it throws a TimeoutException instead of an ExecutionException if
get() times out. (ExecutionExceptions are thrown if the future completes
exceptionally, which is not the case here.)

Test: TH
Change-Id: If1bc359e8fefb819089e4f2885fb45ee7e3a996c
diff --git a/tests/cts/net/src/android/net/cts/ApfIntegrationTest.kt b/tests/cts/net/src/android/net/cts/ApfIntegrationTest.kt
index 79779e2..0e57019 100644
--- a/tests/cts/net/src/android/net/cts/ApfIntegrationTest.kt
+++ b/tests/cts/net/src/android/net/cts/ApfIntegrationTest.kt
@@ -63,8 +63,8 @@
 import java.lang.Thread
 import java.net.InetSocketAddress
 import java.util.concurrent.CompletableFuture
-import java.util.concurrent.ExecutionException
 import java.util.concurrent.TimeUnit
+import java.util.concurrent.TimeoutException
 import kotlin.random.Random
 import kotlin.test.assertFailsWith
 import kotlin.test.assertNotNull
@@ -114,7 +114,7 @@
             private val network: Network
     ) : PacketReader(handler, RCV_BUFFER_SIZE) {
         private var sockFd: FileDescriptor? = null
-        private val futureReply = CompletableFuture<ByteArray>()
+        private var futureReply: CompletableFuture<ByteArray>? = null
 
         override fun createFd(): FileDescriptor {
             // sockFd is closed by calling super.stop()
@@ -129,7 +129,7 @@
             // Only copy the ping data and complete the future.
             val result = recvbuf.sliceArray(8..<length)
             Log.i(TAG, "Received ping reply: ${result.toHexString()}")
-            futureReply.complete(recvbuf.sliceArray(8..<length))
+            futureReply!!.complete(recvbuf.sliceArray(8..<length))
         }
 
         fun sendPing(data: ByteArray) {
@@ -148,20 +148,17 @@
             val icmpHeader = byteArrayOf(0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
             val packet = icmpHeader + data
             Log.i(TAG, "Sent ping: ${packet.toHexString()}")
+            futureReply = CompletableFuture<ByteArray>()
             Os.sendto(sockFd!!, packet, 0, packet.size, 0, PING_DESTINATION)
         }
 
         fun expectPingReply(): ByteArray {
-            return futureReply.get(TIMEOUT_MS, TimeUnit.MILLISECONDS)
+            return futureReply!!.get(TIMEOUT_MS, TimeUnit.MILLISECONDS)
         }
 
         fun expectPingDropped() {
-            assertFailsWith(IllegalStateException::class) {
-                try {
-                    futureReply.get(TIMEOUT_MS, TimeUnit.MILLISECONDS)
-                } catch (e: ExecutionException) {
-                    throw e.cause!!
-                }
+            assertFailsWith(TimeoutException::class) {
+                futureReply!!.get(TIMEOUT_MS, TimeUnit.MILLISECONDS)
             }
         }