From 42c45e2b66790a7fe97acf7a300b025d79f2aa57 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Tue, 31 Jul 2018 09:37:12 -0700 Subject: Dynamically load device-specific recovery UI lib. We used to statically link the device-specific recovery UI extension (`TARGET_RECOVERY_UI_LIB`) into `recovery`. Such a logic can't be easily migrated to Soong, as modules specified by `TARGET_RECOVERY_UI_LIB` may not be built with Soong. Instead of porting all the device-specific codes over, this CL builds and installs the UI lib as a shared library with Android.mk. `recovery` dlopen(3)'s and dlsym(3)'s `make_device` to invoke the device-specific UI lib on start. Note that in order to make dlopen(3) actually working, we have to switch `recovery` to be dynamically linked (we will make the move later anyway). Bug: 110380063 Test: Build and boot into marlin recovery image. Check that device-specific recovery UI is successfully loaded. Change-Id: Ia9861c7559a95f3f50676534540c0cb87cae4574 --- recovery_main.cpp | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'recovery_main.cpp') diff --git a/recovery_main.cpp b/recovery_main.cpp index c79d7d8d8..9a9890de0 100644 --- a/recovery_main.cpp +++ b/recovery_main.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include #include #include @@ -329,7 +330,32 @@ int main(int argc, char** argv) { printf("locale is [%s]\n", locale.c_str()); - Device* device = make_device(); + static constexpr const char* kDefaultLibRecoveryUIExt = "librecovery_ui_ext.so"; + // Intentionally not calling dlclose(3) to avoid potential gotchas (e.g. `make_device` may have + // handed out pointers to code or static [or thread-local] data and doesn't collect them all back + // in on dlclose). + void* librecovery_ui_ext = dlopen(kDefaultLibRecoveryUIExt, RTLD_NOW); + + using MakeDeviceType = decltype(&make_device); + MakeDeviceType make_device_func = nullptr; + if (librecovery_ui_ext == nullptr) { + printf("Failed to dlopen %s: %s\n", kDefaultLibRecoveryUIExt, dlerror()); + } else { + reinterpret_cast(make_device_func) = dlsym(librecovery_ui_ext, "make_device"); + if (make_device_func == nullptr) { + printf("Failed to dlsym make_device: %s\n", dlerror()); + } + } + + Device* device; + if (make_device_func == nullptr) { + printf("Falling back to the default make_device() instead\n"); + device = make_device(); + } else { + printf("Loading make_device from %s\n", kDefaultLibRecoveryUIExt); + device = (*make_device_func)(); + } + if (android::base::GetBoolProperty("ro.boot.quiescent", false)) { printf("Quiescent recovery mode.\n"); device->ResetUI(new StubRecoveryUI()); -- cgit v1.2.3