New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 846633 link

Starred by 1 user

Issue metadata

Status: Fixed
Owner:
Last visit > 30 days ago
Closed: Aug 6
Cc:
EstimatedDays: ----
NextAction: ----
OS: Android
Pri: 3
Type: Bug

Blocking:
issue 820459



Sign in to add a comment

Android: Chrome crashes on startup due to system language selection.

Project Member Reported by digit@chromium.org, May 25 2018

Issue description

Chromium might crash at startup, when it is built as an app bundle with language-based configuration splits. This happens once the user has changed the device's current system locale, and that the corresponding split APK is not installed yet.

This entry is to prevent the issue by ensuring that all Chromium code can deal with this case by using the right fallback Java resources and .pak files. Until it is fixed, language-based splits cannot be enabled!


Now, for a more detailed explanation of the situation:

Android app bundles can generate APK splits where all locale-dependent Java resources and .pak files are stored in language-specific splits (e.g. config_en.apk for English, config_fr.apk for French, etc), separate from the main application split (base.apk).

When this feature is enabled, only the splits corresponding to the current device's configuration are installed. For example, if the device is currently using a French locale, installing the application will actually only install base.apk and config_fr.apk to the device.

Note that:

- There is *always* at least one language split installed (matching the current device's language at install time),

- Once a split is installed, it cannot be removed, except by uninstalling the application as a whole.

- Once a split is installed, any application update will actually update the base.apk and all installed splits at the same time.


A problem arises when the user later decides to change the device's locale (Settings > System > Languages on N). For example, when changing the locale to Spanish, the next Chromium launch will *not* have the config_es.apk split installed yet, and won't be able to use any related Java resources or .pak files.

At the moment, Chromium will crash at runtime due to this, resulting in an unacceptable user experience (crash dialog, and no way to start the browser or understand what's happening). The only solution is to revert to the previous system language, which is not obvious.

IMPORTANT NOTE: *All* system webview locale resources and .pak files are already always stored in the base.apk, thus this issue will never happen for applications using a Webview, only Chromium-based apps like the browser.

If the application was installed through the Play Store, the Google Play Services library will detect the system-wide locale change and try to download the new split as soon as possible. However, this may not be immediate or even possible (e.g. airplane mode).

This means that Chrome needs to fallback to a locale it has resources and .pak files for when this happens.

This entry is to track the issue and provide an adequate solution.

A proposed solution for now is the following:

- Add a new org.chromium.base.LocaleUtils.getCurrentLocale() method
  to return the current Locale that all of Chromium should use. This
  should be called instead of Locale.getDefault() which returns the
  current system default.

  Also adjust all callers of Locale.getDefault() to use 
  getCurrentLocale()


- Ensure the value returned by getCurrentLocale() matches either
  the current system locale, iff the corresponding config split is
  installed.

  Otherwise, it should match a fallback locale which *has* its
  config split installed.

  Since for Java resources (localized UI strings) this issue is not
  specific to Chromium, see how the Play Store client library, which
  manages splits, deals with this. Hopefully, there would be a simple
  API that returns the corresponding value.

  Note that the getCurrentLocale() value is needed *very* early during
  Chromium startup, which means it may not be possible to call this
  API so soon, even if it is provided. Alternative schemes would be
  to store the previously-used locale in a small persistent property
  or data file and use this instead.

- Chromium-specific locale .pak files are stored in the following
  directory for regular (non-app-bundle) APKs:

     chrome.apk!/assets/locales/<locale>.pak

  Where <locale> is a Chromium-specific locale name.
  When using app bundles, however, the path changes to:

     <split>.apk!/assets/locales#lang_<lang>/<locale>.pak

  where <lang> is a 2-char Android-specific country name, and
  <locale> is a Chromium-specific locale name.

  Note that the '#lang_<lang>' part of the sub-directory is not
  removed from the split APKs and must be used explicitly when
  accessing the files through AssetManager.open() or equivalent.

  These files are extracted from the APK on very early startup into
  the app data directory. See the ResourceExtractor class for details.

  The latter must be updated to deal with the new format.

 

Comment 1 by digit@chromium.org, May 25 2018

Another alternative is to use Locale.setDefault() [1] early during startup to change the locale to the right fallback when needed.

This would actually minimize the changes required to the Chromium code base (which after inspection uses Locale.getDefault() in a lot of places) [2]

[1] https://developer.android.com/reference/java/util/Locale#setDefault(java.util.Locale)

[2] https://cs.chromium.org/search/?q=%22Locale.getDefault%22+case:yes&sq=package:chromium&type=cs
This article suggests that it might be more complicated than that:

https://gunhansancar.com/change-language-programmatically-in-android/

Comment 3 by digit@google.com, Jun 6 2018

Summary: Chrome crashes on startup due to system language selection. (was: Make locale support with Android app bundles and language-based splits bullet-proof.)
Thanks for the link Andrew, very interesting. I think our use case is slightly simpler, in the end, because we won't necessarily need to change to a different locale.

I'm renaming this issue to "Chrome crashes on startup due to system language selection", because the problem appears to not be to APK splits.

Let me explain with a simple experiment:

- Use an Android N device, and go to system Settings to change the current
  language to "Furlan", *removing* any other language from the list. This
  matches the "Friulian" language spoken in nothern part of Italy [1],
  identified with the "fur-rIT" locale on Android.

- Note that just after the switch, the Settings application still displays
  everything in English. But the Home screen is properly localized.

- Notice that most applications also display in English as well. The reason for
  that is that the Android framework will fallback to en-rUS when trying to
  display localized strings for the "fur-rIT" or "fur" locale, when the
  application doesn't have any resources for it. This is the way the system
  is designed.

- Now try to start Chrome, and see it crash immediately on startup.

The reason for the crash is that the C++ code needs to access the .pak file
corresponding to the current locale, and cannot find one / open one, since
Chrome does not support Furlan (i.e. there is no fur.pak or fur-IT.pak file
under assets/locales/ or listed in [2]).

This problem is similar to the one described in the initial description for this bug: the .pak file for the current locale is missing, hence Chrome crashes on startup.

So my goal now is to fix the issue, by ensuring that the native code uses the same fallback locale as the Java side. Apparently, how the Android framework selects the actual localized strings is pretty complex, varies by platform release, depends heavily on the set of of asset files loaded in the process, and overlays, and whatnot. In other words, Chrome shall not try to duplicate this logic.

Unfortunately, there is no API to ask the framework directly for a fallback locale (and in the general case, different subsets of an application's strings can be localized differently).

But I think there is way to get something adequate by doing the following:

- Create a set of resource directories matching the Chrome-supported locales
  that contain string definitions, e.g.:

     res/values/strings.xml
     res/values-am/strings.xml
     res/values-ar/strings.xml
     ...
     res/values-en-rUS/strings.xml
     ...

  Where each strings.xml contains the definition of a single string
  named "current_locale", and whose value will be the corresponding
  Chromium-specific locale name.

  I.e.   values-en-rUS/strings.xml defines 'current_locale' as 'en-US',
     or  values-tl/strings.xml defines it as 'fil'.

  Then we can query at runtime the string value using something like:

     ContextUtils.getApplicationContext().getResources().getString(
        org.chromium.base.ui_locale.R.string.current_locale);

  And this should give us the locale used to display the UI, as decided by
  the framework. This will work because we always localize all our strings
  for all our supported locales.

By doing this, native code should be able to match the locale used by the UI, and in the example above, Chrome should start using English as the UI language when the system is set to "Furlan".

[1] https://en.wikipedia.org/wiki/Friulian_language
[2] https://cs.chromium.org/chromium/src/build/config/locales.gni?q=locales.gni&sq=package:chromium&dr

Comment 4 by digit@google.com, Jun 6 2018

Summary: Android: Chrome crashes on startup due to system language selection. (was: Chrome crashes on startup due to system language selection.)
There is existing logic that is supposed to handle this case:

Extracting fallback pak:
https://cs.chromium.org/chromium/src/base/android/java/src/org/chromium/base/ResourceExtractor.java?rcl=324138ca59bab8c60c2a641f8530073934785423&l=218

Choosing fallback pak:
https://cs.chromium.org/chromium/src/ui/base/l10n/l10n_util.cc?rcl=324138ca59bab8c60c2a641f8530073934785423&l=509

What you describe sounds more robust, but I think it's also worth figuring out why the existing logic isn't working.

Comment 6 by digit@google.com, Jun 6 2018

Fwiw, the current language logic cannot be used for the edge case where an APK split isn't installed yet. I already tested that the system may use a different fallback that en-US for Java strings if an appropriate split is already installed.

Certainly agree that your approach is more robust and will work well for splits. Just curious why it's crashing.
Project Member

Comment 8 by bugdroid1@chromium.org, Jun 11 2018

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/88f72c27376cffbe654307274c5df9db56fe77ea

commit 88f72c27376cffbe654307274c5df9db56fe77ea
Author: David 'Digit' Turner <digit@google.com>
Date: Mon Jun 11 09:53:24 2018

android: Move native library extraction to LibraryLoader

Some constants and methods related to extracted native libraries
from the Chrome APK into a private application data directory
are moved from the ResourceExtractor.java class to LibraryLoader.java
instead.

This is a more logical place, since ResourceExtractor.java is going
to be moved out of //base and into //ui/base/ since it is now mostly
related to UI resources.

See referring bug for more context.

BUG= 846633 
R=agrieve@chromium.org, pasko@chromium.org

Change-Id: I7ff442930ee80dfe9230021ce8e099393d51beca
Reviewed-on: https://chromium-review.googlesource.com/1090926
Commit-Queue: David Turner <digit@chromium.org>
Reviewed-by: agrieve <agrieve@chromium.org>
Reviewed-by: Egor Pasko <pasko@chromium.org>
Cr-Commit-Position: refs/heads/master@{#565951}
[modify] https://crrev.com/88f72c27376cffbe654307274c5df9db56fe77ea/base/android/java/src/org/chromium/base/FileUtils.java
[modify] https://crrev.com/88f72c27376cffbe654307274c5df9db56fe77ea/base/android/java/src/org/chromium/base/ResourceExtractor.java
[modify] https://crrev.com/88f72c27376cffbe654307274c5df9db56fe77ea/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
[modify] https://crrev.com/88f72c27376cffbe654307274c5df9db56fe77ea/base/android/java/src/org/chromium/base/library_loader/Linker.java

Project Member

Comment 9 by bugdroid1@chromium.org, Jun 12 2018

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/d58d7c9826b9a941dc837c04dc1d8cef8667a4a8

commit d58d7c9826b9a941dc837c04dc1d8cef8667a4a8
Author: David 'Digit' Turner <digit@google.com>
Date: Tue Jun 12 12:44:02 2018

android: Move ResourceExtractor from base to ui

This prepares for a future CL that will ensure the set of PAK
files extracted by this class match the UI language used by the
Android framework to display localized strings.

BUG= 846633 
R=agrieve@chromium.org, astevenson@chromium.org

Change-Id: I316dc53b23f3fc9139af845c1f9fad7e5b4138a6
Reviewed-on: https://chromium-review.googlesource.com/1091310
Reviewed-by: agrieve <agrieve@chromium.org>
Reviewed-by: David Trainor <dtrainor@chromium.org>
Reviewed-by: Ted Choc <tedchoc@chromium.org>
Commit-Queue: David Turner <digit@chromium.org>
Cr-Commit-Position: refs/heads/master@{#566391}
[modify] https://crrev.com/d58d7c9826b9a941dc837c04dc1d8cef8667a4a8/base/BUILD.gn
[modify] https://crrev.com/d58d7c9826b9a941dc837c04dc1d8cef8667a4a8/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeBrowserInitializer.java
[modify] https://crrev.com/d58d7c9826b9a941dc837c04dc1d8cef8667a4a8/content/public/android/java/src/org/chromium/content/browser/BrowserStartupControllerImpl.java
[modify] https://crrev.com/d58d7c9826b9a941dc837c04dc1d8cef8667a4a8/content/public/test/android/javatests/src/org/chromium/content/browser/test/NativeLibraryTestRule.java
[modify] https://crrev.com/d58d7c9826b9a941dc837c04dc1d8cef8667a4a8/ui/android/BUILD.gn
[rename] https://crrev.com/d58d7c9826b9a941dc837c04dc1d8cef8667a4a8/ui/android/java/src/org/chromium/ui/resources/ResourceExtractor.java

Project Member

Comment 10 by bugdroid1@chromium.org, Jun 19 2018

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/5111ff4bca35f8a1dd89aa9a7ea2f96fdc4055e6

commit 5111ff4bca35f8a1dd89aa9a7ea2f96fdc4055e6
Author: David 'Digit' Turner <digit@google.com>
Date: Tue Jun 19 11:22:38 2018

android: Add android_generated_resources GN template

This CL adds a new GN template to specify a set of Android
resource files generated by another target's action. The
generated files must be stored by the action into a zip
archive, with a layout similar to standard Android res/ folder
(but note that the archive should not have a top-level res/
directory).

+ Update java_strings_grd(), java_strings_grd_prebuilt()
  and jinja_template_resources() to use it.

BUG= 846633 
R=agrieve@chromium.org, estevenson@chromium.org, jbudorick@chromium.org

Change-Id: Ibb0ec100d0922ac1ec3155f4577f40136f233b0b
Reviewed-on: https://chromium-review.googlesource.com/1104355
Commit-Queue: David Turner <digit@chromium.org>
Reviewed-by: John Budorick <jbudorick@chromium.org>
Reviewed-by: agrieve <agrieve@chromium.org>
Reviewed-by: Eric Stevenson <estevenson@chromium.org>
Cr-Commit-Position: refs/heads/master@{#568402}
[modify] https://crrev.com/5111ff4bca35f8a1dd89aa9a7ea2f96fdc4055e6/build/config/android/rules.gni

Project Member

Comment 11 by bugdroid1@chromium.org, Jun 19 2018

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/f0154cc103b927a15ed8224b2e42026b7c95226c

commit f0154cc103b927a15ed8224b2e42026b7c95226c
Author: David 'Digit' Turner <digit@google.com>
Date: Tue Jun 19 17:22:36 2018

android: Small LocaleUtils cleanup

This CL removes un-necessary allocations in LocaleUtils.java
and moves the matching Python CHROME_TO_ANDROID_LANGUAGE_MAP
variable to resource_utils.py, in preparation of a future CL
where it will be used by another Python script as well.

BUG= 846633 
R=agrieve@chromium.org, jbudorick@chromium.org, estevenson@chromium.org

Change-Id: Ie6eba71b259c2fef410afe526b7478dc56866887
Reviewed-on: https://chromium-review.googlesource.com/1106162
Reviewed-by: agrieve <agrieve@chromium.org>
Commit-Queue: David Turner <digit@chromium.org>
Cr-Commit-Position: refs/heads/master@{#568507}
[modify] https://crrev.com/f0154cc103b927a15ed8224b2e42026b7c95226c/base/android/java/src/org/chromium/base/LocaleUtils.java
[modify] https://crrev.com/f0154cc103b927a15ed8224b2e42026b7c95226c/build/android/gyp/compile_resources.py
[modify] https://crrev.com/f0154cc103b927a15ed8224b2e42026b7c95226c/build/android/gyp/util/resource_utils.py

Cc: benmason@chromium.org
Project Member

Comment 13 by bugdroid1@chromium.org, Jun 22 2018

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/26d969cf89623e4c76f6bf5a11549fc1689324da

commit 26d969cf89623e4c76f6bf5a11549fc1689324da
Author: David 'Digit' Turner <digit@google.com>
Date: Fri Jun 22 19:49:11 2018

android: Fix Chrome startup crash due to system language choice.

Chrome currently crashes on startup on Android if the system locale is
set to something that it doesn't support.

For example, set the system locale to 'Furlan': regular Android
applications will fallback to display English strings as a fallback,
but Chrome crashes on startup immediately.

This CL fixes the issue, by detecting which locale the Android framework
uses to display strings effectively, then using this value to extract
the corresponding .pak file, instead of trying to find one that matches
the current system setting.

+ Move compressed locale file detection to background thread.
  Since this now requires I/O access when accessing the
  resources, this operation can no longer be performed on
  the UI thread.

For more details, see associated bug entry.

BUG= 846633 
R=agrieve@chromium.org,astevenson@chromium.org,dtrainor@chromium.org,tedchoc@chromium.org

Change-Id: If2db6136367081ad50b2b80c85b4cc0e1c2c276f
Reviewed-on: https://chromium-review.googlesource.com/1088708
Commit-Queue: David Turner <digit@chromium.org>
Reviewed-by: agrieve <agrieve@chromium.org>
Reviewed-by: Ted Choc <tedchoc@chromium.org>
Cr-Commit-Position: refs/heads/master@{#569738}
[modify] https://crrev.com/26d969cf89623e4c76f6bf5a11549fc1689324da/build/android/gyp/util/build_utils.py
[modify] https://crrev.com/26d969cf89623e4c76f6bf5a11549fc1689324da/ui/android/BUILD.gn
[add] https://crrev.com/26d969cf89623e4c76f6bf5a11549fc1689324da/ui/android/build/create_ui_locale_resources.py
[modify] https://crrev.com/26d969cf89623e4c76f6bf5a11549fc1689324da/ui/android/java/src/org/chromium/ui/base/LocalizationUtils.java
[modify] https://crrev.com/26d969cf89623e4c76f6bf5a11549fc1689324da/ui/android/java/src/org/chromium/ui/resources/ResourceExtractor.java

Project Member

Comment 14 by bugdroid1@chromium.org, Jul 12

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/dc6d74d7b8c120d3d8d90ab8c68c5285e384a7f8

commit dc6d74d7b8c120d3d8d90ab8c68c5285e384a7f8
Author: David 'Digit' Turner <digit@google.com>
Date: Thu Jul 12 17:07:14 2018

android: Update bundletool binary to 0.5.0

This release contains a bugfix required to generate Android
app bundle APKs archives that can be installed on all devices.

For more context, see:
https://buganizer.corp.google.com/issues/110777526

BUG= 846633 , 820459 
R=agrieve@chromium.org, bensmason@chromium.org, yfriedman@chromium.org

Change-Id: Ic71445f49a4548c8610f5d18598cdd3d3d5692c4
Reviewed-on: https://chromium-review.googlesource.com/1135127
Reviewed-by: agrieve <agrieve@chromium.org>
Commit-Queue: David Turner <digit@chromium.org>
Cr-Commit-Position: refs/heads/master@{#574608}
[modify] https://crrev.com/dc6d74d7b8c120d3d8d90ab8c68c5285e384a7f8/DEPS
[modify] https://crrev.com/dc6d74d7b8c120d3d8d90ab8c68c5285e384a7f8/build/android/gyp/bundletool.py
[modify] https://crrev.com/dc6d74d7b8c120d3d8d90ab8c68c5285e384a7f8/third_party/android_build_tools/bundletool/README.chromium

Project Member

Comment 15 by bugdroid1@chromium.org, Jul 13

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/bdb7c6bf6d378e95ddeb81014e30bb19cdd87c86

commit bdb7c6bf6d378e95ddeb81014e30bb19cdd87c86
Author: David 'Digit' Turner <digit@google.com>
Date: Fri Jul 13 12:54:36 2018

android: Enable language-based splits for app bundles.

This is done by adding a new |enable_language_splits| variable to
the android_app_bundle GN template. Note that splitting by
screen_density or ABI currently doesn't make sense for Chromium,
but could be added in the future.

Only the chrome_public_bundle target uses language-based
splits in this CL.

BUG= 846633 , 820459 
R=agrieve@chromium.org, yfriedman@chromium.org
TBR=twellington@chromium.org,tedchoc@chromium.org

Change-Id: Ic89f9dd4b8c78e8b2127bb19208db18bc8027eab
Reviewed-on: https://chromium-review.googlesource.com/1125934
Commit-Queue: David Turner <digit@chromium.org>
Reviewed-by: agrieve <agrieve@chromium.org>
Cr-Commit-Position: refs/heads/master@{#574888}
[modify] https://crrev.com/bdb7c6bf6d378e95ddeb81014e30bb19cdd87c86/build/android/gyp/create_app_bundle.py
[modify] https://crrev.com/bdb7c6bf6d378e95ddeb81014e30bb19cdd87c86/build/android/gyp/util/resource_utils.py
[modify] https://crrev.com/bdb7c6bf6d378e95ddeb81014e30bb19cdd87c86/build/config/android/rules.gni
[modify] https://crrev.com/bdb7c6bf6d378e95ddeb81014e30bb19cdd87c86/chrome/android/BUILD.gn
[modify] https://crrev.com/bdb7c6bf6d378e95ddeb81014e30bb19cdd87c86/ui/android/java/src/org/chromium/ui/base/LocalizationUtils.java
[modify] https://crrev.com/bdb7c6bf6d378e95ddeb81014e30bb19cdd87c86/ui/android/java/src/org/chromium/ui/resources/ResourceExtractor.java

Status: Fixed (was: Started)

Sign in to add a comment