Merge "Use nativeloader to load NativeActivity"
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 \
|
||||||
|
|||||||
@@ -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 },
|
||||||
|
|||||||
Reference in New Issue
Block a user