| Index: chrome/android/java/src/org/chromium/chrome/browser/DeferredStartupHandler.java
|
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/DeferredStartupHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/DeferredStartupHandler.java
|
| index 1e73dc2ec94a3d73f5509e6e9b3036e0342facf1..d222b8e15a16b14bc88639480c3c1926f7b0ad88 100644
|
| --- a/chrome/android/java/src/org/chromium/chrome/browser/DeferredStartupHandler.java
|
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/DeferredStartupHandler.java
|
| @@ -10,6 +10,8 @@ import android.content.SharedPreferences;
|
| import android.content.pm.ResolveInfo;
|
| import android.net.Uri;
|
| import android.os.AsyncTask;
|
| +import android.os.Looper;
|
| +import android.os.MessageQueue;
|
| import android.os.SystemClock;
|
| import android.support.annotation.UiThread;
|
| import android.support.annotation.WorkerThread;
|
| @@ -45,14 +47,17 @@ import org.chromium.chrome.browser.webapps.WebApkVersionManager;
|
| import org.chromium.content.browser.ChildProcessLauncher;
|
|
|
| import java.util.ArrayList;
|
| +import java.util.LinkedList;
|
| import java.util.List;
|
| import java.util.Locale;
|
| +import java.util.Queue;
|
| import java.util.concurrent.TimeUnit;
|
|
|
| /**
|
| * Handler for application level tasks to be completed on deferred startup.
|
| */
|
| public class DeferredStartupHandler {
|
| + private static final String TAG = "DeferredStartupHandler";
|
| /** Prevents race conditions when deleting snapshot database. */
|
| private static final Object SNAPSHOT_DATABASE_LOCK = new Object();
|
| private static final String SNAPSHOT_DATABASE_REMOVED = "snapshot_database_removed";
|
| @@ -62,8 +67,12 @@ public class DeferredStartupHandler {
|
| private static final DeferredStartupHandler INSTANCE = new DeferredStartupHandler();
|
| }
|
|
|
| - private boolean mDeferredStartupComplete;
|
| + private boolean mDeferredStartupInitialized;
|
| + private boolean mDeferredStartupCompleted;
|
| + private long mDeferredStartupDuration;
|
| + private long mMaxTaskDuration;
|
| private final Context mAppContext;
|
| + private final Queue<Runnable> mDeferredTasks;
|
|
|
| /**
|
| * This class is an application specific object that handles the deferred startup.
|
| @@ -75,25 +84,147 @@ public class DeferredStartupHandler {
|
|
|
| private DeferredStartupHandler() {
|
| mAppContext = ContextUtils.getApplicationContext();
|
| + mDeferredTasks = new LinkedList<Runnable>();
|
| + }
|
| +
|
| + /**
|
| + * Initialize and run the next deferred startup task in sequence on the idle handler.
|
| + */
|
| + public void runDeferredTasks() {
|
| + if (!mDeferredStartupInitialized) return;
|
| +
|
| + // Add UMA task last so we get accurate timing.
|
| + mDeferredTasks.add(new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + RecordHistogram.recordLongTimesHistogram(
|
| + "UMA.Debug.EnableCrashUpload.DeferredStartUpDuration",
|
| + mDeferredStartupDuration,
|
| + TimeUnit.MILLISECONDS);
|
| + RecordHistogram.recordLongTimesHistogram(
|
| + "UMA.Debug.EnableCrashUpload.DeferredStartUpMaxTaskDuration",
|
| + mMaxTaskDuration,
|
| + TimeUnit.MILLISECONDS);
|
| + RecordHistogram.recordLongTimesHistogram(
|
| + "UMA.Debug.EnableCrashUpload.DeferredStartUpCompleteTime",
|
| + SystemClock.uptimeMillis() - UmaUtils.getForegroundStartTime(),
|
| + TimeUnit.MILLISECONDS);
|
| + }
|
| + });
|
| +
|
| + Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
|
| + @Override
|
| + public boolean queueIdle() {
|
| + Runnable currentTask = mDeferredTasks.poll();
|
| + if (currentTask == null) {
|
| + mDeferredStartupCompleted = true;
|
| + return false;
|
| + }
|
| +
|
| + long startTime = SystemClock.uptimeMillis();
|
| + currentTask.run();
|
| + long timeTaken = SystemClock.uptimeMillis() - startTime;
|
| +
|
| + mMaxTaskDuration = Math.max(mMaxTaskDuration, timeTaken);
|
| + mDeferredStartupDuration += timeTaken;
|
| + return true;
|
| + }
|
| + });
|
| + }
|
| +
|
| + /**
|
| + * Adds a single deferred task to the queue.
|
| + *
|
| + * @param deferredTask The tasks to be run.
|
| + */
|
| + public void addDeferredTask(Runnable deferredTask) {
|
| + if (mDeferredStartupCompleted) {
|
| + throw new RuntimeException("Scheduling deferred startup task that will never be run.");
|
| + }
|
| + ThreadUtils.assertOnUiThread();
|
| + mDeferredTasks.add(deferredTask);
|
| }
|
|
|
| /**
|
| * Handle application level deferred startup tasks that can be lazily done after all
|
| * the necessary initialization has been completed. Any calls requiring network access should
|
| * probably go here.
|
| + *
|
| + * Keep these tasks short and break up long tasks into multiple smaller tasks, as they run on
|
| + * the UI thread and are blocking. Remember to follow RAIL guidelines, as much as possible, and
|
| + * that most devices are quite slow, so leave enough buffer.
|
| */
|
| @UiThread
|
| - public void onDeferredStartupForApp() {
|
| - if (mDeferredStartupComplete) return;
|
| + public void initDeferredStartupForApp() {
|
| + if (mDeferredStartupInitialized) return;
|
| + mDeferredStartupInitialized = true;
|
| ThreadUtils.assertOnUiThread();
|
|
|
| - long startDeferredStartupTime = SystemClock.uptimeMillis();
|
| -
|
| - RecordHistogram.recordLongTimesHistogram("UMA.Debug.EnableCrashUpload.DeferredStartUptime",
|
| - startDeferredStartupTime - UmaUtils.getMainEntryPointTime(),
|
| + RecordHistogram.recordLongTimesHistogram(
|
| + "UMA.Debug.EnableCrashUpload.DeferredStartUptime2",
|
| + SystemClock.uptimeMillis() - UmaUtils.getForegroundStartTime(),
|
| TimeUnit.MILLISECONDS);
|
|
|
| - // Punt all tasks that may block the UI thread off onto a background thread.
|
| + mDeferredTasks.add(new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + // Punt all tasks that may block on disk off onto a background thread.
|
| + initAsyncDiskTask();
|
| +
|
| + AfterStartupTaskUtils.setStartupComplete();
|
| +
|
| + PartnerBrowserCustomizations.setOnInitializeAsyncFinished(new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + String homepageUrl = HomepageManager.getHomepageUri(mAppContext);
|
| + LaunchMetrics.recordHomePageLaunchMetrics(
|
| + HomepageManager.isHomepageEnabled(mAppContext),
|
| + NewTabPage.isNTPUrl(homepageUrl), homepageUrl);
|
| + }
|
| + });
|
| +
|
| + PartnerBookmarksShim.kickOffReading(mAppContext);
|
| +
|
| + PowerMonitor.create(mAppContext);
|
| +
|
| + ShareHelper.clearSharedImages(mAppContext);
|
| + }
|
| + });
|
| +
|
| + mDeferredTasks.add(new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + // Clear any media notifications that existed when Chrome was last killed.
|
| + MediaCaptureNotificationService.clearMediaNotifications(mAppContext);
|
| +
|
| + startModerateBindingManagementIfNeeded();
|
| +
|
| + recordKeyboardLocaleUma();
|
| + }
|
| + });
|
| +
|
| + final ChromeApplication application = (ChromeApplication) mAppContext;
|
| + mDeferredTasks.add(new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + // Start or stop Physical Web
|
| + PhysicalWeb.onChromeStart(application);
|
| + }
|
| + });
|
| +
|
| + mDeferredTasks.add(new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + // Starts syncing with GSA.
|
| + application.createGsaHelper().startSync();
|
| + }
|
| + });
|
| +
|
| + // This call will add its own tasks to the queue.
|
| + application.initializeSharedClasses();
|
| + }
|
| +
|
| + private void initAsyncDiskTask() {
|
| new AsyncTask<Void, Void, Void>() {
|
| @Override
|
| protected Void doInBackground(Void... params) {
|
| @@ -104,8 +235,8 @@ public class DeferredStartupHandler {
|
| ChromeSwitches.DISABLE_CRASH_DUMP_UPLOAD);
|
| if (!crashDumpDisabled) {
|
| RecordHistogram.recordLongTimesHistogram(
|
| - "UMA.Debug.EnableCrashUpload.Uptime2",
|
| - asyncTaskStartTime - UmaUtils.getMainEntryPointTime(),
|
| + "UMA.Debug.EnableCrashUpload.Uptime3",
|
| + asyncTaskStartTime - UmaUtils.getForegroundStartTime(),
|
| TimeUnit.MILLISECONDS);
|
| PrivacyPreferencesManager.getInstance().enablePotentialCrashUploading();
|
| MinidumpUploadService.tryUploadAllCrashDumps(mAppContext);
|
| @@ -144,48 +275,6 @@ public class DeferredStartupHandler {
|
| }
|
| }
|
| }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
| -
|
| - AfterStartupTaskUtils.setStartupComplete();
|
| -
|
| - PartnerBrowserCustomizations.setOnInitializeAsyncFinished(new Runnable() {
|
| - @Override
|
| - public void run() {
|
| - String homepageUrl = HomepageManager.getHomepageUri(mAppContext);
|
| - LaunchMetrics.recordHomePageLaunchMetrics(
|
| - HomepageManager.isHomepageEnabled(mAppContext),
|
| - NewTabPage.isNTPUrl(homepageUrl), homepageUrl);
|
| - }
|
| - });
|
| -
|
| - // TODO(aruslan): http://b/6397072 This will be moved elsewhere
|
| - PartnerBookmarksShim.kickOffReading(mAppContext);
|
| -
|
| - PowerMonitor.create(mAppContext);
|
| -
|
| - ShareHelper.clearSharedImages(mAppContext);
|
| -
|
| - // Clear any media notifications that existed when Chrome was last killed.
|
| - MediaCaptureNotificationService.clearMediaNotifications(mAppContext);
|
| -
|
| - startModerateBindingManagementIfNeeded();
|
| -
|
| - recordKeyboardLocaleUma();
|
| -
|
| - ChromeApplication application = (ChromeApplication) mAppContext;
|
| - // Starts syncing with GSA.
|
| - application.createGsaHelper().startSync();
|
| -
|
| - application.initializeSharedClasses();
|
| -
|
| - // Start or stop Physical Web
|
| - PhysicalWeb.onChromeStart(application);
|
| -
|
| - mDeferredStartupComplete = true;
|
| -
|
| - RecordHistogram.recordLongTimesHistogram(
|
| - "UMA.Debug.EnableCrashUpload.DeferredStartUpDuration",
|
| - SystemClock.uptimeMillis() - startDeferredStartupTime,
|
| - TimeUnit.MILLISECONDS);
|
| }
|
|
|
| private void startModerateBindingManagementIfNeeded() {
|
| @@ -262,6 +351,6 @@ public class DeferredStartupHandler {
|
| */
|
| @VisibleForTesting
|
| public boolean isDeferredStartupComplete() {
|
| - return mDeferredStartupComplete;
|
| + return mDeferredStartupCompleted;
|
| }
|
| }
|
|
|