From a1f3eda5a08262b238c82059ab61a5a26730caec Mon Sep 17 00:00:00 2001 From: Jason Simmons Date: Thu, 11 Jul 2019 12:39:42 -0700 Subject: [PATCH] Fall back to a fully qualified path to libapp.so if the library can not be loaded by name (#9762) libapp.so contains compiled application Dart code. On most Android systems, this library can be loaded by calling dlopen("libapp.so"), which will search Android's default library directories. On some Android devices this does not work as expected. As a workaround, this patch provides a fallback path to libapp.so based on ApplicationInfo.nativeLibraryDir. Fixes https://github.com/flutter/flutter/issues/35838 --- common/settings.cc | 6 ++++-- common/settings.h | 5 ++++- runtime/dart_snapshot.cc | 7 +++---- shell/common/switches.cc | 9 +++++---- shell/platform/android/io/flutter/view/FlutterMain.java | 5 +++++ .../darwin/ios/framework/Source/FlutterDartProject.mm | 6 +++--- 6 files changed, 24 insertions(+), 14 deletions(-) diff --git a/common/settings.cc b/common/settings.cc index 7a552f3d8e7a3..eab7c01f81bf5 100644 --- a/common/settings.cc +++ b/common/settings.cc @@ -25,8 +25,10 @@ std::string Settings::ToString() const { << std::endl; stream << "isolate_snapshot_instr_path: " << isolate_snapshot_instr_path << std::endl; - stream << "application_library_path: " << application_library_path - << std::endl; + stream << "application_library_path:" << std::endl; + for (const auto& path : application_library_path) { + stream << " " << path << std::endl; + } stream << "temp_directory_path: " << temp_directory_path << std::endl; stream << "dart_flags:" << std::endl; for (const auto& dart_flag : dart_flags) { diff --git a/common/settings.h b/common/settings.h index 7a820ce3d21e9..d55dfbb9f9c51 100644 --- a/common/settings.h +++ b/common/settings.h @@ -73,7 +73,10 @@ struct Settings { // libraries. MappingCallback dart_library_sources_kernel; - std::string application_library_path; + // Path to a library containing the application's compiled Dart code. + // This is a vector so that the embedder can provide fallback paths in + // case the primary path to the library can not be loaded. + std::vector application_library_path; std::string application_kernel_asset; // deprecated std::string application_kernel_list_asset; // deprecated diff --git a/runtime/dart_snapshot.cc b/runtime/dart_snapshot.cc index c666d1c236e62..ca4b75e467ae3 100644 --- a/runtime/dart_snapshot.cc +++ b/runtime/dart_snapshot.cc @@ -44,7 +44,7 @@ static std::unique_ptr GetFileMapping( static std::shared_ptr SearchMapping( MappingCallback embedder_mapping_callback, const std::string& file_path, - const std::string& native_library_path, + const std::vector& native_library_path, const char* native_library_symbol_name, bool is_executable) { // Ask the embedder. There is no fallback as we expect the embedders (via @@ -61,9 +61,8 @@ static std::shared_ptr SearchMapping( } // Look in application specified native library if specified. - if (native_library_path.size() > 0) { - auto native_library = - fml::NativeLibrary::Create(native_library_path.c_str()); + for (const std::string& path : native_library_path) { + auto native_library = fml::NativeLibrary::Create(path.c_str()); auto symbol_mapping = std::make_unique( native_library, native_library_symbol_name); if (symbol_mapping->GetMapping() != nullptr) { diff --git a/shell/common/switches.cc b/shell/common/switches.cc index 1f1455a7e3aa4..0000fedf68c4b 100644 --- a/shell/common/switches.cc +++ b/shell/common/switches.cc @@ -233,9 +233,8 @@ Settings SettingsFromCommandLine(const fml::CommandLine& command_line) { command_line.GetOptionValue(FlagForSwitch(Switch::FlutterAssetsDir), &settings.assets_path); - std::string aot_shared_library_name; - command_line.GetOptionValue(FlagForSwitch(Switch::AotSharedLibraryName), - &aot_shared_library_name); + std::vector aot_shared_library_name = + command_line.GetOptionValues(FlagForSwitch(Switch::AotSharedLibraryName)); std::string snapshot_asset_path; command_line.GetOptionValue(FlagForSwitch(Switch::SnapshotAssetPath), @@ -259,7 +258,9 @@ Settings SettingsFromCommandLine(const fml::CommandLine& command_line) { &isolate_snapshot_instr_filename); if (aot_shared_library_name.size() > 0) { - settings.application_library_path = aot_shared_library_name; + for (std::string_view name : aot_shared_library_name) { + settings.application_library_path.emplace_back(name); + } } else if (snapshot_asset_path.size() > 0) { settings.vm_snapshot_data_path = fml::paths::JoinPaths({snapshot_asset_path, vm_snapshot_data_filename}); diff --git a/shell/platform/android/io/flutter/view/FlutterMain.java b/shell/platform/android/io/flutter/view/FlutterMain.java index 2437af9c274a2..4e671a48e826b 100644 --- a/shell/platform/android/io/flutter/view/FlutterMain.java +++ b/shell/platform/android/io/flutter/view/FlutterMain.java @@ -169,6 +169,11 @@ public static void ensureInitializationComplete(@NonNull Context applicationCont shellArgs.add("--" + ISOLATE_SNAPSHOT_DATA_KEY + "=" + sIsolateSnapshotData); } else { shellArgs.add("--" + AOT_SHARED_LIBRARY_NAME + "=" + sAotSharedLibraryName); + + // Most devices can load the AOT shared library based on the library name + // with no directory path. Provide a fully qualified path to the library + // as a workaround for devices where that fails. + shellArgs.add("--" + AOT_SHARED_LIBRARY_NAME + "=" + applicationInfo.nativeLibraryDir + File.separator + sAotSharedLibraryName); } shellArgs.add("--cache-dir-path=" + PathUtils.getCacheDirectory(applicationContext)); diff --git a/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm b/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm index 47277007a97c3..279a3249c5eb4 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm @@ -70,7 +70,7 @@ if (hasExplicitBundle) { NSString* executablePath = bundle.executablePath; if ([[NSFileManager defaultManager] fileExistsAtPath:executablePath]) { - settings.application_library_path = executablePath.UTF8String; + settings.application_library_path.push_back(executablePath.UTF8String); } } @@ -81,7 +81,7 @@ if (libraryPath.length > 0) { NSString* executablePath = [NSBundle bundleWithPath:libraryPath].executablePath; if (executablePath.length > 0) { - settings.application_library_path = executablePath.UTF8String; + settings.application_library_path.push_back(executablePath.UTF8String); } } } @@ -95,7 +95,7 @@ NSString* executablePath = [NSBundle bundleWithPath:applicationFrameworkPath].executablePath; if (executablePath.length > 0) { - settings.application_library_path = executablePath.UTF8String; + settings.application_library_path.push_back(executablePath.UTF8String); } } }