Chromium Code Reviews| 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..aa7f895b9426f6431e9cd95c1ac420bb8c03eb7a 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,18 @@ import org.chromium.chrome.browser.webapps.WebApkVersionManager; |
| import org.chromium.content.browser.ChildProcessLauncher; |
| import java.util.ArrayList; |
| +import java.util.Collection; |
| +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 +68,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 +85,155 @@ 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) { |
|
Yaron
2016/07/06 14:27:49
Use varags: (i.e. Runnable ... ) and you can drop
Peter Wen
2016/07/06 15:21:36
Done.
|
| + mDeferredTasks.add(deferredTask); |
|
Yaron
2016/07/06 14:27:50
this should error if mDeferredStartupCompleted is
Peter Wen
2016/07/06 15:21:37
Done.
|
| + } |
| + |
| + /** |
| + * Adds a collection of deferred tasks to the queue. |
| + * |
| + * @param deferredTasks The tasks to be run. |
| + */ |
| + public void addDeferredTasks(Collection<Runnable> deferredTasks) { |
| + mDeferredTasks.addAll(deferredTasks); |
| } |
| /** |
| * 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); |
| + } |
| + }); |
| + |
| + // TODO(aruslan): http://b/6397072 This will be moved elsewhere |
|
pasko
2016/07/06 13:03:31
While we are here, let's remove the TODO? It was m
Peter Wen
2016/07/06 15:21:36
Done.
|
| + 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(); |
| + } |
| + }); |
| + |
| + mDeferredTasks.add(new Runnable() { |
| + @Override |
| + public void run() { |
| + ChromeApplication application = (ChromeApplication) mAppContext; |
| + // Start or stop Physical Web |
| + PhysicalWeb.onChromeStart(application); |
| + } |
| + }); |
| + |
| + mDeferredTasks.add(new Runnable() { |
| + @Override |
| + public void run() { |
| + ChromeApplication application = (ChromeApplication) mAppContext; |
|
Yaron
2016/07/06 14:27:50
this is done a few times. just do:
final ChromeApp
Peter Wen
2016/07/06 15:21:37
Done.
|
| + // Starts syncing with GSA. |
| + application.createGsaHelper().startSync(); |
| + } |
| + }); |
| + |
| + // This call will add its own tasks to the queue. |
| + ChromeApplication application = (ChromeApplication) mAppContext; |
| + application.initializeSharedClasses(); |
| + } |
| + |
| + private void initAsyncDiskTask() { |
| new AsyncTask<Void, Void, Void>() { |
| @Override |
| protected Void doInBackground(Void... params) { |
| @@ -104,8 +244,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 +284,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 +360,6 @@ public class DeferredStartupHandler { |
| */ |
| @VisibleForTesting |
| public boolean isDeferredStartupComplete() { |
| - return mDeferredStartupComplete; |
| + return mDeferredStartupCompleted; |
| } |
| } |