diff --git a/thread/tests/integration/src/android/net/thread/utils/FullThreadDevice.java b/thread/tests/integration/src/android/net/thread/utils/FullThreadDevice.java index 46cf562b38..d24059a10b 100644 --- a/thread/tests/integration/src/android/net/thread/utils/FullThreadDevice.java +++ b/thread/tests/integration/src/android/net/thread/utils/FullThreadDevice.java @@ -17,16 +17,16 @@ package android.net.thread.utils; import static android.net.thread.utils.IntegrationTestUtils.SERVICE_DISCOVERY_TIMEOUT; import static android.net.thread.utils.IntegrationTestUtils.waitFor; - import static com.google.common.io.BaseEncoding.base16; +import static java.util.concurrent.TimeUnit.SECONDS; import android.net.InetAddresses; import android.net.IpPrefix; import android.net.nsd.NsdServiceInfo; import android.net.thread.ActiveOperationalDataset; - +import android.os.Handler; +import android.os.HandlerThread; import com.google.errorprone.annotations.FormatMethod; - import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; @@ -39,6 +39,8 @@ import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -60,10 +62,13 @@ public final class FullThreadDevice { private static final float PING_TIMEOUT_0_1_SECOND = 0.1f; // 1 second timeout should be used when response is expected. private static final float PING_TIMEOUT_1_SECOND = 1f; + private static final int READ_LINE_TIMEOUT_SECONDS = 5; private final Process mProcess; private final BufferedReader mReader; private final BufferedWriter mWriter; + private final HandlerThread mReaderHandlerThread; + private final Handler mReaderHandler; private ActiveOperationalDataset mActiveOperationalDataset; @@ -87,11 +92,15 @@ public final class FullThreadDevice { } mReader = new BufferedReader(new InputStreamReader(mProcess.getInputStream())); mWriter = new BufferedWriter(new OutputStreamWriter(mProcess.getOutputStream())); + mReaderHandlerThread = new HandlerThread("FullThreadDeviceReader"); + mReaderHandlerThread.start(); + mReaderHandler = new Handler(mReaderHandlerThread.getLooper()); mActiveOperationalDataset = null; } public void destroy() { mProcess.destroy(); + mReaderHandlerThread.quit(); } /** @@ -213,7 +222,7 @@ public final class FullThreadDevice { public String udpReceive() throws IOException { Pattern pattern = Pattern.compile("> (\\d+) bytes from ([\\da-f:]+) (\\d+) ([\\x00-\\x7F]+)"); - Matcher matcher = pattern.matcher(mReader.readLine()); + Matcher matcher = pattern.matcher(readLine()); matcher.matches(); return matcher.group(4); @@ -500,10 +509,27 @@ public final class FullThreadDevice { } } + private String readLine() throws IOException { + final CompletableFuture future = new CompletableFuture<>(); + mReaderHandler.post( + () -> { + try { + future.complete(mReader.readLine()); + } catch (IOException e) { + future.completeExceptionally(e); + } + }); + try { + return future.get(READ_LINE_TIMEOUT_SECONDS, SECONDS); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + throw new IOException("Failed to read a line from ot-cli-ftd"); + } + } + private List readUntilDone() throws IOException { ArrayList result = new ArrayList<>(); String line; - while ((line = mReader.readLine()) != null) { + while ((line = readLine()) != null) { if (line.equals("Done")) { break; }