1# Microdroid 2 3Microdroid is a (very) lightweight version of Android that is intended to run on 4on-device virtual machines. It is built from the same source code as the regular 5Android, but it is much smaller; no system server, no HALs, no GUI, etc. It is 6intended to host headless & native workloads only. 7 8## Prerequisites 9 10Any 64-bit target (either x86_64 or arm64) is supported. 32-bit target is not 11supported. Note that we currently don't support user builds; only userdebug 12builds are supported. 13 14The only remaining requirement is that `com.android.virt` APEX has to be 15pre-installed. To do this, add the following line in your product makefile. 16 17```make 18$(call inherit-product, packages/modules/Virtualization/apex/product_packages.mk) 19``` 20 21Build the target after adding the line, and flash it. This step needs to be done 22only once for the target. 23 24If you are using `aosp_oriole` (Pixel 6) or `aosp_cf_x86_64_phone` (Cuttlefish), 25adding above line is not necessary as it's already done. 26 27## Building and installing microdroid 28 29Microdroid is part of the `com.android.virt` APEX. To build it and install to 30the device: 31 32```sh 33banchan com.android.virt aosp_arm64 34UNBUNDLED_BUILD_SDKS_FROM_SOURCE=true m apps_only dist 35adb install out/dist/com.android.virt.apex 36adb reboot 37``` 38 39If your target is x86_64 (e.g. `aosp_cf_x86_64_phone`), replace `aosp_arm64` 40with `aosp_x86_64`. 41 42## Building an app 43 44An app in microdroid is a shared library file embedded in an APK. The shared 45library should have an entry point `android_native_main` as shown below: 46 47```C++ 48extern "C" int android_native_main(int argc, char* argv[]) { 49 printf("Hello Microdroid!\n"); 50} 51``` 52 53Then build it as a shared library: 54 55``` 56cc_library_shared { 57 name: "MyMicrodroidApp", 58 srcs: ["**/*.cpp"], 59 sdk_version: "current", 60} 61``` 62 63Then you need a configuration file in JSON format that defines what to load and 64execute in microdroid. The name of the file can be anything and you may have 65multiple configuration files if needed. 66 67```json 68{ 69 "os": { "name": "microdroid" }, 70 "task": { 71 "type": "microdroid_launcher", 72 "command": "MyMicrodroidApp.so" 73 } 74} 75``` 76 77The value of `task.command` should match with the name of the shared library 78defined above. If your app requires APEXes to be imported, you can declare the 79list in `apexes` key like following. 80 81```json 82{ 83 "os": ..., 84 "task": ..., 85 "apexes": [ 86 {"name": "com.android.awesome_apex"} 87 ] 88} 89``` 90 91Embed the shared library and the VM configuration file in an APK: 92 93``` 94android_app { 95 name: "MyApp", 96 srcs: ["**/*.java"], // if there is any java code 97 jni_libs: ["MyMicrodroidApp"], 98 use_embedded_native_libs: true, 99 sdk_version: "current", 100} 101 102// The VM configuration file can be embedded by simply placing it at `./assets` 103// directory. 104``` 105 106Finally, you build the APK. 107 108```sh 109TARGET_BUILD_APPS=MyApp m apps_only dist 110``` 111 112## Running the app on microdroid 113 114First of all, install the APK to the target device. 115 116```sh 117adb install out/dist/MyApp.apk 118``` 119 120`ALL_CAP`s below are placeholders. They need to be replaced with correct 121values: 122 123* `VM_CONFIG_FILE`: the name of the VM config file that you embedded in the APK. 124 (e.g. `vm_config.json`) 125* `PACKAGE_NAME_OF_YOUR_APP`: package name of your app (e.g. `com.acme.app`). 126* `PATH_TO_YOUR_APP`: path to the installed APK on the device. Can be obtained 127 via the following command. 128 ```sh 129 adb shell pm path PACKAGE_NAME_OF_YOUR_APP 130 ``` 131 It shall report a cryptic path similar to `/data/app/~~OgZq==/com.acme.app-HudMahQ==/base.apk`. 132 133Execute the following commands to launch a VM. The VM will boot to microdroid 134and then automatically execute your app (the shared library 135`MyMicrodroidApp.so`). 136 137```sh 138TEST_ROOT=/data/local/tmp/virt 139adb shell /apex/com.android.virt/bin/vm run-app \ 140--log $TEST_ROOT/log.txt \ 141PATH_TO_YOUR_APP \ 142$TEST_ROOT/MyApp.apk.idsig \ 143$TEST_ROOT/instance.img \ 144assets/VM_CONFIG_FILE 145``` 146 147The last command lets you know the CID assigned to the VM. The console output 148from the VM is stored to `$TEST_ROOT/log.txt` file for debugging purpose. If you 149omit the `--log $TEST_ROOT/log.txt` option, it will be emitted to the current 150console. 151 152Stopping the VM can be done as follows: 153 154```sh 155adb shell /apex/com.android.virt/bin/vm stop $CID 156``` 157 158, where `$CID` is the reported CID value. This works only when the `vm` was 159invoked with the `--daemonize` flag. If the flag was not used, press Ctrl+C on 160the console where the `vm run-app` command was invoked. 161 162## ADB 163 164On userdebug builds, you can have an adb connection to microdroid. To do so, 165 166```sh 167adb forward tcp:8000 vsock:$CID:5555 168adb connect localhost:8000 169``` 170 171`$CID` should be the CID that `vm` reported upon execution of the `vm run` 172command in the above. You can also check it with 173`adb shell "/apex/com.android.virt/bin/vm list"`. `5555` must be the value. 174`8000` however can be any port on the development machine. 175 176Done. Now you can log into microdroid. Have fun! 177 178```sh 179$ adb -s localhost:8000 shell 180``` 181