Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(58)

Unified Diff: content/public/android/java/org/chromium/content/browser/LibraryLoader.java

Issue 10377059: Android content shell bringup. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix deps so builds on clean machine Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/public/android/java/org/chromium/content/browser/LibraryLoader.java
diff --git a/content/public/android/java/org/chromium/content/browser/LibraryLoader.java b/content/public/android/java/org/chromium/content/browser/LibraryLoader.java
new file mode 100644
index 0000000000000000000000000000000000000000..ee9b35886111c4164c28b7aa0c64ec1c04c92e12
--- /dev/null
+++ b/content/public/android/java/org/chromium/content/browser/LibraryLoader.java
@@ -0,0 +1,239 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.content.browser;
+
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.text.TextUtils;
+import android.util.Log;
+
+// This class provides functionality to:
+// - synchronously load and register the native library. This is used by callers
+// that can't do anything useful without the native side.
+// - asynchronously load and register the native library. This is used by callers
+// that can do more work in the java-side, and let a separate thread do all the
+// file IO and library loading.
+public class LibraryLoader {
+ private static final String TAG = "LibraryLoader";
+
+ /* TODO(jrg): resolve up and downstream discrepancy; there is no
+ * upstream libchromeview.so */
+ private static String sLibrary = "chromeview";
+
+ private static boolean sLoaded = false;
+
+ private static boolean sInitialized = false;
+
+ private static AsyncTask<Void, Void, Boolean> sAsyncLoader;
+
+ /**
+ * Callback for handling loading of the native library.
+ *
+ * <p> The callback methods will always be triggered on the UI thread.
+ */
+ public static interface Callback {
+ /**
+ * Called when loading the native library is successful.
+ */
+ void onSuccess();
+
+ /**
+ * Called when loading the native library fails.
+ */
+ void onFailure();
+ }
+
+ /**
+ * Sets the library name that is to be loaded. This must be called prior to the library being
+ * loaded the first time.
+ *
+ * @param library The name of the library to be loaded (without the lib prefix).
+ */
+ public static void setLibraryToLoad(String library) {
+ if (TextUtils.equals(sLibrary, library)) return;
+
+ assert !sLoaded : "Setting the library must happen before load is called.";
+ sLibrary = library;
+ }
+
+ /**
+ * This method blocks until the library is fully loaded and initialized;
+ * must be called on the thread that the native will call its "main" thread.
+ */
+ public static void loadAndInitSync() {
+ checkThreadUsage();
+ if (sInitialized) {
+ // Already initialized, nothing to do.
+ return;
+ }
+ if (sAsyncLoader != null) {
+ // Async initialization in progress, wait.
+ waitForAsyncInitialized();
+ return;
+ }
+ loadNow();
+ initializeOnMainThread();
+ }
+
+ /**
+ * Block until the library is fully initialized.
+ * Must be called on the thread that the native will call its "main" thread.
+ */
+ private static void waitForAsyncInitialized() {
+ checkThreadUsage();
+ if (sInitialized) {
+ // Already initialized.
+ return;
+ }
+ synchronized(LibraryLoader.class) {
+ try {
+ while (!sLoaded) {
+ LibraryLoader.class.wait();
+ }
+ // If the UI thread blocked waiting for the task it will already
+ // have handled the library load completion, so don't duplicate that work here.
+ } catch (InterruptedException e) {
+ }
+ }
+ initializeOnMainThread();
+ }
+
+ /**
+ * Kicks off an asynchronous library load, and will asynchronously initialize the
+ * library when that completes.
+ * Must be called on the thread that the native will call its "main" thread.
+ */
+ public static void loadAndInitAsync(final Callback onLoadedListener) {
+ checkThreadUsage();
+ if (sInitialized) {
+ // Already initialized, post our Runnable if needed.
+ if (onLoadedListener != null) {
+ new Handler().post(new Runnable() {
+ @Override
+ public void run() {
+ onLoadedListener.onSuccess();
+ }
+ });
+ }
+ return;
+ }
+ sAsyncLoader = new AsyncTask<Void, Void, Boolean>() {
+ @Override
+ public Boolean doInBackground(Void... voids) {
+ // We're loading the .so in a background thread. Potentially, this
+ // can break native code that relies on static initializers using
+ // thread local storage, as the library would normally load in the
+ // main thread. If do we hit such cases we should remove those static
+ // initializers, as we chrome has banned them.
+ // (Worst case, we can go back to just warming up the file in the system
+ // cache here and do the actual loading in onPostExecute().)
+ return loadNow();
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ if (result) {
+ initializeOnMainThread();
+ if (onLoadedListener != null) onLoadedListener.onSuccess();
+ } else {
+ if (onLoadedListener != null) onLoadedListener.onFailure();
+ }
+
+ }
+ };
+ sAsyncLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+
+ /**
+ * @throws UnsatisfiedLinkError if the library is not yet initialized.
+ */
+ public static void checkIsReady() {
+ if (!sInitialized) {
+ throw new UnsatisfiedLinkError(sLibrary + " is not initialized");
+ }
+ }
+
+ /**
+ * Loads the library and blocks until the load completes. The caller is responsible
+ * for subsequently calling initialize().
+ * May be called on any thread, but should only be called once. Note the thread
+ * this is called on will be the thread that runs the native code's static initializers.
+ * See the comment in doInBackground() for more considerations on this.
+ *
+ * @return Whether the native library was successfully loaded.
+ */
+ static boolean loadNow() {
+ assert !sInitialized;
+ try {
+ Log.i(TAG, "loading: " + sLibrary);
+ System.loadLibrary(sLibrary);
+ Log.i(TAG, "loaded: " + sLibrary);
+ synchronized(LibraryLoader.class) {
+ sLoaded = true;
+ LibraryLoader.class.notifyAll();
+ }
+ } catch (UnsatisfiedLinkError e) {
+ Log.e(TAG, "error loading: " + sLibrary, e);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * initializes the library here and now: must be called on the thread that the
+ * native will call its "main" thread. The library must have previously been
+ * loaded with loadNow.
+ * @param initCommandLine The command line arguments that native command line will
+ * be initialized with.
+ */
+ static void initializeOnMainThread(String[] initCommandLine) {
+ checkThreadUsage();
+ if (sInitialized) {
+ return;
+ }
+ if (!nativeLibraryLoadedOnMainThread(initCommandLine)) {
+ Log.e(TAG, "error calling nativeLibraryLoadedOnMainThread");
+ throw new UnsatisfiedLinkError();
+ }
+ // From this point on, native code is ready to use and checkIsReady()
+ // shouldn't complain from now on (and in fact, it's used by the
+ // following calls).
+ sInitialized = true;
+ CommandLine.enableNativeProxy();
+ TraceEvent.setEnabledToMatchNative();
+ }
+
+ static private void initializeOnMainThread() {
+ checkThreadUsage();
+ if (!sInitialized) {
+ initializeOnMainThread(CommandLine.getJavaSwitchesOrNull());
+ }
+ }
+
+ private LibraryLoader() {
+ }
+
+ // The public API of this class is meant to be used from a single
+ // thread. Internally, we may bounce to a separate thread to actually
+ // load the library.
+ private static Thread sMyThread;
+ private static void checkThreadUsage() {
+ Thread currentThread = java.lang.Thread.currentThread();
+ if (sMyThread == null) {
+ sMyThread = currentThread;
+ } else {
+ if (sMyThread != currentThread) {
+ Log.e(TAG, "Threading violation detected. My thread=" + sMyThread +
+ " but I'm being accessed from thread=" + currentThread);
+ assert false;
+ }
+ }
+ }
+
+ // This is the only method that is registered during System.loadLibrary, as it
+ // happens on a different thread. We then call it on the main thread to register
+ // everything else.
+ private static native boolean nativeLibraryLoadedOnMainThread(String[] initCommandLine);
+}

Powered by Google App Engine
This is Rietveld 408576698