How AOSP creates incompatibilities

Antonin Fouques
7 min readJul 3, 2019

--

In that second part of our “You can fix the 0.1%” series we analyse the origin of the Meizu’s crash we fixed in part one.

AOSP, fragmentation and Support Library

The AOSP (Android Open Source Project) is the whole code of the Android Operating System. It is Open Source and is the base of code for all Android device OEM (Original Equipment Manufacturer, or vendors). OEM can use it out of the box (or with almost no change) like in the Nexus and Pixel Google’s devices, or completely change it like in the Amazon’s Fire tablet.

Android currently has a huge fragmentation between its different versions:

  • 15 versions of Android were released in the last 10 years
  • OEMs can decide whether to update or not their devices
  • Updates can be difficult if they target compl or important changes.

To tackle that issue, Google created in march 2011 the Support Library so developers could use recent framework features on old Android versions. For example, when Google released the TextInputLayout, it was first added in the Design package of the Support Library (and moved in march 2018 in the Material Component package) instead of the AOSP. Android developers can embed this library in their application and use this component. Then, the TextInputLayout can be used on very old Android devices with old versions of Android without updating anything but their usual applications.

OEMs and the AOSP modifications

Since the first public version of Android (Android 1.5 — Cupcake), the whole source code is available (mainly) under the Apache 2.0 license.

“the license allows the user of the software the freedom to use the software for any purpose, to distribute it, to modify it, and to distribute modified versions of the software, under the terms of the license, without concern for royalties” — Wikipedia

Manufacturers must adapt core parts of their system so device sensors and physical elements are recognized by the system. That could be the end of the story (like for the Google Nexus’ devices) but manufacturers like to customize their devices to reflect brand identity. Those overlays are a big mix of UI modifications, base applications (launcher, sms, phone, calculator…) modifications or replacements, features additions, branding applications and even bloatwares. Samsung overlay TouchWiz was probably the most infamous one for developers and end-users.

And that’s where the bad things happens:

  • when facing framework limitations, Android developers must understand how it works and extend it to create what they need, using only the API (public part) of the framework. The advantage of this solution is that the API will be supported forever, and so their solutions should work with any (new) version of Android.
  • On the opposite, system UI overlays developers, when facing a limitation with Android can modify it themself. This way they can do whatever they want, making the code simpler (they generally do the opposite though) and easily reuse their solutions in all the overlay.

There are two main issues with the OEMs overlays:

  • The first one is a problem on the end-users side: complex framework changes will be even harder to maintain in following Android versions. And as OEMs release new smartphone with the new Android versions, they usually don’t bother developing updates for old devices, which leads to an augmentation of the fragmentation.
  • The second problem is on the application developers side: By changing the framework, the overlay developers changes its normal behaviour and may lead to unexpected situations.

Here are some situations of bad overlay modifications that leads to strange behaviour:

We will focus on this last modification and its implications.

The Meizu modification

Meizu is a Chinese OEM with a very small part of the smartphone marketshare. If its first goal is the Chinese market (1.06%) with smartphones only available in China, it also releases some smartphones worldwide (0.09%), especially in Europe (0.16%) but almost nothing in US (0.01%) (sources)

Since 2012, Meizu has been developing its own system UI overlay called Flyme, with international (understand “outside China”) versions since the end of 2015. International versions are not Meizu priority so device owners should not expect system updates or bug fixes. Flyme Overlay is quite successful with the dev community who created kind-of open source versions of it which helped us getting the root cause of the crash.

It is barely readable but here is one of the framework modification they did:

  1. When getting focus, the TextView will define and update the cursors positions, using the hidden utils class Editor (Editor.updateCursorsPositions()) in order to draw it.
  2. This last method should call Editor.updateCursorPosition() but instead Meizu changed the code to call a new implementation, Editor.updateCursorPosition**Mz**().
  3. This last method should calculate how to draw the cursor depending on the parameters. The Meizu new implementation will do a more complicated calculation depending on whether or not the TextView has a hint and a text.
  4. If the TextView has a hint (!TextView.getHint().isEmpty()) and if the TextView has no text (TextView.getText().isEmpty()), it will get the TextView.mHintLayout in order to get its Layout.getLineForOffset() and do its calculations

