Merge "Use nativeloader to load NativeActivity"

This commit is contained in:
Dimitry Ivanov
2015-12-11 20:30:32 +00:00
committed by Gerrit Code Review
5 changed files with 55 additions and 34 deletions

View File

@@ -27,7 +27,8 @@ class ApplicationLoaders
return gApplicationLoaders; 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 * 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); Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, zip);
PathClassLoader pathClassloader = PathClassLoader pathClassloader =
new PathClassLoader(zip, libPath, parent); new PathClassLoader(zip, librarySearchPath, libraryPermittedPath, parent);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
mLoaders.put(zip, pathClassloader); mLoaders.put(zip, pathClassloader);

View File

@@ -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 * With all the combination done (if necessary, actually
@@ -367,14 +375,17 @@ public final class LoadedApk {
*/ */
if (ActivityThread.localLOGV) 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 // Temporarily disable logging of disk reads on the Looper thread
// as this is early and necessary. // as this is early and necessary.
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip, lib, String libraryPermittedPath = mAppDir + File.pathSeparator + mDataDir;
mBaseClassLoader);
mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip, librarySearchPath,
libraryPermittedPath, mBaseClassLoader);
StrictMode.setThreadPolicy(oldPolicy); StrictMode.setThreadPolicy(oldPolicy);
} else { } else {

View File

@@ -35,6 +35,8 @@ import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.WindowManager; import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import dalvik.system.BaseDexClassLoader;
import java.io.File; 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, private native long loadNativeCode(String path, String funcname, MessageQueue queue,
String internalDataPath, String obbPath, String externalDataPath, int sdkVersion, 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 unloadNativeCode(long handle);
private native void onStartNative(long handle); private native void onStartNative(long handle);
private native void onResumeNative(long handle); private native void onResumeNative(long handle);
@@ -158,13 +162,8 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback2,
throw new RuntimeException("Error getting activity info", e); throw new RuntimeException("Error getting activity info", e);
} }
String path = null; BaseDexClassLoader classLoader = (BaseDexClassLoader) getClassLoader();
String path = classLoader.findLibrary(libname);
File libraryFile = new File(ai.applicationInfo.nativeLibraryDir,
System.mapLibraryName(libname));
if (libraryFile.exists()) {
path = libraryFile.getPath();
}
if (path == null) { if (path == null) {
throw new IllegalArgumentException("Unable to find native library: " + libname); 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(), mNativeHandle = loadNativeCode(path, funcname, Looper.myQueue(),
getAbsolutePath(getFilesDir()), getAbsolutePath(getObbDir()), getAbsolutePath(getFilesDir()), getAbsolutePath(getObbDir()),
getAbsolutePath(getExternalFilesDir(null)), getAbsolutePath(getExternalFilesDir(null)),
Build.VERSION.SDK_INT, getAssets(), nativeSavedState); Build.VERSION.SDK_INT, getAssets(), nativeSavedState,
classLoader, classLoader.getLdLibraryPath(),
classLoader.getLibraryPermittedPath());
if (mNativeHandle == 0) { 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); super.onCreate(savedInstanceState);
} }

View File

@@ -251,7 +251,8 @@ LOCAL_SHARED_LIBRARIES := \
libminikin \ libminikin \
libprocessgroup \ libprocessgroup \
libnativebridge \ libnativebridge \
libradio_metadata libradio_metadata \
libnativeloader
LOCAL_SHARED_LIBRARIES += \ LOCAL_SHARED_LIBRARIES += \
libhwui \ libhwui \

View File

