Loading docs/html/preview/behavior-changes.jd +273 −47 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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> Loading Loading
docs/html/preview/behavior-changes.jd +273 −47 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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> Loading