Revamped EngineInitializer

Also contains gyp changes to add a instrumentation test
target for Browser

Change-Id: I2ea26a4a57d9101c54f80f148c9333088016e141
diff --git a/src/com/android/browser/Browser.java b/src/com/android/browser/Browser.java
index d1c127d..6fb8ca2 100644
--- a/src/com/android/browser/Browser.java
+++ b/src/com/android/browser/Browser.java
@@ -63,7 +63,7 @@
                     Log.v(LOGTAG, "Browser.onActivityCreated: activity=" + activity);
                 }
                 if (!(activity instanceof BrowserActivity) && !(activity instanceof BrowserLauncher) ) {
-                    EngineInitializer.getInstance().initializeSync((Context) Browser.this);
+                    EngineInitializer.initializeSync((Context) Browser.this);
                 }
             }
 
diff --git a/src/com/android/browser/BrowserActivity.java b/src/com/android/browser/BrowserActivity.java
index 9b310e2..f1fc421 100644
--- a/src/com/android/browser/BrowserActivity.java
+++ b/src/com/android/browser/BrowserActivity.java
@@ -36,7 +36,6 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
 import android.view.Window;
 
 import org.chromium.base.VisibleForTesting;
@@ -50,7 +49,7 @@
 import org.codeaurora.swe.CookieManager;
 import org.codeaurora.swe.WebView;
 
-public class BrowserActivity extends Activity implements ViewTreeObserver.OnPreDrawListener {
+public class BrowserActivity extends Activity {
 
     public static final String ACTION_SHOW_BOOKMARKS = "show_bookmarks";
     public static final String ACTION_SHOW_BROWSER = "show_browser";
@@ -84,7 +83,10 @@
     };
 
     private Bundle mSavedInstanceState;
-    private EngineInitializer mEngineInitializer;
+    private EngineInitializer.ActivityScheduler mActivityScheduler;
+    public EngineInitializer.ActivityScheduler getScheduler() {
+        return mActivityScheduler;
+    }
 
     @Override
     public void onCreate(Bundle icicle) {
@@ -115,8 +117,7 @@
         }
         */
 
-        mEngineInitializer = EngineInitializer.getInstance();
-        mEngineInitializer.onActivityCreate(BrowserActivity.this);
+        mActivityScheduler = EngineInitializer.onActivityCreate(BrowserActivity.this);
 
         Thread.setDefaultUncaughtExceptionHandler(new CrashLogExceptionHandler(this));
 
@@ -128,23 +129,9 @@
         ViewGroup topLayout = (ViewGroup) findViewById(R.id.main_content);
         topLayout.requestTransparentRegion(topLayout);
 
-        // Add pre-draw listener to start the controller after engine initialization.
-        final ViewTreeObserver observer = getWindow().getDecorView().getViewTreeObserver();
-        observer.addOnPreDrawListener(this);
-
-        mEngineInitializer.initializeResourceExtractor(this);
+        EngineInitializer.onPostActivityCreate(BrowserActivity.this);
     }
 
-    @Override
-    public boolean onPreDraw()
-    {
-        final ViewTreeObserver observer = getWindow().getDecorView().getViewTreeObserver();
-        observer.removeOnPreDrawListener(this);
-        mEngineInitializer.onPreDraw();
-        return true;
-    }
-
-
     public static boolean isTablet(Context context) {
         return context.getResources().getBoolean(R.bool.isTablet);
     }
@@ -166,7 +153,7 @@
         return controller;
     }
 
-    public void onEngineInitializationComplete() {
+    public void startController() {
         Intent intent = (mSavedInstanceState == null) ? getIntent() : null;
         mController.start(intent);
     }
@@ -180,7 +167,7 @@
     @Override
     protected void onNewIntent(Intent intent) {
         if (shouldIgnoreIntents()) return;
-        mEngineInitializer.onNewIntent(intent);
+        EngineInitializer.onNewIntent(BrowserActivity.this, intent);
         // Note: Do not add any more application logic in this method.
         //       Move any additional app logic into handleOnNewIntent().
     }
@@ -221,7 +208,7 @@
     @Override
     protected void onStart() {
         super.onStart();
-        mEngineInitializer.onActivityStart();
+        EngineInitializer.onActivityStart(BrowserActivity.this);
     }
 
     @Override
@@ -230,7 +217,7 @@
         if (LOGV_ENABLED) {
             Log.v(LOGTAG, "BrowserActivity.onResume: this=" + this);
         }
-        mEngineInitializer.onActivityResume();
+        EngineInitializer.onActivityResume(BrowserActivity.this);
         // Note: Do not add any more application logic in this method.
         //       Move any additional app logic into handleOnResume().
     }