@@ -21,6 +21,8 @@
#include <dlfcn.h> #include <dlfcn.h>
#include <fcntl.h> #include <fcntl.h>
#include <memory>
#include <android_runtime/android_app_NativeActivity.h> #include <android_runtime/android_app_NativeActivity.h>
#include <android_runtime/android_util_AssetManager.h> #include <android_runtime/android_util_AssetManager.h>
#include <android_runtime/android_view_Surface.h> #include <android_runtime/android_view_Surface.h>
@@ -39,6 +41,7 @@
#include "android_view_KeyEvent.h" #include "android_view_KeyEvent.h"
#include "nativebridge/native_bridge.h" #include "nativebridge/native_bridge.h"
#include "nativeloader/native_loader.h"
#include "core_jni_helpers.h" #include "core_jni_helpers.h"
@@ -255,18 +258,19 @@ static int mainWorkCallback(int fd, int events, void* data) {
static jlong static jlong
loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName, loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName,
jobject messageQueue, jstring internalDataDir, jstring obbDir, jobject messageQueue, jstring internalDataDir, jstring obbDir,
jstring externalDataDir, jint sdkVersion, jstring externalDataDir, jint sdkVersion, jobject jAssetMgr,
jobject jAssetMgr, jbyteArray savedState) jbyteArray savedState, jobject classLoader, jstring libraryPath,
{ jstring isolationPath) {
if (kLogTrace) { if (kLogTrace) {
ALOGD("loadNativeCode_native"); ALOGD("loadNativeCode_native");
} }
const char* pathStr = env->GetStringUTFChars(path, NULL); const char* pathStr = env->GetStringUTFChars(path, NULL);
NativeCode* code = NULL; std::unique_ptr<NativeCode> code;
bool needNativeBridge = false; bool needNativeBridge = false;
void* handle = dlopen(pathStr, RTLD_LAZY); void* handle = OpenNativeLibrary(env, sdkVersion, pathStr, classLoader,
libraryPath, isolationPath);
if (handle == NULL) { if (handle == NULL) {
if (NativeBridgeIsSupported(pathStr)) { if (NativeBridgeIsSupported(pathStr)) {
handle = NativeBridgeLoadLibrary(pathStr, RTLD_LAZY); handle = NativeBridgeLoadLibrary(pathStr, RTLD_LAZY);
@@ -284,26 +288,23 @@ loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName
funcPtr = dlsym(handle, funcStr); funcPtr = dlsym(handle, funcStr);
} }
code = new NativeCode(handle, (ANativeActivity_createFunc*)funcPtr); code.reset(new NativeCode(handle, (ANativeActivity_createFunc*)funcPtr));
env->ReleaseStringUTFChars(funcName, funcStr); env->ReleaseStringUTFChars(funcName, funcStr);
if (code->createActivityFunc == NULL) { if (code->createActivityFunc == NULL) {
ALOGW("ANativeActivity_onCreate not found"); ALOGW("ANativeActivity_onCreate not found");
delete code;
return 0; return 0;
} }
code->messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueue); code->messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueue);
if (code->messageQueue == NULL) { if (code->messageQueue == NULL) {
ALOGW("Unable to retrieve native MessageQueue"); ALOGW("Unable to retrieve native MessageQueue");
delete code;
return 0; return 0;
} }
int msgpipe[2]; int msgpipe[2];
if (pipe(msgpipe)) { if (pipe(msgpipe)) {
ALOGW("could not create pipe: %s", strerror(errno)); ALOGW("could not create pipe: %s", strerror(errno));
delete code;
return 0; return 0;
} }
code->mainWorkRead = msgpipe[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 " SLOGW_IF(result != 0, "Could not make main work write pipe "
"non-blocking: %s", strerror(errno)); "non-blocking: %s", strerror(errno));
code->messageQueue->getLooper()->addFd( 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; code->ANativeActivity::callbacks = &code->callbacks;
if (env->GetJavaVM(&code->vm) < 0) { if (env->GetJavaVM(&code->vm) < 0) {
ALOGW("NativeActivity GetJavaVM failed"); ALOGW("NativeActivity GetJavaVM failed");
delete code;
return 0; return 0;
} }
code->env = env; code->env = env;
@@ -356,14 +356,18 @@ loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName
rawSavedSize = env->GetArrayLength(savedState); rawSavedSize = env->GetArrayLength(savedState);
} }
code->createActivityFunc(code, rawSavedState, rawSavedSize); code->createActivityFunc(code.get(), rawSavedState, rawSavedSize);
if (rawSavedState != NULL) { if (rawSavedState != NULL) {
env->ReleaseByteArrayElements(savedState, rawSavedState, 0); 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 static void
@@ -651,8 +655,10 @@ onContentRectChanged_native(JNIEnv* env, jobject clazz, jlong handle,
} }
static const JNINativeMethod g_methods[] = { 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", { "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 }, (void*)loadNativeCode_native },
{ "getDlError", "()Ljava/lang/String;", (void*) getDlError_native },
{ "unloadNativeCode", "(J)V", (void*)unloadNativeCode_native }, { "unloadNativeCode", "(J)V", (void*)unloadNativeCode_native },
{ "onStartNative", "(J)V", (void*)onStart_native }, { "onStartNative", "(J)V", (void*)onStart_native },
{ "onResumeNative", "(J)V", (void*)onResume_native }, { "onResumeNative", "(J)V", (void*)onResume_native },