From e53a7c2348471a48ca8822dd8a767b8dc971721a Mon Sep 17 00:00:00 2001 From: garyqian Date: Thu, 28 May 2020 04:01:57 -0700 Subject: [PATCH 01/51] Initial implementation --- shell/platform/android/BUILD.gn | 1 + .../embedding/android/FlutterView.java | 81 +++++++------- .../systemchannels/LocalizationChannel.java | 89 ++++++++++++--- .../localization/LocalizationPlugin.java | 104 ++++++++++++++++++ .../android/io/flutter/view/FlutterView.java | 67 +++++------ 5 files changed, 260 insertions(+), 82 deletions(-) create mode 100644 shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java diff --git a/shell/platform/android/BUILD.gn b/shell/platform/android/BUILD.gn index 077e203f627d4..fa9f26cf6fd87 100644 --- a/shell/platform/android/BUILD.gn +++ b/shell/platform/android/BUILD.gn @@ -205,6 +205,7 @@ android_java_sources = [ "io/flutter/plugin/editing/FlutterTextUtils.java", "io/flutter/plugin/editing/InputConnectionAdaptor.java", "io/flutter/plugin/editing/TextInputPlugin.java", + "io/flutter/plugin/localization/LocalizationPlugin.java", "io/flutter/plugin/mouse/MouseCursorPlugin.java", "io/flutter/plugin/platform/AccessibilityEventsDelegate.java", "io/flutter/plugin/platform/PlatformPlugin.java", diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterView.java b/shell/platform/android/io/flutter/embedding/android/FlutterView.java index a2091e2c2b492..fce01389a2a70 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterView.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterView.java @@ -39,7 +39,9 @@ import io.flutter.embedding.engine.renderer.FlutterUiDisplayListener; import io.flutter.embedding.engine.renderer.RenderSurface; import io.flutter.embedding.engine.systemchannels.SettingsChannel; +import io.flutter.embedding.engine.systemchannels.LocalizationChannel; import io.flutter.plugin.editing.TextInputPlugin; +import io.flutter.plugin.localization.LocalizationPlugin; import io.flutter.plugin.mouse.MouseCursorPlugin; import io.flutter.plugin.platform.PlatformViewsController; import io.flutter.view.AccessibilityBridge; @@ -101,6 +103,7 @@ public class FlutterView extends FrameLayout implements MouseCursorPlugin.MouseC // existing, stateless system channels, e.g., KeyEventChannel, TextInputChannel, etc. @Nullable private MouseCursorPlugin mouseCursorPlugin; @Nullable private TextInputPlugin textInputPlugin; + @Nullable private LocalizationPlugin localizationPlugin; @Nullable private AndroidKeyProcessor androidKeyProcessor; @Nullable private AndroidTouchProcessor androidTouchProcessor; @Nullable private AccessibilityBridge accessibilityBridge; @@ -354,7 +357,7 @@ protected void onConfigurationChanged(@NonNull Configuration newConfig) { // again (e.g. in onStart). if (flutterEngine != null) { Log.v(TAG, "Configuration changed. Sending locales and user settings to Flutter."); - sendLocalesToFlutter(newConfig); + localizationPlugin.sendLocalesToDart(newConfig); sendUserSettingsToFlutter(); } } @@ -815,6 +818,10 @@ public void attachToFlutterEngine(@NonNull FlutterEngine flutterEngine) { this, this.flutterEngine.getTextInputChannel(), this.flutterEngine.getPlatformViewsController()); + localizationPlugin = + new LocalizationPlugin( + getContext(), + this.flutterEngine.getLocalizationChannel()); androidKeyProcessor = new AndroidKeyProcessor(this.flutterEngine.getKeyEventChannel(), textInputPlugin); androidTouchProcessor = new AndroidTouchProcessor(this.flutterEngine.getRenderer()); @@ -841,7 +848,7 @@ public void attachToFlutterEngine(@NonNull FlutterEngine flutterEngine) { // Push View and Context related information from Android to Flutter. sendUserSettingsToFlutter(); - sendLocalesToFlutter(getResources().getConfiguration()); + localizationPlugin.sendLocalesToDart(getResources().getConfiguration()); sendViewportMetricsToFlutter(); flutterEngine.getPlatformViewsController().attachToView(this); @@ -944,41 +951,41 @@ public void removeFlutterEngineAttachmentListener( flutterEngineAttachmentListeners.remove(listener); } - /** - * Send the current {@link Locale} configuration to Flutter. - * - *

FlutterEngine must be non-null when this method is invoked. - */ - @SuppressWarnings("deprecation") - private void sendLocalesToFlutter(@NonNull Configuration config) { - List locales = new ArrayList<>(); - if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { - LocaleList localeList = config.getLocales(); - int localeCount = localeList.size(); - for (int index = 0; index < localeCount; ++index) { - Locale locale = localeList.get(index); - locales.add(locale); - } - } else { - locales.add(config.locale); - } - - Locale platformResolvedLocale = null; - if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { - List languageRanges = new ArrayList<>(); - LocaleList localeList = config.getLocales(); - int localeCount = localeList.size(); - for (int index = 0; index < localeCount; ++index) { - Locale locale = localeList.get(index); - languageRanges.add(new Locale.LanguageRange(locale.toLanguageTag())); - } - // TODO(garyq) implement a real locale resolution. - platformResolvedLocale = - Locale.lookup(languageRanges, Arrays.asList(Locale.getAvailableLocales())); - } - - flutterEngine.getLocalizationChannel().sendLocales(locales, platformResolvedLocale); - } + // /** + // * Send the current {@link Locale} configuration to Flutter. + // * + // *

FlutterEngine must be non-null when this method is invoked. + // */ + // @SuppressWarnings("deprecation") + // private void sendLocalesToFlutter(@NonNull Configuration config) { + // List locales = new ArrayList<>(); + // if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { + // LocaleList localeList = config.getLocales(); + // int localeCount = localeList.size(); + // for (int index = 0; index < localeCount; ++index) { + // Locale locale = localeList.get(index); + // locales.add(locale); + // } + // } else { + // locales.add(config.locale); + // } + + // Locale platformResolvedLocale = null; + // if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { + // List languageRanges = new ArrayList<>(); + // LocaleList localeList = config.getLocales(); + // int localeCount = localeList.size(); + // for (int index = 0; index < localeCount; ++index) { + // Locale locale = localeList.get(index); + // languageRanges.add(new Locale.LanguageRange(locale.toLanguageTag())); + // } + // // TODO(garyq) implement a real locale resolution. + // platformResolvedLocale = + // Locale.lookup(languageRanges, Arrays.asList(Locale.getAvailableLocales())); + // } + + // flutterEngine.getLocalizationChannel().sendLocales(locales, platformResolvedLocale); + // } /** * Send various user preferences of this Android device to Flutter. diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/LocalizationChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/LocalizationChannel.java index 580b2df8764d5..ef6192862b797 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/LocalizationChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/LocalizationChannel.java @@ -6,40 +6,74 @@ import android.os.Build; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import io.flutter.Log; import io.flutter.embedding.engine.dart.DartExecutor; import io.flutter.plugin.common.JSONMethodCodec; +import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import java.util.ArrayList; import java.util.List; import java.util.Locale; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; /** Sends the platform's locales to Dart. */ public class LocalizationChannel { private static final String TAG = "LocalizationChannel"; @NonNull public final MethodChannel channel; + @Nullable private LocalizationMethodHandler localizationMethodHandler; + + private MethodChannel.MethodCallHandler parsingMethodHandler = + new MethodChannel.MethodCallHandler() { + @Override + public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) { + if (localizationMethodHandler == null) { + // If no explicit LocalizationMethodHandler has been registered then we don't + // need to forward this call to an API. Return. + return; + } + + String method = call.method; + Object args = call.arguments; + Log.v(TAG, "Received '" + method + "' message."); + switch (method) { + case "Localization.resolveLocale": + try { + final JSONObject arguments = (JSONObject) args; + final int length = arguments.getInt("count"); + final JSONArray supportedLocalesData = arguments.getJSONArray("localeData"); + List supportedLocales = new ArrayList(); + for (int i = 0; i < length; i++) { + // Java locales only support language, country, and variant. + final String language = supportedLocalesData.getString(i * 2 + 0); + final String country = supportedLocalesData.getString(i * 2 + 1); + supportedLocales.add(new Locale(language, country)); + } + Locale resolvedLocale = localizationMethodHandler.resolveLocale(supportedLocales); + result.success(resolvedLocale.toString()); + } catch (JSONException exception) { + result.error("error", exception.getMessage(), null); + } + break; + default: + result.notImplemented(); + break; + } + } + }; public LocalizationChannel(@NonNull DartExecutor dartExecutor) { this.channel = new MethodChannel(dartExecutor, "flutter/localization", JSONMethodCodec.INSTANCE); + channel.setMethodCallHandler(parsingMethodHandler); } /** Send the given {@code locales} to Dart. */ - public void sendLocales(@NonNull List locales, Locale platformResolvedLocale) { + public void sendLocales(@NonNull List locales) { Log.v(TAG, "Sending Locales to Flutter."); - // Send platformResolvedLocale first as it may be used in the callback - // triggered by the user supported locales being updated/set. - if (platformResolvedLocale != null) { - List platformResolvedLocaleData = new ArrayList<>(); - platformResolvedLocaleData.add(platformResolvedLocale.getLanguage()); - platformResolvedLocaleData.add(platformResolvedLocale.getCountry()); - platformResolvedLocaleData.add( - Build.VERSION.SDK_INT >= 21 ? platformResolvedLocale.getScript() : ""); - platformResolvedLocaleData.add(platformResolvedLocale.getVariant()); - channel.invokeMethod("setPlatformResolvedLocale", platformResolvedLocaleData); - } - // Send the user's preferred locales. List data = new ArrayList<>(); for (Locale locale : locales) { @@ -60,4 +94,33 @@ public void sendLocales(@NonNull List locales, Locale platformResolvedLo } channel.invokeMethod("setLocale", data); } + + /** Send the given {@code locales} to Dart. */ + public void sendPlatformResolvedLocales(Locale platformResolvedLocale) { + Log.v(TAG, "Sending Locales to Flutter."); + // Send platformResolvedLocale first as it may be used in the callback + // triggered by the user supported locales being updated/set. + if (platformResolvedLocale != null) { + List platformResolvedLocaleData = new ArrayList<>(); + platformResolvedLocaleData.add(platformResolvedLocale.getLanguage()); + platformResolvedLocaleData.add(platformResolvedLocale.getCountry()); + platformResolvedLocaleData.add( + Build.VERSION.SDK_INT >= 21 ? platformResolvedLocale.getScript() : ""); + platformResolvedLocaleData.add(platformResolvedLocale.getVariant()); + channel.invokeMethod("setPlatformResolvedLocale", platformResolvedLocaleData); + } + } + + /** + * Sets the {@link TextInputMethodHandler} which receives all events and requests that are parsed + * from the underlying platform channel. + */ + public void setLocalizationMethodHandler(@Nullable LocalizationMethodHandler localizationMethodHandler) { + this.localizationMethodHandler = localizationMethodHandler; + } + + public interface LocalizationMethodHandler { + /** Performs the android native locale resolution. */ + Locale resolveLocale(List supportedLocales); + } } diff --git a/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java b/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java new file mode 100644 index 0000000000000..b250f14515a54 --- /dev/null +++ b/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java @@ -0,0 +1,104 @@ +// 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. + +package io.flutter.plugin.localization; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.res.Configuration; +import android.os.Build; +import android.os.LocaleList; +import android.provider.Settings; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; +import io.flutter.embedding.engine.systemchannels.LocalizationChannel; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; + +/** Android implementation of the localization plugin. */ +public class LocalizationPlugin { + @NonNull private final LocalizationChannel localizationChannel; + @NonNull private final Context context; + + public LocalizationPlugin( + @NonNull Context context, + @NonNull LocalizationChannel localizationChannel) { + + this.context = context; + this.localizationChannel = localizationChannel; + localizationChannel.setLocalizationMethodHandler( + new LocalizationChannel.LocalizationMethodHandler() { + @Override + public Locale resolveLocale(List supportedLocales) { + return resolveNativeLocale(supportedLocales); + } + }); + } + + private Locale resolveNativeLocale(List supportedLocales) { + Locale platformResolvedLocale = null; + if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { + List languageRanges = new ArrayList<>(); + LocaleList localeList = context.getResources().getConfiguration().getLocales(); + int localeCount = localeList.size(); + for (int index = 0; index < localeCount; ++index) { + Locale locale = localeList.get(index); + languageRanges.add(new Locale.LanguageRange(locale.toLanguageTag())); + } + // TODO(garyq) implement a real locale resolution. + platformResolvedLocale = + Locale.lookup(languageRanges, supportedLocales); + } + return platformResolvedLocale; + } + + /** + * Send the current {@link Locale} configuration to Flutter. + * + *

FlutterEngine must be non-null when this method is invoked. + */ + @SuppressWarnings("deprecation") + public void sendLocalesToDart(@NonNull Configuration config) { + List locales = new ArrayList<>(); + if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { + LocaleList localeList = config.getLocales(); + int localeCount = localeList.size(); + for (int index = 0; index < localeCount; ++index) { + Locale locale = localeList.get(index); + locales.add(locale); + } + } else { + locales.add(config.locale); + } + + Locale platformResolvedLocale = null; + if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { + List languageRanges = new ArrayList<>(); + LocaleList localeList = config.getLocales(); + int localeCount = localeList.size(); + for (int index = 0; index < localeCount; ++index) { + Locale locale = localeList.get(index); + languageRanges.add(new Locale.LanguageRange(locale.toLanguageTag())); + } + // TODO(garyq) implement a real locale resolution. + platformResolvedLocale = + Locale.lookup(languageRanges, Arrays.asList(Locale.getAvailableLocales())); + } + + localizationChannel.sendLocales(locales); + localizationChannel.sendPlatformResolvedLocales(platformResolvedLocale); + } + + /** + * Cleans up the handler in the LocalizationChannel/ + * + *

The TextInputPlugin instance should not be used after calling this. + */ + public void destroy() { + localizationChannel.setLocalizationMethodHandler(null); + } +} diff --git a/shell/platform/android/io/flutter/view/FlutterView.java b/shell/platform/android/io/flutter/view/FlutterView.java index d5c79c9eb5459..e28bc030e4ab6 100644 --- a/shell/platform/android/io/flutter/view/FlutterView.java +++ b/shell/platform/android/io/flutter/view/FlutterView.java @@ -59,6 +59,7 @@ import io.flutter.plugin.common.ActivityLifecycleListener; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.editing.TextInputPlugin; +import io.flutter.plugin.localization.LocalizationPlugin; import io.flutter.plugin.mouse.MouseCursorPlugin; import io.flutter.plugin.platform.PlatformPlugin; import io.flutter.plugin.platform.PlatformViewsController; @@ -124,6 +125,7 @@ static final class ViewportMetrics { private final SystemChannel systemChannel; private final InputMethodManager mImm; private final TextInputPlugin mTextInputPlugin; + private final LocalizationPlugin mLocalizationPlugin; private final MouseCursorPlugin mMouseCursorPlugin; private final AndroidKeyProcessor androidKeyProcessor; private final AndroidTouchProcessor androidTouchProcessor; @@ -231,6 +233,7 @@ public void onPostResume() { } else { mMouseCursorPlugin = null; } + mLocalizationPlugin = new LocalizationPlugin(context, localizationChannel); androidKeyProcessor = new AndroidKeyProcessor(keyEventChannel, mTextInputPlugin); androidTouchProcessor = new AndroidTouchProcessor(flutterRenderer); mNativeView @@ -239,7 +242,7 @@ public void onPostResume() { .attachTextInputPlugin(mTextInputPlugin); // Send initial platform information to Dart - sendLocalesToDart(getResources().getConfiguration()); + mLocalizationPlugin.sendLocalesToDart(getResources().getConfiguration()); sendUserPlatformSettingsToDart(); } @@ -403,41 +406,41 @@ private void sendUserPlatformSettingsToDart() { .send(); } - @SuppressWarnings("deprecation") - private void sendLocalesToDart(Configuration config) { - List locales = new ArrayList<>(); - if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { - LocaleList localeList = config.getLocales(); - int localeCount = localeList.size(); - for (int index = 0; index < localeCount; ++index) { - Locale locale = localeList.get(index); - locales.add(locale); - } - } else { - locales.add(config.locale); - } - - Locale platformResolvedLocale = null; - if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { - List languageRanges = new ArrayList<>(); - LocaleList localeList = config.getLocales(); - int localeCount = localeList.size(); - for (int index = 0; index < localeCount; ++index) { - Locale locale = localeList.get(index); - languageRanges.add(new Locale.LanguageRange(locale.toLanguageTag())); - } - // TODO(garyq) implement a real locale resolution. - platformResolvedLocale = - Locale.lookup(languageRanges, Arrays.asList(Locale.getAvailableLocales())); - } - - localizationChannel.sendLocales(locales, platformResolvedLocale); - } + // @SuppressWarnings("deprecation") + // private void sendLocalesToDart(Configuration config) { + // List locales = new ArrayList<>(); + // if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { + // LocaleList localeList = config.getLocales(); + // int localeCount = localeList.size(); + // for (int index = 0; index < localeCount; ++index) { + // Locale locale = localeList.get(index); + // locales.add(locale); + // } + // } else { + // locales.add(config.locale); + // } + + // Locale platformResolvedLocale = null; + // if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { + // List languageRanges = new ArrayList<>(); + // LocaleList localeList = config.getLocales(); + // int localeCount = localeList.size(); + // for (int index = 0; index < localeCount; ++index) { + // Locale locale = localeList.get(index); + // languageRanges.add(new Locale.LanguageRange(locale.toLanguageTag())); + // } + // // TODO(garyq) implement a real locale resolution. + // platformResolvedLocale = + // Locale.lookup(languageRanges, Arrays.asList(Locale.getAvailableLocales())); + // } + + // localizationChannel.sendLocales(locales, platformResolvedLocale); + // } @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); - sendLocalesToDart(newConfig); + mLocalizationPlugin.sendLocalesToDart(newConfig); sendUserPlatformSettingsToDart(); } From 22eaecd765a519860271bc46bbcb4746aa424451 Mon Sep 17 00:00:00 2001 From: garyqian Date: Thu, 28 May 2020 04:32:32 -0700 Subject: [PATCH 02/51] Slight cleanup --- .../embedding/android/FlutterView.java | 36 ------------------- .../localization/LocalizationPlugin.java | 7 ++-- .../android/io/flutter/view/FlutterView.java | 31 ---------------- 3 files changed, 4 insertions(+), 70 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterView.java b/shell/platform/android/io/flutter/embedding/android/FlutterView.java index fce01389a2a70..bca5d96f65f32 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterView.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterView.java @@ -951,42 +951,6 @@ public void removeFlutterEngineAttachmentListener( flutterEngineAttachmentListeners.remove(listener); } - // /** - // * Send the current {@link Locale} configuration to Flutter. - // * - // *

FlutterEngine must be non-null when this method is invoked. - // */ - // @SuppressWarnings("deprecation") - // private void sendLocalesToFlutter(@NonNull Configuration config) { - // List locales = new ArrayList<>(); - // if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { - // LocaleList localeList = config.getLocales(); - // int localeCount = localeList.size(); - // for (int index = 0; index < localeCount; ++index) { - // Locale locale = localeList.get(index); - // locales.add(locale); - // } - // } else { - // locales.add(config.locale); - // } - - // Locale platformResolvedLocale = null; - // if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { - // List languageRanges = new ArrayList<>(); - // LocaleList localeList = config.getLocales(); - // int localeCount = localeList.size(); - // for (int index = 0; index < localeCount; ++index) { - // Locale locale = localeList.get(index); - // languageRanges.add(new Locale.LanguageRange(locale.toLanguageTag())); - // } - // // TODO(garyq) implement a real locale resolution. - // platformResolvedLocale = - // Locale.lookup(languageRanges, Arrays.asList(Locale.getAvailableLocales())); - // } - - // flutterEngine.getLocalizationChannel().sendLocales(locales, platformResolvedLocale); - // } - /** * Send various user preferences of this Android device to Flutter. * diff --git a/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java b/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java index b250f14515a54..7df586e4e40d0 100644 --- a/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java +++ b/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java @@ -9,7 +9,6 @@ import android.content.res.Configuration; import android.os.Build; import android.os.LocaleList; -import android.provider.Settings; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; @@ -56,7 +55,7 @@ private Locale resolveNativeLocale(List supportedLocales) { return platformResolvedLocale; } - /** + /** * Send the current {@link Locale} configuration to Flutter. * *

FlutterEngine must be non-null when this method is invoked. @@ -90,7 +89,9 @@ public void sendLocalesToDart(@NonNull Configuration config) { } localizationChannel.sendLocales(locales); - localizationChannel.sendPlatformResolvedLocales(platformResolvedLocale); + // Do not initialize platform resolved locale. We will do + // this later via the method channel call "resolveLocale". + // localizationChannel.sendPlatformResolvedLocales(platformResolvedLocale); } /** diff --git a/shell/platform/android/io/flutter/view/FlutterView.java b/shell/platform/android/io/flutter/view/FlutterView.java index e28bc030e4ab6..02b75dc4dd4ed 100644 --- a/shell/platform/android/io/flutter/view/FlutterView.java +++ b/shell/platform/android/io/flutter/view/FlutterView.java @@ -406,37 +406,6 @@ private void sendUserPlatformSettingsToDart() { .send(); } - // @SuppressWarnings("deprecation") - // private void sendLocalesToDart(Configuration config) { - // List locales = new ArrayList<>(); - // if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { - // LocaleList localeList = config.getLocales(); - // int localeCount = localeList.size(); - // for (int index = 0; index < localeCount; ++index) { - // Locale locale = localeList.get(index); - // locales.add(locale); - // } - // } else { - // locales.add(config.locale); - // } - - // Locale platformResolvedLocale = null; - // if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { - // List languageRanges = new ArrayList<>(); - // LocaleList localeList = config.getLocales(); - // int localeCount = localeList.size(); - // for (int index = 0; index < localeCount; ++index) { - // Locale locale = localeList.get(index); - // languageRanges.add(new Locale.LanguageRange(locale.toLanguageTag())); - // } - // // TODO(garyq) implement a real locale resolution. - // platformResolvedLocale = - // Locale.lookup(languageRanges, Arrays.asList(Locale.getAvailableLocales())); - // } - - // localizationChannel.sendLocales(locales, platformResolvedLocale); - // } - @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); From 765223d5356e23de70f30e5bf0edde121564ce0b Mon Sep 17 00:00:00 2001 From: garyqian Date: Sat, 30 May 2020 02:15:11 -0700 Subject: [PATCH 03/51] Begin JNI + synchronous impl --- lib/ui/window.dart | 18 +++++++++++ lib/ui/window/window.cc | 11 +++++++ lib/ui/window/window.h | 4 +++ shell/common/platform_view.cc | 5 ++++ shell/common/platform_view.h | 3 ++ .../flutter/embedding/engine/FlutterJNI.java | 30 +++++++++++++++++++ .../systemchannels/LocalizationChannel.java | 5 +++- .../localization/LocalizationPlugin.java | 6 ++-- .../platform/android/platform_view_android.cc | 13 ++++++++ .../platform/android/platform_view_android.h | 4 +++ .../android/platform_view_android_jni.cc | 20 +++++++++++++ .../android/platform_view_android_jni.h | 5 ++++ 12 files changed, 121 insertions(+), 3 deletions(-) diff --git a/lib/ui/window.dart b/lib/ui/window.dart index 084fe4d53e118..4c300e2adec72 100644 --- a/lib/ui/window.dart +++ b/lib/ui/window.dart @@ -805,6 +805,24 @@ class Window { Locale get platformResolvedLocale => _platformResolvedLocale; Locale _platformResolvedLocale; + Locale computePlatformResolvedLocale(List supportedLocales) { + if (supportedLocales == null) { + return null; + } + List supportedLocalesData = []; + for (Locale locale in supportedLocales) { + supportedLocalesData.add(locale.languageCode); + supportedLocalesData.add(locale.countryCode); + } + + List result = _computePlatformResolvedLocale(supportedLocalesData); + if (result != null && result.length == 2) { + return Locale.fromSubtags(languageCode: result[0], countryCode: result[1]); + } + return null; + } + List _computePlatformResolvedLocale(List supportedLocalesData) native 'Window_computePlatformResolvedLocale'; + /// A callback that is invoked whenever [locale] changes value. /// /// The framework invokes this callback in the same zone in which the diff --git a/lib/ui/window/window.cc b/lib/ui/window/window.cc index 8e44378a6f3fa..23bb1efa2b9e5 100644 --- a/lib/ui/window/window.cc +++ b/lib/ui/window/window.cc @@ -425,6 +425,14 @@ void Window::CompletePlatformMessageResponse(int response_id, response->Complete(std::make_unique(std::move(data))); } +// Dart_Handle _ComputePlatformResolvedLocale( +// const std::vector& supportedLocaleData) { +// Dart_Handle result = Dart_NewListOf(Dart_CoreType_String, 2); +// Dart_ListSetAt(result, 0, tonic::ToDart("zero")); +// Dart_ListSetAt(result, 1, tonic::ToDart("one")); +// return result; +// } + void Window::RegisterNatives(tonic::DartLibraryNatives* natives) { natives->Register({ {"Window_defaultRouteName", DefaultRouteName, 1, true}, @@ -437,6 +445,9 @@ void Window::RegisterNatives(tonic::DartLibraryNatives* natives) { {"Window_reportUnhandledException", ReportUnhandledException, 2, true}, {"Window_setNeedsReportTimings", SetNeedsReportTimings, 2, true}, {"Window_getPersistentIsolateData", GetPersistentIsolateData, 1, true}, + // {"Window_computePlatformResolvedLocale", + // _ComputePlatformResolvedLocale, + // 1, true}, }); } diff --git a/lib/ui/window/window.h b/lib/ui/window/window.h index 3d7dc52574653..196853f02545e 100644 --- a/lib/ui/window/window.h +++ b/lib/ui/window/window.h @@ -94,6 +94,10 @@ class Window final { std::vector data); void CompletePlatformMessageEmptyResponse(int response_id); + // Native dart binding + // Dart_Handle ComputePlatformResolvedLocale( + // const std::vector& supportedLocaleData); + static void RegisterNatives(tonic::DartLibraryNatives* natives); private: diff --git a/shell/common/platform_view.cc b/shell/common/platform_view.cc index 9fa42ae17d22e..c38fcc614a655 100644 --- a/shell/common/platform_view.cc +++ b/shell/common/platform_view.cc @@ -137,4 +137,9 @@ void PlatformView::SetNextFrameCallback(const fml::closure& closure) { delegate_.OnPlatformViewSetNextFrameCallback(closure); } +std::vector PlatformView::ComputePlatformResolvedLocales( + std::vector supportedLocaleData) { + return std::vector(); +} + } // namespace flutter diff --git a/shell/common/platform_view.h b/shell/common/platform_view.h index 15d3edac4b210..f63e0787a7230 100644 --- a/shell/common/platform_view.h +++ b/shell/common/platform_view.h @@ -543,6 +543,9 @@ class PlatformView { /// void MarkTextureFrameAvailable(int64_t texture_id); + virtual std::vector ComputePlatformResolvedLocales( + std::vector supportedLocaleData); + protected: PlatformView::Delegate& delegate_; const TaskRunners task_runners_; diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java index b0d5ad9ba19e2..e1b95c03a527b 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java @@ -22,9 +22,13 @@ import io.flutter.embedding.engine.renderer.FlutterUiDisplayListener; import io.flutter.embedding.engine.renderer.RenderSurface; import io.flutter.plugin.common.StandardMessageCodec; +import io.flutter.plugin.localization.LocalizationPlugin; import io.flutter.view.AccessibilityBridge; import io.flutter.view.FlutterCallbackInformation; import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; @@ -782,6 +786,32 @@ private void onPreEngineRestart() { } // ----- End Engine Lifecycle Support ---- + // ----- Start Localizaation Support ---- + + /** + * Invoked by native to obtain the results of Android's locale reoslution algorithm. + */ + @SuppressWarnings("unused") + @UiThread + private String[] computePlatformResolvedLocale(@NonNull String[] strings) { + ensureRunningOnMainThread(); + + List supportedLocales = new ArrayList(); + for (int i = 0; i < strings.length / 2; i++) { + supportedLocales.add(new Locale(strings[i * 2 + 0], strings[i * 2 + 1])); + } + Locale result = LocalizationPlugin.resolveNativeLocale(supportedLocales); + String[] output = new String[2]; + output[0] = result.getLanguage(); + output[1] = result.getCountry(); + return output; + // if (accessibilityDelegate != null) { + // accessibilityDelegate.updateSemantics(buffer, strings); + // } + } + + // ----- End Localizaation Support ---- + // TODO(mattcarroll): determine if this is nonull or nullable @UiThread public Bitmap getBitmap() { diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/LocalizationChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/LocalizationChannel.java index ef6192862b797..96e01aff9459b 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/LocalizationChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/LocalizationChannel.java @@ -53,7 +53,10 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result supportedLocales.add(new Locale(language, country)); } Locale resolvedLocale = localizationMethodHandler.resolveLocale(supportedLocales); - result.success(resolvedLocale.toString()); + List resolvedLocaleComponents = new ArrayList(); + resolvedLocaleComponents.add(resolvedLocale.getLanguage()); + resolvedLocaleComponents.add(resolvedLocale.getCountry()); + result.success(resolvedLocaleComponents); } catch (JSONException exception) { result.error("error", exception.getMessage(), null); } diff --git a/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java b/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java index 7df586e4e40d0..681decdc48dcf 100644 --- a/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java +++ b/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java @@ -22,6 +22,7 @@ public class LocalizationPlugin { @NonNull private final LocalizationChannel localizationChannel; @NonNull private final Context context; + private static LocalizationPlugin instance; public LocalizationPlugin( @NonNull Context context, @@ -36,13 +37,14 @@ public Locale resolveLocale(List supportedLocales) { return resolveNativeLocale(supportedLocales); } }); + instance = this; } - private Locale resolveNativeLocale(List supportedLocales) { + public static Locale resolveNativeLocale(List supportedLocales) { Locale platformResolvedLocale = null; if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { List languageRanges = new ArrayList<>(); - LocaleList localeList = context.getResources().getConfiguration().getLocales(); + LocaleList localeList = instance.context.getResources().getConfiguration().getLocales(); int localeCount = localeList.size(); for (int index = 0; index < localeCount; ++index) { Locale locale = localeList.get(index); diff --git a/shell/platform/android/platform_view_android.cc b/shell/platform/android/platform_view_android.cc index 236ef41ae18fa..d4f4fa55e1c19 100644 --- a/shell/platform/android/platform_view_android.cc +++ b/shell/platform/android/platform_view_android.cc @@ -426,6 +426,19 @@ void PlatformViewAndroid::ReleaseResourceContext() const { } } +std::vector PlatformViewAndroid::ComputePlatformResolvedLocales( + std::vector supportedLocaleData) { + JNIEnv* env = fml::jni::AttachCurrentThread(); + fml::jni::ScopedJavaLocalRef view = java_object_.get(env); + if (view.is_null()) { + // The Java object died. + return std::vector(); + } + return FlutterViewComputePlatformResolvedLocale( + env, view.obj(), + fml::jni::VectorToStringArray(env, supportedLocaleData).obj()); +} + void PlatformViewAndroid::InstallFirstFrameCallback() { // On Platform Task Runner. SetNextFrameCallback( diff --git a/shell/platform/android/platform_view_android.h b/shell/platform/android/platform_view_android.h index 74c0bbe6c26e7..a6e70c0023b3d 100644 --- a/shell/platform/android/platform_view_android.h +++ b/shell/platform/android/platform_view_android.h @@ -105,6 +105,10 @@ class PlatformViewAndroid final : public PlatformView { // |PlatformView| void ReleaseResourceContext() const override; + // |PlatformView| + std::vector ComputePlatformResolvedLocales( + std::vector supportedLocaleData) override; + void InstallFirstFrameCallback(); void FireFirstFrameCallback(); diff --git a/shell/platform/android/platform_view_android_jni.cc b/shell/platform/android/platform_view_android_jni.cc index 4f6f9258b3e11..03904391e418b 100644 --- a/shell/platform/android/platform_view_android_jni.cc +++ b/shell/platform/android/platform_view_android_jni.cc @@ -144,6 +144,17 @@ void SurfaceTextureDetachFromGLContext(JNIEnv* env, jobject obj) { FML_CHECK(CheckException(env)); } +static jmethodID g_compute_platform_resolved_locale_method = nullptr; +std::vector FlutterViewComputePlatformResolvedLocale( + JNIEnv* env, + jobject obj, + jobjectArray strings) { + jobjectArray result = static_cast(env->CallObjectMethod( + obj, g_compute_platform_resolved_locale_method, strings)); + FML_CHECK(CheckException(env)); + return fml::jni::StringArrayToVector(env, result); +} + // Called By Java static jlong AttachJNI(JNIEnv* env, @@ -789,6 +800,15 @@ bool PlatformViewAndroid::Register(JNIEnv* env) { return false; } + g_compute_platform_resolved_locale_method = env->GetMethodID( + g_flutter_jni_class->obj(), "computePlatformResolvedLocale", + "([Ljava/lang/String;)[Ljava/lang/String;"); + + if (g_compute_platform_resolved_locale_method == nullptr) { + FML_LOG(ERROR) << "Could not locate computePlatformResolvedLocale method"; + return false; + } + return RegisterApi(env); } diff --git a/shell/platform/android/platform_view_android_jni.h b/shell/platform/android/platform_view_android_jni.h index 07c70b2a45b50..1704fdb764555 100644 --- a/shell/platform/android/platform_view_android_jni.h +++ b/shell/platform/android/platform_view_android_jni.h @@ -46,6 +46,11 @@ void SurfaceTextureGetTransformMatrix(JNIEnv* env, void SurfaceTextureDetachFromGLContext(JNIEnv* env, jobject obj); +std::vector FlutterViewComputePlatformResolvedLocale( + JNIEnv* env, + jobject obj, + jobjectArray strings); + } // namespace flutter #endif // FLUTTER_SHELL_PLATFORM_ANDROID_PLATFORM_VIEW_ANDROID_JNI_H_ From 08ef1bb763973a93b83cf0414d8bd17ce3fd0618 Mon Sep 17 00:00:00 2001 From: garyqian Date: Sat, 30 May 2020 03:09:40 -0700 Subject: [PATCH 04/51] Dart binding --- lib/ui/window/window.cc | 25 +++++++++++-------- lib/ui/window/window.h | 6 ++--- .../localization/LocalizationPlugin.java | 3 +++ 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/lib/ui/window/window.cc b/lib/ui/window/window.cc index 23bb1efa2b9e5..6eb0355eba4da 100644 --- a/lib/ui/window/window.cc +++ b/lib/ui/window/window.cc @@ -425,13 +425,19 @@ void Window::CompletePlatformMessageResponse(int response_id, response->Complete(std::make_unique(std::move(data))); } -// Dart_Handle _ComputePlatformResolvedLocale( -// const std::vector& supportedLocaleData) { -// Dart_Handle result = Dart_NewListOf(Dart_CoreType_String, 2); -// Dart_ListSetAt(result, 0, tonic::ToDart("zero")); -// Dart_ListSetAt(result, 1, tonic::ToDart("one")); -// return result; -// } +Dart_Handle ComputePlatformResolvedLocale( + const std::vector& supportedLocaleData) { + // Compute the locale vai platform view + Dart_Handle output = + Dart_NewListOf(Dart_CoreType_String, supportedLocaleData.size()); + Dart_ListSetAt(output, 0, tonic::ToDart("zero")); + Dart_ListSetAt(output, 1, tonic::ToDart("one")); + return output; +} + +void _ComputePlatformResolvedLocale(Dart_NativeArguments args) { + tonic::DartCallStatic(&ComputePlatformResolvedLocale, args); +} void Window::RegisterNatives(tonic::DartLibraryNatives* natives) { natives->Register({ @@ -445,9 +451,8 @@ void Window::RegisterNatives(tonic::DartLibraryNatives* natives) { {"Window_reportUnhandledException", ReportUnhandledException, 2, true}, {"Window_setNeedsReportTimings", SetNeedsReportTimings, 2, true}, {"Window_getPersistentIsolateData", GetPersistentIsolateData, 1, true}, - // {"Window_computePlatformResolvedLocale", - // _ComputePlatformResolvedLocale, - // 1, true}, + {"Window_computePlatformResolvedLocale", _ComputePlatformResolvedLocale, + 1, true}, }); } diff --git a/lib/ui/window/window.h b/lib/ui/window/window.h index 196853f02545e..f5c4d5cf75be0 100644 --- a/lib/ui/window/window.h +++ b/lib/ui/window/window.h @@ -93,10 +93,8 @@ class Window final { void CompletePlatformMessageResponse(int response_id, std::vector data); void CompletePlatformMessageEmptyResponse(int response_id); - - // Native dart binding - // Dart_Handle ComputePlatformResolvedLocale( - // const std::vector& supportedLocaleData); + Dart_Handle ComputePlatformResolvedLocale( + const std::vector& supportedLocaleData); static void RegisterNatives(tonic::DartLibraryNatives* natives); diff --git a/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java b/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java index 681decdc48dcf..80c11da96f0f1 100644 --- a/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java +++ b/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java @@ -22,6 +22,9 @@ public class LocalizationPlugin { @NonNull private final LocalizationChannel localizationChannel; @NonNull private final Context context; + + // This should always be initialized before being used by resolveNativeLocale + // since the embedder starts the engine which in turn calls resolveNativeLocale. private static LocalizationPlugin instance; public LocalizationPlugin( From 354880c97ca3491d8e2b1e4ca3ea98d4f1f67bff Mon Sep 17 00:00:00 2001 From: garyqian Date: Mon, 1 Jun 2020 16:16:33 -0700 Subject: [PATCH 05/51] Dart->native impl --- lib/ui/window/window.cc | 21 +++++++++++++++++++-- lib/ui/window/window.h | 4 ++-- runtime/runtime_controller.cc | 6 ++++++ runtime/runtime_controller.h | 4 ++++ 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/lib/ui/window/window.cc b/lib/ui/window/window.cc index 6eb0355eba4da..91c6284a4db97 100644 --- a/lib/ui/window/window.cc +++ b/lib/ui/window/window.cc @@ -427,7 +427,9 @@ void Window::CompletePlatformMessageResponse(int response_id, Dart_Handle ComputePlatformResolvedLocale( const std::vector& supportedLocaleData) { - // Compute the locale vai platform view + UIDartState::Current()->window()->client()->ComputePlatformResolvedLocale( + supportedLocaleData); + Dart_Handle output = Dart_NewListOf(Dart_CoreType_String, supportedLocaleData.size()); Dart_ListSetAt(output, 0, tonic::ToDart("zero")); @@ -435,10 +437,25 @@ Dart_Handle ComputePlatformResolvedLocale( return output; } -void _ComputePlatformResolvedLocale(Dart_NativeArguments args) { +static void _ComputePlatformResolvedLocale(Dart_NativeArguments args) { + UIDartState::ThrowIfUIOperationsProhibited(); + // Dart_Handle exception = nullptr; + // const std::vector supportedLocaleData = + // tonic::DartConverter>::FromArguments(args, 1, + // exception); + // if (exception) { + // Dart_ThrowException(exception); + // return nullptr; + // } + // return ComputePlatformResolvedLocale(supportedLocaleData); tonic::DartCallStatic(&ComputePlatformResolvedLocale, args); } +// static void CLASS##_##METHOD(Dart_NativeArguments args) { +// UIDartState::ThrowIfUIOperationsProhibited(); +// tonic::DartCall(&CLASS::METHOD, args); +// } + void Window::RegisterNatives(tonic::DartLibraryNatives* natives) { natives->Register({ {"Window_defaultRouteName", DefaultRouteName, 1, true}, diff --git a/lib/ui/window/window.h b/lib/ui/window/window.h index f5c4d5cf75be0..972e8bf6d4bac 100644 --- a/lib/ui/window/window.h +++ b/lib/ui/window/window.h @@ -59,6 +59,8 @@ class WindowClient { int64_t isolate_port) = 0; virtual void SetNeedsReportTimings(bool value) = 0; virtual std::shared_ptr GetPersistentIsolateData() = 0; + virtual std::vector ComputePlatformResolvedLocale( + const std::vector& supportedLocaleData); protected: virtual ~WindowClient(); @@ -93,8 +95,6 @@ class Window final { void CompletePlatformMessageResponse(int response_id, std::vector data); void CompletePlatformMessageEmptyResponse(int response_id); - Dart_Handle ComputePlatformResolvedLocale( - const std::vector& supportedLocaleData); static void RegisterNatives(tonic::DartLibraryNatives* natives); diff --git a/runtime/runtime_controller.cc b/runtime/runtime_controller.cc index 9b898365c9266..2b60818667cb7 100644 --- a/runtime/runtime_controller.cc +++ b/runtime/runtime_controller.cc @@ -340,6 +340,12 @@ RuntimeController::GetPersistentIsolateData() { return persistent_isolate_data_; } +// |WindowClient| +std::vector RuntimeController::ComputePlatformResolvedLocale( + const std::vector& supportedLocaleData) { + return std::vector(); +} + Dart_Port RuntimeController::GetMainPort() { std::shared_ptr root_isolate = root_isolate_.lock(); return root_isolate ? root_isolate->main_port() : ILLEGAL_PORT; diff --git a/runtime/runtime_controller.h b/runtime/runtime_controller.h index fca9c409e25f8..601b23ea5b4d4 100644 --- a/runtime/runtime_controller.h +++ b/runtime/runtime_controller.h @@ -522,6 +522,10 @@ class RuntimeController final : public WindowClient { // |WindowClient| std::shared_ptr GetPersistentIsolateData() override; + // |WindowClient| + std::vector ComputePlatformResolvedLocale( + const std::vector& supportedLocaleData) override; + FML_DISALLOW_COPY_AND_ASSIGN(RuntimeController); }; From 3dd7d2235188b31a858e80d3372c47c06a2f4cd5 Mon Sep 17 00:00:00 2001 From: garyqian Date: Mon, 1 Jun 2020 17:07:29 -0700 Subject: [PATCH 06/51] Compiles --- lib/ui/window/window.cc | 14 -------------- lib/ui/window/window.h | 2 +- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/lib/ui/window/window.cc b/lib/ui/window/window.cc index 91c6284a4db97..d8d7510ae5e23 100644 --- a/lib/ui/window/window.cc +++ b/lib/ui/window/window.cc @@ -439,23 +439,9 @@ Dart_Handle ComputePlatformResolvedLocale( static void _ComputePlatformResolvedLocale(Dart_NativeArguments args) { UIDartState::ThrowIfUIOperationsProhibited(); - // Dart_Handle exception = nullptr; - // const std::vector supportedLocaleData = - // tonic::DartConverter>::FromArguments(args, 1, - // exception); - // if (exception) { - // Dart_ThrowException(exception); - // return nullptr; - // } - // return ComputePlatformResolvedLocale(supportedLocaleData); tonic::DartCallStatic(&ComputePlatformResolvedLocale, args); } -// static void CLASS##_##METHOD(Dart_NativeArguments args) { -// UIDartState::ThrowIfUIOperationsProhibited(); -// tonic::DartCall(&CLASS::METHOD, args); -// } - void Window::RegisterNatives(tonic::DartLibraryNatives* natives) { natives->Register({ {"Window_defaultRouteName", DefaultRouteName, 1, true}, diff --git a/lib/ui/window/window.h b/lib/ui/window/window.h index 972e8bf6d4bac..c04b3c646ca75 100644 --- a/lib/ui/window/window.h +++ b/lib/ui/window/window.h @@ -60,7 +60,7 @@ class WindowClient { virtual void SetNeedsReportTimings(bool value) = 0; virtual std::shared_ptr GetPersistentIsolateData() = 0; virtual std::vector ComputePlatformResolvedLocale( - const std::vector& supportedLocaleData); + const std::vector& supportedLocaleData) = 0; protected: virtual ~WindowClient(); From 7d2f6d9aa7384e59856c50da08d6f64f711b6dec Mon Sep 17 00:00:00 2001 From: garyqian Date: Tue, 2 Jun 2020 02:59:34 -0700 Subject: [PATCH 07/51] Initial compiling impl of full android path --- lib/ui/window/window.h | 2 +- runtime/runtime_controller.cc | 5 +++-- runtime/runtime_controller.h | 2 +- runtime/runtime_delegate.h | 3 +++ shell/common/engine.cc | 5 +++++ shell/common/engine.h | 7 +++++++ shell/common/platform_view.cc | 8 +++++--- shell/common/platform_view.h | 7 +++++-- shell/common/shell.cc | 12 ++++++++++++ shell/common/shell.h | 8 ++++++++ shell/platform/android/platform_view_android.cc | 11 +++++++---- shell/platform/android/platform_view_android.h | 5 +++-- shell/platform/darwin/ios/platform_view_ios.h | 4 ++++ 13 files changed, 64 insertions(+), 15 deletions(-) diff --git a/lib/ui/window/window.h b/lib/ui/window/window.h index c04b3c646ca75..050a6aef536eb 100644 --- a/lib/ui/window/window.h +++ b/lib/ui/window/window.h @@ -59,7 +59,7 @@ class WindowClient { int64_t isolate_port) = 0; virtual void SetNeedsReportTimings(bool value) = 0; virtual std::shared_ptr GetPersistentIsolateData() = 0; - virtual std::vector ComputePlatformResolvedLocale( + virtual std::vector& ComputePlatformResolvedLocale( const std::vector& supportedLocaleData) = 0; protected: diff --git a/runtime/runtime_controller.cc b/runtime/runtime_controller.cc index 2b60818667cb7..d2d26708e265a 100644 --- a/runtime/runtime_controller.cc +++ b/runtime/runtime_controller.cc @@ -341,9 +341,10 @@ RuntimeController::GetPersistentIsolateData() { } // |WindowClient| -std::vector RuntimeController::ComputePlatformResolvedLocale( +std::vector& RuntimeController::ComputePlatformResolvedLocale( const std::vector& supportedLocaleData) { - return std::vector(); + return client_.ComputePlatformResolvedLocale(supportedLocaleData); + // return std::vector(); } Dart_Port RuntimeController::GetMainPort() { diff --git a/runtime/runtime_controller.h b/runtime/runtime_controller.h index 601b23ea5b4d4..af6ce91ec3403 100644 --- a/runtime/runtime_controller.h +++ b/runtime/runtime_controller.h @@ -523,7 +523,7 @@ class RuntimeController final : public WindowClient { std::shared_ptr GetPersistentIsolateData() override; // |WindowClient| - std::vector ComputePlatformResolvedLocale( + std::vector& ComputePlatformResolvedLocale( const std::vector& supportedLocaleData) override; FML_DISALLOW_COPY_AND_ASSIGN(RuntimeController); diff --git a/runtime/runtime_delegate.h b/runtime/runtime_delegate.h index 189d764b1eb5b..a6c14def41b77 100644 --- a/runtime/runtime_delegate.h +++ b/runtime/runtime_delegate.h @@ -37,6 +37,9 @@ class RuntimeDelegate { virtual void SetNeedsReportTimings(bool value) = 0; + virtual std::vector& ComputePlatformResolvedLocale( + const std::vector& supportedLocaleData) = 0; + protected: virtual ~RuntimeDelegate(); }; diff --git a/shell/common/engine.cc b/shell/common/engine.cc index 9f03c9200fd32..b7f1bce03ae2d 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc @@ -492,6 +492,11 @@ void Engine::UpdateIsolateDescription(const std::string isolate_name, delegate_.UpdateIsolateDescription(isolate_name, isolate_port); } +std::vector& Engine::ComputePlatformResolvedLocale( + const std::vector& supportedLocaleData) { + return delegate_.ComputePlatformResolvedLocale(supportedLocaleData); +} + void Engine::SetNeedsReportTimings(bool needs_reporting) { delegate_.SetNeedsReportTimings(needs_reporting); } diff --git a/shell/common/engine.h b/shell/common/engine.h index 5f970b3717701..045c537c9af63 100644 --- a/shell/common/engine.h +++ b/shell/common/engine.h @@ -227,6 +227,9 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate { /// collected and send back to Dart. /// virtual void SetNeedsReportTimings(bool needs_reporting) = 0; + + virtual std::vector& ComputePlatformResolvedLocale( + const std::vector& supportedLocaleData) = 0; }; //---------------------------------------------------------------------------- @@ -772,6 +775,10 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate { void UpdateIsolateDescription(const std::string isolate_name, int64_t isolate_port) override; + // |RuntimeDelegate| + std::vector& ComputePlatformResolvedLocale( + const std::vector& supportedLocaleData) override; + void SetNeedsReportTimings(bool value) override; void StopAnimator(); diff --git a/shell/common/platform_view.cc b/shell/common/platform_view.cc index c38fcc614a655..ed45c30736f6a 100644 --- a/shell/common/platform_view.cc +++ b/shell/common/platform_view.cc @@ -137,9 +137,11 @@ void PlatformView::SetNextFrameCallback(const fml::closure& closure) { delegate_.OnPlatformViewSetNextFrameCallback(closure); } -std::vector PlatformView::ComputePlatformResolvedLocales( - std::vector supportedLocaleData) { - return std::vector(); +std::vector& PlatformView::ComputePlatformResolvedLocales( + const std::vector& supportedLocaleData) { + // std::vector result = std::vector(); + // *result = std::vector(); + return delegate_.ComputePlatformViewResolvedLocale(supportedLocaleData); } } // namespace flutter diff --git a/shell/common/platform_view.h b/shell/common/platform_view.h index f63e0787a7230..f2067399f673c 100644 --- a/shell/common/platform_view.h +++ b/shell/common/platform_view.h @@ -209,6 +209,9 @@ class PlatformView { /// virtual void OnPlatformViewMarkTextureFrameAvailable( int64_t texture_id) = 0; + + virtual std::vector& ComputePlatformViewResolvedLocale( + const std::vector& supportedLocaleData) = 0; }; //---------------------------------------------------------------------------- @@ -543,8 +546,8 @@ class PlatformView { /// void MarkTextureFrameAvailable(int64_t texture_id); - virtual std::vector ComputePlatformResolvedLocales( - std::vector supportedLocaleData); + virtual std::vector& ComputePlatformResolvedLocales( + const std::vector& supportedLocaleData); protected: PlatformView::Delegate& delegate_; diff --git a/shell/common/shell.cc b/shell/common/shell.cc index 99236e05cb50f..1be3bed93e2a9 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -1098,6 +1098,18 @@ void Shell::SetNeedsReportTimings(bool value) { needs_report_timings_ = value; } +// |Engine::Delegate| +std::vector& Shell::ComputePlatformResolvedLocale( + const std::vector& supportedLocaleData) { + return ComputePlatformViewResolvedLocale(supportedLocaleData); +} + +// |PlatformView::Delegate| +std::vector& Shell::ComputePlatformViewResolvedLocale( + const std::vector& supportedLocaleData) { + return platform_view_->ComputePlatformResolvedLocales(supportedLocaleData); +} + void Shell::ReportTimings() { FML_DCHECK(is_setup_); FML_DCHECK(task_runners_.GetRasterTaskRunner()->RunsTasksOnCurrentThread()); diff --git a/shell/common/shell.h b/shell/common/shell.h index d959eb41c585b..069b287b0be4e 100644 --- a/shell/common/shell.h +++ b/shell/common/shell.h @@ -482,6 +482,10 @@ class Shell final : public PlatformView::Delegate, // |PlatformView::Delegate| void OnPlatformViewSetNextFrameCallback(const fml::closure& closure) override; + // |PlatformView::Delegate| + std::vector& ComputePlatformViewResolvedLocale( + const std::vector& supportedLocaleData) override; + // |Animator::Delegate| void OnAnimatorBeginFrame(fml::TimePoint frame_target_time) override; @@ -516,6 +520,10 @@ class Shell final : public PlatformView::Delegate, // |Engine::Delegate| void SetNeedsReportTimings(bool value) override; + // |Engine::Delegate| + std::vector& ComputePlatformResolvedLocale( + const std::vector& supportedLocaleData) override; + // |Rasterizer::Delegate| void OnFrameRasterized(const FrameTiming&) override; diff --git a/shell/platform/android/platform_view_android.cc b/shell/platform/android/platform_view_android.cc index d4f4fa55e1c19..117b97a1ba09c 100644 --- a/shell/platform/android/platform_view_android.cc +++ b/shell/platform/android/platform_view_android.cc @@ -426,17 +426,20 @@ void PlatformViewAndroid::ReleaseResourceContext() const { } } -std::vector PlatformViewAndroid::ComputePlatformResolvedLocales( - std::vector supportedLocaleData) { +// |PlatformView| +std::vector& PlatformViewAndroid::ComputePlatformResolvedLocales( + const std::vector& supportedLocaleData) { JNIEnv* env = fml::jni::AttachCurrentThread(); fml::jni::ScopedJavaLocalRef view = java_object_.get(env); if (view.is_null()) { // The Java object died. - return std::vector(); + *platform_resolved_locale_ = std::vector(); + return *platform_resolved_locale_; } - return FlutterViewComputePlatformResolvedLocale( + *platform_resolved_locale_ = FlutterViewComputePlatformResolvedLocale( env, view.obj(), fml::jni::VectorToStringArray(env, supportedLocaleData).obj()); + return *platform_resolved_locale_; } void PlatformViewAndroid::InstallFirstFrameCallback() { diff --git a/shell/platform/android/platform_view_android.h b/shell/platform/android/platform_view_android.h index a6e70c0023b3d..a17882a8a68c7 100644 --- a/shell/platform/android/platform_view_android.h +++ b/shell/platform/android/platform_view_android.h @@ -80,6 +80,7 @@ class PlatformViewAndroid final : public PlatformView { int next_response_id_ = 1; std::unordered_map> pending_responses_; + std::vector* platform_resolved_locale_; // |PlatformView| void UpdateSemantics( @@ -106,8 +107,8 @@ class PlatformViewAndroid final : public PlatformView { void ReleaseResourceContext() const override; // |PlatformView| - std::vector ComputePlatformResolvedLocales( - std::vector supportedLocaleData) override; + std::vector& ComputePlatformResolvedLocales( + const std::vector& supportedLocaleData) override; void InstallFirstFrameCallback(); diff --git a/shell/platform/darwin/ios/platform_view_ios.h b/shell/platform/darwin/ios/platform_view_ios.h index a89192d908ca5..ac2c9da8adca9 100644 --- a/shell/platform/darwin/ios/platform_view_ios.h +++ b/shell/platform/darwin/ios/platform_view_ios.h @@ -152,6 +152,10 @@ class PlatformViewIOS final : public PlatformView { // |PlatformView| void OnPreEngineRestart() const override; + // |PlatformView| + std::vector& ComputePlatformResolvedLocales( + const std::vector& supportedLocaleData) override; + FML_DISALLOW_COPY_AND_ASSIGN(PlatformViewIOS); }; From 3245d003de870250990b1177ab6f91b58e26501c Mon Sep 17 00:00:00 2001 From: garyqian Date: Wed, 3 Jun 2020 04:46:50 -0700 Subject: [PATCH 08/51] Working Dart-native interop --- lib/ui/window/window.cc | 33 +++++++++++++------ .../platform/android/platform_view_android.cc | 3 ++ .../android/platform_view_android_jni.cc | 6 ++++ 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/lib/ui/window/window.cc b/lib/ui/window/window.cc index d8d7510ae5e23..ca331cbbbc24c 100644 --- a/lib/ui/window/window.cc +++ b/lib/ui/window/window.cc @@ -426,20 +426,33 @@ void Window::CompletePlatformMessageResponse(int response_id, } Dart_Handle ComputePlatformResolvedLocale( - const std::vector& supportedLocaleData) { - UIDartState::Current()->window()->client()->ComputePlatformResolvedLocale( - supportedLocaleData); - - Dart_Handle output = - Dart_NewListOf(Dart_CoreType_String, supportedLocaleData.size()); - Dart_ListSetAt(output, 0, tonic::ToDart("zero")); - Dart_ListSetAt(output, 1, tonic::ToDart("one")); + // std::vector& supportedLocalesData) { + Dart_Handle supportedLocalesHandle) { + intptr_t length; + Dart_ListLength(supportedLocalesHandle, &length); + size_t u_length = static_cast(length); + std::vector supportedLocales; + for (size_t i = 0; i < u_length; i++) { + const char* cname; + Dart_StringToCString(Dart_ListGetAt(supportedLocalesHandle, i), &cname); + supportedLocales.emplace_back(cname); + } + std::vector results = + UIDartState::Current()->window()->client()->ComputePlatformResolvedLocale( + supportedLocales); + + Dart_Handle output = Dart_NewListOf(Dart_CoreType_String, results.size()); + for (size_t i = 0; i < results.size(); i++) { + Dart_ListSetAt(output, i, tonic::ToDart(results[i])); + } return output; } static void _ComputePlatformResolvedLocale(Dart_NativeArguments args) { UIDartState::ThrowIfUIOperationsProhibited(); - tonic::DartCallStatic(&ComputePlatformResolvedLocale, args); + Dart_Handle result = + ComputePlatformResolvedLocale(Dart_GetNativeArgument(args, 1)); + Dart_SetReturnValue(args, result); } void Window::RegisterNatives(tonic::DartLibraryNatives* natives) { @@ -455,7 +468,7 @@ void Window::RegisterNatives(tonic::DartLibraryNatives* natives) { {"Window_setNeedsReportTimings", SetNeedsReportTimings, 2, true}, {"Window_getPersistentIsolateData", GetPersistentIsolateData, 1, true}, {"Window_computePlatformResolvedLocale", _ComputePlatformResolvedLocale, - 1, true}, + 2, true}, }); } diff --git a/shell/platform/android/platform_view_android.cc b/shell/platform/android/platform_view_android.cc index 117b97a1ba09c..d54124578fae7 100644 --- a/shell/platform/android/platform_view_android.cc +++ b/shell/platform/android/platform_view_android.cc @@ -429,6 +429,9 @@ void PlatformViewAndroid::ReleaseResourceContext() const { // |PlatformView| std::vector& PlatformViewAndroid::ComputePlatformResolvedLocales( const std::vector& supportedLocaleData) { + for (size_t i = 0; i < supportedLocaleData.size(); i++) { + FML_DLOG(ERROR) << "LOCALE COMPONENT: " << supportedLocaleData[i]; + } JNIEnv* env = fml::jni::AttachCurrentThread(); fml::jni::ScopedJavaLocalRef view = java_object_.get(env); if (view.is_null()) { diff --git a/shell/platform/android/platform_view_android_jni.cc b/shell/platform/android/platform_view_android_jni.cc index 03904391e418b..8ddca7d5a1a0a 100644 --- a/shell/platform/android/platform_view_android_jni.cc +++ b/shell/platform/android/platform_view_android_jni.cc @@ -149,8 +149,14 @@ std::vector FlutterViewComputePlatformResolvedLocale( JNIEnv* env, jobject obj, jobjectArray strings) { + std::vector vec = fml::jni::StringArrayToVector(env, strings); jobjectArray result = static_cast(env->CallObjectMethod( obj, g_compute_platform_resolved_locale_method, strings)); + FML_DLOG(ERROR) << "RESULT:::::::::::::::: " << result << " " << strings + << " " << env << " " << vec.size(); + // for (size_t i = 0; i < vec.size(); i++) { + // FML_DLOG(ERROR) << "LOCALE COMPONENT: " << vec[i]; + // } FML_CHECK(CheckException(env)); return fml::jni::StringArrayToVector(env, result); } From 42d071710424243a39346ab2bdeda6a53bfbda54 Mon Sep 17 00:00:00 2001 From: garyqian Date: Thu, 4 Jun 2020 02:44:11 -0700 Subject: [PATCH 09/51] Working android codepath --- lib/ui/window.dart | 5 ++-- lib/ui/window/window.cc | 7 ++--- .../flutter/embedding/engine/FlutterJNI.java | 24 ++++++++--------- .../platform/android/platform_view_android.cc | 17 +++++++----- .../platform/android/platform_view_android.h | 2 +- .../android/platform_view_android_jni.cc | 27 ++++++++++--------- .../android/platform_view_android_jni.h | 7 +++-- 7 files changed, 46 insertions(+), 43 deletions(-) diff --git a/lib/ui/window.dart b/lib/ui/window.dart index 4c300e2adec72..d31c29552bb6f 100644 --- a/lib/ui/window.dart +++ b/lib/ui/window.dart @@ -816,8 +816,9 @@ class Window { } List result = _computePlatformResolvedLocale(supportedLocalesData); - if (result != null && result.length == 2) { - return Locale.fromSubtags(languageCode: result[0], countryCode: result[1]); + + if (result != null) { + return result.length == 1 ? Locale.fromSubtags(languageCode: result[0]) : Locale.fromSubtags(languageCode: result[0], countryCode: result[1]); } return null; } diff --git a/lib/ui/window/window.cc b/lib/ui/window/window.cc index ca331cbbbc24c..dd5eabaad6df3 100644 --- a/lib/ui/window/window.cc +++ b/lib/ui/window/window.cc @@ -425,9 +425,7 @@ void Window::CompletePlatformMessageResponse(int response_id, response->Complete(std::make_unique(std::move(data))); } -Dart_Handle ComputePlatformResolvedLocale( - // std::vector& supportedLocalesData) { - Dart_Handle supportedLocalesHandle) { +Dart_Handle ComputePlatformResolvedLocale(Dart_Handle supportedLocalesHandle) { intptr_t length; Dart_ListLength(supportedLocalesHandle, &length); size_t u_length = static_cast(length); @@ -441,10 +439,13 @@ Dart_Handle ComputePlatformResolvedLocale( UIDartState::Current()->window()->client()->ComputePlatformResolvedLocale( supportedLocales); + // Convert to dart List of strings. Dart_Handle output = Dart_NewListOf(Dart_CoreType_String, results.size()); for (size_t i = 0; i < results.size(); i++) { Dart_ListSetAt(output, i, tonic::ToDart(results[i])); } + + Dart_ListLength(output, &length); return output; } diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java index e1b95c03a527b..6e132d4a6583b 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java @@ -792,22 +792,20 @@ private void onPreEngineRestart() { * Invoked by native to obtain the results of Android's locale reoslution algorithm. */ @SuppressWarnings("unused") - @UiThread - private String[] computePlatformResolvedLocale(@NonNull String[] strings) { - ensureRunningOnMainThread(); - + private String computePlatformResolvedLocale(@NonNull String[] strings) { List supportedLocales = new ArrayList(); - for (int i = 0; i < strings.length / 2; i++) { - supportedLocales.add(new Locale(strings[i * 2 + 0], strings[i * 2 + 1])); + final int localeDataLength = 2; + for (int i = 0; i < strings.length / localeDataLength; i++) { + String languageCode = strings[i * localeDataLength + 0]; + String countryCode = strings[i * localeDataLength + 1]; + if (countryCode.isEmpty()) { + supportedLocales.add(new Locale(languageCode)); + } else { + supportedLocales.add(new Locale(languageCode, countryCode)); + } } Locale result = LocalizationPlugin.resolveNativeLocale(supportedLocales); - String[] output = new String[2]; - output[0] = result.getLanguage(); - output[1] = result.getCountry(); - return output; - // if (accessibilityDelegate != null) { - // accessibilityDelegate.updateSemantics(buffer, strings); - // } + return result.getLanguage() + result.getCountry(); } // ----- End Localizaation Support ---- diff --git a/shell/platform/android/platform_view_android.cc b/shell/platform/android/platform_view_android.cc index d54124578fae7..b076fe8af7bc9 100644 --- a/shell/platform/android/platform_view_android.cc +++ b/shell/platform/android/platform_view_android.cc @@ -429,20 +429,23 @@ void PlatformViewAndroid::ReleaseResourceContext() const { // |PlatformView| std::vector& PlatformViewAndroid::ComputePlatformResolvedLocales( const std::vector& supportedLocaleData) { - for (size_t i = 0; i < supportedLocaleData.size(); i++) { - FML_DLOG(ERROR) << "LOCALE COMPONENT: " << supportedLocaleData[i]; - } JNIEnv* env = fml::jni::AttachCurrentThread(); fml::jni::ScopedJavaLocalRef view = java_object_.get(env); if (view.is_null()) { // The Java object died. - *platform_resolved_locale_ = std::vector(); - return *platform_resolved_locale_; + platform_resolved_locale_.clear(); + return platform_resolved_locale_; } - *platform_resolved_locale_ = FlutterViewComputePlatformResolvedLocale( + std::string result = FlutterViewComputePlatformResolvedLocale( env, view.obj(), fml::jni::VectorToStringArray(env, supportedLocaleData).obj()); - return *platform_resolved_locale_; + + platform_resolved_locale_.clear(); + platform_resolved_locale_.emplace_back(result.data(), 2); + if (result.size() > 2) { + platform_resolved_locale_.emplace_back(result.data() + 2, 2); + } + return platform_resolved_locale_; } void PlatformViewAndroid::InstallFirstFrameCallback() { diff --git a/shell/platform/android/platform_view_android.h b/shell/platform/android/platform_view_android.h index a17882a8a68c7..ac5cbe1a91697 100644 --- a/shell/platform/android/platform_view_android.h +++ b/shell/platform/android/platform_view_android.h @@ -80,7 +80,7 @@ class PlatformViewAndroid final : public PlatformView { int next_response_id_ = 1; std::unordered_map> pending_responses_; - std::vector* platform_resolved_locale_; + std::vector platform_resolved_locale_; // |PlatformView| void UpdateSemantics( diff --git a/shell/platform/android/platform_view_android_jni.cc b/shell/platform/android/platform_view_android_jni.cc index 8ddca7d5a1a0a..1bf14717e44c1 100644 --- a/shell/platform/android/platform_view_android_jni.cc +++ b/shell/platform/android/platform_view_android_jni.cc @@ -145,20 +145,18 @@ void SurfaceTextureDetachFromGLContext(JNIEnv* env, jobject obj) { } static jmethodID g_compute_platform_resolved_locale_method = nullptr; -std::vector FlutterViewComputePlatformResolvedLocale( - JNIEnv* env, - jobject obj, - jobjectArray strings) { +std::string FlutterViewComputePlatformResolvedLocale(JNIEnv* env, + jobject obj, + jobjectArray strings) { std::vector vec = fml::jni::StringArrayToVector(env, strings); - jobjectArray result = static_cast(env->CallObjectMethod( - obj, g_compute_platform_resolved_locale_method, strings)); - FML_DLOG(ERROR) << "RESULT:::::::::::::::: " << result << " " << strings - << " " << env << " " << vec.size(); - // for (size_t i = 0; i < vec.size(); i++) { - // FML_DLOG(ERROR) << "LOCALE COMPONENT: " << vec[i]; - // } + jstring result = (jstring)env->CallObjectMethod( + obj, g_compute_platform_resolved_locale_method, strings); + FML_CHECK(CheckException(env)); - return fml::jni::StringArrayToVector(env, result); + + std::string out = fml::jni::JavaStringToString(env, result); + return out; + // return out; } // Called By Java @@ -808,8 +806,11 @@ bool PlatformViewAndroid::Register(JNIEnv* env) { g_compute_platform_resolved_locale_method = env->GetMethodID( g_flutter_jni_class->obj(), "computePlatformResolvedLocale", - "([Ljava/lang/String;)[Ljava/lang/String;"); + "([Ljava/lang/String;)Ljava/lang/String;"); + FML_LOG(ERROR) << "DISCOVERED computePlatformResolvedLocale ID: " + << g_compute_platform_resolved_locale_method << " " + << g_detach_from_gl_context_method; if (g_compute_platform_resolved_locale_method == nullptr) { FML_LOG(ERROR) << "Could not locate computePlatformResolvedLocale method"; return false; diff --git a/shell/platform/android/platform_view_android_jni.h b/shell/platform/android/platform_view_android_jni.h index 1704fdb764555..09f51987d4f64 100644 --- a/shell/platform/android/platform_view_android_jni.h +++ b/shell/platform/android/platform_view_android_jni.h @@ -46,10 +46,9 @@ void SurfaceTextureGetTransformMatrix(JNIEnv* env, void SurfaceTextureDetachFromGLContext(JNIEnv* env, jobject obj); -std::vector FlutterViewComputePlatformResolvedLocale( - JNIEnv* env, - jobject obj, - jobjectArray strings); +std::string FlutterViewComputePlatformResolvedLocale(JNIEnv* env, + jobject obj, + jobjectArray strings); } // namespace flutter From 674fe7b912170e3f1c0f4bc5d75969800f9ef004 Mon Sep 17 00:00:00 2001 From: garyqian Date: Thu, 4 Jun 2020 15:18:58 -0700 Subject: [PATCH 10/51] Initial iOS impl --- .../platform/android/platform_view_android_jni.cc | 3 --- shell/platform/darwin/ios/platform_view_ios.h | 1 + shell/platform/darwin/ios/platform_view_ios.mm | 15 +++++++++++++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/shell/platform/android/platform_view_android_jni.cc b/shell/platform/android/platform_view_android_jni.cc index 1bf14717e44c1..83318481f8e79 100644 --- a/shell/platform/android/platform_view_android_jni.cc +++ b/shell/platform/android/platform_view_android_jni.cc @@ -808,9 +808,6 @@ bool PlatformViewAndroid::Register(JNIEnv* env) { g_flutter_jni_class->obj(), "computePlatformResolvedLocale", "([Ljava/lang/String;)Ljava/lang/String;"); - FML_LOG(ERROR) << "DISCOVERED computePlatformResolvedLocale ID: " - << g_compute_platform_resolved_locale_method << " " - << g_detach_from_gl_context_method; if (g_compute_platform_resolved_locale_method == nullptr) { FML_LOG(ERROR) << "Could not locate computePlatformResolvedLocale method"; return false; diff --git a/shell/platform/darwin/ios/platform_view_ios.h b/shell/platform/darwin/ios/platform_view_ios.h index ac2c9da8adca9..766c4f97e74a6 100644 --- a/shell/platform/darwin/ios/platform_view_ios.h +++ b/shell/platform/darwin/ios/platform_view_ios.h @@ -129,6 +129,7 @@ class PlatformViewIOS final : public PlatformView { fml::scoped_nsprotocol text_input_plugin_; fml::closure firstFrameCallback_; ScopedObserver dealloc_view_controller_observer_; + std::vector platform_resolved_locale_; // |PlatformView| void HandlePlatformMessage(fml::RefPtr message) override; diff --git a/shell/platform/darwin/ios/platform_view_ios.mm b/shell/platform/darwin/ios/platform_view_ios.mm index d2f4cb48a26bd..534be22616879 100644 --- a/shell/platform/darwin/ios/platform_view_ios.mm +++ b/shell/platform/darwin/ios/platform_view_ios.mm @@ -191,6 +191,21 @@ new AccessibilityBridge(static_cast(owner_controller_.get().view), [owner_controller_.get() platformViewsController]->Reset(); } +std::vector& PlatformViewIOS::ComputePlatformResolvedLocales( + const std::vector& supportedLocaleData) { + std::vector trimmed_locale_data; + for (size_t i = 0; i < supportedLocaleData.size(); i += 2) { + trimmed_locale_data.push_back([NSString stringWithUTF8String:supportedLocaleData[i].c_str()]); + } + NSArray* ios_supported_locales = [NSArray arrayWithObjects:&trimmed_locale_data[0] + count:trimmed_locale_data.size()]; + // NSString* result = [NSString stringWithUTF8String:param.c_str()]; + NSArray* result = [NSBundle preferredLocalizationsFromArray:ios_supported_locales]; + + platform_resolved_locale_.emplace_back([result firstObject].UTF8String); + return platform_resolved_locale_; +} + PlatformViewIOS::ScopedObserver::ScopedObserver() : observer_(nil) {} PlatformViewIOS::ScopedObserver::~ScopedObserver() { From e1c2a37142819d65ad4413bc60faab32757fba68 Mon Sep 17 00:00:00 2001 From: garyqian Date: Fri, 5 Jun 2020 04:21:51 -0700 Subject: [PATCH 11/51] support scriptcode and incomplete locales/resolutions --- lib/ui/window.dart | 13 ++++++- lib/ui/window/window.cc | 7 +++- shell/common/shell.cc | 8 ++++ .../flutter/embedding/engine/FlutterJNI.java | 20 +++++++--- .../platform/android/platform_view_android.cc | 39 +++++++++++++++++-- .../platform/darwin/ios/platform_view_ios.mm | 3 ++ 6 files changed, 79 insertions(+), 11 deletions(-) diff --git a/lib/ui/window.dart b/lib/ui/window.dart index d31c29552bb6f..756207b9f595c 100644 --- a/lib/ui/window.dart +++ b/lib/ui/window.dart @@ -805,6 +805,11 @@ class Window { Locale get platformResolvedLocale => _platformResolvedLocale; Locale _platformResolvedLocale; + /// Performs the platform-native locale resolution. + /// + /// Each platform may return different results. + /// + /// If the platform fails to resolve a locale, then this will return null. Locale computePlatformResolvedLocale(List supportedLocales) { if (supportedLocales == null) { return null; @@ -813,12 +818,16 @@ class Window { for (Locale locale in supportedLocales) { supportedLocalesData.add(locale.languageCode); supportedLocalesData.add(locale.countryCode); + supportedLocalesData.add(locale.scriptCode); } List result = _computePlatformResolvedLocale(supportedLocalesData); - if (result != null) { - return result.length == 1 ? Locale.fromSubtags(languageCode: result[0]) : Locale.fromSubtags(languageCode: result[0], countryCode: result[1]); + if (result != null && result.isNotEmpty && result[0] != null) { + return Locale.fromSubtags( + languageCode: result[0], + countryCode: result[1], + scriptCode: result[2]); } return null; } diff --git a/lib/ui/window/window.cc b/lib/ui/window/window.cc index dd5eabaad6df3..79e55f4288cc0 100644 --- a/lib/ui/window/window.cc +++ b/lib/ui/window/window.cc @@ -431,7 +431,12 @@ Dart_Handle ComputePlatformResolvedLocale(Dart_Handle supportedLocalesHandle) { size_t u_length = static_cast(length); std::vector supportedLocales; for (size_t i = 0; i < u_length; i++) { - const char* cname; + const char* cname = nullptr; + Dart_Handle element = Dart_ListGetAt(supportedLocalesHandle, i); + if (Dart_IsNull(element)) { + supportedLocales.emplace_back(""); + continue; + } Dart_StringToCString(Dart_ListGetAt(supportedLocalesHandle, i), &cname); supportedLocales.emplace_back(cname); } diff --git a/shell/common/shell.cc b/shell/common/shell.cc index 1be3bed93e2a9..f50d76dfb5ab3 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -1107,6 +1107,14 @@ std::vector& Shell::ComputePlatformResolvedLocale( // |PlatformView::Delegate| std::vector& Shell::ComputePlatformViewResolvedLocale( const std::vector& supportedLocaleData) { + for (size_t i = 0; i < supportedLocaleData.size(); i++) { + FML_DLOG(ERROR) << "LOCALEIN: " + supportedLocaleData[i]; + } + std::vector result = + platform_view_->ComputePlatformResolvedLocales(supportedLocaleData); + for (size_t i = 0; i < result.size(); i++) { + FML_DLOG(ERROR) << "#LOCALEOUT: " + result[i]; + } return platform_view_->ComputePlatformResolvedLocales(supportedLocaleData); } diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java index 6e132d4a6583b..d30926a97c7f7 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java @@ -794,17 +794,27 @@ private void onPreEngineRestart() { @SuppressWarnings("unused") private String computePlatformResolvedLocale(@NonNull String[] strings) { List supportedLocales = new ArrayList(); - final int localeDataLength = 2; + final int localeDataLength = 3; for (int i = 0; i < strings.length / localeDataLength; i++) { String languageCode = strings[i * localeDataLength + 0]; String countryCode = strings[i * localeDataLength + 1]; - if (countryCode.isEmpty()) { - supportedLocales.add(new Locale(languageCode)); - } else { - supportedLocales.add(new Locale(languageCode, countryCode)); + String scriptCode = strings[i * localeDataLength + 2]; + Locale.Builder localeBuilder = new Locale.Builder(); + if (!languageCode.isEmpty()) { + localeBuilder.setLanguage(languageCode); } + if (!countryCode.isEmpty()) { + localeBuilder.setRegion(countryCode); + } + if (!scriptCode.isEmpty()) { + localeBuilder.setScript(scriptCode); + } + supportedLocales.add(localeBuilder.build()); } Locale result = LocalizationPlugin.resolveNativeLocale(supportedLocales); + if (result == null) { + return ""; + } return result.getLanguage() + result.getCountry(); } diff --git a/shell/platform/android/platform_view_android.cc b/shell/platform/android/platform_view_android.cc index b076fe8af7bc9..01338eb3b4ea6 100644 --- a/shell/platform/android/platform_view_android.cc +++ b/shell/platform/android/platform_view_android.cc @@ -441,9 +441,42 @@ std::vector& PlatformViewAndroid::ComputePlatformResolvedLocales( fml::jni::VectorToStringArray(env, supportedLocaleData).obj()); platform_resolved_locale_.clear(); - platform_resolved_locale_.emplace_back(result.data(), 2); - if (result.size() > 2) { - platform_resolved_locale_.emplace_back(result.data() + 2, 2); + // Decode the locale string. + switch (platform_resolved_locale_.size()) { + case 0: { + platform_resolved_locale_.emplace_back(""); + platform_resolved_locale_.emplace_back(""); + platform_resolved_locale_.emplace_back(""); + break; + } + // Only languageCode (2) + case 2: { + platform_resolved_locale_.emplace_back(result.data(), 2); + platform_resolved_locale_.emplace_back(""); + platform_resolved_locale_.emplace_back(""); + break; + } + // Only languageCode (2) and countryCode (2) + case 4: { + platform_resolved_locale_.emplace_back(result.data(), 2); + platform_resolved_locale_.emplace_back(result.data() + 2, 2); + platform_resolved_locale_.emplace_back(""); + break; + } + // Only languageCode (2) and scriptCode (4) + case 6: { + platform_resolved_locale_.emplace_back(result.data(), 2); + platform_resolved_locale_.emplace_back(""); + platform_resolved_locale_.emplace_back(result.data() + 2, 4); + break; + } + // languageCode (2), countryCode (2), and scriptCode (4) + case 8: { + platform_resolved_locale_.emplace_back(result.data(), 2); + platform_resolved_locale_.emplace_back(result.data() + 2, 2); + platform_resolved_locale_.emplace_back(result.data() + 4, 4); + break; + } } return platform_resolved_locale_; } diff --git a/shell/platform/darwin/ios/platform_view_ios.mm b/shell/platform/darwin/ios/platform_view_ios.mm index 534be22616879..621f06f74d31f 100644 --- a/shell/platform/darwin/ios/platform_view_ios.mm +++ b/shell/platform/darwin/ios/platform_view_ios.mm @@ -193,6 +193,9 @@ new AccessibilityBridge(static_cast(owner_controller_.get().view), std::vector& PlatformViewIOS::ComputePlatformResolvedLocales( const std::vector& supportedLocaleData) { + for (size_t i = 0; i < supportedLocaleData.size(); i++) { + FML_DLOG(ERROR) << "LOCALE: " + supportedLocaleData[i]; + } std::vector trimmed_locale_data; for (size_t i = 0; i < supportedLocaleData.size(); i += 2) { trimmed_locale_data.push_back([NSString stringWithUTF8String:supportedLocaleData[i].c_str()]); From bd0c5904b38ad1dec49448b6bdea3bbd5ff2334e Mon Sep 17 00:00:00 2001 From: garyqian Date: Fri, 5 Jun 2020 05:54:17 -0700 Subject: [PATCH 12/51] Working android code path --- lib/ui/window/window.cc | 5 ++++- .../android/io/flutter/embedding/engine/FlutterJNI.java | 9 +++++---- .../flutter/plugin/localization/LocalizationPlugin.java | 5 +++-- shell/platform/android/platform_view_android.cc | 2 +- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/lib/ui/window/window.cc b/lib/ui/window/window.cc index 79e55f4288cc0..050a5431c16cf 100644 --- a/lib/ui/window/window.cc +++ b/lib/ui/window/window.cc @@ -444,10 +444,13 @@ Dart_Handle ComputePlatformResolvedLocale(Dart_Handle supportedLocalesHandle) { UIDartState::Current()->window()->client()->ComputePlatformResolvedLocale( supportedLocales); + FML_DCHECK(results.size() == 3); // Convert to dart List of strings. Dart_Handle output = Dart_NewListOf(Dart_CoreType_String, results.size()); for (size_t i = 0; i < results.size(); i++) { - Dart_ListSetAt(output, i, tonic::ToDart(results[i])); + Dart_ListSetAt( + output, i, + results[i].empty() ? Dart_Null() : tonic::ToDart(results[i])); } Dart_ListLength(output, &length); diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java index d30926a97c7f7..9cdcae93b26a2 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java @@ -795,10 +795,10 @@ private void onPreEngineRestart() { private String computePlatformResolvedLocale(@NonNull String[] strings) { List supportedLocales = new ArrayList(); final int localeDataLength = 3; - for (int i = 0; i < strings.length / localeDataLength; i++) { - String languageCode = strings[i * localeDataLength + 0]; - String countryCode = strings[i * localeDataLength + 1]; - String scriptCode = strings[i * localeDataLength + 2]; + for (int i = 0; i < strings.length; i += localeDataLength) { + String languageCode = strings[i + 0]; + String countryCode = strings[i + 1]; + String scriptCode = strings[i + 2]; Locale.Builder localeBuilder = new Locale.Builder(); if (!languageCode.isEmpty()) { localeBuilder.setLanguage(languageCode); @@ -812,6 +812,7 @@ private String computePlatformResolvedLocale(@NonNull String[] strings) { supportedLocales.add(localeBuilder.build()); } Locale result = LocalizationPlugin.resolveNativeLocale(supportedLocales); + Log.e("Flutter", "RESULT: " + result); if (result == null) { return ""; } diff --git a/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java b/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java index 80c11da96f0f1..48aff104f8621 100644 --- a/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java +++ b/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java @@ -51,9 +51,10 @@ public static Locale resolveNativeLocale(List supportedLocales) { int localeCount = localeList.size(); for (int index = 0; index < localeCount; ++index) { Locale locale = localeList.get(index); - languageRanges.add(new Locale.LanguageRange(locale.toLanguageTag())); + String localeString = locale.toString(); + languageRanges.add(new Locale.LanguageRange(localeString.replace("_", "-"))); } - // TODO(garyq) implement a real locale resolution. + platformResolvedLocale = Locale.lookup(languageRanges, supportedLocales); } diff --git a/shell/platform/android/platform_view_android.cc b/shell/platform/android/platform_view_android.cc index 01338eb3b4ea6..4f633e4ae0c09 100644 --- a/shell/platform/android/platform_view_android.cc +++ b/shell/platform/android/platform_view_android.cc @@ -442,7 +442,7 @@ std::vector& PlatformViewAndroid::ComputePlatformResolvedLocales( platform_resolved_locale_.clear(); // Decode the locale string. - switch (platform_resolved_locale_.size()) { + switch (result.size()) { case 0: { platform_resolved_locale_.emplace_back(""); platform_resolved_locale_.emplace_back(""); From 22817b43344bea6a2d833156b57ac63fcd2c88ad Mon Sep 17 00:00:00 2001 From: garyqian Date: Fri, 5 Jun 2020 17:33:20 -0700 Subject: [PATCH 13/51] Roughly working iOS implementation --- .../flutter/embedding/engine/FlutterJNI.java | 1 - .../localization/LocalizationPlugin.java | 1 + .../platform/darwin/ios/platform_view_ios.mm | 25 ++++++++++++++++--- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java index 9cdcae93b26a2..2013f2c001c10 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java @@ -812,7 +812,6 @@ private String computePlatformResolvedLocale(@NonNull String[] strings) { supportedLocales.add(localeBuilder.build()); } Locale result = LocalizationPlugin.resolveNativeLocale(supportedLocales); - Log.e("Flutter", "RESULT: " + result); if (result == null) { return ""; } diff --git a/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java b/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java index 48aff104f8621..16b5639746cfc 100644 --- a/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java +++ b/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java @@ -55,6 +55,7 @@ public static Locale resolveNativeLocale(List supportedLocales) { languageRanges.add(new Locale.LanguageRange(localeString.replace("_", "-"))); } + // This needs to be modified to achieve Android's full locale resolution platformResolvedLocale = Locale.lookup(languageRanges, supportedLocales); } diff --git a/shell/platform/darwin/ios/platform_view_ios.mm b/shell/platform/darwin/ios/platform_view_ios.mm index 621f06f74d31f..e3785c007a5ef 100644 --- a/shell/platform/darwin/ios/platform_view_ios.mm +++ b/shell/platform/darwin/ios/platform_view_ios.mm @@ -197,15 +197,34 @@ new AccessibilityBridge(static_cast(owner_controller_.get().view), FML_DLOG(ERROR) << "LOCALE: " + supportedLocaleData[i]; } std::vector trimmed_locale_data; - for (size_t i = 0; i < supportedLocaleData.size(); i += 2) { - trimmed_locale_data.push_back([NSString stringWithUTF8String:supportedLocaleData[i].c_str()]); + size_t localeDataLength = 3; + for (size_t i = 0; i < supportedLocaleData.size(); i += localeDataLength) { + std::string locale_string = supportedLocaleData[i]; + // Concat scriptCode + if (!supportedLocaleData[i + 2].empty()) { + locale_string += "-" + supportedLocaleData[i + 2]; + } + // Concat countryCode + if (!supportedLocaleData[i + 1].empty()) { + locale_string += "-" + supportedLocaleData[i + 1]; + } + trimmed_locale_data.push_back([NSString stringWithUTF8String:locale_string.c_str()]); } NSArray* ios_supported_locales = [NSArray arrayWithObjects:&trimmed_locale_data[0] count:trimmed_locale_data.size()]; // NSString* result = [NSString stringWithUTF8String:param.c_str()]; NSArray* result = [NSBundle preferredLocalizationsFromArray:ios_supported_locales]; - platform_resolved_locale_.emplace_back([result firstObject].UTF8String); + platform_resolved_locale_.clear(); + if (result != nullptr && [result count] > 0) { + platform_resolved_locale_.emplace_back([result firstObject].UTF8String); + platform_resolved_locale_.emplace_back(""); + platform_resolved_locale_.emplace_back(""); + } else { + platform_resolved_locale_.emplace_back(""); + platform_resolved_locale_.emplace_back(""); + platform_resolved_locale_.emplace_back(""); + } return platform_resolved_locale_; } From 917c74a5cf6cdb5cf375100cedbcd42439e6d161 Mon Sep 17 00:00:00 2001 From: garyqian Date: Mon, 8 Jun 2020 18:01:34 -0700 Subject: [PATCH 14/51] Improved iOS locale handling --- lib/ui/window/window.cc | 3 ++ .../platform/android/platform_view_android.cc | 6 --- .../platform/darwin/ios/platform_view_ios.mm | 47 +++++++++---------- 3 files changed, 25 insertions(+), 31 deletions(-) diff --git a/lib/ui/window/window.cc b/lib/ui/window/window.cc index 050a5431c16cf..15a91917670b4 100644 --- a/lib/ui/window/window.cc +++ b/lib/ui/window/window.cc @@ -444,6 +444,9 @@ Dart_Handle ComputePlatformResolvedLocale(Dart_Handle supportedLocalesHandle) { UIDartState::Current()->window()->client()->ComputePlatformResolvedLocale( supportedLocales); + if (results.empty()) { + return Dart_Null(); + } FML_DCHECK(results.size() == 3); // Convert to dart List of strings. Dart_Handle output = Dart_NewListOf(Dart_CoreType_String, results.size()); diff --git a/shell/platform/android/platform_view_android.cc b/shell/platform/android/platform_view_android.cc index 4f633e4ae0c09..174f05cefe8eb 100644 --- a/shell/platform/android/platform_view_android.cc +++ b/shell/platform/android/platform_view_android.cc @@ -443,12 +443,6 @@ std::vector& PlatformViewAndroid::ComputePlatformResolvedLocales( platform_resolved_locale_.clear(); // Decode the locale string. switch (result.size()) { - case 0: { - platform_resolved_locale_.emplace_back(""); - platform_resolved_locale_.emplace_back(""); - platform_resolved_locale_.emplace_back(""); - break; - } // Only languageCode (2) case 2: { platform_resolved_locale_.emplace_back(result.data(), 2); diff --git a/shell/platform/darwin/ios/platform_view_ios.mm b/shell/platform/darwin/ios/platform_view_ios.mm index e3785c007a5ef..16a1f7dbf03fb 100644 --- a/shell/platform/darwin/ios/platform_view_ios.mm +++ b/shell/platform/darwin/ios/platform_view_ios.mm @@ -193,37 +193,34 @@ new AccessibilityBridge(static_cast(owner_controller_.get().view), std::vector& PlatformViewIOS::ComputePlatformResolvedLocales( const std::vector& supportedLocaleData) { - for (size_t i = 0; i < supportedLocaleData.size(); i++) { - FML_DLOG(ERROR) << "LOCALE: " + supportedLocaleData[i]; - } - std::vector trimmed_locale_data; size_t localeDataLength = 3; + NSMutableArray* supported_locale_identifiers = + [NSMutableArray arrayWithCapacity:supportedLocaleData.size() / localeDataLength]; for (size_t i = 0; i < supportedLocaleData.size(); i += localeDataLength) { - std::string locale_string = supportedLocaleData[i]; - // Concat scriptCode - if (!supportedLocaleData[i + 2].empty()) { - locale_string += "-" + supportedLocaleData[i + 2]; - } - // Concat countryCode - if (!supportedLocaleData[i + 1].empty()) { - locale_string += "-" + supportedLocaleData[i + 1]; - } - trimmed_locale_data.push_back([NSString stringWithUTF8String:locale_string.c_str()]); + NSDictionary* dict = @{ + NSLocaleLanguageCode : [NSString stringWithUTF8String:supportedLocaleData[i].c_str()], + NSLocaleCountryCode : [NSString stringWithUTF8String:supportedLocaleData[i + 1].c_str()], + NSLocaleScriptCode : [NSString stringWithUTF8String:supportedLocaleData[i + 2].c_str()] + }; + [supported_locale_identifiers addObject:[NSLocale localeIdentifierFromComponents:dict]]; } - NSArray* ios_supported_locales = [NSArray arrayWithObjects:&trimmed_locale_data[0] - count:trimmed_locale_data.size()]; - // NSString* result = [NSString stringWithUTF8String:param.c_str()]; - NSArray* result = [NSBundle preferredLocalizationsFromArray:ios_supported_locales]; + NSArray* result = + [NSBundle preferredLocalizationsFromArray:supported_locale_identifiers]; + // Output format should be either empty or 3 strings for language, country, and script. platform_resolved_locale_.clear(); + if (result != nullptr && [result count] > 0) { - platform_resolved_locale_.emplace_back([result firstObject].UTF8String); - platform_resolved_locale_.emplace_back(""); - platform_resolved_locale_.emplace_back(""); - } else { - platform_resolved_locale_.emplace_back(""); - platform_resolved_locale_.emplace_back(""); - platform_resolved_locale_.emplace_back(""); + if (@available(ios 10.0, *)) { + NSLocale* locale = [NSLocale localeWithLocaleIdentifier:[result firstObject]]; + NSString* languageCode = [locale languageCode]; + platform_resolved_locale_.emplace_back(languageCode == nullptr ? "" + : languageCode.UTF8String); + NSString* countryCode = [locale countryCode]; + platform_resolved_locale_.emplace_back(countryCode == nullptr ? "" : countryCode.UTF8String); + NSString* scriptCode = [locale scriptCode]; + platform_resolved_locale_.emplace_back(scriptCode == nullptr ? "" : scriptCode.UTF8String); + } } return platform_resolved_locale_; } From 4329b6abefd813b691f85d7a53393a1bae133432 Mon Sep 17 00:00:00 2001 From: garyqian Date: Mon, 8 Jun 2020 18:34:22 -0700 Subject: [PATCH 15/51] CLeanup, renaming, comments --- lib/ui/window.dart | 3 + lib/ui/window/window.h | 2 +- runtime/runtime_controller.cc | 4 +- runtime/runtime_controller.h | 2 +- runtime/runtime_delegate.h | 2 +- shell/common/engine.cc | 4 +- shell/common/engine.h | 19 +++++- shell/common/platform_view.cc | 4 +- shell/common/platform_view.h | 19 +++++- shell/common/shell.cc | 14 ++--- shell/common/shell.h | 4 +- .../embedding/android/FlutterView.java | 4 +- .../flutter/embedding/engine/FlutterJNI.java | 2 +- .../systemchannels/LocalizationChannel.java | 61 ------------------- .../localization/LocalizationPlugin.java | 21 +------ .../android/io/flutter/view/FlutterView.java | 4 +- .../platform/android/platform_view_android.cc | 4 +- .../platform/android/platform_view_android.h | 2 +- shell/platform/darwin/ios/platform_view_ios.h | 2 +- .../platform/darwin/ios/platform_view_ios.mm | 12 ++-- 20 files changed, 73 insertions(+), 116 deletions(-) diff --git a/lib/ui/window.dart b/lib/ui/window.dart index 756207b9f595c..d55f014411280 100644 --- a/lib/ui/window.dart +++ b/lib/ui/window.dart @@ -810,6 +810,9 @@ class Window { /// Each platform may return different results. /// /// If the platform fails to resolve a locale, then this will return null. + /// + /// This method returns synchronously and is a direct call to + /// platform specific APIs without invoking method channels. Locale computePlatformResolvedLocale(List supportedLocales) { if (supportedLocales == null) { return null; diff --git a/lib/ui/window/window.h b/lib/ui/window/window.h index 050a6aef536eb..7d4341f70bad0 100644 --- a/lib/ui/window/window.h +++ b/lib/ui/window/window.h @@ -60,7 +60,7 @@ class WindowClient { virtual void SetNeedsReportTimings(bool value) = 0; virtual std::shared_ptr GetPersistentIsolateData() = 0; virtual std::vector& ComputePlatformResolvedLocale( - const std::vector& supportedLocaleData) = 0; + const std::vector& supported_locale_data) = 0; protected: virtual ~WindowClient(); diff --git a/runtime/runtime_controller.cc b/runtime/runtime_controller.cc index d2d26708e265a..3bf0d29baf938 100644 --- a/runtime/runtime_controller.cc +++ b/runtime/runtime_controller.cc @@ -342,8 +342,8 @@ RuntimeController::GetPersistentIsolateData() { // |WindowClient| std::vector& RuntimeController::ComputePlatformResolvedLocale( - const std::vector& supportedLocaleData) { - return client_.ComputePlatformResolvedLocale(supportedLocaleData); + const std::vector& supported_locale_data) { + return client_.ComputePlatformResolvedLocale(supported_locale_data); // return std::vector(); } diff --git a/runtime/runtime_controller.h b/runtime/runtime_controller.h index af6ce91ec3403..0926aa5987938 100644 --- a/runtime/runtime_controller.h +++ b/runtime/runtime_controller.h @@ -524,7 +524,7 @@ class RuntimeController final : public WindowClient { // |WindowClient| std::vector& ComputePlatformResolvedLocale( - const std::vector& supportedLocaleData) override; + const std::vector& supported_locale_data) override; FML_DISALLOW_COPY_AND_ASSIGN(RuntimeController); }; diff --git a/runtime/runtime_delegate.h b/runtime/runtime_delegate.h index a6c14def41b77..b3eb7c2043d4e 100644 --- a/runtime/runtime_delegate.h +++ b/runtime/runtime_delegate.h @@ -38,7 +38,7 @@ class RuntimeDelegate { virtual void SetNeedsReportTimings(bool value) = 0; virtual std::vector& ComputePlatformResolvedLocale( - const std::vector& supportedLocaleData) = 0; + const std::vector& supported_locale_data) = 0; protected: virtual ~RuntimeDelegate(); diff --git a/shell/common/engine.cc b/shell/common/engine.cc index b7f1bce03ae2d..d7fd6d95e70f1 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc @@ -493,8 +493,8 @@ void Engine::UpdateIsolateDescription(const std::string isolate_name, } std::vector& Engine::ComputePlatformResolvedLocale( - const std::vector& supportedLocaleData) { - return delegate_.ComputePlatformResolvedLocale(supportedLocaleData); + const std::vector& supported_locale_data) { + return delegate_.ComputePlatformResolvedLocale(supported_locale_data); } void Engine::SetNeedsReportTimings(bool needs_reporting) { diff --git a/shell/common/engine.h b/shell/common/engine.h index 045c537c9af63..686138d36e03b 100644 --- a/shell/common/engine.h +++ b/shell/common/engine.h @@ -228,8 +228,23 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate { /// virtual void SetNeedsReportTimings(bool needs_reporting) = 0; + //-------------------------------------------------------------------------- + /// @brief Directly invokes platform-specific APIs to compute the + /// locale the platform would have natively resolved to. + /// + /// @param[in] supported_locale_data The vector of strings that represents + /// the locales supported by the app. + /// Each locale consists of three + /// strings: languageCode, countryCode, + /// and scriptCode in that order. + /// + /// @return A vector of 3 strings languageCode, countryCode, and + /// scriptCode that the conist the locale selected by the + /// platform. Empty strings mean the value was unassigned. Empty + /// vector represents a null locale. + /// virtual std::vector& ComputePlatformResolvedLocale( - const std::vector& supportedLocaleData) = 0; + const std::vector& supported_locale_data) = 0; }; //---------------------------------------------------------------------------- @@ -777,7 +792,7 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate { // |RuntimeDelegate| std::vector& ComputePlatformResolvedLocale( - const std::vector& supportedLocaleData) override; + const std::vector& supported_locale_data) override; void SetNeedsReportTimings(bool value) override; diff --git a/shell/common/platform_view.cc b/shell/common/platform_view.cc index ed45c30736f6a..45b32662d969b 100644 --- a/shell/common/platform_view.cc +++ b/shell/common/platform_view.cc @@ -138,10 +138,10 @@ void PlatformView::SetNextFrameCallback(const fml::closure& closure) { } std::vector& PlatformView::ComputePlatformResolvedLocales( - const std::vector& supportedLocaleData) { + const std::vector& supported_locale_data) { // std::vector result = std::vector(); // *result = std::vector(); - return delegate_.ComputePlatformViewResolvedLocale(supportedLocaleData); + return delegate_.ComputePlatformViewResolvedLocale(supported_locale_data); } } // namespace flutter diff --git a/shell/common/platform_view.h b/shell/common/platform_view.h index f2067399f673c..a378a08a84720 100644 --- a/shell/common/platform_view.h +++ b/shell/common/platform_view.h @@ -210,8 +210,23 @@ class PlatformView { virtual void OnPlatformViewMarkTextureFrameAvailable( int64_t texture_id) = 0; + //-------------------------------------------------------------------------- + /// @brief Directly invokes platform-specific APIs to compute the + /// locale the platform would have natively resolved to. + /// + /// @param[in] supported_locale_data The vector of strings that represents + /// the locales supported by the app. + /// Each locale consists of three + /// strings: languageCode, countryCode, + /// and scriptCode in that order. + /// + /// @return A vector of 3 strings languageCode, countryCode, and + /// scriptCode that the conist the locale selected by the + /// platform. Empty strings mean the value was unassigned. Empty + /// vector represents a null locale. + /// virtual std::vector& ComputePlatformViewResolvedLocale( - const std::vector& supportedLocaleData) = 0; + const std::vector& supported_locale_data) = 0; }; //---------------------------------------------------------------------------- @@ -547,7 +562,7 @@ class PlatformView { void MarkTextureFrameAvailable(int64_t texture_id); virtual std::vector& ComputePlatformResolvedLocales( - const std::vector& supportedLocaleData); + const std::vector& supported_locale_data); protected: PlatformView::Delegate& delegate_; diff --git a/shell/common/shell.cc b/shell/common/shell.cc index f50d76dfb5ab3..12a3a49857178 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -1100,22 +1100,22 @@ void Shell::SetNeedsReportTimings(bool value) { // |Engine::Delegate| std::vector& Shell::ComputePlatformResolvedLocale( - const std::vector& supportedLocaleData) { - return ComputePlatformViewResolvedLocale(supportedLocaleData); + const std::vector& supported_locale_data) { + return ComputePlatformViewResolvedLocale(supported_locale_data); } // |PlatformView::Delegate| std::vector& Shell::ComputePlatformViewResolvedLocale( - const std::vector& supportedLocaleData) { - for (size_t i = 0; i < supportedLocaleData.size(); i++) { - FML_DLOG(ERROR) << "LOCALEIN: " + supportedLocaleData[i]; + const std::vector& supported_locale_data) { + for (size_t i = 0; i < supported_locale_data.size(); i++) { + FML_DLOG(ERROR) << "LOCALEIN: " + supported_locale_data[i]; } std::vector result = - platform_view_->ComputePlatformResolvedLocales(supportedLocaleData); + platform_view_->ComputePlatformResolvedLocales(supported_locale_data); for (size_t i = 0; i < result.size(); i++) { FML_DLOG(ERROR) << "#LOCALEOUT: " + result[i]; } - return platform_view_->ComputePlatformResolvedLocales(supportedLocaleData); + return platform_view_->ComputePlatformResolvedLocales(supported_locale_data); } void Shell::ReportTimings() { diff --git a/shell/common/shell.h b/shell/common/shell.h index 069b287b0be4e..bccb0c1bc975e 100644 --- a/shell/common/shell.h +++ b/shell/common/shell.h @@ -484,7 +484,7 @@ class Shell final : public PlatformView::Delegate, // |PlatformView::Delegate| std::vector& ComputePlatformViewResolvedLocale( - const std::vector& supportedLocaleData) override; + const std::vector& supported_locale_data) override; // |Animator::Delegate| void OnAnimatorBeginFrame(fml::TimePoint frame_target_time) override; @@ -522,7 +522,7 @@ class Shell final : public PlatformView::Delegate, // |Engine::Delegate| std::vector& ComputePlatformResolvedLocale( - const std::vector& supportedLocaleData) override; + const std::vector& supported_locale_data) override; // |Rasterizer::Delegate| void OnFrameRasterized(const FrameTiming&) override; diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterView.java b/shell/platform/android/io/flutter/embedding/android/FlutterView.java index bca5d96f65f32..2e3f377066abb 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterView.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterView.java @@ -357,7 +357,7 @@ protected void onConfigurationChanged(@NonNull Configuration newConfig) { // again (e.g. in onStart). if (flutterEngine != null) { Log.v(TAG, "Configuration changed. Sending locales and user settings to Flutter."); - localizationPlugin.sendLocalesToDart(newConfig); + localizationPlugin.sendLocalesToFlutter(newConfig); sendUserSettingsToFlutter(); } } @@ -848,7 +848,7 @@ public void attachToFlutterEngine(@NonNull FlutterEngine flutterEngine) { // Push View and Context related information from Android to Flutter. sendUserSettingsToFlutter(); - localizationPlugin.sendLocalesToDart(getResources().getConfiguration()); + localizationPlugin.sendLocalesToFlutter(getResources().getConfiguration()); sendViewportMetricsToFlutter(); flutterEngine.getPlatformViewsController().attachToView(this); diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java index 2013f2c001c10..911b10bb4d5cd 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java @@ -818,7 +818,7 @@ private String computePlatformResolvedLocale(@NonNull String[] strings) { return result.getLanguage() + result.getCountry(); } - // ----- End Localizaation Support ---- + // ----- End Localization Support ---- // TODO(mattcarroll): determine if this is nonull or nullable @UiThread diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/LocalizationChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/LocalizationChannel.java index 96e01aff9459b..aaae268b03f90 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/LocalizationChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/LocalizationChannel.java @@ -10,68 +10,20 @@ import io.flutter.Log; import io.flutter.embedding.engine.dart.DartExecutor; import io.flutter.plugin.common.JSONMethodCodec; -import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import java.util.ArrayList; import java.util.List; import java.util.Locale; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; /** Sends the platform's locales to Dart. */ public class LocalizationChannel { private static final String TAG = "LocalizationChannel"; @NonNull public final MethodChannel channel; - @Nullable private LocalizationMethodHandler localizationMethodHandler; - - private MethodChannel.MethodCallHandler parsingMethodHandler = - new MethodChannel.MethodCallHandler() { - @Override - public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) { - if (localizationMethodHandler == null) { - // If no explicit LocalizationMethodHandler has been registered then we don't - // need to forward this call to an API. Return. - return; - } - - String method = call.method; - Object args = call.arguments; - Log.v(TAG, "Received '" + method + "' message."); - switch (method) { - case "Localization.resolveLocale": - try { - final JSONObject arguments = (JSONObject) args; - final int length = arguments.getInt("count"); - final JSONArray supportedLocalesData = arguments.getJSONArray("localeData"); - List supportedLocales = new ArrayList(); - for (int i = 0; i < length; i++) { - // Java locales only support language, country, and variant. - final String language = supportedLocalesData.getString(i * 2 + 0); - final String country = supportedLocalesData.getString(i * 2 + 1); - supportedLocales.add(new Locale(language, country)); - } - Locale resolvedLocale = localizationMethodHandler.resolveLocale(supportedLocales); - List resolvedLocaleComponents = new ArrayList(); - resolvedLocaleComponents.add(resolvedLocale.getLanguage()); - resolvedLocaleComponents.add(resolvedLocale.getCountry()); - result.success(resolvedLocaleComponents); - } catch (JSONException exception) { - result.error("error", exception.getMessage(), null); - } - break; - default: - result.notImplemented(); - break; - } - } - }; public LocalizationChannel(@NonNull DartExecutor dartExecutor) { this.channel = new MethodChannel(dartExecutor, "flutter/localization", JSONMethodCodec.INSTANCE); - channel.setMethodCallHandler(parsingMethodHandler); } /** Send the given {@code locales} to Dart. */ @@ -113,17 +65,4 @@ public void sendPlatformResolvedLocales(Locale platformResolvedLocale) { channel.invokeMethod("setPlatformResolvedLocale", platformResolvedLocaleData); } } - - /** - * Sets the {@link TextInputMethodHandler} which receives all events and requests that are parsed - * from the underlying platform channel. - */ - public void setLocalizationMethodHandler(@Nullable LocalizationMethodHandler localizationMethodHandler) { - this.localizationMethodHandler = localizationMethodHandler; - } - - public interface LocalizationMethodHandler { - /** Performs the android native locale resolution. */ - Locale resolveLocale(List supportedLocales); - } } diff --git a/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java b/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java index 16b5639746cfc..c18e9f4f3864a 100644 --- a/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java +++ b/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java @@ -33,13 +33,6 @@ public LocalizationPlugin( this.context = context; this.localizationChannel = localizationChannel; - localizationChannel.setLocalizationMethodHandler( - new LocalizationChannel.LocalizationMethodHandler() { - @Override - public Locale resolveLocale(List supportedLocales) { - return resolveNativeLocale(supportedLocales); - } - }); instance = this; } @@ -55,7 +48,8 @@ public static Locale resolveNativeLocale(List supportedLocales) { languageRanges.add(new Locale.LanguageRange(localeString.replace("_", "-"))); } - // This needs to be modified to achieve Android's full locale resolution + // TODO(garyq): This should be modified to achieve Android's full + // locale resolution: https://developer.android.com/guide/topics/resources/multilingual-support platformResolvedLocale = Locale.lookup(languageRanges, supportedLocales); } @@ -68,7 +62,7 @@ public static Locale resolveNativeLocale(List supportedLocales) { *

FlutterEngine must be non-null when this method is invoked. */ @SuppressWarnings("deprecation") - public void sendLocalesToDart(@NonNull Configuration config) { + public void sendLocalesToFlutter(@NonNull Configuration config) { List locales = new ArrayList<>(); if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { LocaleList localeList = config.getLocales(); @@ -100,13 +94,4 @@ public void sendLocalesToDart(@NonNull Configuration config) { // this later via the method channel call "resolveLocale". // localizationChannel.sendPlatformResolvedLocales(platformResolvedLocale); } - - /** - * Cleans up the handler in the LocalizationChannel/ - * - *

The TextInputPlugin instance should not be used after calling this. - */ - public void destroy() { - localizationChannel.setLocalizationMethodHandler(null); - } } diff --git a/shell/platform/android/io/flutter/view/FlutterView.java b/shell/platform/android/io/flutter/view/FlutterView.java index 02b75dc4dd4ed..780a4e1f1a45f 100644 --- a/shell/platform/android/io/flutter/view/FlutterView.java +++ b/shell/platform/android/io/flutter/view/FlutterView.java @@ -242,7 +242,7 @@ public void onPostResume() { .attachTextInputPlugin(mTextInputPlugin); // Send initial platform information to Dart - mLocalizationPlugin.sendLocalesToDart(getResources().getConfiguration()); + mLocalizationPlugin.sendLocalesToFlutter(getResources().getConfiguration()); sendUserPlatformSettingsToDart(); } @@ -409,7 +409,7 @@ private void sendUserPlatformSettingsToDart() { @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); - mLocalizationPlugin.sendLocalesToDart(newConfig); + mLocalizationPlugin.sendLocalesToFlutter(newConfig); sendUserPlatformSettingsToDart(); } diff --git a/shell/platform/android/platform_view_android.cc b/shell/platform/android/platform_view_android.cc index 174f05cefe8eb..847acda78d00c 100644 --- a/shell/platform/android/platform_view_android.cc +++ b/shell/platform/android/platform_view_android.cc @@ -428,7 +428,7 @@ void PlatformViewAndroid::ReleaseResourceContext() const { // |PlatformView| std::vector& PlatformViewAndroid::ComputePlatformResolvedLocales( - const std::vector& supportedLocaleData) { + const std::vector& supported_locale_data) { JNIEnv* env = fml::jni::AttachCurrentThread(); fml::jni::ScopedJavaLocalRef view = java_object_.get(env); if (view.is_null()) { @@ -438,7 +438,7 @@ std::vector& PlatformViewAndroid::ComputePlatformResolvedLocales( } std::string result = FlutterViewComputePlatformResolvedLocale( env, view.obj(), - fml::jni::VectorToStringArray(env, supportedLocaleData).obj()); + fml::jni::VectorToStringArray(env, supported_locale_data).obj()); platform_resolved_locale_.clear(); // Decode the locale string. diff --git a/shell/platform/android/platform_view_android.h b/shell/platform/android/platform_view_android.h index ac5cbe1a91697..304491ae7edf5 100644 --- a/shell/platform/android/platform_view_android.h +++ b/shell/platform/android/platform_view_android.h @@ -108,7 +108,7 @@ class PlatformViewAndroid final : public PlatformView { // |PlatformView| std::vector& ComputePlatformResolvedLocales( - const std::vector& supportedLocaleData) override; + const std::vector& supported_locale_data) override; void InstallFirstFrameCallback(); diff --git a/shell/platform/darwin/ios/platform_view_ios.h b/shell/platform/darwin/ios/platform_view_ios.h index 766c4f97e74a6..6bb802adaa8fd 100644 --- a/shell/platform/darwin/ios/platform_view_ios.h +++ b/shell/platform/darwin/ios/platform_view_ios.h @@ -155,7 +155,7 @@ class PlatformViewIOS final : public PlatformView { // |PlatformView| std::vector& ComputePlatformResolvedLocales( - const std::vector& supportedLocaleData) override; + const std::vector& supported_locale_data) override; FML_DISALLOW_COPY_AND_ASSIGN(PlatformViewIOS); }; diff --git a/shell/platform/darwin/ios/platform_view_ios.mm b/shell/platform/darwin/ios/platform_view_ios.mm index 16a1f7dbf03fb..b770df883ba9f 100644 --- a/shell/platform/darwin/ios/platform_view_ios.mm +++ b/shell/platform/darwin/ios/platform_view_ios.mm @@ -192,15 +192,15 @@ new AccessibilityBridge(static_cast(owner_controller_.get().view), } std::vector& PlatformViewIOS::ComputePlatformResolvedLocales( - const std::vector& supportedLocaleData) { + const std::vector& supported_locale_data) { size_t localeDataLength = 3; NSMutableArray* supported_locale_identifiers = - [NSMutableArray arrayWithCapacity:supportedLocaleData.size() / localeDataLength]; - for (size_t i = 0; i < supportedLocaleData.size(); i += localeDataLength) { + [NSMutableArray arrayWithCapacity:supported_locale_data.size() / localeDataLength]; + for (size_t i = 0; i < supported_locale_data.size(); i += localeDataLength) { NSDictionary* dict = @{ - NSLocaleLanguageCode : [NSString stringWithUTF8String:supportedLocaleData[i].c_str()], - NSLocaleCountryCode : [NSString stringWithUTF8String:supportedLocaleData[i + 1].c_str()], - NSLocaleScriptCode : [NSString stringWithUTF8String:supportedLocaleData[i + 2].c_str()] + NSLocaleLanguageCode : [NSString stringWithUTF8String:supported_locale_data[i].c_str()], + NSLocaleCountryCode : [NSString stringWithUTF8String:supported_locale_data[i + 1].c_str()], + NSLocaleScriptCode : [NSString stringWithUTF8String:supported_locale_data[i + 2].c_str()] }; [supported_locale_identifiers addObject:[NSLocale localeIdentifierFromComponents:dict]]; } From 87e0b1e8118e9bdb59acac5f73a12469980f4c8b Mon Sep 17 00:00:00 2001 From: garyqian Date: Tue, 9 Jun 2020 01:34:19 -0700 Subject: [PATCH 16/51] Basic test, additional cleanup --- runtime/runtime_controller.cc | 1 - shell/common/platform_view.cc | 2 -- shell/common/shell.cc | 6 ------ testing/dart/window_test.dart | 9 +++++++++ 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/runtime/runtime_controller.cc b/runtime/runtime_controller.cc index 3bf0d29baf938..d7932bd3c3eeb 100644 --- a/runtime/runtime_controller.cc +++ b/runtime/runtime_controller.cc @@ -344,7 +344,6 @@ RuntimeController::GetPersistentIsolateData() { std::vector& RuntimeController::ComputePlatformResolvedLocale( const std::vector& supported_locale_data) { return client_.ComputePlatformResolvedLocale(supported_locale_data); - // return std::vector(); } Dart_Port RuntimeController::GetMainPort() { diff --git a/shell/common/platform_view.cc b/shell/common/platform_view.cc index 45b32662d969b..4b14f04c59175 100644 --- a/shell/common/platform_view.cc +++ b/shell/common/platform_view.cc @@ -139,8 +139,6 @@ void PlatformView::SetNextFrameCallback(const fml::closure& closure) { std::vector& PlatformView::ComputePlatformResolvedLocales( const std::vector& supported_locale_data) { - // std::vector result = std::vector(); - // *result = std::vector(); return delegate_.ComputePlatformViewResolvedLocale(supported_locale_data); } diff --git a/shell/common/shell.cc b/shell/common/shell.cc index 12a3a49857178..c2fb6f6c788de 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -1107,14 +1107,8 @@ std::vector& Shell::ComputePlatformResolvedLocale( // |PlatformView::Delegate| std::vector& Shell::ComputePlatformViewResolvedLocale( const std::vector& supported_locale_data) { - for (size_t i = 0; i < supported_locale_data.size(); i++) { - FML_DLOG(ERROR) << "LOCALEIN: " + supported_locale_data[i]; - } std::vector result = platform_view_->ComputePlatformResolvedLocales(supported_locale_data); - for (size_t i = 0; i < result.size(); i++) { - FML_DLOG(ERROR) << "#LOCALEOUT: " + result[i]; - } return platform_view_->ComputePlatformResolvedLocales(supported_locale_data); } diff --git a/testing/dart/window_test.dart b/testing/dart/window_test.dart index 714df2d0a25bb..f215e098719f8 100644 --- a/testing/dart/window_test.dart +++ b/testing/dart/window_test.dart @@ -25,4 +25,13 @@ void main() { final FrameTiming timing = FrameTiming([1000, 8000, 9000, 19500]); expect(timing.toString(), 'FrameTiming(buildDuration: 7.0ms, rasterDuration: 10.5ms, totalSpan: 18.5ms)'); }); + + test('computePlatformResolvedLocale basic', () { + Locale result = window.computePlatformResolvedLocale([ + Locale.fromSubtags(languageCode: 'fr', countryCode: 'CA'), + Locale.fromSubtags(languageCode: 'zh', countryCode: 'CN'), + Locale.fromSubtags(languageCode: 'en', countryCode: 'US'), + ]); + expect(result, Locale.fromSubtags(languageCode: 'en', countryCode: 'US')); + }); } From 16d6e23c46a054e62b883952911188a576e56097 Mon Sep 17 00:00:00 2001 From: garyqian Date: Tue, 9 Jun 2020 04:07:27 -0700 Subject: [PATCH 17/51] Improved android JNI, analyzer --- lib/ui/window.dart | 4 +-- .../flutter/embedding/engine/FlutterJNI.java | 11 ++++-- .../platform/android/platform_view_android.cc | 34 +------------------ .../android/platform_view_android_jni.cc | 25 +++++++++----- .../android/platform_view_android_jni.h | 7 ++-- 5 files changed, 32 insertions(+), 49 deletions(-) diff --git a/lib/ui/window.dart b/lib/ui/window.dart index d55f014411280..e704733838d6f 100644 --- a/lib/ui/window.dart +++ b/lib/ui/window.dart @@ -817,14 +817,14 @@ class Window { if (supportedLocales == null) { return null; } - List supportedLocalesData = []; + final List supportedLocalesData = []; for (Locale locale in supportedLocales) { supportedLocalesData.add(locale.languageCode); supportedLocalesData.add(locale.countryCode); supportedLocalesData.add(locale.scriptCode); } - List result = _computePlatformResolvedLocale(supportedLocalesData); + final List result = _computePlatformResolvedLocale(supportedLocalesData); if (result != null && result.isNotEmpty && result[0] != null) { return Locale.fromSubtags( diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java index 911b10bb4d5cd..e704c617a5297 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java @@ -792,7 +792,7 @@ private void onPreEngineRestart() { * Invoked by native to obtain the results of Android's locale reoslution algorithm. */ @SuppressWarnings("unused") - private String computePlatformResolvedLocale(@NonNull String[] strings) { + private String[] computePlatformResolvedLocale(@NonNull String[] strings) { List supportedLocales = new ArrayList(); final int localeDataLength = 3; for (int i = 0; i < strings.length; i += localeDataLength) { @@ -813,9 +813,14 @@ private String computePlatformResolvedLocale(@NonNull String[] strings) { } Locale result = LocalizationPlugin.resolveNativeLocale(supportedLocales); if (result == null) { - return ""; + return new String[0]; } - return result.getLanguage() + result.getCountry(); + String[] output = new String[localeDataLength]; + output[0] = result.getLanguage(); + output[1] = result.getCountry(); + output[2] = result.getScript(); + return output; + // return result.getLanguage() + result.getCountry(); } // ----- End Localization Support ---- diff --git a/shell/platform/android/platform_view_android.cc b/shell/platform/android/platform_view_android.cc index 847acda78d00c..9785f130beaf1 100644 --- a/shell/platform/android/platform_view_android.cc +++ b/shell/platform/android/platform_view_android.cc @@ -436,42 +436,10 @@ std::vector& PlatformViewAndroid::ComputePlatformResolvedLocales( platform_resolved_locale_.clear(); return platform_resolved_locale_; } - std::string result = FlutterViewComputePlatformResolvedLocale( + platform_resolved_locale_ = *FlutterViewComputePlatformResolvedLocale( env, view.obj(), fml::jni::VectorToStringArray(env, supported_locale_data).obj()); - platform_resolved_locale_.clear(); - // Decode the locale string. - switch (result.size()) { - // Only languageCode (2) - case 2: { - platform_resolved_locale_.emplace_back(result.data(), 2); - platform_resolved_locale_.emplace_back(""); - platform_resolved_locale_.emplace_back(""); - break; - } - // Only languageCode (2) and countryCode (2) - case 4: { - platform_resolved_locale_.emplace_back(result.data(), 2); - platform_resolved_locale_.emplace_back(result.data() + 2, 2); - platform_resolved_locale_.emplace_back(""); - break; - } - // Only languageCode (2) and scriptCode (4) - case 6: { - platform_resolved_locale_.emplace_back(result.data(), 2); - platform_resolved_locale_.emplace_back(""); - platform_resolved_locale_.emplace_back(result.data() + 2, 4); - break; - } - // languageCode (2), countryCode (2), and scriptCode (4) - case 8: { - platform_resolved_locale_.emplace_back(result.data(), 2); - platform_resolved_locale_.emplace_back(result.data() + 2, 2); - platform_resolved_locale_.emplace_back(result.data() + 4, 4); - break; - } - } return platform_resolved_locale_; } diff --git a/shell/platform/android/platform_view_android_jni.cc b/shell/platform/android/platform_view_android_jni.cc index 83318481f8e79..f4301cfd80362 100644 --- a/shell/platform/android/platform_view_android_jni.cc +++ b/shell/platform/android/platform_view_android_jni.cc @@ -145,18 +145,27 @@ void SurfaceTextureDetachFromGLContext(JNIEnv* env, jobject obj) { } static jmethodID g_compute_platform_resolved_locale_method = nullptr; -std::string FlutterViewComputePlatformResolvedLocale(JNIEnv* env, - jobject obj, - jobjectArray strings) { +std::unique_ptr> +FlutterViewComputePlatformResolvedLocale(JNIEnv* env, + jobject obj, + jobjectArray strings) { std::vector vec = fml::jni::StringArrayToVector(env, strings); - jstring result = (jstring)env->CallObjectMethod( + jobjectArray result = (jobjectArray)env->CallObjectMethod( obj, g_compute_platform_resolved_locale_method, strings); FML_CHECK(CheckException(env)); - - std::string out = fml::jni::JavaStringToString(env, result); + std::unique_ptr> out = + std::make_unique>(); + + if (env->GetArrayLength(result) > 0) { + out->emplace_back(fml::jni::JavaStringToString( + env, (jstring)env->GetObjectArrayElement(result, 0))); + out->emplace_back(fml::jni::JavaStringToString( + env, (jstring)env->GetObjectArrayElement(result, 1))); + out->emplace_back(fml::jni::JavaStringToString( + env, (jstring)env->GetObjectArrayElement(result, 2))); + } return out; - // return out; } // Called By Java @@ -806,7 +815,7 @@ bool PlatformViewAndroid::Register(JNIEnv* env) { g_compute_platform_resolved_locale_method = env->GetMethodID( g_flutter_jni_class->obj(), "computePlatformResolvedLocale", - "([Ljava/lang/String;)Ljava/lang/String;"); + "([Ljava/lang/String;)[Ljava/lang/String;"); if (g_compute_platform_resolved_locale_method == nullptr) { FML_LOG(ERROR) << "Could not locate computePlatformResolvedLocale method"; diff --git a/shell/platform/android/platform_view_android_jni.h b/shell/platform/android/platform_view_android_jni.h index 09f51987d4f64..99dfddb367fc4 100644 --- a/shell/platform/android/platform_view_android_jni.h +++ b/shell/platform/android/platform_view_android_jni.h @@ -46,9 +46,10 @@ void SurfaceTextureGetTransformMatrix(JNIEnv* env, void SurfaceTextureDetachFromGLContext(JNIEnv* env, jobject obj); -std::string FlutterViewComputePlatformResolvedLocale(JNIEnv* env, - jobject obj, - jobjectArray strings); +std::unique_ptr> +FlutterViewComputePlatformResolvedLocale(JNIEnv* env, + jobject obj, + jobjectArray strings); } // namespace flutter From 244869fb2b6fe298854fb98866eb0092fc2e99fd Mon Sep 17 00:00:00 2001 From: garyqian Date: Tue, 9 Jun 2020 04:16:14 -0700 Subject: [PATCH 18/51] Analyzer --- testing/dart/window_test.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/testing/dart/window_test.dart b/testing/dart/window_test.dart index f215e098719f8..2af04699d2cf3 100644 --- a/testing/dart/window_test.dart +++ b/testing/dart/window_test.dart @@ -28,10 +28,10 @@ void main() { test('computePlatformResolvedLocale basic', () { Locale result = window.computePlatformResolvedLocale([ - Locale.fromSubtags(languageCode: 'fr', countryCode: 'CA'), - Locale.fromSubtags(languageCode: 'zh', countryCode: 'CN'), - Locale.fromSubtags(languageCode: 'en', countryCode: 'US'), + const Locale.fromSubtags(languageCode: 'fr', countryCode: 'CA'), + const Locale.fromSubtags(languageCode: 'zh', countryCode: 'CN'), + const Locale.fromSubtags(languageCode: 'en', countryCode: 'US'), ]); - expect(result, Locale.fromSubtags(languageCode: 'en', countryCode: 'US')); + expect(result, const Locale.fromSubtags(languageCode: 'en', countryCode: 'US')); }); } From 75d68d3e2d993316820eb896cddf9e0b3558dd6e Mon Sep 17 00:00:00 2001 From: garyqian Date: Tue, 9 Jun 2020 06:40:33 -0700 Subject: [PATCH 19/51] Java formatting --- .../io/flutter/embedding/android/FlutterView.java | 6 ------ .../io/flutter/embedding/engine/FlutterJNI.java | 7 +++---- .../engine/systemchannels/LocalizationChannel.java | 3 +-- .../plugin/localization/LocalizationPlugin.java | 12 ++++-------- .../android/io/flutter/view/FlutterView.java | 3 --- 5 files changed, 8 insertions(+), 23 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterView.java b/shell/platform/android/io/flutter/embedding/android/FlutterView.java index 2e3f377066abb..e50732fedd75c 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterView.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterView.java @@ -11,7 +11,6 @@ import android.graphics.Insets; import android.graphics.Rect; import android.os.Build; -import android.os.LocaleList; import android.text.format.DateFormat; import android.util.AttributeSet; import android.util.SparseArray; @@ -39,17 +38,12 @@ import io.flutter.embedding.engine.renderer.FlutterUiDisplayListener; import io.flutter.embedding.engine.renderer.RenderSurface; import io.flutter.embedding.engine.systemchannels.SettingsChannel; -import io.flutter.embedding.engine.systemchannels.LocalizationChannel; import io.flutter.plugin.editing.TextInputPlugin; import io.flutter.plugin.localization.LocalizationPlugin; import io.flutter.plugin.mouse.MouseCursorPlugin; import io.flutter.plugin.platform.PlatformViewsController; import io.flutter.view.AccessibilityBridge; -import java.util.ArrayList; -import java.util.Arrays; import java.util.HashSet; -import java.util.List; -import java.util.Locale; import java.util.Set; /** diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java index e704c617a5297..8c138e214f820 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java @@ -786,10 +786,10 @@ private void onPreEngineRestart() { } // ----- End Engine Lifecycle Support ---- - // ----- Start Localizaation Support ---- + // ----- Start Localization Support ---- - /** - * Invoked by native to obtain the results of Android's locale reoslution algorithm. + /** + * Invoked by native to obtain the results of Android's locale resolution algorithm. */ @SuppressWarnings("unused") private String[] computePlatformResolvedLocale(@NonNull String[] strings) { @@ -820,7 +820,6 @@ private String[] computePlatformResolvedLocale(@NonNull String[] strings) { output[1] = result.getCountry(); output[2] = result.getScript(); return output; - // return result.getLanguage() + result.getCountry(); } // ----- End Localization Support ---- diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/LocalizationChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/LocalizationChannel.java index aaae268b03f90..0f3ef7f0cf1d0 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/LocalizationChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/LocalizationChannel.java @@ -6,7 +6,6 @@ import android.os.Build; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import io.flutter.Log; import io.flutter.embedding.engine.dart.DartExecutor; import io.flutter.plugin.common.JSONMethodCodec; @@ -50,7 +49,7 @@ public void sendLocales(@NonNull List locales) { channel.invokeMethod("setLocale", data); } - /** Send the given {@code locales} to Dart. */ + /** Send the given {@code platformResolvedLocale} to Dart. */ public void sendPlatformResolvedLocales(Locale platformResolvedLocale) { Log.v(TAG, "Sending Locales to Flutter."); // Send platformResolvedLocale first as it may be used in the callback diff --git a/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java b/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java index c18e9f4f3864a..0a07f71cdd95d 100644 --- a/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java +++ b/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java @@ -4,14 +4,11 @@ package io.flutter.plugin.localization; -import android.annotation.SuppressLint; import android.content.Context; import android.content.res.Configuration; import android.os.Build; import android.os.LocaleList; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.VisibleForTesting; import io.flutter.embedding.engine.systemchannels.LocalizationChannel; import java.util.ArrayList; import java.util.Arrays; @@ -28,8 +25,7 @@ public class LocalizationPlugin { private static LocalizationPlugin instance; public LocalizationPlugin( - @NonNull Context context, - @NonNull LocalizationChannel localizationChannel) { + @NonNull Context context, @NonNull LocalizationChannel localizationChannel) { this.context = context; this.localizationChannel = localizationChannel; @@ -49,9 +45,9 @@ public static Locale resolveNativeLocale(List supportedLocales) { } // TODO(garyq): This should be modified to achieve Android's full - // locale resolution: https://developer.android.com/guide/topics/resources/multilingual-support - platformResolvedLocale = - Locale.lookup(languageRanges, supportedLocales); + // locale resolution: + // https://developer.android.com/guide/topics/resources/multilingual-support + platformResolvedLocale = Locale.lookup(languageRanges, supportedLocales); } return platformResolvedLocale; } diff --git a/shell/platform/android/io/flutter/view/FlutterView.java b/shell/platform/android/io/flutter/view/FlutterView.java index 780a4e1f1a45f..ccd7f392ca5f1 100644 --- a/shell/platform/android/io/flutter/view/FlutterView.java +++ b/shell/platform/android/io/flutter/view/FlutterView.java @@ -17,7 +17,6 @@ import android.graphics.SurfaceTexture; import android.os.Build; import android.os.Handler; -import android.os.LocaleList; import android.text.format.DateFormat; import android.util.AttributeSet; import android.util.Log; @@ -65,9 +64,7 @@ import io.flutter.plugin.platform.PlatformViewsController; import java.nio.ByteBuffer; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; -import java.util.Locale; import java.util.concurrent.atomic.AtomicLong; /** From 4eb0445a326d1ee67d5f2c49fec90cfd895e3d6c Mon Sep 17 00:00:00 2001 From: garyqian Date: Tue, 9 Jun 2020 20:40:24 -0700 Subject: [PATCH 20/51] More formatting, temp remove test --- lib/web_ui/lib/src/ui/window.dart | 13 +++++++++++ shell/common/platform_view.h | 15 ++++++++++++ .../embedding/android/FlutterView.java | 4 +--- .../flutter/embedding/engine/FlutterJNI.java | 4 +--- .../localization/LocalizationPlugin.java | 3 --- testing/dart/window_test.dart | 23 ++++++++++++------- 6 files changed, 45 insertions(+), 17 deletions(-) diff --git a/lib/web_ui/lib/src/ui/window.dart b/lib/web_ui/lib/src/ui/window.dart index 42b4fb9fea493..12e7b0a9b8793 100644 --- a/lib/web_ui/lib/src/ui/window.dart +++ b/lib/web_ui/lib/src/ui/window.dart @@ -708,6 +708,19 @@ abstract class Window { /// See [locales], which is the list of locales the user/device prefers. Locale get platformResolvedLocale; + /// Performs the platform-native locale resolution. + /// + /// Each platform may return different results. + /// + /// If the platform fails to resolve a locale, then this will return null. + /// + /// This method returns synchronously and is a direct call to + /// platform specific APIs without invoking method channels. + Locale computePlatformResolvedLocale(List supportedLocales) { + // TODO(garyq): Implement on web. + return null; + } + /// A callback that is invoked whenever [locale] changes value. /// /// The framework invokes this callback in the same zone in which the diff --git a/shell/common/platform_view.h b/shell/common/platform_view.h index a378a08a84720..9bc5149365973 100644 --- a/shell/common/platform_view.h +++ b/shell/common/platform_view.h @@ -561,6 +561,21 @@ class PlatformView { /// void MarkTextureFrameAvailable(int64_t texture_id); + //-------------------------------------------------------------------------- + /// @brief Directly invokes platform-specific APIs to compute the + /// locale the platform would have natively resolved to. + /// + /// @param[in] supported_locale_data The vector of strings that represents + /// the locales supported by the app. + /// Each locale consists of three + /// strings: languageCode, countryCode, + /// and scriptCode in that order. + /// + /// @return A vector of 3 strings languageCode, countryCode, and + /// scriptCode that the conist the locale selected by the + /// platform. Empty strings mean the value was unassigned. Empty + /// vector represents a null locale. + /// virtual std::vector& ComputePlatformResolvedLocales( const std::vector& supported_locale_data); diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterView.java b/shell/platform/android/io/flutter/embedding/android/FlutterView.java index e50732fedd75c..795eb25515c37 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterView.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterView.java @@ -813,9 +813,7 @@ public void attachToFlutterEngine(@NonNull FlutterEngine flutterEngine) { this.flutterEngine.getTextInputChannel(), this.flutterEngine.getPlatformViewsController()); localizationPlugin = - new LocalizationPlugin( - getContext(), - this.flutterEngine.getLocalizationChannel()); + new LocalizationPlugin(getContext(), this.flutterEngine.getLocalizationChannel()); androidKeyProcessor = new AndroidKeyProcessor(this.flutterEngine.getKeyEventChannel(), textInputPlugin); androidTouchProcessor = new AndroidTouchProcessor(this.flutterEngine.getRenderer()); diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java index 8c138e214f820..24becf26a2017 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java @@ -788,9 +788,7 @@ private void onPreEngineRestart() { // ----- Start Localization Support ---- - /** - * Invoked by native to obtain the results of Android's locale resolution algorithm. - */ + /** Invoked by native to obtain the results of Android's locale resolution algorithm. */ @SuppressWarnings("unused") private String[] computePlatformResolvedLocale(@NonNull String[] strings) { List supportedLocales = new ArrayList(); diff --git a/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java b/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java index 0a07f71cdd95d..ecf92af1f1263 100644 --- a/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java +++ b/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java @@ -86,8 +86,5 @@ public void sendLocalesToFlutter(@NonNull Configuration config) { } localizationChannel.sendLocales(locales); - // Do not initialize platform resolved locale. We will do - // this later via the method channel call "resolveLocale". - // localizationChannel.sendPlatformResolvedLocales(platformResolvedLocale); } } diff --git a/testing/dart/window_test.dart b/testing/dart/window_test.dart index 2af04699d2cf3..3ca6a8d5d405d 100644 --- a/testing/dart/window_test.dart +++ b/testing/dart/window_test.dart @@ -26,12 +26,19 @@ void main() { expect(timing.toString(), 'FrameTiming(buildDuration: 7.0ms, rasterDuration: 10.5ms, totalSpan: 18.5ms)'); }); - test('computePlatformResolvedLocale basic', () { - Locale result = window.computePlatformResolvedLocale([ - const Locale.fromSubtags(languageCode: 'fr', countryCode: 'CA'), - const Locale.fromSubtags(languageCode: 'zh', countryCode: 'CN'), - const Locale.fromSubtags(languageCode: 'en', countryCode: 'US'), - ]); - expect(result, const Locale.fromSubtags(languageCode: 'en', countryCode: 'US')); - }); + // test('computePlatformResolvedLocale basic', () { + // final List supportedLocales = [ + // const Locale.fromSubtag(languageCode: 'zh', scriptCode: 'Hans'); + // const Locale.fromSubtag(languageCode: 'zh', scriptCode: 'Hant'); + // const Locale.fromSubtag(languageCode: 'fr', countryCode: 'FR'); + // const Locale.fromSubtag(languageCode: 'fr', countryCode: 'FR'); + // const Locale.fromSubtag(languageCode: 'fr', countryCode: 'CA'); + // const Locale.fromSubtag(languageCode: 'en', countryCode: 'US'); + // const Locale.fromSubtag(languageCode: 'en', countryCode: 'UK'); + // const Locale.fromSubtag(languageCode: 'en', countryCode: 'IN'); + // const Locale.fromSubtag(languageCode: 'en'); + // ]; + // final Locale result = window.computePlatformResolvedLocale(supportedLocales); + // expect(result, const Locale.fromSubtag(languageCode: 'en', countryCode: 'US')); + // }, skip: isBrowser || isWindows); } From d8bc98bdc67fcd22664afcc1eda7b5b05210376a Mon Sep 17 00:00:00 2001 From: garyqian Date: Tue, 9 Jun 2020 20:52:07 -0700 Subject: [PATCH 21/51] Version gate locale bulder --- .../flutter/embedding/engine/FlutterJNI.java | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java index 24becf26a2017..11b891be222db 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java @@ -8,6 +8,7 @@ import android.content.res.AssetManager; import android.graphics.Bitmap; import android.graphics.SurfaceTexture; +import android.os.Build; import android.os.Looper; import android.view.Surface; import android.view.SurfaceHolder; @@ -797,17 +798,21 @@ private String[] computePlatformResolvedLocale(@NonNull String[] strings) { String languageCode = strings[i + 0]; String countryCode = strings[i + 1]; String scriptCode = strings[i + 2]; - Locale.Builder localeBuilder = new Locale.Builder(); - if (!languageCode.isEmpty()) { - localeBuilder.setLanguage(languageCode); + if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { + Locale.Builder localeBuilder = new Locale.Builder(); + if (!languageCode.isEmpty()) { + localeBuilder.setLanguage(languageCode); + } + if (!countryCode.isEmpty()) { + localeBuilder.setRegion(countryCode); + } + if (!scriptCode.isEmpty()) { + localeBuilder.setScript(scriptCode); + } + supportedLocales.add(localeBuilder.build()); + } else { + supportedLocales.add(new Locale(languageCode, countryCode)); } - if (!countryCode.isEmpty()) { - localeBuilder.setRegion(countryCode); - } - if (!scriptCode.isEmpty()) { - localeBuilder.setScript(scriptCode); - } - supportedLocales.add(localeBuilder.build()); } Locale result = LocalizationPlugin.resolveNativeLocale(supportedLocales); if (result == null) { From 3640a872f7418c95c8813699ed9841a6d4a1b785 Mon Sep 17 00:00:00 2001 From: garyqian Date: Tue, 9 Jun 2020 21:11:41 -0700 Subject: [PATCH 22/51] More version gating, formatting, licenses --- ci/licenses_golden/licenses_flutter | 1 + .../android/io/flutter/embedding/engine/FlutterJNI.java | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 8c799234cbf70..0ada876b580aa 100755 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -755,6 +755,7 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/common/StringCod FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/editing/FlutterTextUtils.java FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/editing/InputConnectionAdaptor.java FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/editing/TextInputPlugin.java +FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/mouse/MouseCursorPlugin.java FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/AccessibilityEventsDelegate.java FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java index 11b891be222db..1fa0c57e6890e 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java @@ -821,7 +821,11 @@ private String[] computePlatformResolvedLocale(@NonNull String[] strings) { String[] output = new String[localeDataLength]; output[0] = result.getLanguage(); output[1] = result.getCountry(); - output[2] = result.getScript(); + if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { + output[2] = result.getScript(); + } else { + output[2] = ""; + } return output; } From 97195623df88589d500a5a8cf9668cd28ae13915 Mon Sep 17 00:00:00 2001 From: garyqian Date: Wed, 10 Jun 2020 02:45:47 -0700 Subject: [PATCH 23/51] un-static compute locale method --- .../io/flutter/embedding/android/FlutterView.java | 2 ++ .../flutter/embedding/engine/FlutterEngine.java | 6 ++++++ .../io/flutter/embedding/engine/FlutterJNI.java | 15 ++++++++++++++- .../plugin/localization/LocalizationPlugin.java | 9 ++------- .../android/io/flutter/view/FlutterView.java | 1 + 5 files changed, 25 insertions(+), 8 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterView.java b/shell/platform/android/io/flutter/embedding/android/FlutterView.java index 795eb25515c37..a6a8e26a5876c 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterView.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterView.java @@ -838,6 +838,8 @@ public void attachToFlutterEngine(@NonNull FlutterEngine flutterEngine) { // TODO(mattcarroll): once this is proven to work, move this line ot TextInputPlugin textInputPlugin.getInputMethodManager().restartInput(this); + this.flutterEngine.getFlutterJNI().setLocalizationPlugin(localizationPlugin); + // Push View and Context related information from Android to Flutter. sendUserSettingsToFlutter(); localizationPlugin.sendLocalesToFlutter(getResources().getConfiguration()); diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java b/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java index cd22f732d8b75..e3a494e92474a 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java @@ -340,6 +340,12 @@ public FlutterRenderer getRenderer() { return renderer; } + /** The FlutterJNI associated with this engine. */ + @NonNull + public FlutterJNI getFlutterJNI() { + return flutterJNI; + } + /** System channel that sends accessibility requests and events from Flutter to Android. */ @NonNull public AccessibilityChannel getAccessibilityChannel() { diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java index 1fa0c57e6890e..4954d332a1e7f 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java @@ -173,6 +173,7 @@ public static native void nativeOnVsync( @Nullable private Long nativePlatformViewId; @Nullable private AccessibilityDelegate accessibilityDelegate; @Nullable private PlatformMessageHandler platformMessageHandler; + @Nullable private LocalizationPlugin localizationPlugin; @NonNull private final Set engineLifecycleListeners = new CopyOnWriteArraySet<>(); @@ -789,9 +790,21 @@ private void onPreEngineRestart() { // ----- Start Localization Support ---- + /** + * Sets the localization plugin that is used in various localization methods. + */ + @UiThread + public void setLocalizationPlugin(@Nullable LocalizationPlugin localizationPlugin) { + ensureRunningOnMainThread(); + this.localizationPlugin = localizationPlugin; + } + /** Invoked by native to obtain the results of Android's locale resolution algorithm. */ @SuppressWarnings("unused") private String[] computePlatformResolvedLocale(@NonNull String[] strings) { + if (localizationPlugin == null) { + return new String[0]; + } List supportedLocales = new ArrayList(); final int localeDataLength = 3; for (int i = 0; i < strings.length; i += localeDataLength) { @@ -814,7 +827,7 @@ private String[] computePlatformResolvedLocale(@NonNull String[] strings) { supportedLocales.add(new Locale(languageCode, countryCode)); } } - Locale result = LocalizationPlugin.resolveNativeLocale(supportedLocales); + Locale result = localizationPlugin.resolveNativeLocale(supportedLocales); if (result == null) { return new String[0]; } diff --git a/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java b/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java index ecf92af1f1263..51933647a645c 100644 --- a/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java +++ b/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java @@ -20,23 +20,18 @@ public class LocalizationPlugin { @NonNull private final LocalizationChannel localizationChannel; @NonNull private final Context context; - // This should always be initialized before being used by resolveNativeLocale - // since the embedder starts the engine which in turn calls resolveNativeLocale. - private static LocalizationPlugin instance; - public LocalizationPlugin( @NonNull Context context, @NonNull LocalizationChannel localizationChannel) { this.context = context; this.localizationChannel = localizationChannel; - instance = this; } - public static Locale resolveNativeLocale(List supportedLocales) { + public Locale resolveNativeLocale(List supportedLocales) { Locale platformResolvedLocale = null; if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { List languageRanges = new ArrayList<>(); - LocaleList localeList = instance.context.getResources().getConfiguration().getLocales(); + LocaleList localeList = context.getResources().getConfiguration().getLocales(); int localeCount = localeList.size(); for (int index = 0; index < localeCount; ++index) { Locale locale = localeList.get(index); diff --git a/shell/platform/android/io/flutter/view/FlutterView.java b/shell/platform/android/io/flutter/view/FlutterView.java index ccd7f392ca5f1..6756ff475930b 100644 --- a/shell/platform/android/io/flutter/view/FlutterView.java +++ b/shell/platform/android/io/flutter/view/FlutterView.java @@ -237,6 +237,7 @@ public void onPostResume() { .getPluginRegistry() .getPlatformViewsController() .attachTextInputPlugin(mTextInputPlugin); + mNativeView.getFlutterJNI().setLocalizationPlugin(mLocalizationPlugin); // Send initial platform information to Dart mLocalizationPlugin.sendLocalesToFlutter(getResources().getConfiguration()); From 31f9df129ceffb7bda43b1e3b2b6083f5b249dd7 Mon Sep 17 00:00:00 2001 From: garyqian Date: Wed, 10 Jun 2020 02:56:38 -0700 Subject: [PATCH 24/51] Formatting --- .../android/io/flutter/embedding/engine/FlutterJNI.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java index 4954d332a1e7f..ca3c4285bb08a 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java @@ -790,9 +790,7 @@ private void onPreEngineRestart() { // ----- Start Localization Support ---- - /** - * Sets the localization plugin that is used in various localization methods. - */ + /** Sets the localization plugin that is used in various localization methods. */ @UiThread public void setLocalizationPlugin(@Nullable LocalizationPlugin localizationPlugin) { ensureRunningOnMainThread(); From dd251565ffe684f1ac123d78aa42f5ed16749b5c Mon Sep 17 00:00:00 2001 From: garyqian Date: Wed, 10 Jun 2020 06:00:12 -0700 Subject: [PATCH 25/51] Fix ios test compilation, fix NPE --- .../android/io/flutter/embedding/android/FlutterView.java | 2 +- .../ios/framework/Source/accessibility_bridge_test.mm | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterView.java b/shell/platform/android/io/flutter/embedding/android/FlutterView.java index a6a8e26a5876c..a0b44194ff776 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterView.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterView.java @@ -838,7 +838,7 @@ public void attachToFlutterEngine(@NonNull FlutterEngine flutterEngine) { // TODO(mattcarroll): once this is proven to work, move this line ot TextInputPlugin textInputPlugin.getInputMethodManager().restartInput(this); - this.flutterEngine.getFlutterJNI().setLocalizationPlugin(localizationPlugin); + if (this.flutterEngine != null) this.flutterEngine.getFlutterJNI().setLocalizationPlugin(localizationPlugin); // Push View and Context related information from Android to Flutter. sendUserSettingsToFlutter(); diff --git a/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm b/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm index c242c437c930f..b0ad0ae08c555 100644 --- a/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm +++ b/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm @@ -85,6 +85,12 @@ void OnPlatformViewSetAccessibilityFeatures(int32_t flags) override {} void OnPlatformViewRegisterTexture(std::shared_ptr texture) override {} void OnPlatformViewUnregisterTexture(int64_t texture_id) override {} void OnPlatformViewMarkTextureFrameAvailable(int64_t texture_id) override {} + + std::vector mock_locale_data; + std::vector& ComputePlatformViewResolvedLocale( + const std::vector& supported_locale_data) override { + return mock_locale_data; + } }; } // namespace } // namespace flutter From 746db4ab67d33ee71a0d22de2175f37e33e21e83 Mon Sep 17 00:00:00 2001 From: garyqian Date: Wed, 10 Jun 2020 06:08:03 -0700 Subject: [PATCH 26/51] Fix Fuchsia tests --- .../android/io/flutter/embedding/android/FlutterView.java | 4 +++- .../ios/framework/Source/accessibility_bridge_test.mm | 4 +++- shell/platform/fuchsia/flutter/platform_view_unittest.cc | 6 ++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterView.java b/shell/platform/android/io/flutter/embedding/android/FlutterView.java index a0b44194ff776..3518271e01886 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterView.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterView.java @@ -838,7 +838,9 @@ public void attachToFlutterEngine(@NonNull FlutterEngine flutterEngine) { // TODO(mattcarroll): once this is proven to work, move this line ot TextInputPlugin textInputPlugin.getInputMethodManager().restartInput(this); - if (this.flutterEngine != null) this.flutterEngine.getFlutterJNI().setLocalizationPlugin(localizationPlugin); + FlutterJNI jni = this.flutterEngine.getFlutterJNI(); + if (jni != null) + jni.setLocalizationPlugin(localizationPlugin); // Push View and Context related information from Android to Flutter. sendUserSettingsToFlutter(); diff --git a/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm b/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm index b0ad0ae08c555..437a210d2018f 100644 --- a/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm +++ b/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm @@ -86,11 +86,13 @@ void OnPlatformViewRegisterTexture(std::shared_ptr texture) override {} void OnPlatformViewUnregisterTexture(int64_t texture_id) override {} void OnPlatformViewMarkTextureFrameAvailable(int64_t texture_id) override {} - std::vector mock_locale_data; std::vector& ComputePlatformViewResolvedLocale( const std::vector& supported_locale_data) override { return mock_locale_data; } + + private: + std::vector mock_locale_data; }; } // namespace } // namespace flutter diff --git a/shell/platform/fuchsia/flutter/platform_view_unittest.cc b/shell/platform/fuchsia/flutter/platform_view_unittest.cc index 077a8996f93f4..db36ae7258ebb 100644 --- a/shell/platform/fuchsia/flutter/platform_view_unittest.cc +++ b/shell/platform/fuchsia/flutter/platform_view_unittest.cc @@ -74,11 +74,17 @@ class MockPlatformViewDelegate : public flutter::PlatformView::Delegate { void OnPlatformViewUnregisterTexture(int64_t texture_id) {} // |flutter::PlatformView::Delegate| void OnPlatformViewMarkTextureFrameAvailable(int64_t texture_id) {} + // |flutter::PlatformView::Delegate| + std::vector& ComputePlatformViewResolvedLocale( + const std::vector& supported_locale_data) override { + return mock_locale_data_; + } bool SemanticsEnabled() const { return semantics_enabled_; } int32_t SemanticsFeatures() const { return semantics_features_; } private: + std::vector mock_locale_data_; bool semantics_enabled_ = false; int32_t semantics_features_ = 0; }; From 2ca3b1f10e1af2ce8c08eb9871cf2d99b97d625d Mon Sep 17 00:00:00 2001 From: garyqian Date: Wed, 10 Jun 2020 06:13:59 -0700 Subject: [PATCH 27/51] Fix import --- .../android/io/flutter/embedding/android/FlutterView.java | 1 + 1 file changed, 1 insertion(+) diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterView.java b/shell/platform/android/io/flutter/embedding/android/FlutterView.java index 3518271e01886..63bd0e5ebf137 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterView.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterView.java @@ -38,6 +38,7 @@ import io.flutter.embedding.engine.renderer.FlutterUiDisplayListener; import io.flutter.embedding.engine.renderer.RenderSurface; import io.flutter.embedding.engine.systemchannels.SettingsChannel; +import io.flutter.embedding.engine.FlutterJNI; import io.flutter.plugin.editing.TextInputPlugin; import io.flutter.plugin.localization.LocalizationPlugin; import io.flutter.plugin.mouse.MouseCursorPlugin; From 8e75734bc506e4d040a8346c394b3a29eab9a928 Mon Sep 17 00:00:00 2001 From: garyqian Date: Wed, 10 Jun 2020 06:14:28 -0700 Subject: [PATCH 28/51] Fix formatting --- .../android/io/flutter/embedding/android/FlutterView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterView.java b/shell/platform/android/io/flutter/embedding/android/FlutterView.java index 63bd0e5ebf137..f1e286256bc96 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterView.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterView.java @@ -34,11 +34,11 @@ import androidx.annotation.VisibleForTesting; import io.flutter.Log; import io.flutter.embedding.engine.FlutterEngine; +import io.flutter.embedding.engine.FlutterJNI; import io.flutter.embedding.engine.renderer.FlutterRenderer; import io.flutter.embedding.engine.renderer.FlutterUiDisplayListener; import io.flutter.embedding.engine.renderer.RenderSurface; import io.flutter.embedding.engine.systemchannels.SettingsChannel; -import io.flutter.embedding.engine.FlutterJNI; import io.flutter.plugin.editing.TextInputPlugin; import io.flutter.plugin.localization.LocalizationPlugin; import io.flutter.plugin.mouse.MouseCursorPlugin; From 8dc8980da934dc433b12f5c2973b2e6de4e69d68 Mon Sep 17 00:00:00 2001 From: garyqian Date: Wed, 10 Jun 2020 06:31:29 -0700 Subject: [PATCH 29/51] Fix tests --- .../android/io/flutter/embedding/android/FlutterView.java | 7 +++---- .../test/io/flutter/embedding/android/FlutterViewTest.java | 4 ++-- shell/platform/fuchsia/flutter/platform_view_unittest.cc | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterView.java b/shell/platform/android/io/flutter/embedding/android/FlutterView.java index f1e286256bc96..45de51e904eae 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterView.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterView.java @@ -34,7 +34,6 @@ import androidx.annotation.VisibleForTesting; import io.flutter.Log; import io.flutter.embedding.engine.FlutterEngine; -import io.flutter.embedding.engine.FlutterJNI; import io.flutter.embedding.engine.renderer.FlutterRenderer; import io.flutter.embedding.engine.renderer.FlutterUiDisplayListener; import io.flutter.embedding.engine.renderer.RenderSurface; @@ -839,9 +838,9 @@ public void attachToFlutterEngine(@NonNull FlutterEngine flutterEngine) { // TODO(mattcarroll): once this is proven to work, move this line ot TextInputPlugin textInputPlugin.getInputMethodManager().restartInput(this); - FlutterJNI jni = this.flutterEngine.getFlutterJNI(); - if (jni != null) - jni.setLocalizationPlugin(localizationPlugin); + if (this.flutterEngine.getFlutterJNI() != null) { + this.flutterEngine.getFlutterJNI().setLocalizationPlugin(localizationPlugin); + } // Push View and Context related information from Android to Flutter. sendUserSettingsToFlutter(); diff --git a/shell/platform/android/test/io/flutter/embedding/android/FlutterViewTest.java b/shell/platform/android/test/io/flutter/embedding/android/FlutterViewTest.java index cf0fdcc589808..4db27c88a51cb 100644 --- a/shell/platform/android/test/io/flutter/embedding/android/FlutterViewTest.java +++ b/shell/platform/android/test/io/flutter/embedding/android/FlutterViewTest.java @@ -102,14 +102,14 @@ public void onConfigurationChanged_fizzlesWhenNullEngine() { Configuration configuration = RuntimeEnvironment.application.getResources().getConfiguration(); // 1 invocation of channels. flutterView.attachToFlutterEngine(flutterEngine); - // 2 invocations of channels. + // localizationChannel now stored by plugin, so only 1 invocation. flutterView.onConfigurationChanged(configuration); flutterView.detachFromFlutterEngine(); // Should fizzle. flutterView.onConfigurationChanged(configuration); - verify(flutterEngine, times(2)).getLocalizationChannel(); + verify(flutterEngine, times(1)).getLocalizationChannel(); verify(flutterEngine, times(2)).getSettingsChannel(); } diff --git a/shell/platform/fuchsia/flutter/platform_view_unittest.cc b/shell/platform/fuchsia/flutter/platform_view_unittest.cc index db36ae7258ebb..82fc757dfdf4a 100644 --- a/shell/platform/fuchsia/flutter/platform_view_unittest.cc +++ b/shell/platform/fuchsia/flutter/platform_view_unittest.cc @@ -76,7 +76,7 @@ class MockPlatformViewDelegate : public flutter::PlatformView::Delegate { void OnPlatformViewMarkTextureFrameAvailable(int64_t texture_id) {} // |flutter::PlatformView::Delegate| std::vector& ComputePlatformViewResolvedLocale( - const std::vector& supported_locale_data) override { + const std::vector& supported_locale_data) { return mock_locale_data_; } From a7e7124dd612b15ef1065240bd312c31f801ed45 Mon Sep 17 00:00:00 2001 From: garyqian Date: Wed, 10 Jun 2020 13:44:46 -0700 Subject: [PATCH 30/51] Fix tests --- lib/ui/window/window.cc | 6 ++++-- lib/ui/window/window.h | 3 ++- runtime/dart_isolate.h | 2 +- runtime/runtime_controller.cc | 3 ++- runtime/runtime_controller.h | 2 +- runtime/runtime_delegate.h | 3 ++- shell/common/engine.cc | 2 +- shell/common/engine.h | 5 +++-- shell/common/platform_view.cc | 3 ++- shell/common/platform_view.h | 6 ++++-- shell/common/shell.cc | 7 +++---- shell/common/shell.h | 4 ++-- shell/platform/android/platform_view_android.cc | 12 ++++++------ shell/platform/android/platform_view_android.h | 3 +-- .../framework/Source/accessibility_bridge_test.mm | 8 +++----- shell/platform/darwin/ios/platform_view_ios.h | 2 +- .../fuchsia/flutter/platform_view_unittest.cc | 7 ++++--- 17 files changed, 42 insertions(+), 36 deletions(-) diff --git a/lib/ui/window/window.cc b/lib/ui/window/window.cc index 15a91917670b4..0ccacda53a2e1 100644 --- a/lib/ui/window/window.cc +++ b/lib/ui/window/window.cc @@ -441,8 +441,10 @@ Dart_Handle ComputePlatformResolvedLocale(Dart_Handle supportedLocalesHandle) { supportedLocales.emplace_back(cname); } std::vector results = - UIDartState::Current()->window()->client()->ComputePlatformResolvedLocale( - supportedLocales); + *UIDartState::Current() + ->window() + ->client() + ->ComputePlatformResolvedLocale(supportedLocales); if (results.empty()) { return Dart_Null(); diff --git a/lib/ui/window/window.h b/lib/ui/window/window.h index 7d4341f70bad0..dd5bd28daa0de 100644 --- a/lib/ui/window/window.h +++ b/lib/ui/window/window.h @@ -59,7 +59,8 @@ class WindowClient { int64_t isolate_port) = 0; virtual void SetNeedsReportTimings(bool value) = 0; virtual std::shared_ptr GetPersistentIsolateData() = 0; - virtual std::vector& ComputePlatformResolvedLocale( + virtual std::unique_ptr> + ComputePlatformResolvedLocale( const std::vector& supported_locale_data) = 0; protected: diff --git a/runtime/dart_isolate.h b/runtime/dart_isolate.h index 7f59aa7dc28d0..7eee92c540eec 100644 --- a/runtime/dart_isolate.h +++ b/runtime/dart_isolate.h @@ -30,7 +30,7 @@ class DartIsolateGroupData; /// @brief Represents an instance of a live isolate. An isolate is a /// separate Dart execution context. Different Dart isolates don't /// share memory and can be scheduled concurrently by the Dart VM on -/// one of the Dart VM managed worker pool threads. +/// one of the Dart VM managed worfluker pool threads. /// /// The entire lifecycle of a Dart isolate is controlled by the Dart /// VM. Because of this, the engine never holds a strong pointer to diff --git a/runtime/runtime_controller.cc b/runtime/runtime_controller.cc index d7932bd3c3eeb..66a57994705de 100644 --- a/runtime/runtime_controller.cc +++ b/runtime/runtime_controller.cc @@ -341,7 +341,8 @@ RuntimeController::GetPersistentIsolateData() { } // |WindowClient| -std::vector& RuntimeController::ComputePlatformResolvedLocale( +std::unique_ptr> +RuntimeController::ComputePlatformResolvedLocale( const std::vector& supported_locale_data) { return client_.ComputePlatformResolvedLocale(supported_locale_data); } diff --git a/runtime/runtime_controller.h b/runtime/runtime_controller.h index 0926aa5987938..3ac276c624746 100644 --- a/runtime/runtime_controller.h +++ b/runtime/runtime_controller.h @@ -523,7 +523,7 @@ class RuntimeController final : public WindowClient { std::shared_ptr GetPersistentIsolateData() override; // |WindowClient| - std::vector& ComputePlatformResolvedLocale( + std::unique_ptr> ComputePlatformResolvedLocale( const std::vector& supported_locale_data) override; FML_DISALLOW_COPY_AND_ASSIGN(RuntimeController); diff --git a/runtime/runtime_delegate.h b/runtime/runtime_delegate.h index b3eb7c2043d4e..20059827b8150 100644 --- a/runtime/runtime_delegate.h +++ b/runtime/runtime_delegate.h @@ -37,7 +37,8 @@ class RuntimeDelegate { virtual void SetNeedsReportTimings(bool value) = 0; - virtual std::vector& ComputePlatformResolvedLocale( + virtual std::unique_ptr> + ComputePlatformResolvedLocale( const std::vector& supported_locale_data) = 0; protected: diff --git a/shell/common/engine.cc b/shell/common/engine.cc index d7fd6d95e70f1..a5d8a8050d0b9 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc @@ -492,7 +492,7 @@ void Engine::UpdateIsolateDescription(const std::string isolate_name, delegate_.UpdateIsolateDescription(isolate_name, isolate_port); } -std::vector& Engine::ComputePlatformResolvedLocale( +std::unique_ptr> Engine::ComputePlatformResolvedLocale( const std::vector& supported_locale_data) { return delegate_.ComputePlatformResolvedLocale(supported_locale_data); } diff --git a/shell/common/engine.h b/shell/common/engine.h index 686138d36e03b..58b3db4a95508 100644 --- a/shell/common/engine.h +++ b/shell/common/engine.h @@ -243,7 +243,8 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate { /// platform. Empty strings mean the value was unassigned. Empty /// vector represents a null locale. /// - virtual std::vector& ComputePlatformResolvedLocale( + virtual std::unique_ptr> + ComputePlatformResolvedLocale( const std::vector& supported_locale_data) = 0; }; @@ -791,7 +792,7 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate { int64_t isolate_port) override; // |RuntimeDelegate| - std::vector& ComputePlatformResolvedLocale( + std::unique_ptr> ComputePlatformResolvedLocale( const std::vector& supported_locale_data) override; void SetNeedsReportTimings(bool value) override; diff --git a/shell/common/platform_view.cc b/shell/common/platform_view.cc index 4b14f04c59175..c6f3665f5b3a2 100644 --- a/shell/common/platform_view.cc +++ b/shell/common/platform_view.cc @@ -137,7 +137,8 @@ void PlatformView::SetNextFrameCallback(const fml::closure& closure) { delegate_.OnPlatformViewSetNextFrameCallback(closure); } -std::vector& PlatformView::ComputePlatformResolvedLocales( +std::unique_ptr> +PlatformView::ComputePlatformResolvedLocales( const std::vector& supported_locale_data) { return delegate_.ComputePlatformViewResolvedLocale(supported_locale_data); } diff --git a/shell/common/platform_view.h b/shell/common/platform_view.h index 9bc5149365973..f0e0c65c0bf7f 100644 --- a/shell/common/platform_view.h +++ b/shell/common/platform_view.h @@ -225,7 +225,8 @@ class PlatformView { /// platform. Empty strings mean the value was unassigned. Empty /// vector represents a null locale. /// - virtual std::vector& ComputePlatformViewResolvedLocale( + virtual std::unique_ptr> + ComputePlatformViewResolvedLocale( const std::vector& supported_locale_data) = 0; }; @@ -576,7 +577,8 @@ class PlatformView { /// platform. Empty strings mean the value was unassigned. Empty /// vector represents a null locale. /// - virtual std::vector& ComputePlatformResolvedLocales( + virtual std::unique_ptr> + ComputePlatformResolvedLocales( const std::vector& supported_locale_data); protected: diff --git a/shell/common/shell.cc b/shell/common/shell.cc index c2fb6f6c788de..aef32cd962399 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -1099,16 +1099,15 @@ void Shell::SetNeedsReportTimings(bool value) { } // |Engine::Delegate| -std::vector& Shell::ComputePlatformResolvedLocale( +std::unique_ptr> Shell::ComputePlatformResolvedLocale( const std::vector& supported_locale_data) { return ComputePlatformViewResolvedLocale(supported_locale_data); } // |PlatformView::Delegate| -std::vector& Shell::ComputePlatformViewResolvedLocale( +std::unique_ptr> +Shell::ComputePlatformViewResolvedLocale( const std::vector& supported_locale_data) { - std::vector result = - platform_view_->ComputePlatformResolvedLocales(supported_locale_data); return platform_view_->ComputePlatformResolvedLocales(supported_locale_data); } diff --git a/shell/common/shell.h b/shell/common/shell.h index bccb0c1bc975e..325a5f2d93c9d 100644 --- a/shell/common/shell.h +++ b/shell/common/shell.h @@ -483,7 +483,7 @@ class Shell final : public PlatformView::Delegate, void OnPlatformViewSetNextFrameCallback(const fml::closure& closure) override; // |PlatformView::Delegate| - std::vector& ComputePlatformViewResolvedLocale( + std::unique_ptr> ComputePlatformViewResolvedLocale( const std::vector& supported_locale_data) override; // |Animator::Delegate| @@ -521,7 +521,7 @@ class Shell final : public PlatformView::Delegate, void SetNeedsReportTimings(bool value) override; // |Engine::Delegate| - std::vector& ComputePlatformResolvedLocale( + std::unique_ptr> ComputePlatformResolvedLocale( const std::vector& supported_locale_data) override; // |Rasterizer::Delegate| diff --git a/shell/platform/android/platform_view_android.cc b/shell/platform/android/platform_view_android.cc index 9785f130beaf1..51e8d361dceb4 100644 --- a/shell/platform/android/platform_view_android.cc +++ b/shell/platform/android/platform_view_android.cc @@ -427,20 +427,20 @@ void PlatformViewAndroid::ReleaseResourceContext() const { } // |PlatformView| -std::vector& PlatformViewAndroid::ComputePlatformResolvedLocales( +std::unique_ptr> +PlatformViewAndroid::ComputePlatformResolvedLocales( const std::vector& supported_locale_data) { JNIEnv* env = fml::jni::AttachCurrentThread(); fml::jni::ScopedJavaLocalRef view = java_object_.get(env); if (view.is_null()) { // The Java object died. - platform_resolved_locale_.clear(); - return platform_resolved_locale_; + std::unique_ptr> out = + std::make_unique>(); + return out; } - platform_resolved_locale_ = *FlutterViewComputePlatformResolvedLocale( + return FlutterViewComputePlatformResolvedLocale( env, view.obj(), fml::jni::VectorToStringArray(env, supported_locale_data).obj()); - - return platform_resolved_locale_; } void PlatformViewAndroid::InstallFirstFrameCallback() { diff --git a/shell/platform/android/platform_view_android.h b/shell/platform/android/platform_view_android.h index 304491ae7edf5..9d321c4e62daf 100644 --- a/shell/platform/android/platform_view_android.h +++ b/shell/platform/android/platform_view_android.h @@ -80,7 +80,6 @@ class PlatformViewAndroid final : public PlatformView { int next_response_id_ = 1; std::unordered_map> pending_responses_; - std::vector platform_resolved_locale_; // |PlatformView| void UpdateSemantics( @@ -107,7 +106,7 @@ class PlatformViewAndroid final : public PlatformView { void ReleaseResourceContext() const override; // |PlatformView| - std::vector& ComputePlatformResolvedLocales( + std::unique_ptr> ComputePlatformResolvedLocales( const std::vector& supported_locale_data) override; void InstallFirstFrameCallback(); diff --git a/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm b/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm index 437a210d2018f..92869c90802ef 100644 --- a/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm +++ b/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm @@ -86,13 +86,11 @@ void OnPlatformViewRegisterTexture(std::shared_ptr texture) override {} void OnPlatformViewUnregisterTexture(int64_t texture_id) override {} void OnPlatformViewMarkTextureFrameAvailable(int64_t texture_id) override {} - std::vector& ComputePlatformViewResolvedLocale( + std::unique_ptr> ComputePlatformViewResolvedLocale( const std::vector& supported_locale_data) override { - return mock_locale_data; + std::unique_ptr> out = std::make_unique>(); + return out; } - - private: - std::vector mock_locale_data; }; } // namespace } // namespace flutter diff --git a/shell/platform/darwin/ios/platform_view_ios.h b/shell/platform/darwin/ios/platform_view_ios.h index 6bb802adaa8fd..7cd3f3468e627 100644 --- a/shell/platform/darwin/ios/platform_view_ios.h +++ b/shell/platform/darwin/ios/platform_view_ios.h @@ -154,7 +154,7 @@ class PlatformViewIOS final : public PlatformView { void OnPreEngineRestart() const override; // |PlatformView| - std::vector& ComputePlatformResolvedLocales( + std::unique_ptr> ComputePlatformResolvedLocales( const std::vector& supported_locale_data) override; FML_DISALLOW_COPY_AND_ASSIGN(PlatformViewIOS); diff --git a/shell/platform/fuchsia/flutter/platform_view_unittest.cc b/shell/platform/fuchsia/flutter/platform_view_unittest.cc index 82fc757dfdf4a..6d6b30df8f1f6 100644 --- a/shell/platform/fuchsia/flutter/platform_view_unittest.cc +++ b/shell/platform/fuchsia/flutter/platform_view_unittest.cc @@ -75,16 +75,17 @@ class MockPlatformViewDelegate : public flutter::PlatformView::Delegate { // |flutter::PlatformView::Delegate| void OnPlatformViewMarkTextureFrameAvailable(int64_t texture_id) {} // |flutter::PlatformView::Delegate| - std::vector& ComputePlatformViewResolvedLocale( + std::unique_ptr> ComputePlatformViewResolvedLocale( const std::vector& supported_locale_data) { - return mock_locale_data_; + std::unique_ptr> out = + std::make_unique>(); + return out; } bool SemanticsEnabled() const { return semantics_enabled_; } int32_t SemanticsFeatures() const { return semantics_features_; } private: - std::vector mock_locale_data_; bool semantics_enabled_ = false; int32_t semantics_features_ = 0; }; From cfb0ec13e45f0d371f388a11b9b77153ef8f7f43 Mon Sep 17 00:00:00 2001 From: garyqian Date: Wed, 10 Jun 2020 13:58:21 -0700 Subject: [PATCH 31/51] Compiles for iOS --- shell/platform/darwin/ios/platform_view_ios.mm | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/shell/platform/darwin/ios/platform_view_ios.mm b/shell/platform/darwin/ios/platform_view_ios.mm index b770df883ba9f..14fcc2141c478 100644 --- a/shell/platform/darwin/ios/platform_view_ios.mm +++ b/shell/platform/darwin/ios/platform_view_ios.mm @@ -191,7 +191,7 @@ new AccessibilityBridge(static_cast(owner_controller_.get().view), [owner_controller_.get() platformViewsController]->Reset(); } -std::vector& PlatformViewIOS::ComputePlatformResolvedLocales( +std::unique_ptr> PlatformViewIOS::ComputePlatformResolvedLocales( const std::vector& supported_locale_data) { size_t localeDataLength = 3; NSMutableArray* supported_locale_identifiers = @@ -208,21 +208,20 @@ new AccessibilityBridge(static_cast(owner_controller_.get().view), [NSBundle preferredLocalizationsFromArray:supported_locale_identifiers]; // Output format should be either empty or 3 strings for language, country, and script. - platform_resolved_locale_.clear(); + std::unique_ptr> out = std::make_unique>(); if (result != nullptr && [result count] > 0) { if (@available(ios 10.0, *)) { NSLocale* locale = [NSLocale localeWithLocaleIdentifier:[result firstObject]]; NSString* languageCode = [locale languageCode]; - platform_resolved_locale_.emplace_back(languageCode == nullptr ? "" - : languageCode.UTF8String); + out->emplace_back(languageCode == nullptr ? "" : languageCode.UTF8String); NSString* countryCode = [locale countryCode]; - platform_resolved_locale_.emplace_back(countryCode == nullptr ? "" : countryCode.UTF8String); + out->emplace_back(countryCode == nullptr ? "" : countryCode.UTF8String); NSString* scriptCode = [locale scriptCode]; - platform_resolved_locale_.emplace_back(scriptCode == nullptr ? "" : scriptCode.UTF8String); + out->emplace_back(scriptCode == nullptr ? "" : scriptCode.UTF8String); } } - return platform_resolved_locale_; + return out; } PlatformViewIOS::ScopedObserver::ScopedObserver() : observer_(nil) {} From 7c4679f3e8f6780f3d8ac15f675acd2d72beb41b Mon Sep 17 00:00:00 2001 From: garyqian Date: Wed, 10 Jun 2020 17:38:18 -0700 Subject: [PATCH 32/51] New test --- .../flutter/embedding/engine/FlutterJNI.java | 3 +- .../embedding/engine/FlutterJNITest.java | 44 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java index ca3c4285bb08a..02c304a1776ff 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java @@ -799,7 +799,8 @@ public void setLocalizationPlugin(@Nullable LocalizationPlugin localizationPlugi /** Invoked by native to obtain the results of Android's locale resolution algorithm. */ @SuppressWarnings("unused") - private String[] computePlatformResolvedLocale(@NonNull String[] strings) { + @VisibleForTesting + String[] computePlatformResolvedLocale(@NonNull String[] strings) { if (localizationPlugin == null) { return new String[0]; } diff --git a/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java b/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java index 98b8660683837..acaa1a4c0f36d 100644 --- a/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java +++ b/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java @@ -1,9 +1,22 @@ package io.flutter.embedding.engine; import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import android.content.Context; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.os.LocaleList; +import io.flutter.embedding.engine.dart.DartExecutor; import io.flutter.embedding.engine.renderer.FlutterUiDisplayListener; +import io.flutter.embedding.engine.systemchannels.LocalizationChannel; +import io.flutter.plugin.localization.LocalizationPlugin; import java.util.concurrent.atomic.AtomicInteger; +import java.util.Locale; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; @@ -44,4 +57,35 @@ public void onFlutterUiNoLongerDisplayed() {} // --- Verify Results --- assertEquals(1, callbackInvocationCount.get()); } + + @Test + public void computePlatformResolvedLocaleCallsLocalizationPluginProperly() { + // --- Test Setup --- + FlutterJNI flutterJNI = new FlutterJNI(); + + Context context = mock(Context.class); + Resources resources = mock(Resources.class); + Configuration config = mock(Configuration.class); + DartExecutor dartExecutor = mock(DartExecutor.class); + LocaleList localeList = new LocaleList( + new Locale("es", "MX"), + new Locale("zh", "CN"), + new Locale("en", "US") + ); + when(context.getResources()).thenReturn(resources); + when(resources.getConfiguration()).thenReturn(config); + when(config.getLocales()).thenReturn(localeList); + + flutterJNI.setLocalizationPlugin(new LocalizationPlugin(context, new LocalizationChannel(dartExecutor))); + String[] supportedLocales = new String[] { + "fr", "FR", "", + "zh", "", "", + "en", "CA", "" + }; + String[] result = flutterJNI.computePlatformResolvedLocale(supportedLocales); + assertEquals(result.length, 3); + assertEquals(result[0], "zh"); + assertEquals(result[1], ""); + assertEquals(result[2], ""); + } } From 74eb79e9a0f673cc44e11317a4b207bc4598aab0 Mon Sep 17 00:00:00 2001 From: garyqian Date: Wed, 10 Jun 2020 18:00:31 -0700 Subject: [PATCH 33/51] Remove extra imports --- .../test/io/flutter/embedding/engine/FlutterJNITest.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java b/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java index acaa1a4c0f36d..abe359ea6397e 100644 --- a/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java +++ b/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java @@ -1,10 +1,7 @@ package io.flutter.embedding.engine; import static org.junit.Assert.assertEquals; -import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Context; From 27220ed14fc4b8cf374731f76312dcab76baf2ff Mon Sep 17 00:00:00 2001 From: garyqian Date: Wed, 10 Jun 2020 18:13:00 -0700 Subject: [PATCH 34/51] Formatting --- .../embedding/engine/FlutterJNITest.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java b/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java index abe359ea6397e..96d3636895067 100644 --- a/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java +++ b/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java @@ -65,20 +65,19 @@ public void computePlatformResolvedLocaleCallsLocalizationPluginProperly() { Configuration config = mock(Configuration.class); DartExecutor dartExecutor = mock(DartExecutor.class); LocaleList localeList = new LocaleList( - new Locale("es", "MX"), - new Locale("zh", "CN"), - new Locale("en", "US") - ); + new Locale("es", "MX"), new Locale("zh", "CN"), new Locale("en", "US")); when(context.getResources()).thenReturn(resources); when(resources.getConfiguration()).thenReturn(config); when(config.getLocales()).thenReturn(localeList); - flutterJNI.setLocalizationPlugin(new LocalizationPlugin(context, new LocalizationChannel(dartExecutor))); - String[] supportedLocales = new String[] { - "fr", "FR", "", - "zh", "", "", - "en", "CA", "" - }; + flutterJNI.setLocalizationPlugin( + new LocalizationPlugin(context, new LocalizationChannel(dartExecutor))); + String[] supportedLocales = + new String[] { + "fr", "FR", "", + "zh", "", "", + "en", "CA", "" + }; String[] result = flutterJNI.computePlatformResolvedLocale(supportedLocales); assertEquals(result.length, 3); assertEquals(result[0], "zh"); From b454f09e19541c2cc68eb2c149371e17bb268fa6 Mon Sep 17 00:00:00 2001 From: garyqian Date: Wed, 10 Jun 2020 22:22:48 -0700 Subject: [PATCH 35/51] Formatting --- .../test/io/flutter/embedding/engine/FlutterJNITest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java b/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java index 96d3636895067..4f4f18723f560 100644 --- a/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java +++ b/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java @@ -12,8 +12,8 @@ import io.flutter.embedding.engine.renderer.FlutterUiDisplayListener; import io.flutter.embedding.engine.systemchannels.LocalizationChannel; import io.flutter.plugin.localization.LocalizationPlugin; -import java.util.concurrent.atomic.AtomicInteger; import java.util.Locale; +import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; @@ -64,8 +64,8 @@ public void computePlatformResolvedLocaleCallsLocalizationPluginProperly() { Resources resources = mock(Resources.class); Configuration config = mock(Configuration.class); DartExecutor dartExecutor = mock(DartExecutor.class); - LocaleList localeList = new LocaleList( - new Locale("es", "MX"), new Locale("zh", "CN"), new Locale("en", "US")); + LocaleList localeList = + new LocaleList(new Locale("es", "MX"), new Locale("zh", "CN"), new Locale("en", "US")); when(context.getResources()).thenReturn(resources); when(resources.getConfiguration()).thenReturn(config); when(config.getLocales()).thenReturn(localeList); From 4c896deb067969314490f7fd33c5190a7a414c22 Mon Sep 17 00:00:00 2001 From: garyqian Date: Thu, 11 Jun 2020 04:11:27 -0700 Subject: [PATCH 36/51] Basic request path test, fix infinite loop --- shell/common/platform_view.cc | 4 ++- .../embedder/platform_view_embedder.cc | 9 +++++++ .../embedder/platform_view_embedder.h | 4 +++ testing/dart/window_test.dart | 26 ++++++++----------- 4 files changed, 27 insertions(+), 16 deletions(-) diff --git a/shell/common/platform_view.cc b/shell/common/platform_view.cc index c6f3665f5b3a2..146874933e739 100644 --- a/shell/common/platform_view.cc +++ b/shell/common/platform_view.cc @@ -140,7 +140,9 @@ void PlatformView::SetNextFrameCallback(const fml::closure& closure) { std::unique_ptr> PlatformView::ComputePlatformResolvedLocales( const std::vector& supported_locale_data) { - return delegate_.ComputePlatformViewResolvedLocale(supported_locale_data); + std::unique_ptr> out = + std::make_unique>(); + return out; } } // namespace flutter diff --git a/shell/platform/embedder/platform_view_embedder.cc b/shell/platform/embedder/platform_view_embedder.cc index b6daf1946704a..b1a2cac536e54 100644 --- a/shell/platform/embedder/platform_view_embedder.cc +++ b/shell/platform/embedder/platform_view_embedder.cc @@ -93,4 +93,13 @@ std::unique_ptr PlatformViewEmbedder::CreateVSyncWaiter() { platform_dispatch_table_.vsync_callback, task_runners_); } +// |PlatformView| +std::unique_ptr> +PlatformViewEmbedder::ComputePlatformResolvedLocales( + const std::vector& supported_locale_data) { + std::unique_ptr> out = + std::make_unique>(); + return out; +} + } // namespace flutter diff --git a/shell/platform/embedder/platform_view_embedder.h b/shell/platform/embedder/platform_view_embedder.h index 13d4c45684655..9815d94936918 100644 --- a/shell/platform/embedder/platform_view_embedder.h +++ b/shell/platform/embedder/platform_view_embedder.h @@ -76,6 +76,10 @@ class PlatformViewEmbedder final : public PlatformView { // |PlatformView| std::unique_ptr CreateVSyncWaiter() override; + // |PlatformView| + std::unique_ptr> ComputePlatformResolvedLocales( + const std::vector& supported_locale_data) override; + FML_DISALLOW_COPY_AND_ASSIGN(PlatformViewEmbedder); }; diff --git a/testing/dart/window_test.dart b/testing/dart/window_test.dart index 3ca6a8d5d405d..a434482024d69 100644 --- a/testing/dart/window_test.dart +++ b/testing/dart/window_test.dart @@ -26,19 +26,15 @@ void main() { expect(timing.toString(), 'FrameTiming(buildDuration: 7.0ms, rasterDuration: 10.5ms, totalSpan: 18.5ms)'); }); - // test('computePlatformResolvedLocale basic', () { - // final List supportedLocales = [ - // const Locale.fromSubtag(languageCode: 'zh', scriptCode: 'Hans'); - // const Locale.fromSubtag(languageCode: 'zh', scriptCode: 'Hant'); - // const Locale.fromSubtag(languageCode: 'fr', countryCode: 'FR'); - // const Locale.fromSubtag(languageCode: 'fr', countryCode: 'FR'); - // const Locale.fromSubtag(languageCode: 'fr', countryCode: 'CA'); - // const Locale.fromSubtag(languageCode: 'en', countryCode: 'US'); - // const Locale.fromSubtag(languageCode: 'en', countryCode: 'UK'); - // const Locale.fromSubtag(languageCode: 'en', countryCode: 'IN'); - // const Locale.fromSubtag(languageCode: 'en'); - // ]; - // final Locale result = window.computePlatformResolvedLocale(supportedLocales); - // expect(result, const Locale.fromSubtag(languageCode: 'en', countryCode: 'US')); - // }, skip: isBrowser || isWindows); + test('computePlatformResolvedLocale basic', () { + final List supportedLocales = [ + const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans', countryCode: 'CN'), + const Locale.fromSubtags(languageCode: 'fr', countryCode: 'FR'), + const Locale.fromSubtags(languageCode: 'en', countryCode: 'US'), + const Locale.fromSubtags(languageCode: 'en'), + ]; + // The default implementation returns null due to lack of a real platform. + final Locale result = window.computePlatformResolvedLocale(supportedLocales); + expect(result, null); + }); } From 6db66f7d4a21cf0a5018f56a4efbdb5c02845615 Mon Sep 17 00:00:00 2001 From: garyqian Date: Thu, 11 Jun 2020 13:57:48 -0700 Subject: [PATCH 37/51] Kick tests From 15e38d299c06090e6fa776f5fee65bff8fa79fe0 Mon Sep 17 00:00:00 2001 From: garyqian Date: Thu, 11 Jun 2020 14:07:22 -0700 Subject: [PATCH 38/51] API gate test, commends: --- .../io/flutter/embedding/engine/FlutterJNI.java | 4 ++++ .../io/flutter/embedding/engine/FlutterJNITest.java | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java index 02c304a1776ff..a9d8dd661b63c 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java @@ -810,6 +810,7 @@ String[] computePlatformResolvedLocale(@NonNull String[] strings) { String languageCode = strings[i + 0]; String countryCode = strings[i + 1]; String scriptCode = strings[i + 2]; + // Convert to Locales via LocaleBuilder if available (API 24+) to include scriptCode. if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { Locale.Builder localeBuilder = new Locale.Builder(); if (!languageCode.isEmpty()) { @@ -823,10 +824,13 @@ String[] computePlatformResolvedLocale(@NonNull String[] strings) { } supportedLocales.add(localeBuilder.build()); } else { + // Pre-API 24, we fall back on scriptCode-less locales. supportedLocales.add(new Locale(languageCode, countryCode)); } } + Locale result = localizationPlugin.resolveNativeLocale(supportedLocales); + if (result == null) { return new String[0]; } diff --git a/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java b/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java index 4f4f18723f560..14bee33b445de 100644 --- a/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java +++ b/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java @@ -21,6 +21,7 @@ @Config(manifest = Config.NONE) @RunWith(RobolectricTestRunner.class) +@TargetApi(24) // LocaleList and scriptCode are API 24+. public class FlutterJNITest { @Test public void itAllowsFirstFrameListenersToRemoveThemselvesInline() { @@ -83,5 +84,16 @@ public void computePlatformResolvedLocaleCallsLocalizationPluginProperly() { assertEquals(result[0], "zh"); assertEquals(result[1], ""); assertEquals(result[2], ""); + + supportedLocales = + new String[] { + "fr", "FR", "", + "ar", "", "", + "en", "CA", "" + }; + result = flutterJNI.computePlatformResolvedLocale(supportedLocales); + assertEquals(result[0], "en"); + assertEquals(result[1], "CA"); + assertEquals(result[2], ""); } } From 99c8627e08b91d3abe24b8b967a3329d3f369325 Mon Sep 17 00:00:00 2001 From: garyqian Date: Thu, 11 Jun 2020 14:13:50 -0700 Subject: [PATCH 39/51] Imports --- .../android/test/io/flutter/embedding/engine/FlutterJNITest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java b/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java index 14bee33b445de..f466ced7992e6 100644 --- a/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java +++ b/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java @@ -4,6 +4,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import android.annotation.TargetApi; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; From 6d5deb877425983e5fbf53ec8bac80173bf64217 Mon Sep 17 00:00:00 2001 From: garyqian Date: Thu, 11 Jun 2020 14:41:22 -0700 Subject: [PATCH 40/51] add new tests --- .../embedding/engine/FlutterJNITest.java | 24 ++++++++++++++++++- testing/run_tests.py | 2 +- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java b/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java index f466ced7992e6..7d70f71a632f1 100644 --- a/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java +++ b/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java @@ -93,8 +93,30 @@ public void computePlatformResolvedLocaleCallsLocalizationPluginProperly() { "en", "CA", "" }; result = flutterJNI.computePlatformResolvedLocale(supportedLocales); + assertEquals(result.length, 0); // This should change when full algo is implemented. + + supportedLocales = + new String[] { + "fr", "FR", "", + "ar", "", "", + "en", "US", "" + }; + result = flutterJNI.computePlatformResolvedLocale(supportedLocales); + assertEquals(result.length, 3); assertEquals(result[0], "en"); - assertEquals(result[1], "CA"); + assertEquals(result[1], "US"); + assertEquals(result[2], ""); + + supportedLocales = + new String[] { + "ar", "", "", + "es", "MX", "", + "en", "US", "" + }; + result = flutterJNI.computePlatformResolvedLocale(supportedLocales); + assertEquals(result.length, 3); + assertEquals(result[0], "es"); + assertEquals(result[1], "MX"); assertEquals(result[2], ""); } } diff --git a/testing/run_tests.py b/testing/run_tests.py index 35d5173ae3c08..0ce1197220480 100755 --- a/testing/run_tests.py +++ b/testing/run_tests.py @@ -319,7 +319,7 @@ def AssertExpectedJavaVersion(): EXPECTED_VERSION = '1.8' # `java -version` is output to stderr. https://bugs.java.com/bugdatabase/view_bug.do?bug_id=4380614 version_output = subprocess.check_output(['java', '-version'], stderr=subprocess.STDOUT) - match = bool(re.compile('version "%s' % EXPECTED_VERSION).search(version_output)) + match = True#bool(re.compile('version "%s' % EXPECTED_VERSION).search(version_output)) message = "JUnit tests need to be run with Java %s. Check the `java -version` on your PATH." % EXPECTED_VERSION assert match, message From d707d132d3ed28822e4816bc8ee6ae7a6d74195a Mon Sep 17 00:00:00 2001 From: garyqian Date: Thu, 11 Jun 2020 16:03:09 -0700 Subject: [PATCH 41/51] More tests --- .../embedding/engine/FlutterJNITest.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java b/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java index 7d70f71a632f1..7911dbbb93ba8 100644 --- a/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java +++ b/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java @@ -118,5 +118,22 @@ public void computePlatformResolvedLocaleCallsLocalizationPluginProperly() { assertEquals(result[0], "es"); assertEquals(result[1], "MX"); assertEquals(result[2], ""); + + // Empty supportedLocales. + supportedLocales = new String[] {}; + result = flutterJNI.computePlatformResolvedLocale(supportedLocales); + assertEquals(result.length, 0); + + // Empty preferredLocales. + supportedLocales = + new String[] { + "fr", "FR", "", + "zh", "", "", + "en", "CA", "" + }; + localeList = new LocaleList(); + when(config.getLocales()).thenReturn(localeList); + result = flutterJNI.computePlatformResolvedLocale(supportedLocales); + assertEquals(result.length, 0); } } From be46c424a4fc9809dbf5fc3a272c754466f3349b Mon Sep 17 00:00:00 2001 From: garyqian Date: Thu, 11 Jun 2020 16:08:10 -0700 Subject: [PATCH 42/51] Cleanup etra code --- .../plugin/localization/LocalizationPlugin.java | 15 +-------------- testing/run_tests.py | 2 +- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java b/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java index 51933647a645c..6dfda90ba58d4 100644 --- a/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java +++ b/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java @@ -36,6 +36,7 @@ public Locale resolveNativeLocale(List supportedLocales) { for (int index = 0; index < localeCount; ++index) { Locale locale = localeList.get(index); String localeString = locale.toString(); + // This string replacement converts the locale string into the ranges format. languageRanges.add(new Locale.LanguageRange(localeString.replace("_", "-"))); } @@ -66,20 +67,6 @@ public void sendLocalesToFlutter(@NonNull Configuration config) { locales.add(config.locale); } - Locale platformResolvedLocale = null; - if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { - List languageRanges = new ArrayList<>(); - LocaleList localeList = config.getLocales(); - int localeCount = localeList.size(); - for (int index = 0; index < localeCount; ++index) { - Locale locale = localeList.get(index); - languageRanges.add(new Locale.LanguageRange(locale.toLanguageTag())); - } - // TODO(garyq) implement a real locale resolution. - platformResolvedLocale = - Locale.lookup(languageRanges, Arrays.asList(Locale.getAvailableLocales())); - } - localizationChannel.sendLocales(locales); } } diff --git a/testing/run_tests.py b/testing/run_tests.py index 0ce1197220480..35d5173ae3c08 100755 --- a/testing/run_tests.py +++ b/testing/run_tests.py @@ -319,7 +319,7 @@ def AssertExpectedJavaVersion(): EXPECTED_VERSION = '1.8' # `java -version` is output to stderr. https://bugs.java.com/bugdatabase/view_bug.do?bug_id=4380614 version_output = subprocess.check_output(['java', '-version'], stderr=subprocess.STDOUT) - match = True#bool(re.compile('version "%s' % EXPECTED_VERSION).search(version_output)) + match = bool(re.compile('version "%s' % EXPECTED_VERSION).search(version_output)) message = "JUnit tests need to be run with Java %s. Check the `java -version` on your PATH." % EXPECTED_VERSION assert match, message From 131be16ced210d82978975bdba63428ce6c7d553 Mon Sep 17 00:00:00 2001 From: garyqian Date: Thu, 11 Jun 2020 16:10:25 -0700 Subject: [PATCH 43/51] Typo --- runtime/dart_isolate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/dart_isolate.h b/runtime/dart_isolate.h index 7eee92c540eec..7f59aa7dc28d0 100644 --- a/runtime/dart_isolate.h +++ b/runtime/dart_isolate.h @@ -30,7 +30,7 @@ class DartIsolateGroupData; /// @brief Represents an instance of a live isolate. An isolate is a /// separate Dart execution context. Different Dart isolates don't /// share memory and can be scheduled concurrently by the Dart VM on -/// one of the Dart VM managed worfluker pool threads. +/// one of the Dart VM managed worker pool threads. /// /// The entire lifecycle of a Dart isolate is controlled by the Dart /// VM. Because of this, the engine never holds a strong pointer to From 04861c012643aa217477bd0d515adb20cbd47006 Mon Sep 17 00:00:00 2001 From: garyqian Date: Fri, 12 Jun 2020 02:45:02 -0700 Subject: [PATCH 44/51] Formatting --- .../test/io/flutter/embedding/engine/FlutterJNITest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java b/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java index 64fdaa07600e2..0ff5b9b72e885 100644 --- a/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java +++ b/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java @@ -2,9 +2,9 @@ import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.annotation.TargetApi; import android.content.Context; @@ -15,8 +15,8 @@ import io.flutter.embedding.engine.renderer.FlutterUiDisplayListener; import io.flutter.embedding.engine.systemchannels.LocalizationChannel; import io.flutter.plugin.localization.LocalizationPlugin; -import java.util.Locale; import io.flutter.plugin.platform.PlatformViewsController; +import java.util.Locale; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; import org.junit.runner.RunWith; From 2011c7eaa945d4fdc0855a035ffb3b0d165dd539 Mon Sep 17 00:00:00 2001 From: garyqian Date: Fri, 12 Jun 2020 03:04:20 -0700 Subject: [PATCH 45/51] More formatting --- .../io/flutter/plugin/localization/LocalizationPlugin.java | 1 - 1 file changed, 1 deletion(-) diff --git a/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java b/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java index 6dfda90ba58d4..ed75dbb2541d5 100644 --- a/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java +++ b/shell/platform/android/io/flutter/plugin/localization/LocalizationPlugin.java @@ -11,7 +11,6 @@ import androidx.annotation.NonNull; import io.flutter.embedding.engine.systemchannels.LocalizationChannel; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Locale; From 4418471129dbd76ac45a313cf61986f3d0123ecd Mon Sep 17 00:00:00 2001 From: garyqian Date: Mon, 15 Jun 2020 03:41:43 -0700 Subject: [PATCH 46/51] FlutterEngine constructs plugin --- .../embedding/android/FlutterView.java | 6 +-- .../embedding/engine/FlutterEngine.java | 42 +++++++++++-------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterView.java b/shell/platform/android/io/flutter/embedding/android/FlutterView.java index 45de51e904eae..83327a74345e4 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterView.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterView.java @@ -813,7 +813,7 @@ public void attachToFlutterEngine(@NonNull FlutterEngine flutterEngine) { this.flutterEngine.getTextInputChannel(), this.flutterEngine.getPlatformViewsController()); localizationPlugin = - new LocalizationPlugin(getContext(), this.flutterEngine.getLocalizationChannel()); + this.flutterEngine.getLocalizationPlugin(); androidKeyProcessor = new AndroidKeyProcessor(this.flutterEngine.getKeyEventChannel(), textInputPlugin); androidTouchProcessor = new AndroidTouchProcessor(this.flutterEngine.getRenderer()); @@ -838,10 +838,6 @@ public void attachToFlutterEngine(@NonNull FlutterEngine flutterEngine) { // TODO(mattcarroll): once this is proven to work, move this line ot TextInputPlugin textInputPlugin.getInputMethodManager().restartInput(this); - if (this.flutterEngine.getFlutterJNI() != null) { - this.flutterEngine.getFlutterJNI().setLocalizationPlugin(localizationPlugin); - } - // Push View and Context related information from Android to Flutter. sendUserSettingsToFlutter(); localizationPlugin.sendLocalesToFlutter(getResources().getConfiguration()); diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java b/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java index 4d264d39cf63d..27f635fcaad04 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java @@ -28,6 +28,7 @@ import io.flutter.embedding.engine.systemchannels.SettingsChannel; import io.flutter.embedding.engine.systemchannels.SystemChannel; import io.flutter.embedding.engine.systemchannels.TextInputChannel; +import io.flutter.plugin.localization.LocalizationPlugin; import io.flutter.plugin.platform.PlatformViewsController; import java.lang.reflect.Method; import java.util.HashSet; @@ -73,6 +74,7 @@ public class FlutterEngine { @NonNull private final FlutterRenderer renderer; @NonNull private final DartExecutor dartExecutor; @NonNull private final FlutterEnginePluginRegistry pluginRegistry; + @NonNull private final LocalizationPlugin localizationPlugin; // System channels. @NonNull private final AccessibilityChannel accessibilityChannel; @@ -260,21 +262,9 @@ public FlutterEngine( @Nullable String[] dartVmArgs, boolean automaticallyRegisterPlugins, boolean waitForRestorationData) { - this.flutterJNI = flutterJNI; - flutterLoader.startInitialization(context.getApplicationContext()); - flutterLoader.ensureInitializationComplete(context, dartVmArgs); - - flutterJNI.addEngineLifecycleListener(engineLifecycleListener); - flutterJNI.setPlatformViewsController(platformViewsController); - attachToJni(); - this.dartExecutor = new DartExecutor(flutterJNI, context.getAssets()); this.dartExecutor.onAttachedToJNI(); - // TODO(mattcarroll): FlutterRenderer is temporally coupled to attach(). Remove that coupling if - // possible. - this.renderer = new FlutterRenderer(flutterJNI); - accessibilityChannel = new AccessibilityChannel(dartExecutor, flutterJNI); keyEventChannel = new KeyEventChannel(dartExecutor); lifecycleChannel = new LifecycleChannel(dartExecutor); @@ -287,6 +277,22 @@ public FlutterEngine( systemChannel = new SystemChannel(dartExecutor); textInputChannel = new TextInputChannel(dartExecutor); + this.localizationPlugin = new LocalizationPlugin(context, localizationChannel); + + this.flutterJNI = flutterJNI; + flutterLoader.startInitialization(context.getApplicationContext()); + flutterLoader.ensureInitializationComplete(context, dartVmArgs); + + flutterJNI.addEngineLifecycleListener(engineLifecycleListener); + flutterJNI.setPlatformViewsController(platformViewsController); + flutterJNI.setLocalizationPlugin(localizationPlugin); + attachToJni(); + + // TODO(mattcarroll): FlutterRenderer is temporally coupled to attach(). Remove that coupling if + // possible. + this.renderer = new FlutterRenderer(flutterJNI); + + this.platformViewsController = platformViewsController; this.platformViewsController.onAttachedToJNI(); @@ -400,12 +406,6 @@ public FlutterRenderer getRenderer() { return renderer; } - /** The FlutterJNI associated with this engine. */ - @NonNull - public FlutterJNI getFlutterJNI() { - return flutterJNI; - } - /** System channel that sends accessibility requests and events from Flutter to Android. */ @NonNull public AccessibilityChannel getAccessibilityChannel() { @@ -492,6 +492,12 @@ public PluginRegistry getPlugins() { return pluginRegistry; } + /** The LocalizationPlugin this FlutterEngine created. */ + @NonNull + public LocalizationPlugin getLocalizationPlugin() { + return localizationPlugin; + } + /** * {@code PlatformViewsController}, which controls all platform views running within this {@code * FlutterEngine}. From f0859fd386e8cdf0aa96f25f4cdd9b9212b6a9eb Mon Sep 17 00:00:00 2001 From: garyqian Date: Mon, 15 Jun 2020 03:46:11 -0700 Subject: [PATCH 47/51] Fix null analyzer: --- lib/ui/window.dart | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/ui/window.dart b/lib/ui/window.dart index 7e43a1f4e8135..f6c2b2aed4ac8 100644 --- a/lib/ui/window.dart +++ b/lib/ui/window.dart @@ -818,9 +818,6 @@ class Window { /// This method returns synchronously and is a direct call to /// platform specific APIs without invoking method channels. Locale? computePlatformResolvedLocale(List supportedLocales) { - if (supportedLocales == null) { - return null; - } final List supportedLocalesData = []; for (Locale locale in supportedLocales) { supportedLocalesData.add(locale.languageCode); @@ -830,7 +827,7 @@ class Window { final List result = _computePlatformResolvedLocale(supportedLocalesData); - if (result != null && result.isNotEmpty && result[0] != null) { + if (result.isNotEmpty) { return Locale.fromSubtags( languageCode: result[0], countryCode: result[1] == '' ? null : result[1], From 8eb352c90e6d6f9528d90c6dedf551ab75dbd89f Mon Sep 17 00:00:00 2001 From: garyqian Date: Mon, 15 Jun 2020 03:57:47 -0700 Subject: [PATCH 48/51] Fix formatting --- .../android/io/flutter/embedding/android/FlutterView.java | 3 +-- .../android/io/flutter/embedding/engine/FlutterEngine.java | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterView.java b/shell/platform/android/io/flutter/embedding/android/FlutterView.java index 83327a74345e4..c05b37bdb4e67 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterView.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterView.java @@ -812,8 +812,7 @@ public void attachToFlutterEngine(@NonNull FlutterEngine flutterEngine) { this, this.flutterEngine.getTextInputChannel(), this.flutterEngine.getPlatformViewsController()); - localizationPlugin = - this.flutterEngine.getLocalizationPlugin(); + localizationPlugin = this.flutterEngine.getLocalizationPlugin(); androidKeyProcessor = new AndroidKeyProcessor(this.flutterEngine.getKeyEventChannel(), textInputPlugin); androidTouchProcessor = new AndroidTouchProcessor(this.flutterEngine.getRenderer()); diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java b/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java index 27f635fcaad04..1408156ebaf24 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java @@ -292,7 +292,6 @@ public FlutterEngine( // possible. this.renderer = new FlutterRenderer(flutterJNI); - this.platformViewsController = platformViewsController; this.platformViewsController.onAttachedToJNI(); From 5711cf808380ecaa284776e2b5e322569e9baf0b Mon Sep 17 00:00:00 2001 From: garyqian Date: Mon, 15 Jun 2020 04:17:17 -0700 Subject: [PATCH 49/51] Fix test mocking --- .../android/FlutterActivityAndFragmentDelegateTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java b/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java index 5c6198f8983be..2c8e243375fd7 100644 --- a/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java +++ b/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java @@ -32,6 +32,7 @@ import io.flutter.embedding.engine.systemchannels.SettingsChannel; import io.flutter.embedding.engine.systemchannels.SystemChannel; import io.flutter.embedding.engine.systemchannels.TextInputChannel; +import io.flutter.plugin.localization.LocalizationPlugin; import io.flutter.plugin.platform.PlatformViewsController; import org.junit.Before; import org.junit.Test; @@ -626,6 +627,7 @@ private FlutterEngine mockFlutterEngine() { when(engine.getTextInputChannel()).thenReturn(mock(TextInputChannel.class)); when(engine.getMouseCursorChannel()).thenReturn(mock(MouseCursorChannel.class)); when(engine.getActivityControlSurface()).thenReturn(mock(ActivityControlSurface.class)); + when(engine.getLocalizationPlugin()).thenReturn(mock(LocalizationPlugin.class)); return engine; } From c0e78deb9327d51240696c5ae77011d9589749c1 Mon Sep 17 00:00:00 2001 From: garyqian Date: Mon, 15 Jun 2020 04:24:32 -0700 Subject: [PATCH 50/51] Fix test --- .../test/io/flutter/embedding/android/FlutterViewTest.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/shell/platform/android/test/io/flutter/embedding/android/FlutterViewTest.java b/shell/platform/android/test/io/flutter/embedding/android/FlutterViewTest.java index 4db27c88a51cb..55263f387d0de 100644 --- a/shell/platform/android/test/io/flutter/embedding/android/FlutterViewTest.java +++ b/shell/platform/android/test/io/flutter/embedding/android/FlutterViewTest.java @@ -101,15 +101,14 @@ public void onConfigurationChanged_fizzlesWhenNullEngine() { Configuration configuration = RuntimeEnvironment.application.getResources().getConfiguration(); // 1 invocation of channels. - flutterView.attachToFlutterEngine(flutterEngine); - // localizationChannel now stored by plugin, so only 1 invocation. + flutterView.attachToFlutterEngine(flutterEngine);. flutterView.onConfigurationChanged(configuration); flutterView.detachFromFlutterEngine(); // Should fizzle. flutterView.onConfigurationChanged(configuration); - verify(flutterEngine, times(1)).getLocalizationChannel(); + verify(flutterEngine, times(1)).getLocalizationPlugin(); verify(flutterEngine, times(2)).getSettingsChannel(); } From 12c2bf04d5052e983014153377933b7106b71dd4 Mon Sep 17 00:00:00 2001 From: garyqian Date: Mon, 15 Jun 2020 04:31:12 -0700 Subject: [PATCH 51/51] Typo --- .../test/io/flutter/embedding/android/FlutterViewTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/platform/android/test/io/flutter/embedding/android/FlutterViewTest.java b/shell/platform/android/test/io/flutter/embedding/android/FlutterViewTest.java index 55263f387d0de..7461674f243b0 100644 --- a/shell/platform/android/test/io/flutter/embedding/android/FlutterViewTest.java +++ b/shell/platform/android/test/io/flutter/embedding/android/FlutterViewTest.java @@ -101,7 +101,7 @@ public void onConfigurationChanged_fizzlesWhenNullEngine() { Configuration configuration = RuntimeEnvironment.application.getResources().getConfiguration(); // 1 invocation of channels. - flutterView.attachToFlutterEngine(flutterEngine);. + flutterView.attachToFlutterEngine(flutterEngine); flutterView.onConfigurationChanged(configuration); flutterView.detachFromFlutterEngine();