Chromium Code Reviews| 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.content.Context; | 7 import android.content.Context; |
| 8 import android.os.AsyncTask; | 8 import android.os.AsyncTask; |
| 9 import android.os.SystemClock; | 9 import android.os.SystemClock; |
| 10 | 10 |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 122 } | 122 } |
| 123 } | 123 } |
| 124 | 124 |
| 125 private LibraryLoader(int libraryProcessType) { | 125 private LibraryLoader(int libraryProcessType) { |
| 126 mLibraryProcessType = libraryProcessType; | 126 mLibraryProcessType = libraryProcessType; |
| 127 mPrefetchLibraryHasBeenCalled = new AtomicBoolean(); | 127 mPrefetchLibraryHasBeenCalled = new AtomicBoolean(); |
| 128 } | 128 } |
| 129 | 129 |
| 130 /** | 130 /** |
| 131 * This method blocks until the library is fully loaded and initialized. | 131 * This method blocks until the library is fully loaded and initialized. |
| 132 * | |
| 133 * @param context The context in which the method is called. | |
| 134 */ | 132 */ |
| 135 public void ensureInitialized(Context context) throws ProcessInitException { | 133 public void ensureInitialized() throws ProcessInitException { |
| 136 // TODO(wnwen): Move this call appropriately down to the tests that need it. | |
| 137 ContextUtils.initApplicationContext(context.getApplicationContext()); | |
| 138 synchronized (sLock) { | 134 synchronized (sLock) { |
| 139 if (mInitialized) { | 135 if (mInitialized) { |
| 140 // Already initialized, nothing to do. | 136 // Already initialized, nothing to do. |
| 141 return; | 137 return; |
| 142 } | 138 } |
| 143 loadAlreadyLocked(context); | 139 loadAlreadyLocked(ContextUtils.getApplicationContext()); |
| 144 initializeAlreadyLocked(); | 140 initializeAlreadyLocked(); |
| 145 } | 141 } |
| 146 } | 142 } |
| 147 | 143 |
| 148 /** | 144 /** |
| 149 * Checks if library is fully loaded and initialized. | 145 * Checks if library is fully loaded and initialized. |
| 150 */ | 146 */ |
| 151 public static boolean isInitialized() { | 147 public static boolean isInitialized() { |
| 152 return sInstance != null && sInstance.mInitialized; | 148 return sInstance != null && sInstance.mInitialized; |
| 153 } | 149 } |
| 154 | 150 |
| 155 /** | 151 /** |
| 156 * Loads the library and blocks until the load completes. The caller is resp onsible | 152 * Loads the library and blocks until the load completes. The caller is resp onsible |
| 157 * for subsequently calling ensureInitialized(). | 153 * for subsequently calling ensureInitialized(). |
| 158 * May be called on any thread, but should only be called once. Note the thr ead | 154 * May be called on any thread, but should only be called once. Note the thr ead |
| 159 * this is called on will be the thread that runs the native code's static i nitializers. | 155 * this is called on will be the thread that runs the native code's static i nitializers. |
| 160 * See the comment in doInBackground() for more considerations on this. | 156 * See the comment in doInBackground() for more considerations on this. |
| 161 * | 157 * |
| 162 * @param context The context the code is running. | |
| 163 * | |
| 164 * @throws ProcessInitException if the native library failed to load. | 158 * @throws ProcessInitException if the native library failed to load. |
| 165 */ | 159 */ |
| 166 public void loadNow(Context context) throws ProcessInitException { | 160 public void loadNow() throws ProcessInitException { |
| 161 loadNowOverrideApplicationContext(ContextUtils.getApplicationContext()); | |
| 162 } | |
| 163 | |
| 164 /** | |
| 165 * Override kept for callers that need to load from a different app context. Do not use unless | |
| 166 * specifically required to load from another context that is not the curren t process's app | |
| 167 * context. | |
| 168 * | |
| 169 * @param appContext The overriding app context to be used to load libraries . | |
| 170 * @throws ProcessInitException if the native library failed to load with th is context. | |
| 171 */ | |
| 172 public void loadNowOverrideApplicationContext(Context appContext) throws Pro cessInitException { | |
| 173 if (mLoaded && appContext != ContextUtils.getApplicationContext()) { | |
|
Ted C
2016/09/28 17:27:46
should this be in the synchronized block since tha
Peter Wen
2016/09/29 18:41:38
Done. Thanks!
| |
| 174 throw new IllegalStateException("Duplicate attempt to load from alte rnate context."); | |
| 175 } | |
| 167 synchronized (sLock) { | 176 synchronized (sLock) { |
| 168 loadAlreadyLocked(context); | 177 loadAlreadyLocked(appContext); |
| 169 } | 178 } |
| 170 } | 179 } |
| 171 | 180 |
| 172 /** | 181 /** |
| 173 * initializes the library here and now: must be called on the thread that t he | 182 * initializes the library here and now: must be called on the thread that t he |
| 174 * native will call its "main" thread. The library must have previously been | 183 * native will call its "main" thread. The library must have previously been |
| 175 * loaded with loadNow. | 184 * loaded with loadNow. |
| 176 */ | 185 */ |
| 177 public void initialize() throws ProcessInitException { | 186 public void initialize() throws ProcessInitException { |
| 178 synchronized (sLock) { | 187 synchronized (sLock) { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 243 } | 252 } |
| 244 | 253 |
| 245 // Loaded successfully, so record if we loaded directly from an APK. | 254 // Loaded successfully, so record if we loaded directly from an APK. |
| 246 if (zipFilePath != null) { | 255 if (zipFilePath != null) { |
| 247 mLibraryWasLoadedFromApk = true; | 256 mLibraryWasLoadedFromApk = true; |
| 248 } | 257 } |
| 249 } | 258 } |
| 250 | 259 |
| 251 // Invoke either Linker.loadLibrary(...) or System.loadLibrary(...), trigger ing | 260 // Invoke either Linker.loadLibrary(...) or System.loadLibrary(...), trigger ing |
| 252 // JNI_OnLoad in native code | 261 // JNI_OnLoad in native code |
| 253 private void loadAlreadyLocked(Context context) throws ProcessInitException { | 262 private void loadAlreadyLocked(Context appContext) throws ProcessInitExcepti on { |
| 254 try { | 263 try { |
| 255 if (!mLoaded) { | 264 if (!mLoaded) { |
| 256 assert !mInitialized; | 265 assert !mInitialized; |
| 257 | 266 |
| 258 long startTime = SystemClock.uptimeMillis(); | 267 long startTime = SystemClock.uptimeMillis(); |
| 259 | 268 |
| 260 if (Linker.isUsed()) { | 269 if (Linker.isUsed()) { |
| 261 // Load libraries using the Chromium linker. | 270 // Load libraries using the Chromium linker. |
| 262 Linker linker = Linker.getInstance(); | 271 Linker linker = Linker.getInstance(); |
| 263 linker.prepareLibraryLoad(); | 272 linker.prepareLibraryLoad(); |
| 264 | 273 |
| 265 for (String library : NativeLibraries.LIBRARIES) { | 274 for (String library : NativeLibraries.LIBRARIES) { |
| 266 // Don't self-load the linker. This is because the build system is | 275 // Don't self-load the linker. This is because the build system is |
| 267 // not clever enough to understand that all the librarie s packaged | 276 // not clever enough to understand that all the librarie s packaged |
| 268 // in the final .apk don't need to be explicitly loaded. | 277 // in the final .apk don't need to be explicitly loaded. |
| 269 if (linker.isChromiumLinkerLibrary(library)) { | 278 if (linker.isChromiumLinkerLibrary(library)) { |
| 270 if (DEBUG) Log.i(TAG, "ignoring self-linker load"); | 279 if (DEBUG) Log.i(TAG, "ignoring self-linker load"); |
| 271 continue; | 280 continue; |
| 272 } | 281 } |
| 273 | 282 |
| 274 // Determine where the library should be loaded from. | 283 // Determine where the library should be loaded from. |
| 275 String zipFilePath = null; | 284 String zipFilePath = null; |
| 276 String libFilePath = System.mapLibraryName(library); | 285 String libFilePath = System.mapLibraryName(library); |
| 277 if (Linker.isInZipFile()) { | 286 if (Linker.isInZipFile()) { |
| 278 // Load directly from the APK. | 287 // Load directly from the APK. |
| 279 zipFilePath = context.getApplicationInfo().sourceDir ; | 288 zipFilePath = appContext.getApplicationInfo().source Dir; |
| 280 Log.i(TAG, "Loading " + library + " from within " + zipFilePath); | 289 Log.i(TAG, "Loading " + library + " from within " + zipFilePath); |
| 281 } else { | 290 } else { |
| 282 // The library is in its own file. | 291 // The library is in its own file. |
| 283 Log.i(TAG, "Loading " + library); | 292 Log.i(TAG, "Loading " + library); |
| 284 } | 293 } |
| 285 | 294 |
| 286 // Load the library using this Linker. May throw Unsatis fiedLinkError. | 295 // Load the library using this Linker. May throw Unsatis fiedLinkError. |
| 287 loadLibrary(linker, zipFilePath, libFilePath); | 296 loadLibrary(linker, zipFilePath, libFilePath); |
| 288 } | 297 } |
| 289 | 298 |
| 290 linker.finishLibraryLoad(); | 299 linker.finishLibraryLoad(); |
| 291 } else { | 300 } else { |
| 292 if (sLibraryPreloader != null) { | 301 if (sLibraryPreloader != null) { |
| 293 mLibraryPreloaderStatus = sLibraryPreloader.loadLibrary( context); | 302 mLibraryPreloaderStatus = sLibraryPreloader.loadLibrary( appContext); |
| 294 } | 303 } |
| 295 // Load libraries using the system linker. | 304 // Load libraries using the system linker. |
| 296 for (String library : NativeLibraries.LIBRARIES) { | 305 for (String library : NativeLibraries.LIBRARIES) { |
| 297 System.loadLibrary(library); | 306 System.loadLibrary(library); |
| 298 } | 307 } |
| 299 } | 308 } |
| 300 | 309 |
| 301 long stopTime = SystemClock.uptimeMillis(); | 310 long stopTime = SystemClock.uptimeMillis(); |
| 302 mLibraryLoadTimeMs = stopTime - startTime; | 311 mLibraryLoadTimeMs = stopTime - startTime; |
| 303 Log.i(TAG, String.format("Time to load native libraries: %d ms ( timestamps %d-%d)", | 312 Log.i(TAG, String.format("Time to load native libraries: %d ms ( timestamps %d-%d)", |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 371 | 380 |
| 372 // From this point on, native code is ready to use and checkIsReady() | 381 // From this point on, native code is ready to use and checkIsReady() |
| 373 // shouldn't complain from now on (and in fact, it's used by the | 382 // shouldn't complain from now on (and in fact, it's used by the |
| 374 // following calls). | 383 // following calls). |
| 375 // Note that this flag can be accessed asynchronously, so any initializa tion | 384 // Note that this flag can be accessed asynchronously, so any initializa tion |
| 376 // must be performed before. | 385 // must be performed before. |
| 377 mInitialized = true; | 386 mInitialized = true; |
| 378 } | 387 } |
| 379 | 388 |
| 380 // Called after all native initializations are complete. | 389 // Called after all native initializations are complete. |
| 381 public void onNativeInitializationComplete(Context context) { | 390 public void onNativeInitializationComplete() { |
| 382 recordBrowserProcessHistogram(context); | 391 recordBrowserProcessHistogram(); |
| 383 } | 392 } |
| 384 | 393 |
| 385 // Record Chromium linker histogram state for the main browser process. Call ed from | 394 // Record Chromium linker histogram state for the main browser process. Call ed from |
| 386 // onNativeInitializationComplete(). | 395 // onNativeInitializationComplete(). |
| 387 private void recordBrowserProcessHistogram(Context context) { | 396 private void recordBrowserProcessHistogram() { |
| 388 if (Linker.getInstance().isUsed()) { | 397 if (Linker.getInstance().isUsed()) { |
| 389 nativeRecordChromiumAndroidLinkerBrowserHistogram(mIsUsingBrowserSha redRelros, | 398 nativeRecordChromiumAndroidLinkerBrowserHistogram( |
| 390 mLoadAtFixedAddres sFailed, | 399 mIsUsingBrowserSharedRelros, |
| 391 getLibraryLoadFrom ApkStatus(context), | 400 mLoadAtFixedAddressFailed, |
| 392 mLibraryLoadTimeMs ); | 401 getLibraryLoadFromApkStatus(), |
| 402 mLibraryLoadTimeMs); | |
| 393 } | 403 } |
| 394 if (sLibraryPreloader != null) { | 404 if (sLibraryPreloader != null) { |
| 395 nativeRecordLibraryPreloaderBrowserHistogram(mLibraryPreloaderStatus ); | 405 nativeRecordLibraryPreloaderBrowserHistogram(mLibraryPreloaderStatus ); |
| 396 } | 406 } |
| 397 } | 407 } |
| 398 | 408 |
| 399 // Returns the device's status for loading a library directly from the APK f ile. | 409 // Returns the device's status for loading a library directly from the APK f ile. |
| 400 // This method can only be called when the Chromium linker is used. | 410 // This method can only be called when the Chromium linker is used. |
| 401 private int getLibraryLoadFromApkStatus(Context context) { | 411 private int getLibraryLoadFromApkStatus() { |
| 402 assert Linker.getInstance().isUsed(); | 412 assert Linker.getInstance().isUsed(); |
| 403 | 413 |
| 404 if (mLibraryWasLoadedFromApk) { | 414 if (mLibraryWasLoadedFromApk) { |
| 405 return LibraryLoadFromApkStatusCodes.SUCCESSFUL; | 415 return LibraryLoadFromApkStatusCodes.SUCCESSFUL; |
| 406 } | 416 } |
| 407 | 417 |
| 408 // There were no libraries to be loaded directly from the APK file. | 418 // There were no libraries to be loaded directly from the APK file. |
| 409 return LibraryLoadFromApkStatusCodes.UNKNOWN; | 419 return LibraryLoadFromApkStatusCodes.UNKNOWN; |
| 410 } | 420 } |
| 411 | 421 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 479 | 489 |
| 480 // Finds the ranges corresponding to the native library pages, forks a new | 490 // Finds the ranges corresponding to the native library pages, forks a new |
| 481 // process to prefetch these pages and waits for it. The new process then | 491 // process to prefetch these pages and waits for it. The new process then |
| 482 // terminates. This is blocking. | 492 // terminates. This is blocking. |
| 483 private static native boolean nativeForkAndPrefetchNativeLibrary(); | 493 private static native boolean nativeForkAndPrefetchNativeLibrary(); |
| 484 | 494 |
| 485 // Returns the percentage of the native library code page that are currently reseident in | 495 // Returns the percentage of the native library code page that are currently reseident in |
| 486 // memory. | 496 // memory. |
| 487 private static native int nativePercentageOfResidentNativeLibraryCode(); | 497 private static native int nativePercentageOfResidentNativeLibraryCode(); |
| 488 } | 498 } |
| OLD | NEW |