If you didn’t notice, there is a problem in this code: it assumes that if getHint() is not empty, then getHintLayout() must return a not null value. We will see later on that this assumption is incorrect.

The TextInputLayout

In may 2015, Google released the version 22.2.0 of its Android Support Library. This version introduced the TextInputLayout component for showing EditText hint and error text as floating labels. In april 2018, this component was moved to the Material Component library.

The idea of float label pattern was introduced on septembre 2013 by the Design Director of Studio Mds, Matt D. Smith. Several developers created their Android implementations during the year 2014, until the Google Android developer Chris Banesintroduced the FloatLabelLayout. One year later, this implementation would be added to the Android Support Library as TextInputLayout and became part of the Material Design guidelines.

At the end of may 2018, the Android team from Google NYC released a new version of their library Material Component in their alpha version 1.0.0-alpha3, and a stable version 1.0.0 in november 2018.

This version provides accessibility support for TextInputLayout: developers must provide a hint to the user to describe the EditText content, that will be shown as a placeholder of the EditText when it is empty. For blind users (and for some automatic testing tools), the hint is read when the EditText get the focus, with the method TextView.getHint() (EditText is an extension of TextView). But with the TextInputLayout, the TextInputEditText’s hint is absorbed by its parent, the TextInputLayout. If it’s still shown to usual users, blind users (and some testing tools) don’t have the feedback from the TextInputEditText.getHint()anymore.

The above modification fixes this behaviour by returning TextInputLayout.getHint()when calling the TextInputEditText.getHint() method.

The Meizu crash

If we combine the conclusion of last two chapters, we can understand the crash:

  • Meizu modification assumed that:
  1. if TextView.getHint().isNotEmpty()
  2. then TextView.getHintLayout() is not null
  3. so they can call TextView.getHintLayout().getLineForOffset().
  • TextInputEditText inherits TextView and TextInputEditText.getHint() returns TextInputLayout.getHint() value even if no hint has been defined in TextInputEditText
  • Finally, if a TextInputEditText gets focus on a Muzei device, there will be a NullPointerException and the application will crash.

Conclusion

AOSP license allowing anybody to use it, modifying it and redistribute it is the strength and the weakness of Android. It led it to have around 75% of the worlwide mobile market share, but it is also widely fragmented and OEMs use to modify the framework not often for the best. As the fragmentation problem as been handled by the Android Support Library, the framework modifications are way more complex to prevent and until the OEMs don’t accept to not modify it, the Android team and the community will have to handle each issue at a time.

So please, Device Manufacturer and OS developers, please, don’t touch the Android framework!

Photo credit: Arrested Development

Thank you to the Qonto Android team (Guillaume Le Roy, BoD and Jean-Philippe Denis) for the help and reviewing this article.

notes:

Don’t workaround, fix the Library

Here is some development where modifying a library with the community was preferred as finding a workaround for ourselves:

oct 2012: CyanogenMod Trebuchet: Adapt Launcher Dock and Apps button to the newly phablets
video: https://www.youtube.com/watch?v=S3bu3Las8ws&feature=plcp
Commit : https://github.com/LineageOS/android_packages_apps_Trebuchet/commit/e74a54343ce7896b5005154e8bcbc7d5f06c7808

dec 2012: SlidingMenu: Prevent a ViewPager to be ignored when using a SlidingMenu (Jeremy Feinstein Library mainly used prior to the Google Android Navigation Drawer component)
PR: https://github.com/jfeinstein10/SlidingMenu/pull/176

apr 2019: Fix Lottie animation when cancelling system animation
PR: https://github.com/airbnb/lottie-android/pull/1187

may 2019: CountryCodePicker Library : Small fix upper/lower case error creating errors in tests
PR: https://github.com/hbb20/CountryCodePickerProject/pull/313

may 2019: Material Components : Fix TextInputLayout crash when used on Meizu devices
PR: https://github.com/material-components/material-components-android/pull/358

--

--