OSDN Git Service

Docs: Updated 'NDK Apps Linking to Platform Libraries'
authorAdarsh Fernando <adarshf@google.com>
Tue, 14 Jun 2016 03:33:27 +0000 (20:33 -0700)
committerAdarsh Fernando <adarshf@google.com>
Wed, 15 Jun 2016 03:33:16 +0000 (20:33 -0700)
- updated compatibility with future platform releases
- expanded on ways to dignose and debug

Bug: 29215157
Change-Id: Ie63d024eac9914d4553419c734132696fb94d7e5

docs/html/preview/behavior-changes.jd

index 66dce7a..acdc490 100644 (file)
@@ -370,70 +370,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 -&gt; GetJavaVM from &lt;jni.h&gt;
 AndroidRuntime::getJNIEnv -&gt; JavaVM::GetEnv or
@@ -441,18 +661,24 @@ JavaVM::AttachCurrentThread from &lt;jni.h&gt;.
 </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 &lt;sys/system_properties.h&gt;
 </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>