diff --git a/DEPS b/DEPS index 11be5753661..1beaadf2c53 100644 --- a/DEPS +++ b/DEPS @@ -116,7 +116,7 @@ allowed_hosts = [ ] deps = { - 'src': 'https://github.com/flutter/buildroot.git' + '@' + '19317704cfb7be72c7d81953f634674ea8bee5ea', + 'src': 'https://github.com/flutter/buildroot.git' + '@' + '13ca742ec8b3d7761877197d74b003d3e646d805', # Fuchsia compatibility # diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 828ff5bd94d..4df1c866548 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -391,6 +391,7 @@ FILE: ../../../flutter/shell/platform/android/android_context_gl.cc FILE: ../../../flutter/shell/platform/android/android_context_gl.h FILE: ../../../flutter/shell/platform/android/android_environment_gl.cc FILE: ../../../flutter/shell/platform/android/android_environment_gl.h +FILE: ../../../flutter/shell/platform/android/android_exports.lst FILE: ../../../flutter/shell/platform/android/android_external_texture_gl.cc FILE: ../../../flutter/shell/platform/android/android_external_texture_gl.h FILE: ../../../flutter/shell/platform/android/android_native_window.cc diff --git a/common/settings.h b/common/settings.h index d131695f4b5..d51052f3c1e 100644 --- a/common/settings.h +++ b/common/settings.h @@ -105,6 +105,7 @@ struct Settings { bool verbose_logging = false; std::string log_tag = "flutter"; std::string icu_data_path; + MappingCallback icu_mapper; // Assets settings fml::UniqueFD::element_type assets_dir = diff --git a/fml/icu_util.cc b/fml/icu_util.cc index a432fcf9899..fa0cc02b9c2 100644 --- a/fml/icu_util.cc +++ b/fml/icu_util.cc @@ -10,6 +10,7 @@ #include "flutter/fml/build_config.h" #include "flutter/fml/logging.h" #include "flutter/fml/mapping.h" +#include "flutter/fml/native_library.h" #include "flutter/fml/paths.h" #include "third_party/icu/source/common/unicode/udata.h" @@ -22,6 +23,10 @@ class ICUContext { valid_ = SetupMapping(icu_data_path) && SetupICU(); } + ICUContext(std::unique_ptr mapping) : mapping_(std::move(mapping)) { + valid_ = SetupICU(); + } + ~ICUContext() = default; bool SetupMapping(const std::string& icu_data_path) { @@ -99,5 +104,17 @@ void InitializeICU(const std::string& icu_data_path) { [&icu_data_path]() { InitializeICUOnce(icu_data_path); }); } +void InitializeICUFromMappingOnce(std::unique_ptr mapping) { + static ICUContext* context = new ICUContext(std::move(mapping)); + FML_CHECK(context->IsValid()) + << "Unable to initialize the ICU context from a mapping."; +} + +void InitializeICUFromMapping(std::unique_ptr mapping) { + std::call_once(g_icu_init_flag, [mapping = std::move(mapping)]() mutable { + InitializeICUFromMappingOnce(std::move(mapping)); + }); +} + } // namespace icu } // namespace fml diff --git a/fml/icu_util.h b/fml/icu_util.h index edde00b8137..22b7a906efc 100644 --- a/fml/icu_util.h +++ b/fml/icu_util.h @@ -8,12 +8,15 @@ #include #include "flutter/fml/macros.h" +#include "flutter/fml/mapping.h" namespace fml { namespace icu { void InitializeICU(const std::string& icu_data_path = ""); +void InitializeICUFromMapping(std::unique_ptr mapping); + } // namespace icu } // namespace fml diff --git a/shell/common/shell.cc b/shell/common/shell.cc index c517946f2c5..2a00a44605b 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -189,6 +189,8 @@ static void PerformInitializationTasks(const blink::Settings& settings) { if (settings.icu_data_path.size() != 0) { fml::icu::InitializeICU(settings.icu_data_path); + } else if (settings.icu_mapper) { + fml::icu::InitializeICUFromMapping(settings.icu_mapper()); } else { FML_DLOG(WARNING) << "Skipping ICU initialization in the shell."; } diff --git a/shell/common/switches.cc b/shell/common/switches.cc index 295118bfec4..5b4f1abe2d5 100644 --- a/shell/common/switches.cc +++ b/shell/common/switches.cc @@ -9,6 +9,7 @@ #include #include +#include "flutter/fml/native_library.h" #include "flutter/fml/paths.h" #include "flutter/fml/string_view.h" #include "flutter/shell/version/version.h" @@ -121,6 +122,17 @@ static bool GetSwitchValue(const fml::CommandLine& command_line, return false; } +std::unique_ptr GetSymbolMapping(std::string symbol_prefix) { + fml::RefPtr proc_library = + fml::NativeLibrary::CreateForCurrentProcess(); + const uint8_t* mapping = + proc_library->ResolveSymbol((symbol_prefix + "_start").c_str()); + const intptr_t size = reinterpret_cast( + proc_library->ResolveSymbol((symbol_prefix + "_size").c_str())); + FML_CHECK(mapping && size) << "Unable to resolve symbols: " << symbol_prefix; + return std::make_unique(mapping, size); +} + blink::Settings SettingsFromCommandLine(const fml::CommandLine& command_line) { blink::Settings settings = {}; @@ -213,6 +225,14 @@ 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; + command_line.GetOptionValue(FlagForSwitch(Switch::ICUSymbolPrefix), + &icu_symbol_prefix); + settings.icu_mapper = [icu_symbol_prefix] { + return GetSymbolMapping(icu_symbol_prefix); + }; + } settings.use_test_fonts = command_line.HasOption(FlagForSwitch(Switch::UseTestFonts)); diff --git a/shell/common/switches.h b/shell/common/switches.h index b278e32d6f3..c20589dea62 100644 --- a/shell/common/switches.h +++ b/shell/common/switches.h @@ -48,6 +48,10 @@ DEF_SWITCH(AotIsolateSnapshotInstructions, "read and executable. AotSnapshotPath must be present.") DEF_SWITCH(CacheDirPath, "cache-dir-path", "Path to the cache directory.") DEF_SWITCH(ICUDataFilePath, "icu-data-file-path", "Path to the ICU data file.") +DEF_SWITCH(ICUSymbolPrefix, + "icu-symbol-prefix", + "Prefix for the symbols representing ICU data linked into the " + "Flutter library.") DEF_SWITCH(DartFlags, "dart-flags", "Flags passed directly to the Dart VM without being interpreted " diff --git a/shell/platform/android/BUILD.gn b/shell/platform/android/BUILD.gn index 0e4ec9a9582..e9d2a961f81 100644 --- a/shell/platform/android/BUILD.gn +++ b/shell/platform/android/BUILD.gn @@ -49,10 +49,12 @@ shared_library("flutter_shell_native") { "platform_view_android_jni.h", "vsync_waiter_android.cc", "vsync_waiter_android.h", + "$root_build_dir/flutter_icu/icudtl.o", ] deps = [ ":android_gpu_configuration", + ":icudtl_object", "$flutter_root/assets", "$flutter_root/common", "$flutter_root/flow", @@ -90,6 +92,8 @@ shared_library("flutter_shell_native") { "EGL", "GLESv2", ] + + ldflags = ["-Wl,--version-script=" + rebase_path("android_exports.lst")] } java_library("flutter_shell_java") { @@ -200,19 +204,25 @@ java_prebuilt("android_arch_lifecycle_viewmodel") { jar_path = "//third_party/android_support/android_arch_lifecycle_viewmodel.jar" } -copy("flutter_shell_assets") { - visibility = [ ":*" ] +action("icudtl_object") { + script = "$flutter_root/sky/tools/objcopy.py" - sources = [ - "//third_party/icu/flutter/icudtl.dat", + icudtl_input = "//third_party/icu/flutter/icudtl.dat" + icudtl_output = "$root_build_dir/flutter_icu/icudtl.o" + + inputs = [ + "$icudtl_input", ] outputs = [ - "$root_build_dir/flutter_shell_assets/{{source_file_part}}", + "$icudtl_output", ] - deps = [ - "//third_party/icu:icudata", + args = [ + "--objcopy", rebase_path(android_objcopy), + "--input", rebase_path(icudtl_input), + "--output", rebase_path(icudtl_output), + "--arch", current_cpu, ] } @@ -222,7 +232,6 @@ action("android") { inputs = [ "$root_build_dir/flutter_java.jar", "$root_build_dir/lib.stripped/libflutter.so", - "$root_build_dir/flutter_shell_assets/icudtl.dat", ] outputs = [ @@ -234,8 +243,6 @@ action("android") { rebase_path("flutter.jar", root_build_dir, root_build_dir), "--dist_jar", rebase_path("flutter_java.jar", root_build_dir, root_build_dir), - "--asset_dir", - rebase_path("flutter_shell_assets", root_build_dir, root_build_dir), "--native_lib", rebase_path("lib.stripped/libflutter.so", root_build_dir, root_build_dir), "--android_abi", @@ -243,7 +250,6 @@ action("android") { ] deps = [ - ":flutter_shell_assets", ":flutter_shell_java", ":flutter_shell_native", ] diff --git a/shell/platform/android/android_exports.lst b/shell/platform/android/android_exports.lst new file mode 100644 index 00000000000..3bea8e22e38 --- /dev/null +++ b/shell/platform/android/android_exports.lst @@ -0,0 +1,14 @@ +# Copyright 2013 The Flutter Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Linker script that exports the minimal symbols required for libflutter.so + +{ + global: + JNI_OnLoad; + _binary_icudtl_dat_start; + _binary_icudtl_dat_size; + local: + *; +}; diff --git a/shell/platform/android/io/flutter/view/FlutterMain.java b/shell/platform/android/io/flutter/view/FlutterMain.java index 9b0edbeed0b..c59e9ab1fb2 100644 --- a/shell/platform/android/io/flutter/view/FlutterMain.java +++ b/shell/platform/android/io/flutter/view/FlutterMain.java @@ -62,10 +62,6 @@ public class FlutterMain { private static final String DEFAULT_KERNEL_BLOB = "kernel_blob.bin"; private static final String DEFAULT_FLUTTER_ASSETS_DIR = "flutter_assets"; - // Assets that are shared among all Flutter apps within an APK. - private static final String SHARED_ASSET_DIR = "flutter_shared"; - private static final String SHARED_ASSET_ICU_DATA = "icudtl.dat"; - private static String fromFlutterAssets(String filePath) { return sFlutterAssetsDir + File.separator + filePath; } @@ -85,7 +81,6 @@ public class FlutterMain { private static boolean sIsPrecompiledAsBlobs; private static boolean sIsPrecompiledAsSharedLibrary; private static Settings sSettings; - private static String sIcuDataPath; private static final class ImmutableSetBuilder { static ImmutableSetBuilder newInstance() { @@ -188,7 +183,7 @@ public class FlutterMain { sResourceExtractor.waitForCompletion(); List shellArgs = new ArrayList<>(); - shellArgs.add("--icu-data-file-path=" + sIcuDataPath); + shellArgs.add("--icu-symbol-prefix=_binary_icudtl_dat"); if (args != null) { Collections.addAll(shellArgs, args); } @@ -284,10 +279,6 @@ public class FlutterMain { sResourceExtractor = new ResourceExtractor(context); - String icuAssetPath = SHARED_ASSET_DIR + File.separator + SHARED_ASSET_ICU_DATA; - sResourceExtractor.addResource(icuAssetPath); - sIcuDataPath = PathUtils.getDataDirectory(applicationContext) + File.separator + icuAssetPath; - sResourceExtractor .addResource(fromFlutterAssets(sFlx)) .addResource(fromFlutterAssets(sAotVmSnapshotData)) diff --git a/sky/tools/objcopy.py b/sky/tools/objcopy.py new file mode 100644 index 00000000000..b8da36d43b8 --- /dev/null +++ b/sky/tools/objcopy.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python +# Copyright 2013 The Flutter Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import argparse +import os +import subprocess +import sys + +# BFD architecture names recognized by objcopy. +BFD_ARCH = { + 'arm': 'arm', + 'arm64': 'aarch64', + 'x86': 'i386', + 'x64': 'i386:x86-64', +} + +# BFD target names recognized by objcopy. +BFD_TARGET = { + 'arm': 'elf32-littlearm', + 'arm64': 'elf64-littleaarch64', + 'x86': 'elf32-i386', + 'x64': 'elf64-x86-64', +} + +def main(): + parser = argparse.ArgumentParser(description='Convert a data file to an object file') + parser.add_argument('--objcopy', type=str, required=True) + parser.add_argument('--input', type=str, required=True) + parser.add_argument('--output', type=str, required=True) + parser.add_argument('--arch', type=str, required=True) + + args = parser.parse_args() + + input_dir, input_file = os.path.split(args.input) + output_path = os.path.abspath(args.output) + + subprocess.check_call([ + args.objcopy, + '-I', 'binary', + '-O', BFD_TARGET[args.arch], + '-B', BFD_ARCH[args.arch], + input_file, + output_path, + ], cwd=input_dir) + +if __name__ == '__main__': + sys.exit(main())