2021-02-25 12:00:47 +00:00
|
|
|
# Microdroid
|
|
|
|
|
|
|
|
Microdroid is a (very) lightweight version of Android that is intended to run on
|
|
|
|
on-device virtual machines. It is built from the same source code as the regular
|
|
|
|
Android, but it is much smaller; no system server, no HALs, no GUI, etc. It is
|
|
|
|
intended to host headless & native workloads only.
|
|
|
|
|
2021-06-21 05:39:12 +00:00
|
|
|
## Prerequisites
|
2021-02-25 12:00:47 +00:00
|
|
|
|
2021-08-16 12:16:50 +00:00
|
|
|
Any 64-bit target (either x86_64 or arm64) is supported. 32-bit target is not
|
2021-06-21 05:39:12 +00:00
|
|
|
supported. Note that we currently don't support user builds; only userdebug
|
|
|
|
builds are supported.
|
2021-02-25 12:00:47 +00:00
|
|
|
|
2021-07-06 12:01:21 +00:00
|
|
|
The only remaining requirement is that `com.android.virt` APEX has to be
|
2021-06-21 05:39:12 +00:00
|
|
|
pre-installed. To do this, add the following line in your product makefile.
|
2021-02-25 12:00:47 +00:00
|
|
|
|
2021-06-21 05:39:12 +00:00
|
|
|
```make
|
|
|
|
$(call inherit-product, packages/modules/Virtualization/apex/product_packages.mk)
|
2021-05-25 11:08:07 +00:00
|
|
|
```
|
|
|
|
|
2021-06-21 05:39:12 +00:00
|
|
|
Build the target after adding the line, and flash it. This step needs to be done
|
|
|
|
only once for the target.
|
|
|
|
|
|
|
|
If you are using `yukawa` (VIM3L) or `aosp_cf_x86_64_phone` (Cuttlefish), adding
|
|
|
|
above line is not necessary as it's already done.
|
2021-05-25 11:08:07 +00:00
|
|
|
|
2021-06-21 05:39:12 +00:00
|
|
|
Instructions for building and flashing Android for `yukawa` can be found
|
|
|
|
[here](../docs/getting_started/yukawa.md).
|
2021-05-25 11:08:07 +00:00
|
|
|
|
2021-06-21 05:39:12 +00:00
|
|
|
## Building and installing microdroid
|
|
|
|
|
|
|
|
Microdroid is part of the `com.android.virt` APEX. To build it and install to
|
|
|
|
the device:
|
2021-05-25 11:08:07 +00:00
|
|
|
|
|
|
|
```sh
|
2021-06-21 05:39:12 +00:00
|
|
|
banchan com.android.virt aosp_arm64
|
|
|
|
m apps_only dist
|
|
|
|
adb install out/dist/com.android.virt.apex
|
|
|
|
adb reboot
|
2021-02-25 12:00:47 +00:00
|
|
|
```
|
|
|
|
|
2021-08-16 12:16:50 +00:00
|
|
|
If your target is x86_64 (e.g. `aosp_cf_x86_64_phone`), replace `aosp_arm64`
|
2021-06-21 05:39:12 +00:00
|
|
|
with `aosp_x86_64`.
|
2021-02-25 12:00:47 +00:00
|
|
|
|
2021-06-21 05:39:12 +00:00
|
|
|
## Building an app
|
2021-02-25 12:00:47 +00:00
|
|
|
|
2021-06-21 05:39:12 +00:00
|
|
|
An app in microdroid is a shared library file embedded in an APK. The shared
|
|
|
|
library should have an entry point `android_native_main` as shown below:
|
|
|
|
|
|
|
|
```C++
|
|
|
|
extern "C" int android_native_main(int argc, char* argv[]) {
|
|
|
|
printf("Hello Microdroid!\n");
|
|
|
|
}
|
|
|
|
```
|
2021-06-15 16:59:10 +00:00
|
|
|
|
2021-06-21 05:39:12 +00:00
|
|
|
Then build it as a shared library:
|
|
|
|
|
|
|
|
```
|
|
|
|
cc_library_shared {
|
|
|
|
name: "MyMicrodroidApp",
|
|
|
|
srcs: ["**/*.cpp"],
|
|
|
|
sdk_version: "current",
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Then you need a configuration file in JSON format that defines what to load and
|
|
|
|
execute in microdroid. The name of the file can be anything and you may have
|
|
|
|
multiple configuration files if needed.
|
|
|
|
|
|
|
|
```json
|
2021-05-06 15:18:22 +00:00
|
|
|
{
|
2021-08-16 12:16:50 +00:00
|
|
|
"os": { "name": "microdroid" },
|
2021-06-21 05:39:12 +00:00
|
|
|
"task": {
|
|
|
|
"type": "microdroid_launcher",
|
2021-06-23 07:57:53 +00:00
|
|
|
"command": "MyMicrodroidApp.so"
|
2021-07-01 07:17:16 +00:00
|
|
|
}
|
2021-05-06 15:18:22 +00:00
|
|
|
}
|
2021-06-21 05:39:12 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
The value of `task.command` should match with the name of the shared library
|
2021-08-16 12:16:50 +00:00
|
|
|
defined above. If your app requires APEXes to be imported, you can declare the
|
2021-07-27 10:57:49 +00:00
|
|
|
list in `apexes` key like following.
|
|
|
|
|
2021-07-01 07:17:16 +00:00
|
|
|
```json
|
|
|
|
{
|
|
|
|
"os": ...,
|
|
|
|
"task": ...,
|
|
|
|
"apexes": [
|
|
|
|
{"name": "com.android.awesome_apex"}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
```
|
2021-06-21 05:39:12 +00:00
|
|
|
|
|
|
|
Embed the shared library and the VM configuration file in an APK:
|
|
|
|
|
|
|
|
```
|
|
|
|
android_app {
|
|
|
|
name: "MyApp",
|
|
|
|
srcs: ["**/*.java"], // if there is any java code
|
|
|
|
jni_libs: ["MyMicrodroidApp"],
|
|
|
|
use_embedded_native_libs: true,
|
|
|
|
sdk_version: "current",
|
|
|
|
}
|
|
|
|
|
|
|
|
// The VM configuration file can be embedded by simply placing it at `./assets`
|
2021-07-27 10:57:49 +00:00
|
|
|
// directory.
|
2021-06-21 05:39:12 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
Finally, you build and sign the APK.
|
|
|
|
|
|
|
|
```sh
|
2021-07-27 10:57:49 +00:00
|
|
|
TARGET_BUILD_APPS=MyApp m apps_only dist
|
2021-06-21 05:39:12 +00:00
|
|
|
m apksigner
|
2021-06-23 07:57:53 +00:00
|
|
|
apksigner sign --ks path_to_keystore out/dist/MyApp.apk
|
2021-06-21 05:39:12 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
`path_to_keystore` should be replaced with the actual path to the keystore,
|
|
|
|
which can be created as follows:
|
2021-06-15 16:59:10 +00:00
|
|
|
|
2021-06-21 05:39:12 +00:00
|
|
|
```sh
|
|
|
|
keytool -keystore my_keystore -genkey -alias my_key
|
|
|
|
```
|
|
|
|
|
|
|
|
Make sure that `.apk.idsig` file is also generated in the same directory as the
|
|
|
|
signed APK.
|
|
|
|
|
|
|
|
## Running the app on microdroid
|
|
|
|
|
|
|
|
First of all, install the signed APK to the target device.
|
|
|
|
|
|
|
|
```sh
|
2021-06-23 07:57:53 +00:00
|
|
|
adb install out/dist/MyApp.apk
|
2021-06-21 05:39:12 +00:00
|
|
|
```
|
|
|
|
|
2021-06-25 19:14:16 +00:00
|
|
|
`ALL_CAP`s below are placeholders. They need to be replaced with correct
|
2021-06-21 05:39:12 +00:00
|
|
|
values:
|
2021-08-16 12:16:50 +00:00
|
|
|
|
2021-06-21 05:39:12 +00:00
|
|
|
* `VM_CONFIG_FILE`: the name of the VM config file that you embedded in the APK.
|
2021-06-25 19:14:16 +00:00
|
|
|
(e.g. `vm_config.json`)
|
|
|
|
* `PACKAGE_NAME_OF_YOUR_APP`: package name of your app (e.g. `com.acme.app`).
|
2021-06-21 05:39:12 +00:00
|
|
|
* `PATH_TO_YOUR_APP`: path to the installed APK on the device. Can be obtained
|
|
|
|
via the following command.
|
2021-06-25 19:14:16 +00:00
|
|
|
```sh
|
|
|
|
adb shell pm path PACKAGE_NAME_OF_YOUR_APP
|
|
|
|
```
|
|
|
|
It shall report a cryptic path similar to `/data/app/~~OgZq==/com.acme.app-HudMahQ==/base.apk`.
|
2021-05-06 15:18:22 +00:00
|
|
|
|
2021-06-25 19:14:16 +00:00
|
|
|
Push idsig of the APK to the device.
|
2021-05-11 08:49:26 +00:00
|
|
|
|
|
|
|
```sh
|
2021-06-21 05:39:12 +00:00
|
|
|
TEST_ROOT=/data/local/tmp/virt
|
2021-07-27 10:57:49 +00:00
|
|
|
adb shell mkdir $TEST_ROOT
|
|
|
|
adb push out/dist/MyApp.apk.idsig $TEST_ROOT/
|
2021-05-06 15:18:22 +00:00
|
|
|
```
|
2021-03-03 11:27:38 +00:00
|
|
|
|
2021-06-21 05:39:12 +00:00
|
|
|
Execute the following commands to launch a VM. The VM will boot to microdroid
|
|
|
|
and then automatically execute your app (the shared library
|
|
|
|
`MyMicrodroidApp.so`).
|
|
|
|
|
|
|
|
```sh
|
|
|
|
TEST_ROOT=/data/local/tmp/virt
|
2021-07-27 10:57:49 +00:00
|
|
|
adb shell /apex/com.android.virt/bin/vm run-app \
|
|
|
|
--log $TEST_ROOT/log.txt \
|
|
|
|
PATH_TO_YOUR_APP \
|
|
|
|
$TEST_ROOT/MyApp.apk.idsig \
|
|
|
|
$TEST_ROOT/instance.img \
|
|
|
|
assets/VM_CONFIG_FILE
|
2021-06-21 05:39:12 +00:00
|
|
|
```
|
|
|
|
|
2021-06-29 08:16:09 +00:00
|
|
|
The last command lets you know the CID assigned to the VM. The console output
|
2021-07-27 10:57:49 +00:00
|
|
|
from the VM is stored to `$TEST_ROOT/log.txt` file for debugging purpose. If you
|
|
|
|
omit the `--log $TEST_ROOT/log.txt` option, it will be emitted to the current
|
|
|
|
console.
|
2021-06-21 05:39:12 +00:00
|
|
|
|
|
|
|
Stopping the VM can be done as follows:
|
|
|
|
|
|
|
|
```sh
|
2021-08-16 12:16:50 +00:00
|
|
|
adb shell /apex/com.android.virt/bin/vm stop $CID
|
2021-06-21 05:39:12 +00:00
|
|
|
```
|
|
|
|
|
2021-08-16 12:16:50 +00:00
|
|
|
, where `$CID` is the reported CID value. This works only when the `vm` was
|
2021-07-27 10:57:49 +00:00
|
|
|
invoked with the `--daemonize` flag. If the flag was not used, press Ctrl+C on
|
|
|
|
the console where the `vm run-app` command was invoked.
|
2021-06-21 05:39:12 +00:00
|
|
|
|
2021-03-03 11:27:38 +00:00
|
|
|
## ADB
|
|
|
|
|
2021-06-21 05:39:12 +00:00
|
|
|
On userdebug builds, you can have an adb connection to microdroid. To do so,
|
|
|
|
|
2021-05-06 15:18:22 +00:00
|
|
|
```sh
|
2021-06-21 05:39:12 +00:00
|
|
|
adb forward tcp:8000 vsock:$CID:5555
|
|
|
|
adb connect localhost:8000
|
2021-03-03 11:27:38 +00:00
|
|
|
```
|
|
|
|
|
2021-08-16 12:16:50 +00:00
|
|
|
`$CID` should be the CID that `vm` reported upon execution of the `vm run`
|
|
|
|
command in the above. You can also check it with
|
|
|
|
`adb shell "/apex/com.android.virt/bin/vm list"`. `5555` must be the value.
|
|
|
|
`8000` however can be any port on the development machine.
|
2021-03-03 11:27:38 +00:00
|
|
|
|
|
|
|
Done. Now you can log into microdroid. Have fun!
|
|
|
|
|
2021-05-06 15:18:22 +00:00
|
|
|
```sh
|
2021-03-03 11:27:38 +00:00
|
|
|
$ adb -s localhost:8000 shell
|
|
|
|
```
|