From b1ef62bb3834af6bdf8017e56b2cc614a566229e Mon Sep 17 00:00:00 2001 From: Dimitry Ivanov Date: Wed, 20 Apr 2016 14:09:32 -0700 Subject: [PATCH 1/2] Extract pathclassloader initialization to a separate class To be able to reuse this code when creating a classloader for the system_server. Bug: http://b/27245894 Bug: http://b/27702070 Change-Id: I928175a39a1beb0446d863a5b8f5edf94686e768 (cherry picked from commit 5d7d777fa6f47ade2097e77d3d9ddb52c26d77d6) --- core/java/android/app/ApplicationLoaders.java | 31 +++------- .../internal/os/PathClassLoaderFactory.java | 62 +++++++++++++++++++ core/jni/Android.mk | 2 +- core/jni/AndroidRuntime.cpp | 4 +- ...id_internal_os_PathClassLoaderFactory.cpp} | 6 +- 5 files changed, 78 insertions(+), 27 deletions(-) create mode 100644 core/java/com/android/internal/os/PathClassLoaderFactory.java rename core/jni/{android_app_ApplicationLoaders.cpp => com_android_internal_os_PathClassLoaderFactory.cpp} (85%) diff --git a/core/java/android/app/ApplicationLoaders.java b/core/java/android/app/ApplicationLoaders.java index 0fc097e2e7062..d89e1864f36fd 100644 --- a/core/java/android/app/ApplicationLoaders.java +++ b/core/java/android/app/ApplicationLoaders.java @@ -18,6 +18,7 @@ package android.app; import android.os.Trace; import android.util.ArrayMap; +import com.android.internal.os.PathClassLoaderFactory; import dalvik.system.PathClassLoader; class ApplicationLoaders { @@ -51,24 +52,19 @@ class ApplicationLoaders { if (loader != null) { return loader; } - + Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, zip); - PathClassLoader pathClassloader = - new PathClassLoader(zip, librarySearchPath, parent); + PathClassLoader pathClassloader = PathClassLoaderFactory.createClassLoader( + zip, + librarySearchPath, + libraryPermittedPath, + parent, + targetSdkVersion, + isBundled); - String errorMessage = createClassloaderNamespace(pathClassloader, - targetSdkVersion, - librarySearchPath, - libraryPermittedPath, - isBundled); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); - if (errorMessage != null) { - throw new UnsatisfiedLinkError("Unable to create namespace for the classloader " + - pathClassloader + ": " + errorMessage); - } - mLoaders.put(zip, pathClassloader); return pathClassloader; } @@ -80,12 +76,6 @@ class ApplicationLoaders { } } - private static native String createClassloaderNamespace(ClassLoader classLoader, - int targetSdkVersion, - String librarySearchPath, - String libraryPermittedPath, - boolean isShared); - /** * Adds a new path the classpath of the given loader. * @throws IllegalStateException if the provided class loader is not a {@link PathClassLoader}. @@ -100,6 +90,5 @@ class ApplicationLoaders { private final ArrayMap mLoaders = new ArrayMap(); - private static final ApplicationLoaders gApplicationLoaders - = new ApplicationLoaders(); + private static final ApplicationLoaders gApplicationLoaders = new ApplicationLoaders(); } diff --git a/core/java/com/android/internal/os/PathClassLoaderFactory.java b/core/java/com/android/internal/os/PathClassLoaderFactory.java new file mode 100644 index 0000000000000..e5d36940a628a --- /dev/null +++ b/core/java/com/android/internal/os/PathClassLoaderFactory.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.os; + +import dalvik.system.PathClassLoader; + +/** + * Creates path class loaders. + * + * @hide + */ +public class PathClassLoaderFactory { + // Unconstructable + private PathClassLoaderFactory() {} + + /** + * Create a PathClassLoader and initialize a linker-namespace for it. + * + * @hide + */ + public static PathClassLoader createClassLoader(String dexPath, + String librarySearchPath, + String libraryPermittedPath, + ClassLoader parent, + int targetSdkVersion, + boolean isNamespaceShared) { + PathClassLoader pathClassloader = new PathClassLoader(dexPath, librarySearchPath, parent); + + String errorMessage = createClassloaderNamespace(pathClassloader, + targetSdkVersion, + librarySearchPath, + libraryPermittedPath, + isNamespaceShared); + + if (errorMessage != null) { + throw new UnsatisfiedLinkError("Unable to create namespace for the classloader " + + pathClassloader + ": " + errorMessage); + } + + return pathClassloader; + } + + private static native String createClassloaderNamespace(ClassLoader classLoader, + int targetSdkVersion, + String librarySearchPath, + String libraryPermittedPath, + boolean isNamespaceShared); +} diff --git a/core/jni/Android.mk b/core/jni/Android.mk index 06d9b294d8484..986a5fd722fe4 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -34,7 +34,6 @@ LOCAL_SRC_FILES:= \ com_google_android_gles_jni_EGLImpl.cpp \ com_google_android_gles_jni_GLImpl.cpp.arm \ android_app_Activity.cpp \ - android_app_ApplicationLoaders.cpp \ android_app_NativeActivity.cpp \ android_app_admin_SecurityLog.cpp \ android_opengl_EGL14.cpp \ @@ -174,6 +173,7 @@ LOCAL_SRC_FILES:= \ android_content_res_Configuration.cpp \ android_animation_PropertyValuesHolder.cpp \ com_android_internal_net_NetworkStatsFactory.cpp \ + com_android_internal_os_PathClassLoaderFactory.cpp \ com_android_internal_os_Zygote.cpp \ com_android_internal_util_VirtualRefBasePtr.cpp \ com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index f889dd48a6ed8..c2273d6f80b64 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -179,7 +179,6 @@ extern int register_android_backup_BackupDataOutput(JNIEnv *env); extern int register_android_backup_FileBackupHelperBase(JNIEnv *env); extern int register_android_backup_BackupHelperDispatcher(JNIEnv *env); extern int register_android_app_backup_FullBackup(JNIEnv *env); -extern int register_android_app_ApplicationLoaders(JNIEnv* env); extern int register_android_app_Activity(JNIEnv *env); extern int register_android_app_ActivityThread(JNIEnv *env); extern int register_android_app_NativeActivity(JNIEnv *env); @@ -200,6 +199,7 @@ extern int register_android_content_res_Configuration(JNIEnv* env); extern int register_android_animation_PropertyValuesHolder(JNIEnv *env); extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env); extern int register_com_android_internal_net_NetworkStatsFactory(JNIEnv *env); +extern int register_com_android_internal_os_PathClassLoaderFactory(JNIEnv* env); extern int register_com_android_internal_os_Zygote(JNIEnv *env); extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv *env); @@ -1355,6 +1355,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_net_NetworkUtils), REG_JNI(register_android_net_TrafficStats), REG_JNI(register_android_os_MemoryFile), + REG_JNI(register_com_android_internal_os_PathClassLoaderFactory), REG_JNI(register_com_android_internal_os_Zygote), REG_JNI(register_com_android_internal_util_VirtualRefBasePtr), REG_JNI(register_android_hardware_Camera), @@ -1386,7 +1387,6 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_backup_FileBackupHelperBase), REG_JNI(register_android_backup_BackupHelperDispatcher), REG_JNI(register_android_app_backup_FullBackup), - REG_JNI(register_android_app_ApplicationLoaders), REG_JNI(register_android_app_Activity), REG_JNI(register_android_app_ActivityThread), REG_JNI(register_android_app_NativeActivity), diff --git a/core/jni/android_app_ApplicationLoaders.cpp b/core/jni/com_android_internal_os_PathClassLoaderFactory.cpp similarity index 85% rename from core/jni/android_app_ApplicationLoaders.cpp rename to core/jni/com_android_internal_os_PathClassLoaderFactory.cpp index 89f22eba0f306..a7a912cd0e05c 100644 --- a/core/jni/android_app_ApplicationLoaders.cpp +++ b/core/jni/com_android_internal_os_PathClassLoaderFactory.cpp @@ -39,13 +39,13 @@ static const JNINativeMethod g_methods[] = { reinterpret_cast(createClassloaderNamespace_native) }, }; -static const char* const kApplicationLoadersPathName = "android/app/ApplicationLoaders"; +static const char* const kPathClassLoaderFactoryPathName = "com/android/internal/os/PathClassLoaderFactory"; namespace android { -int register_android_app_ApplicationLoaders(JNIEnv* env) { - return RegisterMethodsOrDie(env, kApplicationLoadersPathName, g_methods, NELEM(g_methods)); +int register_com_android_internal_os_PathClassLoaderFactory(JNIEnv* env) { + return RegisterMethodsOrDie(env, kPathClassLoaderFactoryPathName, g_methods, NELEM(g_methods)); } } // namespace android From 89dad3360ea6ae2fa0c4eb70a760b8d6bcb98b82 Mon Sep 17 00:00:00 2001 From: Dimitry Ivanov Date: Wed, 20 Apr 2016 16:02:00 -0700 Subject: [PATCH 2/2] Create linker namespace for the system server classloader Bug: http://b/27702070 Change-Id: I12c9448e877202937cf558de75042bcb46f6a933 (cherry picked from commit eb5866d4b05b6c000385be4a536544e27ca13335) --- .../com/android/internal/os/ZygoteInit.java | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index 78b5d61d3f1a3..a4794a3e8291f 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -475,7 +475,9 @@ public class ZygoteInit { } else { ClassLoader cl = null; if (systemServerClasspath != null) { - cl = new PathClassLoader(systemServerClasspath, ClassLoader.getSystemClassLoader()); + cl = createSystemServerClassLoader(systemServerClasspath, + parsedArgs.targetSdkVersion); + Thread.currentThread().setContextClassLoader(cl); } @@ -488,6 +490,23 @@ public class ZygoteInit { /* should never reach here */ } + /** + * Creates a PathClassLoader for the system server. It also creates + * a shared namespace associated with the classloader to let it access + * platform-private native libraries. + */ + private static PathClassLoader createSystemServerClassLoader(String systemServerClasspath, + int targetSdkVersion) { + String librarySearchPath = System.getProperty("java.library.path"); + + return PathClassLoaderFactory.createClassLoader(systemServerClasspath, + librarySearchPath, + null /* libraryPermittedPath */, + ClassLoader.getSystemClassLoader(), + targetSdkVersion, + true /* isNamespaceShared */); + } + /** * Performs dex-opt on the elements of {@code classPath}, if needed. We * choose the instruction set of the current runtime.