README.md
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