Add the onPayloadStarted callback API
The API is called back to the client when the payload starts in the VM.
The standard output from the payload is accessible via the
ParcelFileDescriptor argument as well.
Bug: 192904048
Test: run MicrodroidDemoApp and check that the payload output is shown.
Change-Id: Ie2afbb455496eec21617b94940ed4386a4865876
diff --git a/demo/java/com/android/microdroid/demo/MainActivity.java b/demo/java/com/android/microdroid/demo/MainActivity.java
index baf0242..b6c7714 100644
--- a/demo/java/com/android/microdroid/demo/MainActivity.java
+++ b/demo/java/com/android/microdroid/demo/MainActivity.java
@@ -18,7 +18,9 @@
import android.app.Application;
import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
import android.system.virtualmachine.VirtualMachine;
+import android.system.virtualmachine.VirtualMachineCallback;
import android.system.virtualmachine.VirtualMachineConfig;
import android.system.virtualmachine.VirtualMachineException;
import android.system.virtualmachine.VirtualMachineManager;
@@ -36,6 +38,7 @@
import androidx.lifecycle.ViewModelProvider;
import java.io.BufferedReader;
+import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.ExecutorService;
@@ -52,10 +55,12 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView consoleView = (TextView) findViewById(R.id.consoleOutput);
+ TextView payloadView = (TextView) findViewById(R.id.payloadOutput);
Button runStopButton = (Button) findViewById(R.id.runStopButton);
- ScrollView scrollView = (ScrollView) findViewById(R.id.scrollview);
+ ScrollView scrollView = (ScrollView) findViewById(R.id.scrollConsoleOutput);
- // When the console model is updated, append the new line to the text view.
+ // When the console output or payload output is updated, append the new line to the
+ // corresponding text view.
VirtualMachineModel model = new ViewModelProvider(this).get(VirtualMachineModel.class);
model.getConsoleOutput()
.observeForever(
@@ -66,6 +71,14 @@
scrollView.fullScroll(View.FOCUS_DOWN);
}
});
+ model.getPayloadOutput()
+ .observeForever(
+ new Observer<String>() {
+ @Override
+ public void onChanged(String line) {
+ payloadView.append(line + "\n");
+ }
+ });
// When the VM status is updated, change the label of the button
model.getStatus()
@@ -75,9 +88,10 @@
public void onChanged(VirtualMachine.Status status) {
if (status == VirtualMachine.Status.RUNNING) {
runStopButton.setText("Stop");
+ consoleView.setText("");
+ payloadView.setText("");
} else {
runStopButton.setText("Run");
- consoleView.setText("");
}
}
});
@@ -101,6 +115,7 @@
public static class VirtualMachineModel extends AndroidViewModel {
private VirtualMachine mVirtualMachine;
private final MutableLiveData<String> mConsoleOutput = new MutableLiveData<>();
+ private final MutableLiveData<String> mPayloadOutput = new MutableLiveData<>();
private final MutableLiveData<VirtualMachine.Status> mStatus = new MutableLiveData<>();
public VirtualMachineModel(Application app) {
@@ -121,6 +136,31 @@
VirtualMachineManager vmm = VirtualMachineManager.getInstance(getApplication());
mVirtualMachine = vmm.getOrCreate("demo_vm", config);
mVirtualMachine.run();
+ mVirtualMachine.setCallback(
+ new VirtualMachineCallback() {
+ @Override
+ public void onPayloadStarted(
+ VirtualMachine vm, ParcelFileDescriptor out) {
+ try {
+ BufferedReader reader =
+ new BufferedReader(
+ new InputStreamReader(
+ new FileInputStream(
+ out.getFileDescriptor())));
+ String line;
+ while ((line = reader.readLine()) != null) {
+ mPayloadOutput.postValue(line);
+ }
+ } catch (IOException e) {
+ // Consume
+ }
+ }
+
+ @Override
+ public void onDied(VirtualMachine vm) {
+ mStatus.postValue(VirtualMachine.Status.STOPPED);
+ }
+ });
mStatus.postValue(mVirtualMachine.getStatus());
} catch (VirtualMachineException e) {
throw new RuntimeException(e);
@@ -164,6 +204,11 @@
return mConsoleOutput;
}
+ /** Returns the payload output from the VM */
+ public LiveData<String> getPayloadOutput() {
+ return mPayloadOutput;
+ }
+
/** Returns the status of the VM */
public LiveData<VirtualMachine.Status> getStatus() {
return mStatus;
diff --git a/demo/res/layout/activity_main.xml b/demo/res/layout/activity_main.xml
index cd30f35..e100027 100644
--- a/demo/res/layout/activity_main.xml
+++ b/demo/res/layout/activity_main.xml
@@ -33,10 +33,38 @@
android:text="Debug mode" />
</LinearLayout>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:text="App output:" />
+
<ScrollView
- android:id="@+id/scrollview"
+ android:id="@+id/scrollPayloadOutput"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="0dp"
+ android:layout_weight="1">
+
+ <TextView
+ android:id="@+id/payloadOutput"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="#9089e0"
+ android:fontFamily="monospace"
+ android:textColor="#000000" />
+ </ScrollView>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:text="Console output:" />
+
+ <ScrollView
+ android:id="@+id/scrollConsoleOutput"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="2">
<TextView
android:id="@+id/consoleOutput"