Support i18n apex in Microdroid environment
The i18n APEX expects the ANDROID_I18N_ROOT and ANDROID_TZDATA_ROOT
variables to be configured.
The ANDROID_I18N_ROOT should be set to /apex/com.android.i18n, since
this is where i18n libs are located. It is no-op if i18n APEX is not
mounted.
For now the ANDROID_TZDATA_ROOT is set to a non-existent path, since
libicu seem to work correctly without it. We might need to also add
tzdata APEX to support APIS that depend on tzdata.
Bug: 390557313
Test: atest MicrodroidTests
Change-Id: Id89bd26a9bcb7b6d0aa0935171be4a4bdf916a20
diff --git a/build/microdroid/init.rc b/build/microdroid/init.rc
index 672f47d..ce26a35 100644
--- a/build/microdroid/init.rc
+++ b/build/microdroid/init.rc
@@ -35,6 +35,16 @@
# (In Android this happens inside apexd-bootstrap.)
wait_for_prop ro.cold_boot_done true
+ # We need to define ANDROID_TZDATA_ROOT otherwise libicu complains.
+ # For now set it to a non-existent value, because libicu APIs that don't depend on tzdata work
+ # correctly without it.
+ # Once loading tzdata APEX is supported, we can set this value to /apex/com.android.tzdata.
+ # This is no-op for most microdroid VMs, and is only used if com.android.i18n APEX was mounted.
+ export ANDROID_TZDATA_ROOT /does/not/exist
+ # Set ANDROID_I18N_ROOT otherwise libicu will complain.
+ # This is no-op for most microdroid VMs, and is only used if com.android.i18n APEX was mounted.
+ export ANDROID_I18N_ROOT /apex/com.android.i18n
+
on init
mkdir /mnt/apk 0755 root root
mkdir /mnt/extra-apk 0755 root root
diff --git a/tests/testapk/Android.bp b/tests/testapk/Android.bp
index 99300e2..284d706 100644
--- a/tests/testapk/Android.bp
+++ b/tests/testapk/Android.bp
@@ -47,6 +47,7 @@
],
jni_libs: [
"MicrodroidTestNativeLib",
+ "MicrodroidTestNativeLibWithLibIcu",
"MicrodroidIdleNativeLib",
"MicrodroidEmptyNativeLib",
"MicrodroidExitNativeLib",
@@ -188,6 +189,17 @@
}
cc_library_shared {
+ name: "MicrodroidTestNativeLibWithLibIcu",
+ defaults: ["MicrodroidTestNativeLibDefaults"],
+ shared_libs: [
+ "libicu",
+ ],
+ cflags: [
+ "-D__MICRODROID_TEST_PAYLOAD_USES_LIBICU__",
+ ],
+}
+
+cc_library_shared {
name: "MicrodroidTestNativeLibSub",
defaults: ["avf_build_flags_cc"],
srcs: ["src/native/testlib.cpp"],
diff --git a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
index e2379d7..58fa262 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -2760,7 +2760,7 @@
grantPermission(USE_RELAXED_MICRODROID_ROLLBACK_PROTECTION_PERMISSION);
VirtualMachineConfig config =
- newVmConfigBuilderWithPayloadBinary("MicrodroidTestNativeLib.so")
+ newVmConfigBuilderWithPayloadBinary("MicrodroidTestNativeLibWithLibIcu.so")
.setDebugLevel(DEBUG_LEVEL_FULL)
.build();
diff --git a/tests/testapk/src/native/testbinary.cpp b/tests/testapk/src/native/testbinary.cpp
index c3904b7..355cfb1 100644
--- a/tests/testapk/src/native/testbinary.cpp
+++ b/tests/testapk/src/native/testbinary.cpp
@@ -30,6 +30,9 @@
#include <stdio.h>
#include <sys/capability.h>
#include <sys/system_properties.h>
+#ifdef __MICRODROID_TEST_PAYLOAD_USES_LIBICU__
+#include <unicode/uchar.h>
+#endif
#include <unistd.h>
#include <vm_main.h>
#include <vm_payload_restricted.h>
@@ -385,10 +388,13 @@
}
ScopedAStatus checkLibIcuIsAccessible() override {
+#ifdef __MICRODROID_TEST_PAYLOAD_USES_LIBICU__
static constexpr const char* kLibIcuPath = "/apex/com.android.i18n/lib64/libicu.so";
if (access(kLibIcuPath, R_OK) == 0) {
- // TODO(ioffe): call an API provided by libicu.so and check that it returns expected
- // value.
+ if (!u_hasBinaryProperty(U'❤' /* Emoji heart U+2764 */, UCHAR_EMOJI)) {
+ return ScopedAStatus::fromExceptionCodeWithMessage(EX_SERVICE_SPECIFIC,
+ "libicu broken!");
+ }
return ScopedAStatus::ok();
} else {
std::string msg = "failed to access " + std::string(kLibIcuPath) + "(" +
@@ -396,6 +402,12 @@
return ScopedAStatus::fromExceptionCodeWithMessage(EX_SERVICE_SPECIFIC,
msg.c_str());
}
+#else
+ return ScopedAStatus::
+ fromExceptionCodeWithMessage(EX_SERVICE_SPECIFIC,
+ "should be only used together with "
+ "MicrodroidTestNativeLibWithLibIcu.so payload");
+#endif
}
ScopedAStatus quit() override { exit(0); }