| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.base.library_loader; | 5 package org.chromium.base.library_loader; |
| 6 | 6 |
| 7 import android.annotation.TargetApi; | 7 import android.annotation.TargetApi; |
| 8 import android.content.Context; | 8 import android.content.Context; |
| 9 import android.content.pm.ApplicationInfo; | 9 import android.content.pm.ApplicationInfo; |
| 10 import android.content.pm.PackageInfo; | 10 import android.content.pm.PackageInfo; |
| 11 import android.os.AsyncTask; | 11 import android.os.AsyncTask; |
| 12 import android.os.Build; | 12 import android.os.Build; |
| 13 import android.os.SystemClock; | 13 import android.os.SystemClock; |
| 14 import android.util.Log; | |
| 15 | 14 |
| 16 import org.chromium.base.CalledByNative; | 15 import org.chromium.base.CalledByNative; |
| 17 import org.chromium.base.CommandLine; | 16 import org.chromium.base.CommandLine; |
| 18 import org.chromium.base.JNINamespace; | 17 import org.chromium.base.JNINamespace; |
| 18 import org.chromium.base.Log; |
| 19 import org.chromium.base.PackageUtils; | 19 import org.chromium.base.PackageUtils; |
| 20 import org.chromium.base.TraceEvent; | 20 import org.chromium.base.TraceEvent; |
| 21 import org.chromium.base.VisibleForTesting; | |
| 22 import org.chromium.base.metrics.RecordHistogram; | 21 import org.chromium.base.metrics.RecordHistogram; |
| 23 | 22 |
| 23 import java.util.concurrent.atomic.AtomicBoolean; |
| 24 |
| 24 import javax.annotation.Nullable; | 25 import javax.annotation.Nullable; |
| 25 | 26 |
| 26 /** | 27 /** |
| 27 * This class provides functionality to load and register the native libraries. | 28 * This class provides functionality to load and register the native libraries. |
| 28 * Callers are allowed to separate loading the libraries from initializing them. | 29 * Callers are allowed to separate loading the libraries from initializing them. |
| 29 * This may be an advantage for Android Webview, where the libraries can be load
ed | 30 * This may be an advantage for Android Webview, where the libraries can be load
ed |
| 30 * by the zygote process, but then needs per process initialization after the | 31 * by the zygote process, but then needs per process initialization after the |
| 31 * application processes are forked from the zygote process. | 32 * application processes are forked from the zygote process. |
| 32 * | 33 * |
| 33 * The libraries may be loaded and initialized from any thread. Synchronization | 34 * The libraries may be loaded and initialized from any thread. Synchronization |
| 34 * primitives are used to ensure that overlapping requests from different | 35 * primitives are used to ensure that overlapping requests from different |
| 35 * threads are handled sequentially. | 36 * threads are handled sequentially. |
| 36 * | 37 * |
| 37 * See also base/android/library_loader/library_loader_hooks.cc, which contains | 38 * See also base/android/library_loader/library_loader_hooks.cc, which contains |
| 38 * the native counterpart to this class. | 39 * the native counterpart to this class. |
| 39 */ | 40 */ |
| 40 @JNINamespace("base::android") | 41 @JNINamespace("base::android") |
| 41 public class LibraryLoader { | 42 public class LibraryLoader { |
| 42 private static final String TAG = "LibraryLoader"; | 43 private static final String TAG = "cr.library_loader"; |
| 43 | 44 |
| 44 // Set to true to enable debug logs. | 45 // Set to true to enable debug logs. |
| 45 private static final boolean DEBUG = false; | 46 private static final boolean DEBUG = false; |
| 46 | 47 |
| 47 // Guards all access to the libraries | 48 // Guards all access to the libraries |
| 48 private static final Object sLock = new Object(); | 49 private static final Object sLock = new Object(); |
| 49 | 50 |
| 50 // The singleton instance of LibraryLoader. | 51 // The singleton instance of LibraryLoader. |
| 51 private static volatile LibraryLoader sInstance; | 52 private static volatile LibraryLoader sInstance; |
| 52 | 53 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 66 | 67 |
| 67 // One-way switches recording attempts to use Relro sharing in the browser. | 68 // One-way switches recording attempts to use Relro sharing in the browser. |
| 68 // The flags are used to report UMA stats later. | 69 // The flags are used to report UMA stats later. |
| 69 private boolean mIsUsingBrowserSharedRelros; | 70 private boolean mIsUsingBrowserSharedRelros; |
| 70 private boolean mLoadAtFixedAddressFailed; | 71 private boolean mLoadAtFixedAddressFailed; |
| 71 | 72 |
| 72 // One-way switch becomes true if the Chromium library was loaded from the | 73 // One-way switch becomes true if the Chromium library was loaded from the |
| 73 // APK file directly. | 74 // APK file directly. |
| 74 private boolean mLibraryWasLoadedFromApk; | 75 private boolean mLibraryWasLoadedFromApk; |
| 75 | 76 |
| 76 // One-way switch becomes false if the Chromium library should be loaded | |
| 77 // directly from the APK file but it was compressed or not aligned. | |
| 78 private boolean mLibraryIsMappableInApk = true; | |
| 79 | |
| 80 // The type of process the shared library is loaded in. | 77 // The type of process the shared library is loaded in. |
| 81 // This member can be accessed from multiple threads simultaneously, so it h
ave to be | 78 // This member can be accessed from multiple threads simultaneously, so it h
ave to be |
| 82 // final (like now) or be protected in some way (volatile of synchronized). | 79 // final (like now) or be protected in some way (volatile of synchronized). |
| 83 private final int mLibraryProcessType; | 80 private final int mLibraryProcessType; |
| 84 | 81 |
| 82 // One-way switch that becomes true once |
| 83 // {@link asyncPrefetchLibrariesToMemory} has been called. |
| 84 private final AtomicBoolean mPrefetchLibraryHasBeenCalled; |
| 85 |
| 86 // The number of milliseconds it took to load all the native libraries, whic
h |
| 87 // will be reported via UMA. Set once when the libraries are done loading. |
| 88 private long mLibraryLoadTimeMs; |
| 89 |
| 85 /** | 90 /** |
| 86 * @param libraryProcessType the process the shared library is loaded in. re
fer to | 91 * @param libraryProcessType the process the shared library is loaded in. re
fer to |
| 87 * LibraryProcessType for possible values. | 92 * LibraryProcessType for possible values. |
| 88 * @return LibraryLoader if existing, otherwise create a new one. | 93 * @return LibraryLoader if existing, otherwise create a new one. |
| 89 */ | 94 */ |
| 90 public static LibraryLoader get(int libraryProcessType) throws ProcessInitEx
ception { | 95 public static LibraryLoader get(int libraryProcessType) throws ProcessInitEx
ception { |
| 91 synchronized (sLock) { | 96 synchronized (sLock) { |
| 92 if (sInstance != null) { | 97 if (sInstance != null) { |
| 93 if (sInstance.mLibraryProcessType == libraryProcessType) return
sInstance; | 98 if (sInstance.mLibraryProcessType == libraryProcessType) return
sInstance; |
| 94 throw new ProcessInitException( | 99 throw new ProcessInitException( |
| 95 LoaderErrors.LOADER_ERROR_NATIVE_LIBRARY_LOAD_FAILED); | 100 LoaderErrors.LOADER_ERROR_NATIVE_LIBRARY_LOAD_FAILED); |
| 96 } | 101 } |
| 97 sInstance = new LibraryLoader(libraryProcessType); | 102 sInstance = new LibraryLoader(libraryProcessType); |
| 98 return sInstance; | 103 return sInstance; |
| 99 } | 104 } |
| 100 } | 105 } |
| 101 | 106 |
| 102 private LibraryLoader(int libraryProcessType) { | 107 private LibraryLoader(int libraryProcessType) { |
| 103 mLibraryProcessType = libraryProcessType; | 108 mLibraryProcessType = libraryProcessType; |
| 104 } | 109 mPrefetchLibraryHasBeenCalled = new AtomicBoolean(); |
| 105 | |
| 106 /** | |
| 107 * The same as ensureInitialized(null, false), should only be called | |
| 108 * by non-browser processes. | |
| 109 * | |
| 110 * @throws ProcessInitException | |
| 111 */ | |
| 112 @VisibleForTesting | |
| 113 public void ensureInitialized() throws ProcessInitException { | |
| 114 ensureInitialized(null, false); | |
| 115 } | 110 } |
| 116 | 111 |
| 117 /** | 112 /** |
| 118 * This method blocks until the library is fully loaded and initialized. | 113 * This method blocks until the library is fully loaded and initialized. |
| 119 * | 114 * |
| 120 * @param context The context in which the method is called, the caller | 115 * @param context The context in which the method is called. |
| 121 * may pass in a null context if it doesn't know in which context it | |
| 122 * is running. | |
| 123 * | |
| 124 * @param shouldDeleteFallbackLibraries The flag tells whether the method | |
| 125 * should delete the fallback libraries or not. | |
| 126 */ | 116 */ |
| 127 public void ensureInitialized( | 117 public void ensureInitialized(Context context) throws ProcessInitException { |
| 128 Context context, boolean shouldDeleteFallbackLibraries) | |
| 129 throws ProcessInitException { | |
| 130 synchronized (sLock) { | 118 synchronized (sLock) { |
| 131 if (mInitialized) { | 119 if (mInitialized) { |
| 132 // Already initialized, nothing to do. | 120 // Already initialized, nothing to do. |
| 133 return; | 121 return; |
| 134 } | 122 } |
| 135 loadAlreadyLocked(context, shouldDeleteFallbackLibraries); | 123 loadAlreadyLocked(context); |
| 136 initializeAlreadyLocked(); | 124 initializeAlreadyLocked(); |
| 137 } | 125 } |
| 138 } | 126 } |
| 139 | 127 |
| 140 /** | 128 /** |
| 141 * Checks if library is fully loaded and initialized. | 129 * Checks if library is fully loaded and initialized. |
| 142 */ | 130 */ |
| 143 public static boolean isInitialized() { | 131 public static boolean isInitialized() { |
| 144 return sInstance != null && sInstance.mInitialized; | 132 return sInstance != null && sInstance.mInitialized; |
| 145 } | 133 } |
| 146 | 134 |
| 147 /** | 135 /** |
| 148 * The same as loadNow(null, false), should only be called by | |
| 149 * non-browser process. | |
| 150 * | |
| 151 * @throws ProcessInitException | |
| 152 */ | |
| 153 public void loadNow() throws ProcessInitException { | |
| 154 loadNow(null, false); | |
| 155 } | |
| 156 | |
| 157 /** | |
| 158 * Loads the library and blocks until the load completes. The caller is resp
onsible | 136 * Loads the library and blocks until the load completes. The caller is resp
onsible |
| 159 * for subsequently calling ensureInitialized(). | 137 * for subsequently calling ensureInitialized(). |
| 160 * May be called on any thread, but should only be called once. Note the thr
ead | 138 * May be called on any thread, but should only be called once. Note the thr
ead |
| 161 * this is called on will be the thread that runs the native code's static i
nitializers. | 139 * this is called on will be the thread that runs the native code's static i
nitializers. |
| 162 * See the comment in doInBackground() for more considerations on this. | 140 * See the comment in doInBackground() for more considerations on this. |
| 163 * | 141 * |
| 164 * @param context The context the code is running, or null if it doesn't hav
e one. | 142 * @param context The context the code is running. |
| 165 * @param shouldDeleteFallbackLibraries The flag tells whether the method | |
| 166 * should delete the old fallback libraries or not. | |
| 167 * | 143 * |
| 168 * @throws ProcessInitException if the native library failed to load. | 144 * @throws ProcessInitException if the native library failed to load. |
| 169 */ | 145 */ |
| 170 public void loadNow(Context context, boolean shouldDeleteFallbackLibraries) | 146 public void loadNow(Context context) throws ProcessInitException { |
| 171 throws ProcessInitException { | |
| 172 synchronized (sLock) { | 147 synchronized (sLock) { |
| 173 loadAlreadyLocked(context, shouldDeleteFallbackLibraries); | 148 loadAlreadyLocked(context); |
| 174 } | 149 } |
| 175 } | 150 } |
| 176 | 151 |
| 177 /** | 152 /** |
| 178 * initializes the library here and now: must be called on the thread that t
he | 153 * initializes the library here and now: must be called on the thread that t
he |
| 179 * native will call its "main" thread. The library must have previously been | 154 * native will call its "main" thread. The library must have previously been |
| 180 * loaded with loadNow. | 155 * loaded with loadNow. |
| 181 */ | 156 */ |
| 182 public void initialize() throws ProcessInitException { | 157 public void initialize() throws ProcessInitException { |
| 183 synchronized (sLock) { | 158 synchronized (sLock) { |
| 184 initializeAlreadyLocked(); | 159 initializeAlreadyLocked(); |
| 185 } | 160 } |
| 186 } | 161 } |
| 187 | 162 |
| 188 /** Prefetches the native libraries in a background thread. | 163 /** Prefetches the native libraries in a background thread. |
| 189 * | 164 * |
| 190 * Launches an AsyncTask that, through a short-lived forked process, reads a | 165 * Launches an AsyncTask that, through a short-lived forked process, reads a |
| 191 * part of each page of the native library. This is done to warm up the | 166 * part of each page of the native library. This is done to warm up the |
| 192 * page cache, turning hard page faults into soft ones. | 167 * page cache, turning hard page faults into soft ones. |
| 193 * | 168 * |
| 194 * This is done this way, as testing shows that fadvise(FADV_WILLNEED) is | 169 * This is done this way, as testing shows that fadvise(FADV_WILLNEED) is |
| 195 * detrimental to the startup time. | 170 * detrimental to the startup time. |
| 196 * | |
| 197 * @param context the application context. | |
| 198 */ | 171 */ |
| 199 public void asyncPrefetchLibrariesToMemory(final Context context) { | 172 public void asyncPrefetchLibrariesToMemory() { |
| 173 if (!mPrefetchLibraryHasBeenCalled.compareAndSet(false, true)) return; |
| 200 new AsyncTask<Void, Void, Void>() { | 174 new AsyncTask<Void, Void, Void>() { |
| 201 @Override | 175 @Override |
| 202 protected Void doInBackground(Void... params) { | 176 protected Void doInBackground(Void... params) { |
| 203 TraceEvent.begin("LibraryLoader.asyncPrefetchLibrariesToMemory")
; | 177 TraceEvent.begin("LibraryLoader.asyncPrefetchLibrariesToMemory")
; |
| 204 boolean success = nativeForkAndPrefetchNativeLibrary(); | 178 boolean success = nativeForkAndPrefetchNativeLibrary(); |
| 205 if (!success) { | 179 if (!success) { |
| 206 Log.w(TAG, "Forking a process to prefetch the native library
failed."); | 180 Log.w(TAG, "Forking a process to prefetch the native library
failed."); |
| 207 } | 181 } |
| 208 RecordHistogram.recordBooleanHistogram("LibraryLoader.PrefetchSt
atus", success); | 182 RecordHistogram.recordBooleanHistogram("LibraryLoader.PrefetchSt
atus", success); |
| 209 TraceEvent.end("LibraryLoader.asyncPrefetchLibrariesToMemory"); | 183 TraceEvent.end("LibraryLoader.asyncPrefetchLibrariesToMemory"); |
| 210 return null; | 184 return null; |
| 211 } | 185 } |
| 212 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); | 186 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); |
| 213 } | 187 } |
| 214 | 188 |
| 215 // Invoke System.loadLibrary(...), triggering JNI_OnLoad in native code | 189 // Invoke System.loadLibrary(...), triggering JNI_OnLoad in native code |
| 216 private void loadAlreadyLocked( | 190 private void loadAlreadyLocked(Context context) throws ProcessInitException
{ |
| 217 Context context, boolean shouldDeleteFallbackLibraries) | |
| 218 throws ProcessInitException { | |
| 219 try { | 191 try { |
| 220 if (!mLoaded) { | 192 if (!mLoaded) { |
| 221 assert !mInitialized; | 193 assert !mInitialized; |
| 222 | 194 |
| 223 long startTime = SystemClock.uptimeMillis(); | 195 long startTime = SystemClock.uptimeMillis(); |
| 224 boolean useChromiumLinker = Linker.isUsed(); | 196 Linker linker = Linker.getInstance(); |
| 225 boolean fallbackWasUsed = false; | 197 boolean useChromiumLinker = linker.isUsed(); |
| 226 | 198 |
| 227 if (useChromiumLinker) { | 199 if (useChromiumLinker) { |
| 228 // Determine the APK file path. | 200 // Determine the APK file path. |
| 229 String apkFilePath = null; | 201 String apkFilePath = getLibraryApkPath(context); |
| 230 if (context != null) { | |
| 231 apkFilePath = getLibraryApkPath(context); | |
| 232 } else { | |
| 233 Log.w(TAG, "could not check load from APK support due to
null context"); | |
| 234 } | |
| 235 | |
| 236 // Load libraries using the Chromium linker. | 202 // Load libraries using the Chromium linker. |
| 237 Linker.prepareLibraryLoad(); | 203 linker.prepareLibraryLoad(); |
| 238 | 204 |
| 239 for (String library : NativeLibraries.LIBRARIES) { | 205 for (String library : NativeLibraries.LIBRARIES) { |
| 240 // Don't self-load the linker. This is because the build
system is | 206 // Don't self-load the linker. This is because the build
system is |
| 241 // not clever enough to understand that all the librarie
s packaged | 207 // not clever enough to understand that all the librarie
s packaged |
| 242 // in the final .apk don't need to be explicitly loaded. | 208 // in the final .apk don't need to be explicitly loaded. |
| 243 if (Linker.isChromiumLinkerLibrary(library)) { | 209 if (linker.isChromiumLinkerLibrary(library)) { |
| 244 if (DEBUG) Log.i(TAG, "ignoring self-linker load"); | 210 if (DEBUG) Log.i(TAG, "ignoring self-linker load"); |
| 245 continue; | 211 continue; |
| 246 } | 212 } |
| 247 | 213 |
| 248 // Determine where the library should be loaded from. | 214 // Determine where the library should be loaded from. |
| 249 String zipFilePath = null; | 215 String zipFilePath = null; |
| 250 String libFilePath = System.mapLibraryName(library); | 216 String libFilePath = System.mapLibraryName(library); |
| 251 if (apkFilePath != null && Linker.isInZipFile()) { | 217 if (linker.isInZipFile()) { |
| 252 // The library is in the APK file. | 218 // Load directly from the APK. |
| 253 if (!Linker.checkLibraryIsMappableInApk(apkFilePath,
libFilePath)) { | 219 zipFilePath = apkFilePath; |
| 254 mLibraryIsMappableInApk = false; | 220 Log.i(TAG, |
| 255 } | 221 "Loading " + library + " directly from withi
n " + apkFilePath); |
| 256 if (mLibraryIsMappableInApk) { | |
| 257 // Load directly from the APK. | |
| 258 zipFilePath = apkFilePath; | |
| 259 Log.i(TAG, "Loading " + library + " directly fro
m within " | |
| 260 + apkFilePath); | |
| 261 } else { | |
| 262 // Unpack library fallback. | |
| 263 Log.i(TAG, "Loading " + library | |
| 264 + " using unpack library fallback from w
ithin " | |
| 265 + apkFilePath); | |
| 266 libFilePath = LibraryLoaderHelper.buildFallbackL
ibrary( | |
| 267 context, library); | |
| 268 fallbackWasUsed = true; | |
| 269 Log.i(TAG, "Built fallback library " + libFilePa
th); | |
| 270 } | |
| 271 } else { | 222 } else { |
| 272 // The library is in its own file. | 223 // The library is in its own file. |
| 273 Log.i(TAG, "Loading " + library); | 224 Log.i(TAG, "Loading " + library); |
| 274 } | 225 } |
| 275 | 226 |
| 276 // Load the library. | 227 // Load the library. |
| 277 boolean isLoaded = false; | 228 boolean isLoaded = false; |
| 278 if (Linker.isUsingBrowserSharedRelros()) { | 229 if (linker.isUsingBrowserSharedRelros()) { |
| 279 mIsUsingBrowserSharedRelros = true; | 230 mIsUsingBrowserSharedRelros = true; |
| 280 try { | 231 try { |
| 281 loadLibrary(zipFilePath, libFilePath); | 232 loadLibrary(zipFilePath, libFilePath); |
| 282 isLoaded = true; | 233 isLoaded = true; |
| 283 } catch (UnsatisfiedLinkError e) { | 234 } catch (UnsatisfiedLinkError e) { |
| 284 Log.w(TAG, "Failed to load native library with s
hared RELRO, " | 235 Log.w(TAG, "Failed to load native library with s
hared RELRO, " |
| 285 + "retrying without"); | 236 + "retrying without"); |
| 286 Linker.disableSharedRelros(); | 237 linker.disableSharedRelros(); |
| 287 mLoadAtFixedAddressFailed = true; | 238 mLoadAtFixedAddressFailed = true; |
| 288 } | 239 } |
| 289 } | 240 } |
| 290 if (!isLoaded) { | 241 if (!isLoaded) { |
| 291 loadLibrary(zipFilePath, libFilePath); | 242 loadLibrary(zipFilePath, libFilePath); |
| 292 } | 243 } |
| 293 } | 244 } |
| 294 | 245 |
| 295 Linker.finishLibraryLoad(); | 246 linker.finishLibraryLoad(); |
| 296 } else { | 247 } else { |
| 297 // Load libraries using the system linker. | 248 // Load libraries using the system linker. |
| 298 for (String library : NativeLibraries.LIBRARIES) { | 249 for (String library : NativeLibraries.LIBRARIES) { |
| 299 System.loadLibrary(library); | 250 System.loadLibrary(library); |
| 300 } | 251 } |
| 301 } | 252 } |
| 302 | 253 |
| 303 if (!fallbackWasUsed && context != null | |
| 304 && shouldDeleteFallbackLibraries) { | |
| 305 LibraryLoaderHelper.deleteLibrariesAsynchronously( | |
| 306 context, LibraryLoaderHelper.LOAD_FROM_APK_FALLBACK_
DIR); | |
| 307 } | |
| 308 | |
| 309 long stopTime = SystemClock.uptimeMillis(); | 254 long stopTime = SystemClock.uptimeMillis(); |
| 255 mLibraryLoadTimeMs = stopTime - startTime; |
| 310 Log.i(TAG, String.format("Time to load native libraries: %d ms (
timestamps %d-%d)", | 256 Log.i(TAG, String.format("Time to load native libraries: %d ms (
timestamps %d-%d)", |
| 311 stopTime - startTime, | 257 mLibraryLoadTimeMs, startTime % 10000, stopTi
me % 10000)); |
| 312 startTime % 10000, | |
| 313 stopTime % 10000)); | |
| 314 | 258 |
| 315 mLoaded = true; | 259 mLoaded = true; |
| 316 } | 260 } |
| 317 } catch (UnsatisfiedLinkError e) { | 261 } catch (UnsatisfiedLinkError e) { |
| 318 throw new ProcessInitException(LoaderErrors.LOADER_ERROR_NATIVE_LIBR
ARY_LOAD_FAILED, e); | 262 throw new ProcessInitException(LoaderErrors.LOADER_ERROR_NATIVE_LIBR
ARY_LOAD_FAILED, e); |
| 319 } | 263 } |
| 320 // Check that the version of the library we have loaded matches the vers
ion we expect | 264 // Check that the version of the library we have loaded matches the vers
ion we expect |
| 321 Log.i(TAG, String.format( | 265 Log.i(TAG, String.format("Expected native library version number \"%s\",
" |
| 322 "Expected native library version number \"%s\"," | 266 + "actual native library version number \"%s\
"", |
| 323 + "actual native library version number \"%s\"", | 267 NativeLibraries.sVersionNumber, nativeGetVersionNumbe
r())); |
| 324 NativeLibraries.sVersionNumber, | |
| 325 nativeGetVersionNumber())); | |
| 326 if (!NativeLibraries.sVersionNumber.equals(nativeGetVersionNumber())) { | 268 if (!NativeLibraries.sVersionNumber.equals(nativeGetVersionNumber())) { |
| 327 throw new ProcessInitException(LoaderErrors.LOADER_ERROR_NATIVE_LIBR
ARY_WRONG_VERSION); | 269 throw new ProcessInitException(LoaderErrors.LOADER_ERROR_NATIVE_LIBR
ARY_WRONG_VERSION); |
| 328 } | 270 } |
| 329 } | 271 } |
| 330 | 272 |
| 331 // Returns whether the given split name is that of the ABI split. | 273 // Returns whether the given split name is that of the ABI split. |
| 332 private static boolean isAbiSplit(String splitName) { | 274 private static boolean isAbiSplit(String splitName) { |
| 333 // The split name for the ABI split is manually set in the build rules. | 275 // The split name for the ABI split is manually set in the build rules. |
| 334 return splitName.startsWith("abi_"); | 276 return splitName.startsWith("abi_"); |
| 335 } | 277 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 349 return appInfo.splitSourceDirs[i]; | 291 return appInfo.splitSourceDirs[i]; |
| 350 } | 292 } |
| 351 } | 293 } |
| 352 } | 294 } |
| 353 return appInfo.sourceDir; | 295 return appInfo.sourceDir; |
| 354 } | 296 } |
| 355 | 297 |
| 356 // Load a native shared library with the Chromium linker. If the zip file | 298 // Load a native shared library with the Chromium linker. If the zip file |
| 357 // path is not null, the library is loaded directly from the zip file. | 299 // path is not null, the library is loaded directly from the zip file. |
| 358 private void loadLibrary(@Nullable String zipFilePath, String libFilePath) { | 300 private void loadLibrary(@Nullable String zipFilePath, String libFilePath) { |
| 359 Linker.loadLibrary(zipFilePath, libFilePath); | 301 Linker.getInstance().loadLibrary(zipFilePath, libFilePath); |
| 360 if (zipFilePath != null) { | 302 if (zipFilePath != null) { |
| 361 mLibraryWasLoadedFromApk = true; | 303 mLibraryWasLoadedFromApk = true; |
| 362 } | 304 } |
| 363 } | 305 } |
| 364 | 306 |
| 365 // The WebView requires the Command Line to be switched over before | 307 // The WebView requires the Command Line to be switched over before |
| 366 // initialization is done. This is okay in the WebView's case since the | 308 // initialization is done. This is okay in the WebView's case since the |
| 367 // JNI is already loaded by this point. | 309 // JNI is already loaded by this point. |
| 368 public void switchCommandLineForWebView() { | 310 public void switchCommandLineForWebView() { |
| 369 synchronized (sLock) { | 311 synchronized (sLock) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 419 } | 361 } |
| 420 | 362 |
| 421 // Called after all native initializations are complete. | 363 // Called after all native initializations are complete. |
| 422 public void onNativeInitializationComplete(Context context) { | 364 public void onNativeInitializationComplete(Context context) { |
| 423 recordBrowserProcessHistogram(context); | 365 recordBrowserProcessHistogram(context); |
| 424 } | 366 } |
| 425 | 367 |
| 426 // Record Chromium linker histogram state for the main browser process. Call
ed from | 368 // Record Chromium linker histogram state for the main browser process. Call
ed from |
| 427 // onNativeInitializationComplete(). | 369 // onNativeInitializationComplete(). |
| 428 private void recordBrowserProcessHistogram(Context context) { | 370 private void recordBrowserProcessHistogram(Context context) { |
| 429 if (Linker.isUsed()) { | 371 if (Linker.getInstance().isUsed()) { |
| 430 nativeRecordChromiumAndroidLinkerBrowserHistogram(mIsUsingBrowserSha
redRelros, | 372 nativeRecordChromiumAndroidLinkerBrowserHistogram(mIsUsingBrowserSha
redRelros, |
| 431 mLoadAtFixedAddres
sFailed, | 373 mLoadAtFixedAddressFailed, getLibraryLoadFromApkStatus(conte
xt), |
| 432 getLibraryLoadFrom
ApkStatus(context)); | 374 mLibraryLoadTimeMs); |
| 433 } | 375 } |
| 434 } | 376 } |
| 435 | 377 |
| 436 // Returns the device's status for loading a library directly from the APK f
ile. | 378 // Returns the device's status for loading a library directly from the APK f
ile. |
| 437 // This method can only be called when the Chromium linker is used. | 379 // This method can only be called when the Chromium linker is used. |
| 438 private int getLibraryLoadFromApkStatus(Context context) { | 380 private int getLibraryLoadFromApkStatus(Context context) { |
| 439 assert Linker.isUsed(); | 381 assert Linker.getInstance().isUsed(); |
| 440 | 382 |
| 441 if (mLibraryWasLoadedFromApk) { | 383 if (mLibraryWasLoadedFromApk) { |
| 442 return LibraryLoadFromApkStatusCodes.SUCCESSFUL; | 384 return LibraryLoadFromApkStatusCodes.SUCCESSFUL; |
| 443 } | 385 } |
| 444 | 386 |
| 445 if (!mLibraryIsMappableInApk) { | |
| 446 return LibraryLoadFromApkStatusCodes.USED_UNPACK_LIBRARY_FALLBACK; | |
| 447 } | |
| 448 | |
| 449 // There were no libraries to be loaded directly from the APK file. | 387 // There were no libraries to be loaded directly from the APK file. |
| 450 return LibraryLoadFromApkStatusCodes.UNKNOWN; | 388 return LibraryLoadFromApkStatusCodes.UNKNOWN; |
| 451 } | 389 } |
| 452 | 390 |
| 453 // Register pending Chromium linker histogram state for renderer processes.
This cannot be | 391 // Register pending Chromium linker histogram state for renderer processes.
This cannot be |
| 454 // recorded as a histogram immediately because histograms and IPC are not re
ady at the | 392 // recorded as a histogram immediately because histograms and IPC are not re
ady at the |
| 455 // time it are captured. This function stores a pending value, so that a lat
er call to | 393 // time it are captured. This function stores a pending value, so that a lat
er call to |
| 456 // RecordChromiumAndroidLinkerRendererHistogram() will record it correctly. | 394 // RecordChromiumAndroidLinkerRendererHistogram() will record it correctly. |
| 457 public void registerRendererProcessHistogram(boolean requestedSharedRelro, | 395 public void registerRendererProcessHistogram(boolean requestedSharedRelro, |
| 458 boolean loadAtFixedAddressFaile
d) { | 396 boolean loadAtFixedAddressFaile
d) { |
| 459 if (Linker.isUsed()) { | 397 if (Linker.getInstance().isUsed()) { |
| 460 nativeRegisterChromiumAndroidLinkerRendererHistogram(requestedShared
Relro, | 398 nativeRegisterChromiumAndroidLinkerRendererHistogram( |
| 461 loadAtFixedAddr
essFailed); | 399 requestedSharedRelro, loadAtFixedAddressFailed, mLibraryLoad
TimeMs); |
| 462 } | 400 } |
| 463 } | 401 } |
| 464 | 402 |
| 465 /** | 403 /** |
| 466 * @return the process the shared library is loaded in, see the LibraryProce
ssType | 404 * @return the process the shared library is loaded in, see the LibraryProce
ssType |
| 467 * for possible values. | 405 * for possible values. |
| 468 */ | 406 */ |
| 469 @CalledByNative | 407 @CalledByNative |
| 470 public static int getLibraryProcessType() { | 408 public static int getLibraryProcessType() { |
| 471 if (sInstance == null) return LibraryProcessType.PROCESS_UNINITIALIZED; | 409 if (sInstance == null) return LibraryProcessType.PROCESS_UNINITIALIZED; |
| 472 return sInstance.mLibraryProcessType; | 410 return sInstance.mLibraryProcessType; |
| 473 } | 411 } |
| 474 | 412 |
| 475 private native void nativeInitCommandLine(String[] initCommandLine); | 413 private native void nativeInitCommandLine(String[] initCommandLine); |
| 476 | 414 |
| 477 // Only methods needed before or during normal JNI registration are during S
ystem.OnLoad. | 415 // Only methods needed before or during normal JNI registration are during S
ystem.OnLoad. |
| 478 // nativeLibraryLoaded is then called to register everything else. This pro
cess is called | 416 // nativeLibraryLoaded is then called to register everything else. This pro
cess is called |
| 479 // "initialization". This method will be mapped (by generated code) to the
LibraryLoaded | 417 // "initialization". This method will be mapped (by generated code) to the
LibraryLoaded |
| 480 // definition in base/android/library_loader/library_loader_hooks.cc. | 418 // definition in base/android/library_loader/library_loader_hooks.cc. |
| 481 // | 419 // |
| 482 // Return true on success and false on failure. | 420 // Return true on success and false on failure. |
| 483 private native boolean nativeLibraryLoaded(); | 421 private native boolean nativeLibraryLoaded(); |
| 484 | 422 |
| 485 // Method called to record statistics about the Chromium linker operation fo
r the main | 423 // Method called to record statistics about the Chromium linker operation fo
r the main |
| 486 // browser process. Indicates whether the linker attempted relro sharing for
the browser, | 424 // browser process. Indicates whether the linker attempted relro sharing for
the browser, |
| 487 // and if it did, whether the library failed to load at a fixed address. Als
o records | 425 // and if it did, whether the library failed to load at a fixed address. Als
o records |
| 488 // support for loading a library directly from the APK file. | 426 // support for loading a library directly from the APK file, and the number
of milliseconds |
| 427 // it took to load the libraries. |
| 489 private native void nativeRecordChromiumAndroidLinkerBrowserHistogram( | 428 private native void nativeRecordChromiumAndroidLinkerBrowserHistogram( |
| 490 boolean isUsingBrowserSharedRelros, | 429 boolean isUsingBrowserSharedRelros, boolean loadAtFixedAddressFailed
, |
| 491 boolean loadAtFixedAddressFailed, | 430 int libraryLoadFromApkStatus, long libraryLoadTime); |
| 492 int libraryLoadFromApkStatus); | |
| 493 | 431 |
| 494 // Method called to register (for later recording) statistics about the Chro
mium linker | 432 // Method called to register (for later recording) statistics about the Chro
mium linker |
| 495 // operation for a renderer process. Indicates whether the linker attempted
relro sharing, | 433 // operation for a renderer process. Indicates whether the linker attempted
relro sharing, |
| 496 // and if it did, whether the library failed to load at a fixed address. | 434 // and if it did, whether the library failed to load at a fixed address. Als
o records the |
| 435 // number of milliseconds it took to load the libraries. |
| 497 private native void nativeRegisterChromiumAndroidLinkerRendererHistogram( | 436 private native void nativeRegisterChromiumAndroidLinkerRendererHistogram( |
| 498 boolean requestedSharedRelro, | 437 boolean requestedSharedRelro, boolean loadAtFixedAddressFailed, long
libraryLoadTime); |
| 499 boolean loadAtFixedAddressFailed); | |
| 500 | 438 |
| 501 // Get the version of the native library. This is needed so that we can chec
k we | 439 // Get the version of the native library. This is needed so that we can chec
k we |
| 502 // have the right version before initializing the (rest of the) JNI. | 440 // have the right version before initializing the (rest of the) JNI. |
| 503 private native String nativeGetVersionNumber(); | 441 private native String nativeGetVersionNumber(); |
| 504 | 442 |
| 505 // Finds the ranges corresponding to the native library pages, forks a new | 443 // Finds the ranges corresponding to the native library pages, forks a new |
| 506 // process to prefetch these pages and waits for it. The new process then | 444 // process to prefetch these pages and waits for it. The new process then |
| 507 // terminates. This is blocking. | 445 // terminates. This is blocking. |
| 508 private static native boolean nativeForkAndPrefetchNativeLibrary(); | 446 private static native boolean nativeForkAndPrefetchNativeLibrary(); |
| 509 } | 447 } |
| OLD | NEW |