The Perils of Loading Native Libraries on Android

Hilal Alsibai
Nov 7, 2015 · 7 min read

Enter the Dreaded “UnsatisfiedLinkError”

Moreover, in certain instances some of the native libraries were loaded properly, but not all.

Idea #1 — User Devices are Running out of Space

Idea #2 — Native Libraries were not being included in Updates

Idea #3 — Debug the issue directly with a real user

[…] the issue was with Android’s PackageManager installation process.

Getting to a Solution

Context.getApplicationInfo().sourceDir;
The total number of UnsatisfiedLinkError exceptions thrown on a daily basis
Context.getPackageManager().getInstallerPackageName(packageName);

Introducing ReLinker

System.loadLibrary(“mylibrary”);
ReLinker.loadLibrary(context, “mylibrary”)

Finally done

Acknowledgements

/**
* Try to load a native library using a workaround of
* http://b/13216167.
*
* Workaround for b/13216167 was adapted from code in
* https://googleplex-android-review.git.corp.google.com/#/c/433061
*
* More details about http://b/13216167:
* PackageManager may fail to update shared library.
*
* Native library directory in an updated package is a symbolic link
* to a directory in /data/app-lib/<package name>, for example:
* /data/data/com.android.chrome/lib -> /data/app-lib/com.android.chrome[-1].
* When updating the application, the PackageManager create a new directory,
* e.g., /data/app-lib/com.android.chrome-2, and remove the old symlink and
* recreate one to the new directory. However, on some devices (e.g. Sony Xperia),
* the symlink was updated, but fails to extract new native libraries from
* the new apk.
+
* We make the following changes to alleviate the issue:
* 1) name the native library with apk version code, e.g.,
* libchrome.1750.136.so, 1750.136 is Chrome version number;
* 2) first try to load the library using System.loadLibrary,
* if that failed due to the library file was not found,
* search the named library in a /data/data/com.android.chrome/app_lib
* directory. Because of change 1), each version has a different native
* library name, so avoid mistakenly using the old native library.
*
* If named library is not in /data/data/com.android.chrome/app_lib directory,
* extract native libraries from apk and cache in the directory.
*
* This function doesn’t throw UnsatisfiedLinkError, the caller needs to
* check the return value.
*/

Keepsafe Engineering

Engineering problems at Keepsafe. Find open source projects at www.github.com/keepsafe.

Hilal Alsibai

Written by

Keepsafe Engineering

Engineering problems at Keepsafe. Find open source projects at www.github.com/keepsafe.