Improving Stability with Private C/C++ Symbol Restrictions in Android N

Your ads will be inserted here by

Easy Ads.

Please go to the plugin admin page to set up your ad code.

Posted by Dimitry Ivanov & Elliott Hughes, Software Engineers

As documented in the Android N
behavioral changes, to protect Android users and apps from unforeseen
crashes, Android N will restrict which libraries your C/C++ code can link
against at runtime. As a result, if your app uses any private symbols from
platform libraries, you will need to update it to either use the public NDK APIs
or to include its own copy of those libraries. Some libraries are public: the
Native Development Kit (NDK) exposes libandroid, libc, libcamera2ndk, libdl,
libGLES, libjnigraphics, liblog, libm, libmediandk, libOpenMAXAL, libOpenSLES,
libstdc++, libvulkan, and libz as part of the NDK API. Other libraries are
private, and Android N only allows access to them for platform HALs, system
daemons, and the like. If you aren’t sure whether your app uses private
libraries, you can immediately check it for warnings on the N Developer Preview.

We’re making this change because it’s painful for users when their apps stop
working after a platform update. Whether they blame the app developer or the
platform, everybody loses. Users should have a consistent app experience across
updates, and developers shouldn’t have to make emergency app updates to handle
platform changes. For that reason, we recommend against using private C/C++
symbols. Private symbols aren’t tested as part of the Compatibility Test Suite
(CTS) that all Android devices must pass. They may not exist, or they may behave
differently. This makes apps that use them more likely to fail on specific
devices, or on future releases — as many developers found when Android 6.0
Marshmallow switched from OpenSSL to BoringSSL.

You may be surprised that there’s no STL in the list of NDK libraries. The three
STL implementations included in the NDK — the LLVM libc++, the GNU STL, and
libstlport — are intended to be bundled with your app, either by statically
linking into your library, or by inclusion as a separate shared library. In the
past, some developers have assumed that they didn’t need to package the library
because the OS itself had a copy. This assumption is incorrect: a particular STL
implementation may disappear (as was the case with stlport, which was removed in
Marshmallow), may never have been available (as is the case with the GNU STL),
or it may change in ABI incompatible ways (as is the case with the LLVM libc++).

In order to reduce the user impact of this transition, we’ve identified a set of
libraries that see significant use from Google Play’s most-installed apps, and
that are feasible for us to support in the short term (including
libandroid_runtime.so, libcutils.so, libcrypto.so, and libssl.so). For legacy
code in N, we will temporarily support these libraries in order to give you more
time to transition. Note that we don’t intend to continue this support in any
future Android platform release, so if you see a warning that means your code
will not work in a future release — please fix it now!


Table 1. What to expect if your app is linking against private native libraries.

Libraries App’s targetSdkVersion Runtime access via dynamic linker Impact, N Developer Preview Impact, Final N Release Impact, future platform version
NDK Public Any Accessible
Private (graylist) <=23 Temporarily accessible Warning / Toast Warning Error
>=24 Restricted Error Error Error
Private (all other)> Any Restricted Error Error Error

What behavior will I see?

Your ads will be inserted here by

Easy Ads.

Please go to the plugin admin page to set up your ad code.

Please test your app during the N Previews.

  • N Preview behavior
    • All public NDK libraries ( libandroid, libc, libcamera2ndk, libdl, libGLES,
      libjnigraphics, liblog, libm, libmediandk, libOpenMAXAL, libOpenSLES, libstdc++,
      libvulkan, and libz), plus libraries that are part of your app are accessible.

    • For all other libraries you’ll see a warning in logcat and a toast on the
      display. This will happen only if your app’s targetSdkVersion is less than N. If
      you change your manifest to target N, loading will fail: Java’s
      System.loadLibrary will throw, and C/C++’s dlopen(3) will return NULL.

  • N Final Release behavior
    • All NDK libraries ( libandroid, libc, libcamera2ndk, libdl, libGLES,
      libjnigraphics, liblog, libm, libmediandk, libOpenMAXAL, libOpenSLES, libstdc++,
      libvulkan, and libz), plus libraries that are part of your app are accessible.

    • For the temporarily accessible libraries (such as libandroid_runtime.so,
      libcutils.so, libcrypto.so, and libssl.so), you’ll see a warning in logcat for
      all API levels before N, but loading will fail if you update your app so that
      its targetSdkVersion is N or later.

    • Attempts to load any other libraries will fail in the final release of
      Android N, even if your app is targeting a pre-N platform version.

    • Future platform behavior
      • In O, all access to the temporarily accessible libraries will be removed.
        As a result, you should plan to update your app regardless of your
        targetSdkVersion prior to O. If you believe there is missing functionality from
        the NDK API that will make it impossible for you to transition off a temporarily
        accessible library, please file a bug here.

What do the errors look like?

Here’s some example logcat output from an app that hasn’t bumped its target SDK
version (and so the restriction isn’t fully enforced because this is only the
developer preview):

03-21 17:07:51.502 31234 31234 W linker : library "libandroid_runtime.so" ("/system/lib/libandroid_runtime.so") needed or dlopened by "/data/app/com.popular-app.android-2/lib/arm/libapplib.so" is not accessible for the namespace "classloader-namespace" - the access is temporarily granted as a workaround for http://b/26394120

This is telling you that your library “libapplib.so” refers to the library
“libandroid_runtime.so”, which is a private library.

When Android N ships, or if you set your target SDK version to N now, you’ll see
something like this if you try to use System.loadLibrary from Java:

java.lang.UnsatisfiedLinkError: dlopen failed: library "libcutils.so" ("/system/lib/libcutils.so") needed or dlopened by "/system/lib/libnativeloader.so" is not accessible for the namespace "classloader-namespace"
at java.lang.Runtime.loadLibrary0(Runtime.java:977)
at java.lang.System.loadLibrary(System.java:1602)

If you’re using dlopen(3) from
C/C++ you’ll get a NULL return and dlerror(3) will
return the same “dlopen failed…” string as shown above.

For more information about how to check if your app is using private symbols,
see the FAQ on developer.android.com.


Android Developers Blog

Your ads will be inserted here by

Easy Ads.

Please go to the plugin admin page to set up your ad code.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

* Copy This Password *

* Type Or Paste Password Here *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>