Do not loop infinitely in callback function
If we do, the callback receiver won't get other calls.
Test: MicrodroidDemoApp
Change-Id: Ib2d40e2dd120c07a500294ae483d072e6b01ae0f
diff --git a/demo/java/com/android/microdroid/demo/MainActivity.java b/demo/java/com/android/microdroid/demo/MainActivity.java
index 044a55d..8974475 100644
--- a/demo/java/com/android/microdroid/demo/MainActivity.java
+++ b/demo/java/com/android/microdroid/demo/MainActivity.java
@@ -41,6 +41,7 @@
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -120,16 +121,67 @@
private final MutableLiveData<String> mConsoleOutput = new MutableLiveData<>();
private final MutableLiveData<String> mPayloadOutput = new MutableLiveData<>();
private final MutableLiveData<VirtualMachine.Status> mStatus = new MutableLiveData<>();
+ private ExecutorService mExecutorService;
public VirtualMachineModel(Application app) {
super(app);
mStatus.setValue(VirtualMachine.Status.DELETED);
}
+ private static void postOutput(MutableLiveData<String> output, InputStream stream)
+ throws IOException {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
+ String line;
+ while ((line = reader.readLine()) != null && !Thread.interrupted()) {
+ output.postValue(line);
+ }
+ }
+
/** Runs a VM */
public void run(boolean debug) {
// Create a VM and run it.
// TODO(jiyong): remove the call to idsigPath
+ mExecutorService = Executors.newFixedThreadPool(2);
+
+ VirtualMachineCallback callback =
+ new VirtualMachineCallback() {
+ // store reference to ExecutorService to avoid race condition
+ private final ExecutorService mService = mExecutorService;
+
+ @Override
+ public void onPayloadStarted(
+ VirtualMachine vm, ParcelFileDescriptor stream) {
+ if (stream == null) {
+ mPayloadOutput.postValue("(no output available)");
+ return;
+ }
+
+ mService.execute(
+ new Runnable() {
+ @Override
+ public void run() {
+ try {
+ postOutput(
+ mPayloadOutput,
+ new FileInputStream(
+ stream.getFileDescriptor()));
+ } catch (IOException e) {
+ Log.e(
+ TAG,
+ "IOException while reading payload: "
+ + e.getMessage());
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onDied(VirtualMachine vm) {
+ mService.shutdownNow();
+ mStatus.postValue(VirtualMachine.Status.STOPPED);
+ }
+ };
+
try {
VirtualMachineConfig.Builder builder =
new VirtualMachineConfig.Builder(getApplication(), "assets/vm_config.json")
@@ -138,58 +190,25 @@
VirtualMachineManager vmm = VirtualMachineManager.getInstance(getApplication());
mVirtualMachine = vmm.getOrCreate("demo_vm", config);
mVirtualMachine.run();
- mVirtualMachine.setCallback(
- new VirtualMachineCallback() {
- @Override
- public void onPayloadStarted(
- VirtualMachine vm, ParcelFileDescriptor stream) {
- if (stream == null) {
- mPayloadOutput.postValue("(no output available)");
- return;
- }
- try {
- BufferedReader reader =
- new BufferedReader(
- new InputStreamReader(
- new FileInputStream(
- stream.getFileDescriptor())));
- String line;
- while ((line = reader.readLine()) != null) {
- mPayloadOutput.postValue(line);
- }
- } catch (IOException e) {
- Log.e(TAG, "IOException while reading payload: "
- + e.getMessage());
- }
- }
-
- @Override
- public void onDied(VirtualMachine vm) {
- mStatus.postValue(VirtualMachine.Status.STOPPED);
- }
- });
+ mVirtualMachine.setCallback(callback);
mStatus.postValue(mVirtualMachine.getStatus());
} catch (VirtualMachineException e) {
throw new RuntimeException(e);
}
// Read console output from the VM in the background
- ExecutorService executorService = Executors.newFixedThreadPool(1);
- executorService.execute(
+ mExecutorService.execute(
new Runnable() {
@Override
public void run() {
try {
- BufferedReader reader =
- new BufferedReader(
- new InputStreamReader(
- mVirtualMachine.getConsoleOutputStream()));
- while (true) {
- String line = reader.readLine();
- mConsoleOutput.postValue(line);
- }
+ postOutput(
+ mConsoleOutput, mVirtualMachine.getConsoleOutputStream());
} catch (IOException | VirtualMachineException e) {
- // Consume
+ Log.e(
+ TAG,
+ "Exception while posting console output: "
+ + e.getMessage());
}
}
});
@@ -203,6 +222,7 @@
// Consume
}
mVirtualMachine = null;
+ mExecutorService.shutdownNow();
mStatus.postValue(VirtualMachine.Status.STOPPED);
}