Write an AVF app

A AVF-compatible app has two parts: The portion of the app running on the host Android OS and the portion of the app running on Microdroid within a pVM.

The portion of the app running on Android implements the user interface, non-confidential business logic, and creates and manages the lifecycle of a pVM.

The portion of the app running on Microdroid, within a pVM, is responsible for performing any tasks that need to be performed securely.

To launch and communicate with the pVM portion of your app, your host application creates a pVM and runs a native shared library within the pVM. This library implements a binder service that the host portion of the app uses to communicate with the portion of the app within a pVM. Figure 1 shows the two parts of the application and the binder communication channel:

AVF app loading and communication

Figure 1. AVF app loading and communication

Set up the configuration file

Your vm_config.json file should have an entry for the pVM's operating system and shared library. The following assets/vm_config.json file shows config file entries for Microdroid and a shared native library:

{
  "os": {
    "name": "microdroid"
  },
  "task": {
    "type": "microdroid_launcher",
    "command": MicrodroidTestNativeLib.so",
  }
}

Implement the binder service

Within your shared library, implement a binder service. For example:

extern "C"
int android_native_main(int, char**) {
  // Implement your binder service here
}

Create app code

In the host portion of your app, create code that prepares the configuration file, loads (or creates) a handle to the VM, and runs the VM. For example:

// Prepare the configuration file
VirtualMachineConfig config = new VirtualMachineConfig
  .Builder(getApplication(), "assets/vm_config.json")
  .build();

// Load (or create) the handle to a VM
VirtualMachine vm = VirtualMachineManager
  .getInstance(getApplication())
  .getOrCreate("my_vm", config);

// Run the VM
vm.run();

Communicate with VM portion of your app

To communicate with the VM portion of your app, you first register a callback to be notified when the binder service on the VM is ready. When notified, you connect to the binder server and then talk with the server using the custom AIDL interface. For example:

// Register the callback
vm.setCallback(Executors.newSingleThreadExecutor(),
  new VirtualmachineCallback() {
  @Override
  public void onPayloadReady(VirtualMachine vm) {
    // Connect to the binder server
    IBinder binder = vm.connectToVsockServer(PORT).get();
    IMyService svc = IMyService.Stub.asInterface(binder);
    // Talk with server using custom AIDL interface
    Result res = svc.doSomething();
  }
}); //exception handling & proper threading omitted
vm.run();

To download source code for a demo app that demonstrates the steps in this document, refer to MicrodroidDemo.