| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.android_webview.crash; | 5 package org.chromium.android_webview.crash; |
| 6 | 6 |
| 7 import android.annotation.TargetApi; | 7 import android.annotation.TargetApi; |
| 8 import android.app.Service; | 8 import android.app.Service; |
| 9 import android.app.job.JobInfo; | 9 import android.app.job.JobInfo; |
| 10 import android.app.job.JobScheduler; | |
| 11 import android.content.ComponentName; | |
| 12 import android.content.Context; | 10 import android.content.Context; |
| 13 import android.content.Intent; | 11 import android.content.Intent; |
| 14 import android.os.Binder; | 12 import android.os.Binder; |
| 15 import android.os.Build; | 13 import android.os.Build; |
| 16 import android.os.IBinder; | 14 import android.os.IBinder; |
| 17 import android.os.ParcelFileDescriptor; | 15 import android.os.ParcelFileDescriptor; |
| 16 import android.os.PersistableBundle; |
| 18 | 17 |
| 19 import org.chromium.base.Log; | 18 import org.chromium.base.Log; |
| 20 import org.chromium.base.VisibleForTesting; | 19 import org.chromium.base.VisibleForTesting; |
| 21 import org.chromium.components.minidump_uploader.CrashFileManager; | 20 import org.chromium.components.minidump_uploader.CrashFileManager; |
| 21 import org.chromium.components.minidump_uploader.MinidumpUploadJobService; |
| 22 | 22 |
| 23 import java.io.File; | 23 import java.io.File; |
| 24 import java.io.IOException; | 24 import java.io.IOException; |
| 25 | 25 |
| 26 /** | 26 /** |
| 27 * Service that is responsible for receiving crash dumps from an application, fo
r upload. | 27 * Service that is responsible for receiving crash dumps from an application, fo
r upload. |
| 28 */ | 28 */ |
| 29 @TargetApi(Build.VERSION_CODES.LOLLIPOP) | 29 @TargetApi(Build.VERSION_CODES.LOLLIPOP) |
| 30 public class CrashReceiverService extends Service { | 30 public class CrashReceiverService extends Service { |
| 31 private static final String TAG = "CrashReceiverService"; | 31 private static final String TAG = "CrashReceiverService"; |
| 32 | 32 |
| 33 private static final String WEBVIEW_CRASH_DIR = "WebView_Crashes"; | 33 private static final String WEBVIEW_CRASH_DIR = "WebView_Crashes"; |
| 34 private static final String WEBVIEW_TMP_CRASH_DIR = "WebView_Crashes_Tmp"; | 34 private static final String WEBVIEW_TMP_CRASH_DIR = "WebView_Crashes_Tmp"; |
| 35 | 35 |
| 36 private static final int MINIDUMP_UPLOADING_JOB_ID = 42; | |
| 37 // Initial back-off time for upload-job, this is set to a fairly high number
(30 minutes) to | |
| 38 // increase the chance of performing uploads in batches if the initial uploa
d fails. | |
| 39 private static final int JOB_BACKOFF_TIME_IN_MS = 1000 * 60 * 30; | |
| 40 // Back-off policy for upload-job. | |
| 41 private static final int JOB_BACKOFF_POLICY = JobInfo.BACKOFF_POLICY_EXPONEN
TIAL; | |
| 42 | |
| 43 private Object mCopyingLock = new Object(); | 36 private Object mCopyingLock = new Object(); |
| 44 private boolean mIsCopying = false; | 37 private boolean mIsCopying = false; |
| 45 | 38 |
| 46 @Override | 39 @Override |
| 47 public void onCreate() { | 40 public void onCreate() { |
| 48 super.onCreate(); | 41 super.onCreate(); |
| 49 } | 42 } |
| 50 | 43 |
| 51 private final ICrashReceiverService.Stub mBinder = new ICrashReceiverService
.Stub() { | 44 private final ICrashReceiverService.Stub mBinder = new ICrashReceiverService
.Stub() { |
| 52 @Override | 45 @Override |
| (...skipping 15 matching lines...) Expand all Loading... |
| 68 ParcelFileDescriptor[] fileDescriptors, boolean scheduleUploads) { | 61 ParcelFileDescriptor[] fileDescriptors, boolean scheduleUploads) { |
| 69 if (!waitUntilWeCanCopy()) { | 62 if (!waitUntilWeCanCopy()) { |
| 70 Log.e(TAG, "something went wrong when waiting to copy minidumps, bai
ling!"); | 63 Log.e(TAG, "something went wrong when waiting to copy minidumps, bai
ling!"); |
| 71 return; | 64 return; |
| 72 } | 65 } |
| 73 | 66 |
| 74 try { | 67 try { |
| 75 boolean copySucceeded = copyMinidumps(context, uid, fileDescriptors)
; | 68 boolean copySucceeded = copyMinidumps(context, uid, fileDescriptors)
; |
| 76 if (copySucceeded && scheduleUploads) { | 69 if (copySucceeded && scheduleUploads) { |
| 77 // Only schedule a new job if there actually are any files to up
load. | 70 // Only schedule a new job if there actually are any files to up
load. |
| 78 scheduleNewJob(); | 71 MinidumpUploadJobService.scheduleUpload(this, AwMinidumpUploadJo
bService.class, |
| 72 JobInfo.NETWORK_TYPE_UNMETERED, PersistableBundle.EMPTY)
; |
| 79 } | 73 } |
| 80 } finally { | 74 } finally { |
| 81 synchronized (mCopyingLock) { | 75 synchronized (mCopyingLock) { |
| 82 mIsCopying = false; | 76 mIsCopying = false; |
| 83 mCopyingLock.notifyAll(); | 77 mCopyingLock.notifyAll(); |
| 84 } | 78 } |
| 85 } | 79 } |
| 86 } | 80 } |
| 87 | 81 |
| 88 /** | 82 /** |
| 89 * Wait until we are allowed to copy minidumps. | 83 * Wait until we are allowed to copy minidumps. |
| 90 * @return whether we are actually allowed to copy the files - if false we s
hould just bail. | 84 * @return whether we are actually allowed to copy the files - if false we s
hould just bail. |
| 91 */ | 85 */ |
| 92 private boolean waitUntilWeCanCopy() { | 86 private boolean waitUntilWeCanCopy() { |
| 93 synchronized (mCopyingLock) { | 87 synchronized (mCopyingLock) { |
| 94 while (mIsCopying) { | 88 while (mIsCopying) { |
| 95 try { | 89 try { |
| 96 mCopyingLock.wait(); | 90 mCopyingLock.wait(); |
| 97 } catch (InterruptedException e) { | 91 } catch (InterruptedException e) { |
| 98 Log.e(TAG, "Was interrupted when waiting to copy minidumps",
e); | 92 Log.e(TAG, "Was interrupted when waiting to copy minidumps",
e); |
| 99 return false; | 93 return false; |
| 100 } | 94 } |
| 101 } | 95 } |
| 102 mIsCopying = true; | 96 mIsCopying = true; |
| 103 return true; | 97 return true; |
| 104 } | 98 } |
| 105 } | 99 } |
| 106 | 100 |
| 107 private void scheduleNewJob() { | |
| 108 JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_
SCHEDULER_SERVICE); | |
| 109 JobInfo newJob = new JobInfo | |
| 110 .Builder(MINIDUMP_UPLOADING_JOB_ID /* jobId */, | |
| 111 new ComponentName(this, AwMinidumpUploa
dJobService.class)) | |
| 112 .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UN
METERED) | |
| 113 // Minimum delay when a job is retried (a retry
will happen when | |
| 114 // there are minidumps left after trying to upl
oad all minidumps - | |
| 115 // this could e.g. happen if we add more minidu
mps at the same time | |
| 116 // as uploading old ones). | |
| 117 .setBackoffCriteria(JOB_BACKOFF_TIME_IN_MS, JOB
_BACKOFF_POLICY) | |
| 118 .build(); | |
| 119 if (jobScheduler.schedule(newJob) == JobScheduler.RESULT_FAILURE) { | |
| 120 throw new RuntimeException("couldn't schedule " + newJob); | |
| 121 } | |
| 122 } | |
| 123 | |
| 124 /** | 101 /** |
| 125 * Copy minidumps from the {@param fileDescriptors} to the directory where W
ebView stores its | 102 * Copy minidumps from the {@param fileDescriptors} to the directory where W
ebView stores its |
| 126 * minidump files. {@param context} is used to look up the directory in whic
h the files will be | 103 * minidump files. {@param context} is used to look up the directory in whic
h the files will be |
| 127 * saved. | 104 * saved. |
| 128 * @return whether any minidump was copied. | 105 * @return whether any minidump was copied. |
| 129 */ | 106 */ |
| 130 @VisibleForTesting | 107 @VisibleForTesting |
| 131 public static boolean copyMinidumps( | 108 public static boolean copyMinidumps( |
| 132 Context context, int uid, ParcelFileDescriptor[] fileDescriptors) { | 109 Context context, int uid, ParcelFileDescriptor[] fileDescriptors) { |
| 133 CrashFileManager crashFileManager = new CrashFileManager(createWebViewCr
ashDir(context)); | 110 CrashFileManager crashFileManager = new CrashFileManager(createWebViewCr
ashDir(context)); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 211 @VisibleForTesting | 188 @VisibleForTesting |
| 212 public static File getWebViewTmpCrashDir(Context context) { | 189 public static File getWebViewTmpCrashDir(Context context) { |
| 213 return new File(context.getCacheDir(), WEBVIEW_TMP_CRASH_DIR); | 190 return new File(context.getCacheDir(), WEBVIEW_TMP_CRASH_DIR); |
| 214 } | 191 } |
| 215 | 192 |
| 216 @Override | 193 @Override |
| 217 public IBinder onBind(Intent intent) { | 194 public IBinder onBind(Intent intent) { |
| 218 return mBinder; | 195 return mBinder; |
| 219 } | 196 } |
| 220 } | 197 } |
| OLD | NEW |