diff --git a/core/java/android/app/ApplicationLoaders.java b/core/java/android/app/ApplicationLoaders.java index 413c3699db088..ddb2d46eb1185 100644 --- a/core/java/android/app/ApplicationLoaders.java +++ b/core/java/android/app/ApplicationLoaders.java @@ -27,7 +27,8 @@ class ApplicationLoaders 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 @@ class ApplicationLoaders 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 c2bf28a931c8e..01209227273ee 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -359,7 +359,15 @@ public final class LoadedApk { } } - 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 @@ -367,14 +375,17 @@ public final class LoadedApk { */ 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 2e05edb2e7d9e..dcf1c8019d4fb 100644 --- a/core/java/android/app/NativeActivity.java +++ b/core/java/android/app/NativeActivity.java @@ -35,6 +35,8 @@ import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; +import dalvik.system.BaseDexClassLoader; + import java.io.File; /** @@ -93,7 +95,9 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback2, 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 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback2, } 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 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback2, 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 4c68e015e5311..86412926b3ce2 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -251,7 +251,8 @@ LOCAL_SHARED_LIBRARIES := \ 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 95be3f27b625a..6ecb3fb19f624 100644 --- a/core/jni/android_app_NativeActivity.cpp +++ b/core/jni/android_app_NativeActivity.cpp @@ -21,6 +21,8 @@ #include #include +#include + #include #include #include @@ -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 int mainWorkCallback(int fd, int events, void* data) { 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 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 @@ loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName 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 @@ loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName 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 @@ loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName 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 @@ onContentRectChanged_native(JNIEnv* env, jobject clazz, jlong handle, } 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 },