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.SystemClock; | 8 import android.os.SystemClock; |
9 import android.util.Log; | 9 import android.util.Log; |
10 | 10 |
11 import org.chromium.base.CommandLine; | 11 import org.chromium.base.CommandLine; |
12 import org.chromium.base.JNINamespace; | 12 import org.chromium.base.JNINamespace; |
13 import org.chromium.base.TraceEvent; | 13 import org.chromium.base.TraceEvent; |
14 | 14 |
15 import javax.annotation.Nullable; | |
16 | |
15 /** | 17 /** |
16 * This class provides functionality to load and register the native libraries. | 18 * This class provides functionality to load and register the native libraries. |
17 * Callers are allowed to separate loading the libraries from initializing them. | 19 * Callers are allowed to separate loading the libraries from initializing them. |
18 * This may be an advantage for Android Webview, where the libraries can be load ed | 20 * This may be an advantage for Android Webview, where the libraries can be load ed |
19 * by the zygote process, but then needs per process initialization after the | 21 * by the zygote process, but then needs per process initialization after the |
20 * application processes are forked from the zygote process. | 22 * application processes are forked from the zygote process. |
21 * | 23 * |
22 * The libraries may be loaded and initialized from any thread. Synchronization | 24 * The libraries may be loaded and initialized from any thread. Synchronization |
23 * primitives are used to ensure that overlapping requests from different | 25 * primitives are used to ensure that overlapping requests from different |
24 * threads are handled sequentially. | 26 * threads are handled sequentially. |
(...skipping 21 matching lines...) Expand all Loading... | |
46 // One-way switch becomes true when the libraries are initialized ( | 48 // One-way switch becomes true when the libraries are initialized ( |
47 // by calling nativeLibraryLoaded, which forwards to LibraryLoaded(...) in | 49 // by calling nativeLibraryLoaded, which forwards to LibraryLoaded(...) in |
48 // library_loader_hooks.cc). | 50 // library_loader_hooks.cc). |
49 private static boolean sInitialized = false; | 51 private static boolean sInitialized = false; |
50 | 52 |
51 // One-way switches recording attempts to use Relro sharing in the browser. | 53 // One-way switches recording attempts to use Relro sharing in the browser. |
52 // The flags are used to report UMA stats later. | 54 // The flags are used to report UMA stats later. |
53 private static boolean sIsUsingBrowserSharedRelros = false; | 55 private static boolean sIsUsingBrowserSharedRelros = false; |
54 private static boolean sLoadAtFixedAddressFailed = false; | 56 private static boolean sLoadAtFixedAddressFailed = false; |
55 | 57 |
56 // One-way switch becomes true if the library was loaded from the APK file | 58 // One-way switch becomes true if the device supports loading the Chromium |
57 // directly. | 59 // library directly from the APK. |
60 private static boolean sLibraryLoadFromApkSupported = false; | |
61 | |
62 // One-way switch becomes true if the Chromium library was loaded from the | |
63 // APK file directly. | |
58 private static boolean sLibraryWasLoadedFromApk = false; | 64 private static boolean sLibraryWasLoadedFromApk = false; |
59 | 65 |
60 // One-way switch becomes false if the Chromium library should be loaded | 66 // One-way switch becomes false if the Chromium library should be loaded |
61 // directly from the APK file but it was not aligned. | 67 // directly from the APK file but it was not aligned. |
62 private static boolean sLibraryWasAlignedInApk = true; | 68 private static boolean sLibraryWasAlignedInApk = true; |
63 | 69 |
64 // One-way switch becomes true if the system library loading failed, | 70 // One-way switch becomes true if the system library loading failed, |
65 // and the right native library was found and loaded by the hack. | 71 // and the right native library was found and loaded by the hack. |
66 // The flag is used to report UMA stats later. | 72 // The flag is used to report UMA stats later. |
67 private static boolean sNativeLibraryHackWasUsed = false; | 73 private static boolean sNativeLibraryHackWasUsed = false; |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
161 Context context, boolean shouldDeleteOldWorkaroundLibraries) | 167 Context context, boolean shouldDeleteOldWorkaroundLibraries) |
162 throws ProcessInitException { | 168 throws ProcessInitException { |
163 try { | 169 try { |
164 if (!sLoaded) { | 170 if (!sLoaded) { |
165 assert !sInitialized; | 171 assert !sInitialized; |
166 | 172 |
167 long startTime = SystemClock.uptimeMillis(); | 173 long startTime = SystemClock.uptimeMillis(); |
168 boolean useChromiumLinker = Linker.isUsed(); | 174 boolean useChromiumLinker = Linker.isUsed(); |
169 | 175 |
170 if (useChromiumLinker) { | 176 if (useChromiumLinker) { |
177 String apkFilename = null; | |
178 | |
179 // Check if the device supports loading a library directly f rom the APK file. | |
180 if (context != null) { | |
181 apkFilename = context.getApplicationInfo().sourceDir; | |
182 sLibraryLoadFromApkSupported = Linker.checkLibraryLoadFr omApkSupport( | |
183 apkFilename); | |
184 } else { | |
185 Log.w(TAG, "loadAlreadyLocked(): null context"); | |
186 } | |
187 | |
171 // Load libraries using the Chromium linker. | 188 // Load libraries using the Chromium linker. |
172 Linker.prepareLibraryLoad(); | 189 Linker.prepareLibraryLoad(); |
173 | 190 |
174 for (String library : NativeLibraries.LIBRARIES) { | 191 for (String library : NativeLibraries.LIBRARIES) { |
175 // Don't self-load the linker. This is because the build system is | 192 // Don't self-load the linker. This is because the build system is |
176 // not clever enough to understand that all the librarie s packaged | 193 // not clever enough to understand that all the librarie s packaged |
177 // in the final .apk don't need to be explicitly loaded. | 194 // in the final .apk don't need to be explicitly loaded. |
178 if (Linker.isChromiumLinkerLibrary(library)) { | 195 if (Linker.isChromiumLinkerLibrary(library)) { |
179 if (DEBUG) Log.i(TAG, "ignoring self-linker load"); | 196 if (DEBUG) Log.i(TAG, "ignoring self-linker load"); |
180 continue; | 197 continue; |
181 } | 198 } |
182 | 199 |
183 String zipfile = null; | 200 // Determine where the library should be loaded from. |
184 if (Linker.isInZipFile()) { | 201 String zipFilename = null; |
185 zipfile = context.getApplicationInfo().sourceDir; | 202 String libFilename = System.mapLibraryName(library); |
186 sLibraryWasAlignedInApk = Linker.checkLibraryAligned InApk( | 203 if (apkFilename != null && Linker.isInZipFile()) { |
187 zipfile, System.mapLibraryName(library)); | 204 // The library is in the APK file. |
188 Log.i(TAG, "Loading " + library + " from within " + zipfile); | 205 if (!Linker.checkLibraryAlignedInApk( |
206 apkFilename, System.mapLibraryName(library)) ) { | |
Anton
2014/10/29 13:35:35
Replace System.mapLibraryName(library) with libFil
petrcermak
2014/10/29 14:01:01
Done.
| |
207 sLibraryWasAlignedInApk = false; | |
208 } | |
209 if (sLibraryLoadFromApkSupported && sLibraryWasAlign edInApk) { | |
210 // Load directly from the APK. | |
211 Log.i(TAG, "Loading " + library + " directly fro m within " + | |
212 apkFilename); | |
213 zipFilename = apkFilename; | |
214 } else { | |
215 // Fallback. | |
216 Log.i(TAG, "Loading " + library + " using fallba ck from within " + | |
217 apkFilename); | |
218 libFilename = LibraryLoaderHelper.buildFallbackL ibrary( | |
219 context, apkFilename, libFilename); | |
220 Log.i(TAG, "Built fallback library " + libFilena me); | |
221 } | |
189 } else { | 222 } else { |
190 Log.i(TAG, "Loading: " + library); | 223 // The library is in its own file. |
224 Log.i(TAG, "Loading " + library); | |
191 } | 225 } |
192 | 226 |
227 // Load the library. | |
193 boolean isLoaded = false; | 228 boolean isLoaded = false; |
194 if (Linker.isUsingBrowserSharedRelros()) { | 229 if (Linker.isUsingBrowserSharedRelros()) { |
195 sIsUsingBrowserSharedRelros = true; | 230 sIsUsingBrowserSharedRelros = true; |
196 try { | 231 try { |
197 if (zipfile != null) { | 232 loadLibrary(zipFilename, libFilename); |
198 Linker.loadLibraryInZipFile(zipfile, library ); | |
199 sLibraryWasLoadedFromApk = true; | |
200 } else { | |
201 Linker.loadLibrary(library); | |
202 } | |
203 isLoaded = true; | 233 isLoaded = true; |
204 } catch (UnsatisfiedLinkError e) { | 234 } catch (UnsatisfiedLinkError e) { |
205 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, " + |
206 "retrying without"); | 236 "retrying without"); |
207 Linker.disableSharedRelros(); | 237 Linker.disableSharedRelros(); |
208 sLoadAtFixedAddressFailed = true; | 238 sLoadAtFixedAddressFailed = true; |
209 } | 239 } |
210 } | 240 } |
211 if (!isLoaded) { | 241 if (!isLoaded) { |
212 if (zipfile != null) { | 242 loadLibrary(zipFilename, libFilename); |
213 Linker.loadLibraryInZipFile(zipfile, library); | |
214 sLibraryWasLoadedFromApk = true; | |
215 } else { | |
216 Linker.loadLibrary(library); | |
217 } | |
218 } | 243 } |
219 } | 244 } |
220 | 245 |
221 Linker.finishLibraryLoad(); | 246 Linker.finishLibraryLoad(); |
222 } else { | 247 } else { |
223 // Load libraries using the system linker. | 248 // Load libraries using the system linker. |
224 for (String library : NativeLibraries.LIBRARIES) { | 249 for (String library : NativeLibraries.LIBRARIES) { |
225 try { | 250 try { |
226 System.loadLibrary(library); | 251 System.loadLibrary(library); |
227 } catch (UnsatisfiedLinkError e) { | 252 } catch (UnsatisfiedLinkError e) { |
(...skipping 30 matching lines...) Expand all Loading... | |
258 Log.i(TAG, String.format( | 283 Log.i(TAG, String.format( |
259 "Expected native library version number \"%s\"," + | 284 "Expected native library version number \"%s\"," + |
260 "actual native library version number \"%s\"", | 285 "actual native library version number \"%s\"", |
261 NativeLibraries.sVersionNumber, | 286 NativeLibraries.sVersionNumber, |
262 nativeGetVersionNumber())); | 287 nativeGetVersionNumber())); |
263 if (!NativeLibraries.sVersionNumber.equals(nativeGetVersionNumber())) { | 288 if (!NativeLibraries.sVersionNumber.equals(nativeGetVersionNumber())) { |
264 throw new ProcessInitException(LoaderErrors.LOADER_ERROR_NATIVE_LIBR ARY_WRONG_VERSION); | 289 throw new ProcessInitException(LoaderErrors.LOADER_ERROR_NATIVE_LIBR ARY_WRONG_VERSION); |
265 } | 290 } |
266 } | 291 } |
267 | 292 |
293 // Load a native shared library with the Chromium linker. If the zip file | |
294 // filename is not null, the library is loaded directly from the zip file. | |
295 private static void loadLibrary(@Nullable String zipFilename, String libFile name) { | |
296 if (zipFilename != null) { | |
297 sLibraryWasLoadedFromApk = true; | |
298 } | |
299 Linker.loadLibrary(zipFilename, libFilename); | |
300 } | |
301 | |
268 // The WebView requires the Command Line to be switched over before | 302 // The WebView requires the Command Line to be switched over before |
269 // initialization is done. This is okay in the WebView's case since the | 303 // initialization is done. This is okay in the WebView's case since the |
270 // JNI is already loaded by this point. | 304 // JNI is already loaded by this point. |
271 public static void switchCommandLineForWebView() { | 305 public static void switchCommandLineForWebView() { |
272 synchronized (sLock) { | 306 synchronized (sLock) { |
273 ensureCommandLineSwitchedAlreadyLocked(); | 307 ensureCommandLineSwitchedAlreadyLocked(); |
274 } | 308 } |
275 } | 309 } |
276 | 310 |
277 // Switch the CommandLine over from Java to native if it hasn't already been done. | 311 // Switch the CommandLine over from Java to native if it hasn't already been done. |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
394 private static native void nativeRegisterChromiumAndroidLinkerRendererHistog ram( | 428 private static native void nativeRegisterChromiumAndroidLinkerRendererHistog ram( |
395 boolean requestedSharedRelro, | 429 boolean requestedSharedRelro, |
396 boolean loadAtFixedAddressFailed); | 430 boolean loadAtFixedAddressFailed); |
397 | 431 |
398 // Get the version of the native library. This is needed so that we can chec k we | 432 // Get the version of the native library. This is needed so that we can chec k we |
399 // have the right version before initializing the (rest of the) JNI. | 433 // have the right version before initializing the (rest of the) JNI. |
400 private static native String nativeGetVersionNumber(); | 434 private static native String nativeGetVersionNumber(); |
401 | 435 |
402 private static native void nativeRecordNativeLibraryHack(boolean usedHack); | 436 private static native void nativeRecordNativeLibraryHack(boolean usedHack); |
403 } | 437 } |
OLD | NEW |