diff options
| -rw-r--r-- | docs/html/preview/behavior-changes.jd | 320 |
1 files changed, 273 insertions, 47 deletions
diff --git a/docs/html/preview/behavior-changes.jd b/docs/html/preview/behavior-changes.jd index d54b222c36c7..b38f1b8d6dbe 100644 --- a/docs/html/preview/behavior-changes.jd +++ b/docs/html/preview/behavior-changes.jd @@ -378,70 +378,290 @@ see <a href="{@docRoot}training/secure-file-sharing/index.html">Sharing Files</a <h2 id="ndk">NDK Apps Linking to Platform Libraries</h2> <p> - Android N includes namespace changes to prevent loading of non-public APIs. - If you use the NDK, you should only be using public APIs from the Android - platform. Using non-public APIs in the next official release of Android - can cause your app to crash. + Starting in Android N, the system prevents apps from dynamically linking + against non-NDK libraries, which may cause your app to crash. This change in + behavior aims to create a consistent app experience across platform updates + and different devices. Even though your code might not be linking against + private libraries, it's possible that a third-party static library in your + app could be doing so. Therefore, all developers should check to make sure + that their apps do not crash on devices running Android N. If your app uses + native code, you should only be using <a href= + "{@docRoot}ndk/guides/stable_apis.html">public NDK APIs</a>. </p> <p> - In order to alert you to use of non-public APIs, apps running on an Android N - device generate an error in logcat output when an app calls a non-public API. - This error is also displayed on the device screen as a message to help - raise awareness of this situation. You should review your app code to - remove use of non-public platform APIs and thoroughly test your apps using - a preview device or emulator. + There are three ways your app might be trying to access private platform + APIs: </p> -<p> - If your app depends on platform libraries, see the NDK documentation for - typical fixes for replacing common private APIs with public API equivalents. - You may also be linking to platform libraries without realizing it, - especially if your app uses a library that is part of the platform (such as - <code>libpng</code>), but is not part of the NDK. In that case, ensure that - your APK contains all the .so files you intended to link against. -</p> +<ul> + <li>Your app directly accesses private platform libraries. You should update + your app to include its own copy of those libraries or use the <a href= + "{@docRoot}ndk/guides/stable_apis.html">public NDK APIs</a>. + </li> -<p class="caution"> - <strong>Caution:</strong> Some third-party libraries may link to non-public - APIs. If your app uses these libraries, your app may crash when running - on the next official release of Android. -</p> + <li>Your app uses a third-party library that accesses private platform + libraries. Even if you are certain your app doesn't access private libraries + directly, you should still test your app for this scenario. + </li> + + <li>Your app references a library that is not included in its APK. For + example, this could happen if you tried to use your own copy of OpenSSL but + forgot to bundle it with your app's APK. The app may run normally on versions + of Android platform that includes <code>libcrypto.so</code>. However, the app + could crash on later versions of Android that do not include this library + (such as, Android 6.0 and later). To fix this, ensure that you bundle all + your non-NDK libraries with your APK. + </li> +</ul> + +<p> + Apps should not use native libraries that are not included in the NDK because + they may change or be removed between different versions of Android. The + switch from OpenSSL to BoringSSL is an example of such a change. Also, + because there are no compatibility requirements for platform libraries not + included in the NDK, different devices may offer different levels of + compatibility. +</p> + +<p> + In order to reduce the impact that this restriction may have on currently + released apps, a set of libraries that see significant use—such as + <code>libandroid_runtime.so</code>, <code>libcutils.so</code>, + <code>libcrypto.so</code>, and <code>libssl.so</code>—are temporarily + accessible on N for apps targeting API level 23 or lower. If your app loads + one of these libraries, logcat generates a warning and a toast appears on the + target device to notify you. If you see these warnings, you should update + your app to either include its own copy of those libraries or only use the + public NDK APIs. Future releases of the Android platform may restrict the use + of private libraries altogether and cause your app to crash. +</p> + +<p> + All apps generate a runtime error when they call an API that is neither + public nor temporarily accessible. The result is that + <code>System.loadLibrary</code> and <code>dlopen(3)</code> both return + <code>NULL</code>, and may cause your app to crash. You should review your + app code to remove use of private platform APIs and thoroughly test your apps + using a preview device or emulator. If you are unsure whether your app uses + private libraries, you can <a href="#ndk-errors">check logcat</a> to identify + the runtime error. +</p> + +<p> + The following table describes the behavior you should expect to see from an + app depending on its use of private native libraries and its target API + level (<code>android:targetSdkVersion</code>). +</p> + +<table id="ndk-table"> + <col width="15%"> + <col width="15%"> + <col width="15%"> + <col width="20%"> + <col width="20%"> + <col width="20%"> + <tr> + <th scope="col"> + Libraries + </th> + <th scope="col"> + Target API level + </th> + <th scope="col"> + Runtime access via dynamic linker + </th> + <th scope="col"> + N Developer Preview behavior + </th> + <th scope="col"> + Final N Release behavior + </th> + <th scope="col"> + Future Android platform behavior + </th> + </tr> + +<tr> + <td> + NDK Public + </td> + + <td> + Any + </td> + + <td style="background-color:#DCEDC8"> + Accessible + </td> + + <td style="background-color:#DCEDC8"> + Works as expected + </td> + + <td style="background-color:#DCEDC8"> + Works as expected + </td> + + <td style="background-color:#DCEDC8"> + Works as expected + </td> +</tr> + +<tr> + <td> + Private (temporarily accessible private libraries) + </td> + + <td> + 23 or lower + </td> + + <td style="background-color:#FFF9C4"> + Temporarily accessible + </td> + + <td style="background-color:#FFF9C4"> + Works as expected, but you receive a logcat warning and a message on the + target device. + </td> + + <td style="background-color:#FFF9C4"> + Works as expected, but you receive a logcat warning. + </td> + + <td style="background-color:#ffcdd2"> + Runtime error + </td> +</tr> + +<tr> + <td> + Private (temporarily accessible private libraries) + </td> + + <td> + 24 or higher + </td> + + <td style="background-color:#ffcdd2"> + Restricted + </td> + + <td style="background-color:#ffcdd2"> + Runtime error + </td> + + <td style="background-color:#ffcdd2"> + Runtime error + </td> + + <td style="background-color:#ffcdd2"> + Runtime error + </td> +</tr> + +<tr> + <td> + Private (other) + </td> + + <td> + Any + </td> + + <td style="background-color:#ffcdd2"> + Restricted + </td> + + <td style="background-color:#ffcdd2"> + Runtime error + </td> + + <td style="background-color:#ffcdd2"> + Runtime error + </td> + + <td style="background-color:#ffcdd2"> + Runtime error + </td> +</tr> +</table> + +<h3 id="ndk-errors"> + Check if your app uses private libraries +</h3> <p> - Apps should not depend on or use native libraries that are not included in - the NDK, because they may change, or be removed from one Android release to - another. The switch from OpenSSL to BoringSSL is an example of such a change. - Also, different devices may offer different levels of compatibility, because - there are no compatibility requirements for platform libraries not included - in the NDK. If you must access non-NDK libraries on older devices, make the - loading dependent on the Android API level. + To help you identify issues loading private libraries, logcat may generate a + warning or runtime error. For example, if your app targets API level 23 or + lower, and tries to access a private library on a device running Android N, + you may see a warning similar to the following: </p> +<pre class="no-pretty-print"> +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 +</pre> + <p> - To help you diagnose these types problems here are some example Java and NDK - errors you might encounter when attempting to build your app with Android N: + These logcat warnings tell you which which library is trying to access a + private platform API, but will not cause your app to crash. If the app + targets API level 24 or higher, however, logcat generates the following + runtime error and your app may crash: </p> -<p>Example Java error:</p> <pre class="no-pretty-print"> -java.lang.UnsatisfiedLinkError: dlopen failed: library "/system/lib/libcutils.so" - is not accessible for the namespace "classloader-namespace" +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) </pre> -<p>Example NDK error:</p> +<p> + You may also see these logcat outputs if your app uses third-party libraries + that dynamically link to private platform APIs. The readelf tool in the + Android NDK allows you to generate a list of all dynamically linked shared + libraries of a given <code>.so</code> file by running the following command: +</p> + <pre class="no-pretty-print"> -dlopen failed: cannot locate symbol "__system_property_get" referenced by ... +aarch64-linux-android-readelf -dW libMyLibrary.so </pre> +<h3 id="ndk-update"> + Update your app +</h3> <p> - Here are some typical fixes for apps encountering these types of errors: + Here are some steps you can take to fix these types of errors and make + sure your app doesn't crash on future platform updates: </p> <ul> - <li>Use of getJavaVM and getJNIEnv from libandroid_runtime.so can be replaced - with standard JNI functions: + <li> + If your app uses private platform libraries, you should update it to include + its own copy of those libraries or use the <a href= + "{@docRoot}ndk/guides/stable_apis.html">public NDK APIs</a>. + </li> + + <li> + If your app uses a third-party library that accesses private symbols, contact + the library author to update the library. + </li> + + <li> + Make sure you package all your non-NDK libraries with your APK. + </li> + + <li>Use standard JNI functions instead of <code>getJavaVM</code> and + <code>getJNIEnv</code> from <code>libandroid_runtime.so</code>: + <pre class="no-pretty-print"> AndroidRuntime::getJavaVM -> GetJavaVM from <jni.h> AndroidRuntime::getJNIEnv -> JavaVM::GetEnv or @@ -449,18 +669,24 @@ JavaVM::AttachCurrentThread from <jni.h>. </pre> </li> - <li>Use of {@code property_get} symbol from {@code libcutils.so} can be - replaced with the public {@code alternative __system_property_get}. - To do this, use {@code __system_property_get} with the following include: + <li>Use {@code __system_property_get} instead of the private {@code property_get} + symbol from {@code libcutils.so}. To do this, use {@code __system_property_get} + with the following include: + <pre> #include <sys/system_properties.h> </pre> + <p class="note"> + <strong>Note:</strong> The availability and contents of system properties is + not tested through CTS. A better fix would be to avoid using these + properties altogether. + </p> </li> - <li>Use of {@code SSL_ctrl} symbol from {@code libcrypto.so} should be - replaced with an app local version. For example, you should statically link - {@code libcyrpto.a} in your {@code .so} file or include your own dynamically - {@code libcrypto.so} from BoringSSL or OpenSSL in your app. + <li>Use a local version of the {@code SSL_ctrl} symbol from {@code + libcrypto.so}. For example, you should statically link {@code libcyrpto.a} in + your {@code .so} file, or include a dynamically linked version of {@code + libcrypto.so} from BoringSSL/OpenSSL and package it in your APK. </li> </ul> |