Use nativeloader to load NativeActivity

System apps are the exception and they can
access internal platform libraries (this
is needed for bundled apps to work correctly).

Also fix the way NativeActivity loads the native
library to correspond to the way BaseDexClassloader
does it.

Bug: http://b/22548808
Bub: http://b/25777936
Change-Id: Idc94cdded182ea2cb1cbebc76c336cc3394c7ebe
(cherry picked from commit 6f06ad7df1362e9e5b252689f452bdeee2e5af46)
diff --git a/core/java/android/app/ApplicationLoaders.java b/core/java/android/app/ApplicationLoaders.java
index 413c369..ddb2d46 100644
--- a/core/java/android/app/ApplicationLoaders.java
+++ b/core/java/android/app/ApplicationLoaders.java
@@ -27,7 +27,8 @@
         return gApplicationLoaders;
     }
 
-    public ClassLoader getClassLoader(String zip, String libPath, ClassLoader parent)
+    public ClassLoader getClassLoader(String zip, String librarySearchPath,
+                                      String libraryPermittedPath, ClassLoader parent)
     {
         /*
          * This is the parent we use if they pass "null" in.  In theory
@@ -55,7 +56,7 @@
     
                 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, zip);
                 PathClassLoader pathClassloader =
-                    new PathClassLoader(zip, libPath, parent);
+                    new PathClassLoader(zip, librarySearchPath, libraryPermittedPath, parent);
                 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
 
                 mLoaders.put(zip, pathClassloader);
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 891558f..7313fd1 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -366,7 +366,15 @@
                     }
                 }
 
-                final String lib = TextUtils.join(File.pathSeparator, libPaths);
+                if (mApplicationInfo.isSystemApp()) {
+                    // Add path to system libraries to libPaths;
+                    // Access to system libs should be limited
+                    // to bundled applications; this is why updated
+                    // system apps are not included.
+                    libPaths.add(System.getProperty("java.library.path"));
+                }
+
+                final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths);
 
                 /*
                  * With all the combination done (if necessary, actually
@@ -374,14 +382,17 @@
                  */
 
                 if (ActivityThread.localLOGV)
-                    Slog.v(ActivityThread.TAG, "Class path: " + zip + ", JNI path: " + lib);
+                    Slog.v(ActivityThread.TAG, "Class path: " + zip +
+                            ", JNI path: " + librarySearchPath);
 
                 // Temporarily disable logging of disk reads on the Looper thread
                 // as this is early and necessary.
                 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
 
-                mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip, lib,
-                        mBaseClassLoader);
+                String libraryPermittedPath = mAppDir + File.pathSeparator + mDataDir;
+
+                mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip, librarySearchPath,
+                        libraryPermittedPath, mBaseClassLoader);
 
                 StrictMode.setThreadPolicy(oldPolicy);
             } else {
diff --git a/core/java/android/app/NativeActivity.java b/core/java/android/app/NativeActivity.java
index 1370000..aa14cb5 100644
--- a/core/java/android/app/NativeActivity.java
+++ b/core/java/android/app/NativeActivity.java
@@ -35,6 +35,8 @@
 import android.view.WindowManager;
 import android.view.inputmethod.InputMethodManager;
 
+import dalvik.system.BaseDexClassLoader;
+
 import java.io.File;
 
 /**
@@ -93,7 +95,9 @@
     
     private native long loadNativeCode(String path, String funcname, MessageQueue queue,
             String internalDataPath, String obbPath, String externalDataPath, int sdkVersion,
-            AssetManager assetMgr, byte[] savedState);
+            AssetManager assetMgr, byte[] savedState, ClassLoader classLoader, String libraryPath,
+            String isolationPath);
+    private native String getDlError();
     private native void unloadNativeCode(long handle);
     private native void onStartNative(long handle);
     private native void onResumeNative(long handle);
@@ -157,15 +161,10 @@
         } catch (PackageManager.NameNotFoundException e) {
             throw new RuntimeException("Error getting activity info", e);
         }
-        
-        String path = null;
-        
-        File libraryFile = new File(ai.applicationInfo.nativeLibraryDir,
-                System.mapLibraryName(libname));
-        if (libraryFile.exists()) {
-            path = libraryFile.getPath();
-        }
-        
+
+        BaseDexClassLoader classLoader = (BaseDexClassLoader) getClassLoader();
+        String path = classLoader.findLibrary(libname);
+
         if (path == null) {
             throw new IllegalArgumentException("Unable to find native library: " + libname);
         }
@@ -176,10 +175,13 @@
         mNativeHandle = loadNativeCode(path, funcname, Looper.myQueue(),
                 getAbsolutePath(getFilesDir()), getAbsolutePath(getObbDir()),
                 getAbsolutePath(getExternalFilesDir(null)),
-                Build.VERSION.SDK_INT, getAssets(), nativeSavedState);
+                Build.VERSION.SDK_INT, getAssets(), nativeSavedState,
+                classLoader, classLoader.getLdLibraryPath(),
+                classLoader.getLibraryPermittedPath());
 
         if (mNativeHandle == 0) {
-            throw new IllegalArgumentException("Unable to load native library: " + path);
+            throw new UnsatisfiedLinkError(
+                    "Unable to load native library \"" + path + "\": " + getDlError());
         }
         super.onCreate(savedInstanceState);
     }
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index f1e7afb..bdbd096 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -250,7 +250,8 @@
     libminikin \
     libprocessgroup \
     libnativebridge \
-    libradio_metadata
+    libradio_metadata \
+    libnativeloader
 
 LOCAL_SHARED_LIBRARIES += \
     libhwui \
diff --git a/core/jni/android_app_NativeActivity.cpp b/core/jni/android_app_NativeActivity.cpp
index 95be3f2..6ecb3fb 100644
--- a/core/jni/android_app_NativeActivity.cpp
+++ b/core/jni/android_app_NativeActivity.cpp
@@ -21,6 +21,8 @@
 #include <dlfcn.h>
 #include <fcntl.h>
 
+#include <memory>
+
 #include <android_runtime/android_app_NativeActivity.h>
 #include <android_runtime/android_util_AssetManager.h>
 #include <android_runtime/android_view_Surface.h>
@@ -39,6 +41,7 @@
 #include "android_view_KeyEvent.h"
 
 #include "nativebridge/native_bridge.h"
+#include "nativeloader/native_loader.h"
 
 #include "core_jni_helpers.h"
 
@@ -255,18 +258,19 @@
 static jlong
 loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName,
         jobject messageQueue, jstring internalDataDir, jstring obbDir,
-        jstring externalDataDir, jint sdkVersion,
-        jobject jAssetMgr, jbyteArray savedState)
-{
+        jstring externalDataDir, jint sdkVersion, jobject jAssetMgr,
+        jbyteArray savedState, jobject classLoader, jstring libraryPath,
+        jstring isolationPath) {
     if (kLogTrace) {
         ALOGD("loadNativeCode_native");
     }
 
     const char* pathStr = env->GetStringUTFChars(path, NULL);
-    NativeCode* code = NULL;
+    std::unique_ptr<NativeCode> code;
     bool needNativeBridge = false;
 
-    void* handle = dlopen(pathStr, RTLD_LAZY);
+    void* handle = OpenNativeLibrary(env, sdkVersion, pathStr, classLoader,
+                                     libraryPath, isolationPath);
     if (handle == NULL) {
         if (NativeBridgeIsSupported(pathStr)) {
             handle = NativeBridgeLoadLibrary(pathStr, RTLD_LAZY);
@@ -284,26 +288,23 @@
             funcPtr = dlsym(handle, funcStr);
         }
 
-        code = new NativeCode(handle, (ANativeActivity_createFunc*)funcPtr);
+        code.reset(new NativeCode(handle, (ANativeActivity_createFunc*)funcPtr));
         env->ReleaseStringUTFChars(funcName, funcStr);
 
         if (code->createActivityFunc == NULL) {
             ALOGW("ANativeActivity_onCreate not found");
-            delete code;
             return 0;
         }
         
         code->messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueue);
         if (code->messageQueue == NULL) {
             ALOGW("Unable to retrieve native MessageQueue");
-            delete code;
             return 0;
         }
         
         int msgpipe[2];
         if (pipe(msgpipe)) {
             ALOGW("could not create pipe: %s", strerror(errno));
-            delete code;
             return 0;
         }
         code->mainWorkRead = msgpipe[0];
@@ -315,12 +316,11 @@
         SLOGW_IF(result != 0, "Could not make main work write pipe "
                 "non-blocking: %s", strerror(errno));
         code->messageQueue->getLooper()->addFd(
-                code->mainWorkRead, 0, ALOOPER_EVENT_INPUT, mainWorkCallback, code);
+                code->mainWorkRead, 0, ALOOPER_EVENT_INPUT, mainWorkCallback, code.get());
         
         code->ANativeActivity::callbacks = &code->callbacks;
         if (env->GetJavaVM(&code->vm) < 0) {
             ALOGW("NativeActivity GetJavaVM failed");
-            delete code;
             return 0;
         }
         code->env = env;
@@ -356,14 +356,18 @@
             rawSavedSize = env->GetArrayLength(savedState);
         }
 
-        code->createActivityFunc(code, rawSavedState, rawSavedSize);
+        code->createActivityFunc(code.get(), rawSavedState, rawSavedSize);
 
         if (rawSavedState != NULL) {
             env->ReleaseByteArrayElements(savedState, rawSavedState, 0);
         }
     }
     
-    return (jlong)code;
+    return (jlong)code.release();
+}
+
+static jstring getDlError_native(JNIEnv* env, jobject clazz) {
+  return env->NewStringUTF(dlerror());
 }
 
 static void
@@ -651,8 +655,10 @@
 }
 
 static const JNINativeMethod g_methods[] = {
-    { "loadNativeCode", "(Ljava/lang/String;Ljava/lang/String;Landroid/os/MessageQueue;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILandroid/content/res/AssetManager;[B)J",
-            (void*)loadNativeCode_native },
+    { "loadNativeCode",
+        "(Ljava/lang/String;Ljava/lang/String;Landroid/os/MessageQueue;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILandroid/content/res/AssetManager;[BLjava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/String;)J",
+        (void*)loadNativeCode_native },
+    { "getDlError", "()Ljava/lang/String;", (void*) getDlError_native },
     { "unloadNativeCode", "(J)V", (void*)unloadNativeCode_native },
     { "onStartNative", "(J)V", (void*)onStart_native },
     { "onResumeNative", "(J)V", (void*)onResume_native },