@@ -245,12 +232,17 @@
 
     @Override
     protected void onStop() {
-        mEngineInitializer.onActivityStop();
+        EngineInitializer.onActivityStop(BrowserActivity.this);
         super.onStop();
         // Note: Do not add any more application logic in this method.
         //       Move any additional app logic into handleOnStop().
     }
 
+    protected void handleOnStop() {
+        CookieManager.getInstance().flushCookieStore();
+        mController.onPause();
+    }
+
     @Override
     public boolean onMenuOpened(int featureId, Menu menu) {
         if (Window.FEATURE_OPTIONS_PANEL == featureId) {
@@ -285,7 +277,7 @@
 
     @Override
     protected void onPause() {
-        mEngineInitializer.onActivityPause();
+        EngineInitializer.onActivityPause(BrowserActivity.this);
         super.onPause();
         // Note: Do not add any more application logic in this method.
         //       Move any additional app logic into handleOnPause().
@@ -295,21 +287,13 @@
         // Note: Intentionally left blank
     }
 
-    protected void handleOnStop() {
-        CookieManager.getInstance().flushCookieStore();
-        mController.onPause();
-    }
-
     @Override
     protected void onDestroy() {
         if (LOGV_ENABLED) {
             Log.v(LOGTAG, "BrowserActivity.onDestroy: this=" + this);
         }
         super.onDestroy();
-        // mEngineInitializer can be null if onCreate is not called before onDestroy
-        // it happens when starting the activity with an intent while the screen is locked.
-        if (mEngineInitializer != null)
-            mEngineInitializer.onActivityDestroy();
+        EngineInitializer.onActivityDestroy(BrowserActivity.this);
         mController.onDestroy();
         mController = NullController.INSTANCE;
         if (!Locale.getDefault().equals(mCurrentLocale) || killOnExitDialog) {
@@ -402,7 +386,7 @@
     @Override
     protected void onActivityResult (int requestCode, int resultCode,
                                      Intent intent) {
-        mEngineInitializer.onActivityResult(requestCode, resultCode, intent);
+        EngineInitializer.onActivityResult(BrowserActivity.this, requestCode, resultCode, intent);
     }
 
     protected void handleOnActivityResult (int requestCode, int resultCode, Intent intent) {
diff --git a/src/com/android/browser/EngineInitializer.java b/src/com/android/browser/EngineInitializer.java
index ef88458..7a0c236 100644
--- a/src/com/android/browser/EngineInitializer.java
+++ b/src/com/android/browser/EngineInitializer.java
@@ -37,34 +37,31 @@
 import android.os.Looper;
 import android.os.StrictMode;
 import android.util.Log;
+import android.view.ViewTreeObserver;
 
 import org.codeaurora.swe.BrowserCommandLine;
 import org.codeaurora.swe.Engine;
 
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.concurrent.CancellationException;
 import java.util.concurrent.ExecutionException;
 
 import org.chromium.base.VisibleForTesting;
 
 public class EngineInitializer {
+
     private final static String LOGTAG = "EngineInitializer";
+    //Command line flag for strict mode
+    private final static String STRICT_MODE = "enable-strict-mode";
 
-    private BrowserActivity mActivity;
+    private static boolean mInitializationStarted = false;
+    private static boolean mSynchronousInitialization = false;
+    private static boolean mInitializationCompleted = false;
+    private static Handler mUiThreadHandler;
 
-    private boolean mNotifyActivity = false;
-    private boolean mActivityReady = false;
-    private boolean mActivityDestroyed = false;
-    private boolean mActivityStartPending = false;
-    private boolean mOnResumePending  = false;
-
-    private boolean mFirstDrawCompleted = false;
-    private boolean mLibraryLoaded = false;
-    private boolean mInitializationCompleted = false;
-
-    private Handler mUiThreadHandler;
-
-    class ActivityResult
+    static class ActivityResult
     {
         public Intent data;
         public int requestCode;
@@ -77,48 +74,198 @@
             this.data = data;
         }
     }
-    private ArrayList<ActivityResult> mPendingActivityResults = null;
-    private ArrayList<Intent> mPendingIntents = null;
 
-    private static EngineInitializer sEngineInitializer = null;
-    public static  EngineInitializer getInstance() {
-        if (sEngineInitializer == null) {
-            sEngineInitializer = new EngineInitializer();
+    public static class ActivityScheduler implements ViewTreeObserver.OnPreDrawListener
+    {
+        private BrowserActivity mActivity = null;
+        private ArrayList<ActivityResult> mPendingActivityResults = null;
+        private ArrayList<Intent> mPendingIntents = null;
+
+        private boolean mFirstDrawCompleted = false;
+        private boolean mOnStartPending = false;
+        private boolean mOnPausePending  = false;
+        private boolean mEngineInitialized = false;
+        private boolean mCanForwardEvents = false;
+
+        public ActivityScheduler(BrowserActivity activity)
+        {
+            mActivity = activity;
+            mFirstDrawCompleted = false;
+            mOnStartPending = false;
+            mOnPausePending  = false;
+            mPendingIntents = null;
+            mPendingActivityResults = null;
+            mEngineInitialized = false;
+            mCanForwardEvents = false;
         }
-        return sEngineInitializer;
+
+        @VisibleForTesting
+        public boolean firstDrawCompleted() { return mFirstDrawCompleted; }
+        @VisibleForTesting
+        public boolean onStartPending() { return mOnStartPending; }
+        @VisibleForTesting
+        public boolean onPausePending() { return mOnPausePending; }
+        @VisibleForTesting
+        public boolean engineInitialized() { return mEngineInitialized; }
+        @VisibleForTesting
+        public boolean canForwardEvents() { return mCanForwardEvents; }
+
+        public void processPendingEvents() {
+            assert runningOnUiThread() : "Tried to initialize the engine on the wrong thread.";
+
+            if (mOnStartPending) {
+                mOnStartPending = false;
+                mActivity.handleOnStart();
+            }
+            if (mOnPausePending) {
+                mActivity.handleOnPause();
+                mOnPausePending = false;
+            }
+            if (mPendingIntents != null) {
+                for (int i = 0; i < mPendingIntents.size(); i++) {
+                    mActivity.handleOnNewIntent(mPendingIntents.get(i));
+                }
+                mPendingIntents = null;
+            }
+            if (mPendingActivityResults != null) {
+                for (int i = 0; i < mPendingActivityResults.size(); i++) {
+                    ActivityResult result = mPendingActivityResults.get(i);
+                    mActivity.handleOnActivityResult(result.requestCode, result.resultCode, result.data);
+                }
+                mPendingActivityResults = null;
+            }
+            mCanForwardEvents = true;
+        }
+
+        public void onActivityCreate(boolean engineInitialized) {
+            mEngineInitialized = engineInitialized;
+            if (!mEngineInitialized) {
+                // Engine initialization is not completed, we should wait for the onPreDraw() notification.
+                final ViewTreeObserver observer = mActivity.getWindow().getDecorView().getViewTreeObserver();
+                observer.addOnPreDrawListener(this);
+            } else {
+                mFirstDrawCompleted = true;
+                mCanForwardEvents = true;
+            }
+        }
+
+        @Override
+        public boolean onPreDraw() {
+            final ViewTreeObserver observer = mActivity.getWindow().getDecorView().getViewTreeObserver();
+            observer.removeOnPreDrawListener(this);
+
+            if (mFirstDrawCompleted)
+                return true;
+
+            mFirstDrawCompleted = true;
+            if (mEngineInitialized) {
+                postOnUiThread(new Runnable() {
+                    @Override
+                    public void run() {
+                        mActivity.startController();
+                        processPendingEvents();
+                    }
+                });
+            }
+            return true;
+        }
+
+        public void onEngineInitializationCompletion(boolean synchronous) {
+            if (synchronous) {
+                // Don't wait for pre-draw notification if it is synchronous
+                onPreDraw();
+            }
+            mEngineInitialized = true;
+            if (mFirstDrawCompleted) {
+                mActivity.startController();
+                processPendingEvents();
+            }
+        }
+
+        public void onActivityPause() {
+            if (mCanForwardEvents) {
+                mActivity.handleOnPause();
+                return;
+            }
+            mOnPausePending = true;
+        }
+
+        public void onActivityResume() {
+            if (mCanForwardEvents) {
+                mActivity.handleOnResume();
+                return;
+            }
+            mOnPausePending = false;
+        }
+
+        public void onActivityStart() {
+            if (mCanForwardEvents) {
+                mActivity.handleOnStart();
+                // TODO: We have no reliable mechanism to know when the app goes background.
+                //ChildProcessLauncher.onBroughtToForeground();
+                return;
+            }
+            mOnStartPending = true;
+        }
+
+        public void onActivityStop() {
+            if (!mCanForwardEvents) {
+                initializeSync(mActivity.getApplicationContext());
+            }
+            mActivity.handleOnStop();
+        }
+
+        public void onActivityResult(int requestCode, int resultCode, Intent data) {
+            if (mCanForwardEvents) {
+                mActivity.handleOnActivityResult(requestCode, resultCode, data);
+                return;
+            }
+            if (mPendingActivityResults == null) {
+                mPendingActivityResults = new ArrayList<ActivityResult>(1);
+            }
+            mPendingActivityResults.add(new ActivityResult(requestCode, resultCode, data));
+        }
+
+        public void onNewIntent(Intent intent) {
+            if (mCanForwardEvents) {
+                mActivity.handleOnNewIntent(intent);
+                return;
+            }
+
+            if (mPendingIntents == null) {
+                mPendingIntents = new ArrayList<Intent>(1);
+            }
+            mPendingIntents.add(intent);
+        }
     }
 
+    private static HashMap<BrowserActivity, ActivityScheduler> mActivitySchedulerMap = null;
     private static long sDelayForTesting = 0;
 
-    //Command line flag for strict mode
-    private static final String STRICT_MODE = "enable-strict-mode";
-
     @VisibleForTesting
     public static void setDelayForTesting(long delay)
     {
         sDelayForTesting = delay;
     }
 
-    private EngineInitializer() {
-        mUiThreadHandler = new Handler(Looper.getMainLooper());
-    }
-
     @VisibleForTesting
-    public boolean isInitialized()
+    public static boolean isInitialized()
     {
         return mInitializationCompleted;
     }
 
-    public boolean runningOnUiThread() {
+    public static boolean runningOnUiThread() {
         return mUiThreadHandler.getLooper() == Looper.myLooper();
     }
 
-    public void postOnUiThread(Runnable task) {
+    public static void postOnUiThread(Runnable task) {
         mUiThreadHandler.post(task);
     }
 
-    private class InitializeTask extends AsyncTask<Void, Void, Boolean> {
-        public InitializeTask() {
+    private static class InitializeTask extends AsyncTask<Void, Void, Boolean> {
+        private Context mApplicationContext;
+        public InitializeTask(Context ctx) {
+            mApplicationContext = ctx;
         }
         @Override
         protected Boolean doInBackground(Void... unused) {
@@ -129,9 +276,9 @@
                     Thread.sleep(sDelayForTesting);
                 }
 
-                Engine.loadNativeLibraries(mActivity.getApplicationContext());
+                Engine.loadNativeLibraries(mApplicationContext);
 
-                Engine.warmUpChildProcess(mActivity.getApplicationContext());
+                Engine.warmUpChildProcess(mApplicationContext);
 
                 return true;
             }
@@ -144,17 +291,14 @@
 
         @Override
         protected void onPostExecute (Boolean result) {
-            mLibraryLoaded = true;
-            if (mFirstDrawCompleted) {
-                completeInitializationOnUiThread(mActivity.getApplicationContext());
-            }
+            completeInitializationOnUiThread(mApplicationContext);
         }
     }
-    private InitializeTask mInitializeTask = null;
+    private static InitializeTask mInitializeTask = null;
 
-    public void initializeSync(Context ctx) {
+    public static void initializeSync(Context ctx) {
         assert runningOnUiThread() : "Tried to initialize the engine on the wrong thread.";
-
+        mSynchronousInitialization = true;
         if (mInitializeTask != null) {
             try {
                 // Wait for the InitializeTask to finish.
@@ -168,40 +312,47 @@
             }
         }
         completeInitializationOnUiThread(ctx);
+        mSynchronousInitialization = false;
     }
 
-    private void reset(BrowserActivity newActivity) {
-        mActivity = newActivity;
-        mActivityStartPending = false;
-        mOnResumePending  = false;
-        mNotifyActivity = true;
-        mActivityReady = false;
-        mPendingIntents = null;
-        mPendingActivityResults = null;
-        mFirstDrawCompleted = false;
-        mActivityDestroyed = false;
-    }
-
-    public void onActivityCreate(BrowserActivity activity) {
-        assert runningOnUiThread() : "Tried to initialize the engine on the wrong thread.";
-        reset(activity);
+    private static void initialize(Context ctx) {
         if (!mInitializationCompleted) {
-            Engine.initializeCommandLine(mActivity.getApplicationContext());
-            mInitializeTask = new InitializeTask();
-            mInitializeTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+            if (!mInitializationStarted) {
+                mInitializationStarted = true;
+                mUiThreadHandler = new Handler(Looper.getMainLooper());
+                Engine.initializeCommandLine(ctx);
+                mInitializeTask = new InitializeTask(ctx);
+                mInitializeTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+                mActivitySchedulerMap = new HashMap<BrowserActivity, ActivityScheduler>();
+            } else {
+                // This is not the first activity, wait for the engine initialization to finish.
+                initializeSync(ctx);
+            }
         }
     }
 
-    private void completeInitialization() {
-        postOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                completeInitializationOnUiThread(mActivity.getApplicationContext());
-            }
-        });
+    public static ActivityScheduler onActivityCreate(BrowserActivity activity) {
+        assert runningOnUiThread() : "Tried to initialize the engine on the wrong thread.";
+
+        Context ctx = activity.getApplicationContext();
+        ActivityScheduler scheduler = new ActivityScheduler(activity);
+        initialize(ctx);
+
+        scheduler.onActivityCreate(mInitializationCompleted);
+        if (!mInitializationCompleted) {
+            mActivitySchedulerMap.put(activity, scheduler);
+        }
+        return scheduler;
     }
 
-    private void completeInitializationOnUiThread(Context ctx) {
+    public static void onPostActivityCreate(BrowserActivity activity) {
+        EngineInitializer.initializeResourceExtractor(activity);
+        if (EngineInitializer.isInitialized()) {
+            activity.startController();
+        }
+    }
+
+    private static void completeInitializationOnUiThread(Context ctx) {
         assert runningOnUiThread() : "Tried to initialize the engine on the wrong thread.";
 
         if (!mInitializationCompleted) {
@@ -230,184 +381,55 @@
             //Enable remote debugging by default
             Engine.setWebContentsDebuggingEnabled(true);
             mInitializationCompleted = true;
-            mLibraryLoaded = true;
+            mInitializationStarted = true;
             BrowserSettings.getInstance().onEngineInitializationComplete();
-        }
-        if (mActivity != null && mNotifyActivity) {
-            mNotifyActivity = false;
-            postOnUiThread(new Runnable() {
-                @Override
-                public void run() {
-                    mActivity.onEngineInitializationComplete();
-                    mActivityReady = true;
-                    processPendingEvents();
+            Engine.resumeTracing(ctx);
+
+            if (mActivitySchedulerMap != null) {
+                for (Map.Entry<BrowserActivity, ActivityScheduler> entry : mActivitySchedulerMap.entrySet()) {
+                    entry.getValue().onEngineInitializationCompletion(mSynchronousInitialization);
                 }
-            });
-        }
-
-    }
-
-    private void completeInitializationAsynOnUiThread(final Context ctx) {
-        assert runningOnUiThread() : "Tried to initialize the engine on the wrong thread.";
-
-        if (!mInitializationCompleted) {
-            // TODO: Evaluate the benefit of async Engine.initialize()
-            Engine.StartupCallback callback =
-                new Engine.StartupCallback() {
-                    @Override
-                    public void onSuccess(boolean alreadyStarted) {
-                        if (Looper.myLooper() == Looper.getMainLooper()) {
-                            Log.e(LOGTAG, "SWE engine initialization success");
-                             // Add the browser commandline options
-                            BrowserConfig.getInstance(ctx).initCommandLineSwitches();
-
-                            //Note: Only enable this for debugging.
-                            if (BrowserCommandLine.hasSwitch(STRICT_MODE)) {
-                                Log.v(LOGTAG, "StrictMode enabled");
-                                StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
-                                        .detectDiskReads()
-                                        .detectDiskWrites()
-                                        .detectNetwork()
-                                        .penaltyLog()
-                                        .build());
-                                StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
-                                        .detectLeakedSqlLiteObjects()
-                                        .detectLeakedClosableObjects()
-                                        .penaltyLog()
-                                        .penaltyDeath()
-                                        .build());
-                            }
-
-                            //Enable remote debugging by default
-                            Engine.setWebContentsDebuggingEnabled(true);
-                            mInitializationCompleted = true;
-                            mLibraryLoaded = true;
-                            BrowserSettings.getInstance().onEngineInitializationComplete();
-
-                            if (mActivity != null && mNotifyActivity) {
-                                mNotifyActivity = false;
-                                postOnUiThread(new Runnable() {
-                                    @Override
-                                    public void run() {
-                                        mActivity.onEngineInitializationComplete();
-                                        mActivityReady = true;
-                                        processPendingEvents();
-                                    }
-                                });
-                            }
-                        }
-                    }
-
-                    @Override
-                    public void onFailure() {
-                        Log.e(LOGTAG, "SWE engine initialization failed");
-                    }
-            };
-            Engine.initialize(ctx, callback);
-        }
-    }
-
-    private void processPendingEvents() {
-        assert runningOnUiThread() : "Tried to initialize the engine on the wrong thread.";
-
-        if (mActivityStartPending) {
-            mActivityStartPending = false;
-            onActivityStart();
-        }
-        if (mPendingIntents != null) {
-            for (int i = 0; i < mPendingIntents.size(); i++) {
-                mActivity.handleOnNewIntent(mPendingIntents.get(i));
+                mActivitySchedulerMap.clear();
             }
-            mPendingIntents = null;
-        }
-        if (mPendingActivityResults != null) {
-            for (int i = 0; i < mPendingActivityResults.size(); i++) {
-                ActivityResult result = mPendingActivityResults.get(i);
-                mActivity.handleOnActivityResult(result.requestCode, result.resultCode, result.data);
-            }
-            mPendingActivityResults = null;
-        }
-        if (mOnResumePending && !mActivityDestroyed) {
-            onActivityResume();
-        }
-        mOnResumePending = false;
-    }
-
-    public void onPreDraw() {
-        mFirstDrawCompleted = true;
-        if (mLibraryLoaded) {
-            completeInitialization();
         }
     }
 
-    public void initializeResourceExtractor(Context ctx) {
+    public static void initializeResourceExtractor(Context ctx) {
         Engine.startExtractingResources(ctx);
     }
 
-    public void onActivityPause() {
-        mOnResumePending = false;
-        if (mActivityReady) {
-            mActivity.handleOnPause();
-        }
+    public static void onPreDraw(BrowserActivity activity) {
+        activity.getScheduler().onPreDraw();
     }
 
-    public void onActivityStop() {
-        mActivityStartPending = false;
-        if (mActivityReady) {
-            Engine.pauseTracing(mActivity.getApplicationContext());
-            mActivity.handleOnStop();
-        }
+    public static void onActivityPause(BrowserActivity activity) {
+        activity.getScheduler().onActivityPause();
     }
 
-    public void onActivityResume() {
-        if (mActivityReady) {
-            mActivity.handleOnResume();
-            return;
-        }
-        mOnResumePending = true;
+    public static void onActivityStop(BrowserActivity activity) {
+        activity.getScheduler().onActivityStop();
     }
 
-    public void onActivityStart() {
-        if (mActivityReady) {
-            Engine.resumeTracing(mActivity.getApplicationContext());
-            mActivity.handleOnStart();
-            // TODO: We have no reliable mechanism to know when the app goes background.
-            //ChildProcessLauncher.onBroughtToForeground();
-            return;
-        }
-        mActivityStartPending = true;
+    public static void onActivityResume(BrowserActivity activity) {
+        activity.getScheduler().onActivityResume();
     }
 
-    public void onActivityResult(int requestCode, int resultCode, Intent data) {
-        if (mActivityReady) {
-            mActivity.handleOnActivityResult(requestCode, resultCode, data);
-            return;
-        }
-        if (mPendingActivityResults == null) {
-            mPendingActivityResults = new ArrayList<ActivityResult>(1);
-        }
-        mPendingActivityResults.add(new ActivityResult(requestCode, resultCode, data));
+    public static void onActivityStart(BrowserActivity activity) {
+        activity.getScheduler().onActivityStart();
     }
 
-    public void onNewIntent(Intent intent) {
+    public static void onActivityResult(BrowserActivity activity, int requestCode, int resultCode, Intent data) {
+        activity.getScheduler().onActivityResult(requestCode, resultCode, data);
+    }
+
+    public static void onNewIntent(BrowserActivity activity, Intent intent) {
         if (BrowserActivity.ACTION_RESTART.equals(intent.getAction())) {
             Engine.releaseSpareChildProcess();
         }
-        if (mActivityReady) {
-            mActivity.handleOnNewIntent(intent);
-            return;
-        }
-
-        if (mPendingIntents == null) {
-            mPendingIntents = new ArrayList<Intent>(1);
-        }
-        mPendingIntents.add(intent);
+        activity.getScheduler().onNewIntent(intent);
     }
 
-    public void onActivityDestroy() {
+    public static void onActivityDestroy(BrowserActivity activity) {
         Engine.releaseSpareChildProcess();
-        mActivityDestroyed = true;
     }
-
-
 }
diff --git a/src/com/android/browser/test/EngineInitializerTest.java b/src/com/android/browser/test/EngineInitializerTest.java
deleted file mode 100644
index f1d8acc..0000000
--- a/src/com/android/browser/test/EngineInitializerTest.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- *  Copyright (c) 2014 The Linux Foundation. All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *      * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- *       copyright notice, this list of conditions and the following
- *       disclaimer in the documentation and/or other materials provided
- *       with the distribution.
- *     * Neither the name of The Linux Foundation nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- *  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- *  ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- *  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- *  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- *  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-package com.android.browser.test;
-
-import android.app.Activity;
-import android.app.Instrumentation;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.test.InstrumentationTestCase;
-import android.view.KeyEvent;
-
-import com.android.browser.BrowserActivity;
-import com.android.browser.BrowserPreferencesPage;
-import com.android.browser.EngineInitializer;
-
-public class EngineInitializerTest extends InstrumentationTestCase {
-
-    private Instrumentation mInstrumentation;
-    private Context mContext;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mInstrumentation = getInstrumentation();
-        mContext = getInstrumentation().getTargetContext();
-    }
-
-
-    public void test01() throws Throwable {
-        Intent localIntent = new Intent();
-        localIntent.setClassName("com.android.swe.browser", BrowserActivity.class.getName());
-        localIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
-
-        final Activity activity = mInstrumentation.startActivitySync(localIntent);
-
-        Intent restart = new Intent(BrowserActivity.ACTION_RESTART, null);
-        restart.setClassName("com.android.swe.browser", BrowserActivity.class.getName());
-        restart.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
-
-        mInstrumentation.callActivityOnNewIntent(activity, restart);
-
-        Thread.sleep(2000);
-
-        mInstrumentation.waitForIdleSync();
-
-        assertEquals(EngineInitializer.getInstance().isInitialized(), true);
-
-    }
-
-
-    public void test02() throws Throwable {
-
-        EngineInitializer.setDelayForTesting(1000);
-
-        Intent localIntent = new Intent();
-        localIntent.setClassName("com.android.swe.browser", BrowserActivity.class.getName());
-        localIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
-
-        final Activity browserActivity = mInstrumentation.startActivitySync(localIntent);
-
-        Intent pref = new Intent();
-        pref.setClassName("com.android.swe.browser", BrowserPreferencesPage.class.getName());
-        pref.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
-
-        final Activity preferencesActivity = mInstrumentation.startActivitySync(pref);
-
-        Thread.sleep(2000);
-
-        mInstrumentation.waitForIdleSync();
-
-        assertEquals(EngineInitializer.getInstance().isInitialized(), true);
-    }
-
-
-    public void test03() throws Throwable {
-
-        EngineInitializer.setDelayForTesting(2000);
-
-        Intent pref = new Intent();
-        pref.setClassName("com.android.swe.browser", BrowserPreferencesPage.class.getName());
-        pref.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
-
-        final Activity preferencesActivity = mInstrumentation.startActivitySync(pref);
-
-        assertEquals(EngineInitializer.getInstance().isInitialized(), true);
-
-        Intent localIntent = new Intent();
-        localIntent.setClassName("com.android.swe.browser", BrowserActivity.class.getName());
-        localIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
-
-        final Activity browserActivity = mInstrumentation.startActivitySync(localIntent);
-
-        Thread.sleep(3000);
-
-        mInstrumentation.waitForIdleSync();
-
-    }
-
-
-    public void test04() throws Throwable {
-
-        EngineInitializer.setDelayForTesting(2000);
-
-
-        Intent localIntent = new Intent();
-        localIntent.setClassName("com.android.swe.browser", BrowserActivity.class.getName());
-        localIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
-
-        final Activity browserActivity = mInstrumentation.startActivitySync(localIntent);
-
-        final Intent restart = new Intent(BrowserActivity.ACTION_RESTART, null);
-        restart.setClassName("com.android.swe.browser", BrowserActivity.class.getName());
-        restart.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
-
-        runTestOnUiThread(new Runnable () {
-            @Override
-            public void run() {
-                mInstrumentation.callActivityOnNewIntent(browserActivity, restart);
-            }
-        });
-
-        Intent pref = new Intent();
-        pref.setClassName("com.android.swe.browser", BrowserPreferencesPage.class.getName());
-        pref.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
-        final Activity preferencesActivity = mInstrumentation.startActivitySync(pref);
-
-        Thread.sleep(3000);
-
-        mInstrumentation.waitForIdleSync();
-
-        assertEquals(EngineInitializer.getInstance().isInitialized(), true);
-    }
-
-
-    public void test05() throws Throwable {
-
-        EngineInitializer.setDelayForTesting(2000);
-
-
-        Intent localIntent = new Intent();
-        localIntent.setClassName("com.android.swe.browser", BrowserActivity.class.getName());
-        localIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
-
-        final Activity browserActivity = mInstrumentation.startActivitySync(localIntent);
-
-        runTestOnUiThread(new Runnable () {
-            @Override
-            public void run() {
-                Bundle outState = new Bundle();
-                mInstrumentation.callActivityOnSaveInstanceState(browserActivity, outState);
-                mInstrumentation.callActivityOnDestroy(browserActivity);
-            }
-        });
-
-        Thread.sleep(3000);
-
-        mInstrumentation.waitForIdleSync();
-
-        assertEquals(EngineInitializer.getInstance().isInitialized(), true);
-    }
-
-
-    public void test06() throws Throwable {
-
-        EngineInitializer.setDelayForTesting(2000);
-
-
-        Intent localIntent = new Intent();
-        localIntent.setClassName("com.android.swe.browser", BrowserActivity.class.getName());
-        localIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
-
-        final Activity browserActivity = mInstrumentation.startActivitySync(localIntent);
-
-        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_MENU);
-
-        Thread.sleep(3000);
-
-        mInstrumentation.waitForIdleSync();
-
-        assertEquals(EngineInitializer.getInstance().isInitialized(), true);
-    }
-
-}