Skip to content

Commit

Permalink
Look up ICU symbols based on the path to libflutter.so as a fallback (f…
Browse files Browse the repository at this point in the history
…lutter#8139)

The ICU data is packaged within libflutter.so, and the engine uses
dlsym(RTLD_DEFAULT) to look up the ICU data symbols in the libraries
loaded by the process.

This approach apparently fails on some Xiaomi devices.  If RTLD_DEFAULT
can not find the symbols, then the platform will pass the path to the
libflutter.so library so the engine can use that to resolve the symbols.

Fixes flutter/flutter#28208
  • Loading branch information
jason-simmons authored Mar 13, 2019
1 parent 59715b7 commit 9f50dae
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 9 deletions.
36 changes: 27 additions & 9 deletions shell/common/switches.cc
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,29 @@ static bool GetSwitchValue(const fml::CommandLine& command_line,
return false;
}

std::unique_ptr<fml::Mapping> GetSymbolMapping(std::string symbol_prefix) {
fml::RefPtr<fml::NativeLibrary> proc_library =
std::unique_ptr<fml::Mapping> GetSymbolMapping(std::string symbol_prefix,
std::string native_lib_path) {
const uint8_t* mapping;
intptr_t size;

auto lookup_symbol = [&mapping, &size, symbol_prefix](
const fml::RefPtr<fml::NativeLibrary>& library) {
mapping = library->ResolveSymbol((symbol_prefix + "_start").c_str());
size = reinterpret_cast<intptr_t>(
library->ResolveSymbol((symbol_prefix + "_size").c_str()));
};

fml::RefPtr<fml::NativeLibrary> library =
fml::NativeLibrary::CreateForCurrentProcess();
const uint8_t* mapping =
proc_library->ResolveSymbol((symbol_prefix + "_start").c_str());
const intptr_t size = reinterpret_cast<intptr_t>(
proc_library->ResolveSymbol((symbol_prefix + "_size").c_str()));
lookup_symbol(library);

if (!(mapping && size)) {
// Symbol lookup for the current process fails on some devices. As a
// fallback, try doing the lookup based on the path to the Flutter library.
library = fml::NativeLibrary::Create(native_lib_path.c_str());
lookup_symbol(library);
}

FML_CHECK(mapping && size) << "Unable to resolve symbols: " << symbol_prefix;
return std::make_unique<fml::NonOwnedMapping>(mapping, size);
}
Expand Down Expand Up @@ -228,11 +244,13 @@ blink::Settings SettingsFromCommandLine(const fml::CommandLine& command_line) {
command_line.GetOptionValue(FlagForSwitch(Switch::ICUDataFilePath),
&settings.icu_data_path);
if (command_line.HasOption(FlagForSwitch(Switch::ICUSymbolPrefix))) {
std::string icu_symbol_prefix;
std::string icu_symbol_prefix, native_lib_path;
command_line.GetOptionValue(FlagForSwitch(Switch::ICUSymbolPrefix),
&icu_symbol_prefix);
settings.icu_mapper = [icu_symbol_prefix] {
return GetSymbolMapping(icu_symbol_prefix);
command_line.GetOptionValue(FlagForSwitch(Switch::ICUNativeLibPath),
&native_lib_path);
settings.icu_mapper = [icu_symbol_prefix, native_lib_path] {
return GetSymbolMapping(icu_symbol_prefix, native_lib_path);
};
}
}
Expand Down
3 changes: 3 additions & 0 deletions shell/common/switches.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ DEF_SWITCH(ICUSymbolPrefix,
"icu-symbol-prefix",
"Prefix for the symbols representing ICU data linked into the "
"Flutter library.")
DEF_SWITCH(ICUNativeLibPath,
"icu-native-lib-path",
"Path to the library file that exports the ICU data.")
DEF_SWITCH(DartFlags,
"dart-flags",
"Flags passed directly to the Dart VM without being interpreted "
Expand Down
6 changes: 6 additions & 0 deletions shell/platform/android/io/flutter/view/FlutterMain.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.app.AlarmManager;
Expand Down Expand Up @@ -195,7 +196,12 @@ public static void ensureInitializationComplete(Context applicationContext, Stri
sResourceExtractor.waitForCompletion();

List<String> shellArgs = new ArrayList<>();

shellArgs.add("--icu-symbol-prefix=_binary_icudtl_dat");
ApplicationInfo applicationInfo = applicationContext.getPackageManager().getApplicationInfo(
applicationContext.getPackageName(), PackageManager.GET_META_DATA);
shellArgs.add("--icu-native-lib-path=" + applicationInfo.nativeLibraryDir + File.separator + DEFAULT_LIBRARY);

if (args != null) {
Collections.addAll(shellArgs, args);
}
Expand Down

0 comments on commit 9f50dae

Please sign in to comment.