Add API for configuring a VM to run in debug mode
Bug: 185211964
Test: run the demo app
Change-Id: I960839037b2f23dbce1552199d9c9e59c36053e2
diff --git a/demo/java/com/android/microdroid/demo/MainActivity.java b/demo/java/com/android/microdroid/demo/MainActivity.java
index 976e37e..6373b55 100644
--- a/demo/java/com/android/microdroid/demo/MainActivity.java
+++ b/demo/java/com/android/microdroid/demo/MainActivity.java
@@ -22,6 +22,10 @@
import android.system.virtualmachine.VirtualMachineConfig;
import android.system.virtualmachine.VirtualMachineException;
import android.system.virtualmachine.VirtualMachineManager;
+import android.view.View;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.ScrollView;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
@@ -47,38 +51,77 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
+ TextView consoleView = (TextView) findViewById(R.id.consoleOutput);
+ Button runStopButton = (Button) findViewById(R.id.runStopButton);
+ ScrollView scrollView = (ScrollView) findViewById(R.id.scrollview);
- // Whenthe console model is updated, append the new line to the text view.
- TextView view = (TextView) findViewById(R.id.textview);
+ // When the console model is updated, append the new line to the text view.
VirtualMachineModel model = new ViewModelProvider(this).get(VirtualMachineModel.class);
model.getConsoleOutput()
.observeForever(
new Observer<String>() {
@Override
public void onChanged(String line) {
- view.append(line + "\n");
+ consoleView.append(line + "\n");
+ scrollView.fullScroll(View.FOCUS_DOWN);
}
});
+
+ // When the VM status is updated, change the label of the button
+ model.getStatus()
+ .observeForever(
+ new Observer<VirtualMachine.Status>() {
+ @Override
+ public void onChanged(VirtualMachine.Status status) {
+ if (status == VirtualMachine.Status.RUNNING) {
+ runStopButton.setText("Stop");
+ } else {
+ runStopButton.setText("Run");
+ consoleView.setText("");
+ }
+ }
+ });
+
+ // When the button is clicked, run or stop the VM
+ runStopButton.setOnClickListener(
+ new View.OnClickListener() {
+ public void onClick(View v) {
+ if (model.getStatus().getValue() == VirtualMachine.Status.RUNNING) {
+ model.stop();
+ } else {
+ CheckBox debugModeCheckBox = (CheckBox) findViewById(R.id.debugMode);
+ final boolean debug = debugModeCheckBox.isChecked();
+ model.run(debug);
+ }
+ }
+ });
}
/** Models a virtual machine and console output from it. */
public static class VirtualMachineModel extends AndroidViewModel {
- private final VirtualMachine mVirtualMachine;
+ private VirtualMachine mVirtualMachine;
private final MutableLiveData<String> mConsoleOutput = new MutableLiveData<>();
+ private final MutableLiveData<VirtualMachine.Status> mStatus = new MutableLiveData<>();
public VirtualMachineModel(Application app) {
super(app);
+ mStatus.setValue(VirtualMachine.Status.DELETED);
+ }
+ /** Runs a VM */
+ public void run(boolean debug) {
// Create a VM and run it.
// TODO(jiyong): remove the call to idsigPath
try {
- VirtualMachineConfig config =
+ VirtualMachineConfig.Builder builder =
new VirtualMachineConfig.Builder(getApplication(), "assets/vm_config.json")
.idsigPath("/data/local/tmp/virt/MicrodroidDemoApp.apk.idsig")
- .build();
+ .debugMode(debug);
+ VirtualMachineConfig config = builder.build();
VirtualMachineManager vmm = VirtualMachineManager.getInstance(getApplication());
mVirtualMachine = vmm.create("demo_vm", config);
mVirtualMachine.run();
+ mStatus.postValue(mVirtualMachine.getStatus());
} catch (VirtualMachineException e) {
throw new RuntimeException(e);
}
@@ -105,8 +148,25 @@
});
}
+ /** Stops the running VM */
+ public void stop() {
+ try {
+ mVirtualMachine.stop();
+ } catch (VirtualMachineException e) {
+ // Consume
+ }
+ mVirtualMachine = null;
+ mStatus.postValue(VirtualMachine.Status.STOPPED);
+ }
+
+ /** Returns the console output from the VM */
public LiveData<String> getConsoleOutput() {
return mConsoleOutput;
}
+
+ /** 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 026382f..cd30f35 100644
--- a/demo/res/layout/activity_main.xml
+++ b/demo/res/layout/activity_main.xml
@@ -9,18 +9,43 @@
android:textAlignment="textStart"
tools:context=".MainActivity">
- <ScrollView
- android:id="@+id/scrollview"
+ <LinearLayout
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:orientation="vertical">
- <TextView
- android:id="@+id/textview"
+ <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="#FFEB3B"
- android:fontFamily="monospace"
- android:textColor="#000000" />
- </ScrollView>
+ android:orientation="horizontal">
+
+ <Button
+ android:id="@+id/runStopButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Run" />
+
+ <CheckBox
+ android:id="@+id/debugMode"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="Debug mode" />
+ </LinearLayout>
+
+ <ScrollView
+ android:id="@+id/scrollview"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <TextView
+ android:id="@+id/consoleOutput"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="#FFEB3B"
+ android:fontFamily="monospace"
+ android:textColor="#000000" />
+ </ScrollView>
+ </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>