Add API for configuring a VM to run in debug mode
Bug: 185211964 Test: run the demo app Change-Id: I960839037b2f23dbce1552199d9c9e59c36053e2
This commit is contained in:
parent
d542e92021
commit
af1a74b084
|
@ -22,6 +22,10 @@ import android.system.virtualmachine.VirtualMachine;
|
|||
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 @@ public class MainActivity extends AppCompatActivity {
|
|||
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 @@ public class MainActivity extends AppCompatActivity {
|
|||
});
|
||||
}
|
||||
|
||||
/** 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -43,10 +43,12 @@ public final class VirtualMachineConfig {
|
|||
private static final String KEY_APKPATH = "apkPath";
|
||||
private static final String KEY_IDSIGPATH = "idsigPath";
|
||||
private static final String KEY_PAYLOADCONFIGPATH = "payloadConfigPath";
|
||||
private static final String KEY_DEBUGMODE = "debugMode";
|
||||
|
||||
// Paths to the APK and its idsig file of this application.
|
||||
private final String mApkPath;
|
||||
private final String mIdsigPath;
|
||||
private final boolean mDebugMode;
|
||||
|
||||
/**
|
||||
* Path within the APK to the payload config file that defines software aspects of this config.
|
||||
|
@ -55,10 +57,12 @@ public final class VirtualMachineConfig {
|
|||
|
||||
// TODO(jiyong): add more items like # of cpu, size of ram, debuggability, etc.
|
||||
|
||||
private VirtualMachineConfig(String apkPath, String idsigPath, String payloadConfigPath) {
|
||||
private VirtualMachineConfig(
|
||||
String apkPath, String idsigPath, String payloadConfigPath, boolean debugMode) {
|
||||
mApkPath = apkPath;
|
||||
mIdsigPath = idsigPath;
|
||||
mPayloadConfigPath = payloadConfigPath;
|
||||
mDebugMode = debugMode;
|
||||
}
|
||||
|
||||
/** Loads a config from a stream, for example a file. */
|
||||
|
@ -81,7 +85,8 @@ public final class VirtualMachineConfig {
|
|||
if (payloadConfigPath == null) {
|
||||
throw new VirtualMachineException("No payloadConfigPath");
|
||||
}
|
||||
return new VirtualMachineConfig(apkPath, idsigPath, payloadConfigPath);
|
||||
final boolean debugMode = b.getBoolean(KEY_DEBUGMODE);
|
||||
return new VirtualMachineConfig(apkPath, idsigPath, payloadConfigPath, debugMode);
|
||||
}
|
||||
|
||||
/** Persists this config to a stream, for example a file. */
|
||||
|
@ -91,6 +96,7 @@ public final class VirtualMachineConfig {
|
|||
b.putString(KEY_APKPATH, mApkPath);
|
||||
b.putString(KEY_IDSIGPATH, mIdsigPath);
|
||||
b.putString(KEY_PAYLOADCONFIGPATH, mPayloadConfigPath);
|
||||
b.putBoolean(KEY_DEBUGMODE, mDebugMode);
|
||||
b.writeToStream(output);
|
||||
}
|
||||
|
||||
|
@ -110,6 +116,7 @@ public final class VirtualMachineConfig {
|
|||
parcel.apk = ParcelFileDescriptor.open(new File(mApkPath), MODE_READ_ONLY);
|
||||
parcel.idsig = ParcelFileDescriptor.open(new File(mIdsigPath), MODE_READ_ONLY);
|
||||
parcel.configPath = mPayloadConfigPath;
|
||||
parcel.debug = mDebugMode;
|
||||
return parcel;
|
||||
}
|
||||
|
||||
|
@ -117,6 +124,7 @@ public final class VirtualMachineConfig {
|
|||
public static class Builder {
|
||||
private Context mContext;
|
||||
private String mPayloadConfigPath;
|
||||
private boolean mDebugMode;
|
||||
private String mIdsigPath; // TODO(jiyong): remove this
|
||||
// TODO(jiyong): add more items like # of cpu, size of ram, debuggability, etc.
|
||||
|
||||
|
@ -124,6 +132,13 @@ public final class VirtualMachineConfig {
|
|||
public Builder(Context context, String payloadConfigPath) {
|
||||
mContext = context;
|
||||
mPayloadConfigPath = payloadConfigPath;
|
||||
mDebugMode = false;
|
||||
}
|
||||
|
||||
/** Enables or disables the debug mode */
|
||||
public Builder debugMode(boolean enableOrDisable) {
|
||||
mDebugMode = enableOrDisable;
|
||||
return this;
|
||||
}
|
||||
|
||||
// TODO(jiyong): remove this. Apps shouldn't need to set the path to the idsig file. It
|
||||
|
@ -137,7 +152,7 @@ public final class VirtualMachineConfig {
|
|||
/** Builds an immutable {@link VirtualMachineConfig} */
|
||||
public VirtualMachineConfig build() {
|
||||
final String apkPath = mContext.getPackageCodePath();
|
||||
return new VirtualMachineConfig(apkPath, mIdsigPath, mPayloadConfigPath);
|
||||
return new VirtualMachineConfig(apkPath, mIdsigPath, mPayloadConfigPath, mDebugMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue