| 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 da9b5c71430d53507317473f94ca65faec56fbb5..a2b3aed6310c8feca9be0393bf9479e67c7b1316 100644
|
| --- a/chrome/android/java/src/org/chromium/chrome/browser/DeferredStartupHandler.java
|
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/DeferredStartupHandler.java
|
| @@ -6,46 +6,17 @@ package org.chromium.chrome.browser;
|
|
|
| import android.annotation.SuppressLint;
|
| import android.content.Context;
|
| -import android.content.SharedPreferences;
|
| -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;
|
|
|
| import org.chromium.base.ContextUtils;
|
| -import org.chromium.base.Log;
|
| -import org.chromium.base.PowerMonitor;
|
| import org.chromium.base.ThreadUtils;
|
| -import org.chromium.base.TraceEvent;
|
| import org.chromium.base.VisibleForTesting;
|
| import org.chromium.base.metrics.RecordHistogram;
|
| -import org.chromium.chrome.browser.bookmarkswidget.BookmarkWidgetProvider;
|
| -import org.chromium.chrome.browser.crash.LogcatExtractionRunnable;
|
| -import org.chromium.chrome.browser.crash.MinidumpUploadService;
|
| -import org.chromium.chrome.browser.init.ProcessInitializationHandler;
|
| -import org.chromium.chrome.browser.metrics.LaunchMetrics;
|
| import org.chromium.chrome.browser.metrics.UmaUtils;
|
| -import org.chromium.chrome.browser.notifications.ChannelsUpdater;
|
| -import org.chromium.chrome.browser.ntp.NewTabPage;
|
| -import org.chromium.chrome.browser.offlinepages.OfflinePageUtils;
|
| -import org.chromium.chrome.browser.partnerbookmarks.PartnerBookmarksShim;
|
| -import org.chromium.chrome.browser.partnercustomizations.HomepageManager;
|
| -import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomizations;
|
| -import org.chromium.chrome.browser.precache.PrecacheLauncher;
|
| -import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
|
| -import org.chromium.chrome.browser.share.ShareHelper;
|
| -import org.chromium.chrome.browser.webapps.ChromeWebApkHost;
|
| -import org.chromium.chrome.browser.webapps.WebApkVersionManager;
|
| -import org.chromium.chrome.browser.webapps.WebappRegistry;
|
| -import org.chromium.components.minidump_uploader.CrashFileManager;
|
|
|
| -import java.io.File;
|
| -import java.util.Arrays;
|
| -import java.util.Date;
|
| import java.util.LinkedList;
|
| -import java.util.List;
|
| import java.util.Queue;
|
| import java.util.concurrent.TimeUnit;
|
|
|
| @@ -53,18 +24,11 @@ import java.util.concurrent.TimeUnit;
|
| * Handler for application level tasks to be completed on deferred startup.
|
| */
|
| public class DeferredStartupHandler {
|
| - private static final String TAG = "DeferredStartup";
|
| - /** 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";
|
| - private static final String SNAPSHOT_DATABASE_NAME = "snapshots.db";
|
| -
|
| private static class Holder {
|
| @SuppressLint("StaticFieldLeak")
|
| private static final DeferredStartupHandler INSTANCE = new DeferredStartupHandler();
|
| }
|
|
|
| - private boolean mDeferredStartupInitializedForApp;
|
| private boolean mDeferredStartupCompletedForApp;
|
| private long mDeferredStartupDuration;
|
| private long mMaxTaskDuration;
|
| @@ -106,7 +70,7 @@ public class DeferredStartupHandler {
|
| public boolean queueIdle() {
|
| Runnable currentTask = mDeferredTasks.poll();
|
| if (currentTask == null) {
|
| - if (mDeferredStartupInitializedForApp && !mDeferredStartupCompletedForApp) {
|
| + if (!mDeferredStartupCompletedForApp) {
|
| mDeferredStartupCompletedForApp = true;
|
| recordDeferredStartupStats();
|
| }
|
| @@ -149,246 +113,6 @@ public class DeferredStartupHandler {
|
| }
|
|
|
| /**
|
| - * 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 initDeferredStartupForApp() {
|
| - if (mDeferredStartupInitializedForApp) return;
|
| - mDeferredStartupInitializedForApp = true;
|
| - ThreadUtils.assertOnUiThread();
|
| -
|
| - RecordHistogram.recordLongTimesHistogram("UMA.Debug.EnableCrashUpload.DeferredStartUptime2",
|
| - SystemClock.uptimeMillis() - UmaUtils.getForegroundStartTime(),
|
| - TimeUnit.MILLISECONDS);
|
| -
|
| - mDeferredTasks.add(new Runnable() {
|
| - @Override
|
| - public void run() {
|
| - // Punt all tasks that may block on disk off onto a background thread.
|
| - initAsyncDiskTask();
|
| -
|
| - DefaultBrowserInfo.initBrowserFetcher();
|
| -
|
| - 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();
|
| -
|
| - ShareHelper.clearSharedImages();
|
| -
|
| - OfflinePageUtils.clearSharedOfflineFiles(mAppContext);
|
| -
|
| - if (ChannelsUpdater.getInstance().shouldUpdateChannels()) {
|
| - initChannelsAsync();
|
| - }
|
| - }
|
| - });
|
| -
|
| - ProcessInitializationHandler.getInstance().initializeDeferredStartupTasks();
|
| - }
|
| -
|
| - private void initChannelsAsync() {
|
| - new AsyncTask<Void, Void, Void>() {
|
| - @Override
|
| - protected Void doInBackground(Void... params) {
|
| - ChannelsUpdater.getInstance().updateChannels();
|
| - return null;
|
| - }
|
| -
|
| - }
|
| - .executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
|
| - }
|
| -
|
| - private void initAsyncDiskTask() {
|
| - new AsyncTask<Void, Void, Void>() {
|
| - /**
|
| - * The threshold after which it's no longer appropriate to try to attach logcat output
|
| - * to a minidump file.
|
| - * Note: This threshold of 12 hours was chosen fairly imprecisely, based on the
|
| - * following intuition: On the one hand, Chrome can only access its own logcat output,
|
| - * so the most recent lines should be relevant when available. On a typical device,
|
| - * multiple hours of logcat output are available. On the other hand, it's important to
|
| - * provide an escape hatch in case the logcat extraction code itself crashes, as
|
| - * described in the doesCrashMinidumpNeedLogcat() documentation. Since this is a fairly
|
| - * small and relatively frequently-executed piece of code, crashes are expected to be
|
| - * unlikely; so it's okay for the escape hatch to be hard to use -- it's intended as an
|
| - * extreme last resort.
|
| - */
|
| - private static final long LOGCAT_RELEVANCE_THRESHOLD_IN_HOURS = 12;
|
| -
|
| - private long mAsyncTaskStartTime;
|
| -
|
| - @Override
|
| - protected Void doInBackground(Void... params) {
|
| - try {
|
| - TraceEvent.begin("ChromeBrowserInitializer.onDeferredStartup.doInBackground");
|
| - mAsyncTaskStartTime = SystemClock.uptimeMillis();
|
| -
|
| - initCrashReporting();
|
| -
|
| - // Initialize the WebappRegistry if it's not already initialized. Must be in
|
| - // async task due to shared preferences disk access on N.
|
| - WebappRegistry.getInstance();
|
| -
|
| - // Force a widget refresh in order to wake up any possible zombie widgets.
|
| - // This is needed to ensure the right behavior when the process is suddenly
|
| - // killed.
|
| - BookmarkWidgetProvider.refreshAllWidgets(mAppContext);
|
| -
|
| - // Initialize whether or not precaching is enabled.
|
| - PrecacheLauncher.updatePrecachingEnabled(mAppContext);
|
| -
|
| - if (ChromeWebApkHost.isEnabled()) {
|
| - WebApkVersionManager.updateWebApksIfNeeded();
|
| - }
|
| -
|
| - removeSnapshotDatabase();
|
| -
|
| - // Warm up all web app shared prefs. This must be run after the WebappRegistry
|
| - // instance is initialized.
|
| - WebappRegistry.warmUpSharedPrefs();
|
| -
|
| - return null;
|
| - } finally {
|
| - TraceEvent.end("ChromeBrowserInitializer.onDeferredStartup.doInBackground");
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - protected void onPostExecute(Void params) {
|
| - // Must be run on the UI thread after the WebappRegistry has been completely warmed.
|
| - WebappRegistry.getInstance().unregisterOldWebapps(System.currentTimeMillis());
|
| -
|
| - RecordHistogram.recordLongTimesHistogram(
|
| - "UMA.Debug.EnableCrashUpload.DeferredStartUpAsyncTaskDuration",
|
| - SystemClock.uptimeMillis() - mAsyncTaskStartTime, TimeUnit.MILLISECONDS);
|
| - }
|
| -
|
| - /**
|
| - * Initializes the crash reporting system. More specifically, enables the crash
|
| - * reporting system if it is user-permitted, and initiates uploading of any pending
|
| - * crash reports. Also updates some UMA metrics and performs cleanup in the local crash
|
| - * minidump storage directory.
|
| - */
|
| - private void initCrashReporting() {
|
| - RecordHistogram.recordLongTimesHistogram("UMA.Debug.EnableCrashUpload.Uptime3",
|
| - mAsyncTaskStartTime - UmaUtils.getForegroundStartTime(),
|
| - TimeUnit.MILLISECONDS);
|
| -
|
| - // Crash reports can be uploaded as part of a background service even while the main
|
| - // Chrome activity is not running, and hence regular metrics reporting is not
|
| - // possible. Instead, metrics are temporarily written to prefs; export those prefs
|
| - // to UMA metrics here.
|
| - MinidumpUploadService.storeBreakpadUploadStatsInUma(
|
| - ChromePreferenceManager.getInstance());
|
| -
|
| - // Likewise, this is a good time to process and clean up any pending or stale crash
|
| - // reports left behind by previous runs.
|
| - CrashFileManager crashFileManager =
|
| - new CrashFileManager(ContextUtils.getApplicationContext().getCacheDir());
|
| - crashFileManager.cleanOutAllNonFreshMinidumpFiles();
|
| -
|
| - // Finally, uploading any pending crash reports.
|
| - File[] minidumps = crashFileManager.getAllMinidumpFiles(
|
| - MinidumpUploadService.MAX_TRIES_ALLOWED);
|
| - int numMinidumpsSansLogcat = 0;
|
| - for (File minidump : minidumps) {
|
| - if (CrashFileManager.isMinidumpMIMEFirstTry(minidump.getName())) {
|
| - ++numMinidumpsSansLogcat;
|
| - }
|
| - }
|
| - // TODO(isherman): These two histograms are intended to be temporary, and can
|
| - // probably be removed around the M60 timeframe: http://crbug.com/699785
|
| - RecordHistogram.recordSparseSlowlyHistogram(
|
| - "Stability.Android.PendingMinidumpsOnStartup", minidumps.length);
|
| - RecordHistogram.recordSparseSlowlyHistogram(
|
| - "Stability.Android.PendingMinidumpsOnStartup.SansLogcat",
|
| - numMinidumpsSansLogcat);
|
| - if (minidumps.length == 0) return;
|
| -
|
| - Log.i(TAG, "Attempting to upload %d accumulated crash dumps.", minidumps.length);
|
| - File mostRecentMinidump = minidumps[0];
|
| - if (doesCrashMinidumpNeedLogcat(mostRecentMinidump)) {
|
| - AsyncTask.THREAD_POOL_EXECUTOR.execute(
|
| - new LogcatExtractionRunnable(mostRecentMinidump));
|
| -
|
| - // The JobScheduler will schedule uploads for all of the available minidumps
|
| - // once the logcat is attached. But if the JobScheduler API is not being used,
|
| - // then the logcat extraction process will only initiate an upload for the first
|
| - // minidump; it's required to manually initiate uploads for all of the remaining
|
| - // minidumps.
|
| - if (!MinidumpUploadService.shouldUseJobSchedulerForUploads()) {
|
| - List<File> remainingMinidumps =
|
| - Arrays.asList(minidumps).subList(1, minidumps.length);
|
| - for (File minidump : remainingMinidumps) {
|
| - MinidumpUploadService.tryUploadCrashDump(minidump);
|
| - }
|
| - }
|
| - } else if (MinidumpUploadService.shouldUseJobSchedulerForUploads()) {
|
| - MinidumpUploadService.scheduleUploadJob();
|
| - } else {
|
| - MinidumpUploadService.tryUploadAllCrashDumps();
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Returns whether or not it's appropriate to try to extract recent logcat output and
|
| - * include that logcat output alongside the given {@param minidump} in a crash report.
|
| - * Logcat output should only be extracted if (a) it hasn't already been extracted for
|
| - * this minidump file, and (b) the minidump is fairly fresh. The freshness check is
|
| - * important for two reasons: (1) First of all, it helps avoid including irrelevant
|
| - * logcat output for a crash report. (2) Secondly, it provides an escape hatch that can
|
| - * help circumvent a possible infinite crash loop, if the code responsible for
|
| - * extracting and appending the logcat content is itself crashing. That is, the user can
|
| - * wait 12 hours prior to relaunching Chrome, at which point this potential crash loop
|
| - * would be circumvented.
|
| - * @return Whether to try to include logcat output in the crash report corresponding to
|
| - * the given minidump.
|
| - */
|
| - private boolean doesCrashMinidumpNeedLogcat(File minidump) {
|
| - if (!CrashFileManager.isMinidumpMIMEFirstTry(minidump.getName())) return false;
|
| -
|
| - long ageInMillis = new Date().getTime() - minidump.lastModified();
|
| - long ageInHours = TimeUnit.HOURS.convert(ageInMillis, TimeUnit.MILLISECONDS);
|
| - return ageInHours < LOGCAT_RELEVANCE_THRESHOLD_IN_HOURS;
|
| - }
|
| - }
|
| - .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
| - }
|
| -
|
| - /**
|
| - * Deletes the snapshot database which is no longer used because the feature has been removed
|
| - * in Chrome M41.
|
| - */
|
| - @WorkerThread
|
| - private void removeSnapshotDatabase() {
|
| - synchronized (SNAPSHOT_DATABASE_LOCK) {
|
| - SharedPreferences prefs = ContextUtils.getAppSharedPreferences();
|
| - if (!prefs.getBoolean(SNAPSHOT_DATABASE_REMOVED, false)) {
|
| - mAppContext.deleteDatabase(SNAPSHOT_DATABASE_NAME);
|
| - prefs.edit().putBoolean(SNAPSHOT_DATABASE_REMOVED, true).apply();
|
| - }
|
| - }
|
| - }
|
| -
|
| - /**
|
| * @return Whether deferred startup has been completed.
|
| */
|
| @VisibleForTesting
|
|
|