Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1353)

Side by Side Diff: chrome/android/java_staging/src/org/chromium/chrome/browser/crash/MinidumpUploadService.java

Issue 1141283003: Upstream oodles of Chrome for Android code into Chromium. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: final patch? Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.chrome.browser.crash;
6
7 import android.app.IntentService;
8 import android.content.Context;
9 import android.content.Intent;
10 import android.content.SharedPreferences;
11 import android.os.AsyncTask;
12 import android.preference.PreferenceManager;
13 import android.util.Log;
14
15 import org.chromium.base.VisibleForTesting;
16 import org.chromium.base.metrics.RecordUserAction;
17 import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
18 import org.chromium.chrome.browser.preferences.privacy.PrivacyPreferencesManager ;
19
20 import java.io.File;
21
22 /**
23 * Service that is responsible for uploading crash minidumps to the Google crash server.
24 */
25 public class MinidumpUploadService extends IntentService {
26
27 private static final String TAG = "MinidumpUploadService";
28
29 // Intent actions
30 private static final String ACTION_FIND_LAST =
31 "com.google.android.apps.chrome.crash.ACTION_FIND_LAST";
32 @VisibleForTesting
33 static final String ACTION_FIND_ALL =
34 "com.google.android.apps.chrome.crash.ACTION_FIND_ALL";
35 @VisibleForTesting
36 static final String ACTION_UPLOAD =
37 "com.google.android.apps.chrome.crash.ACTION_UPLOAD";
38
39 // Intent bundle keys
40 @VisibleForTesting
41 static final String FILE_TO_UPLOAD_KEY = "minidump_file";
42 static final String UPLOAD_LOG_KEY = "upload_log";
43
44 /**
45 * The number of times we will try to upload a crash.
46 */
47 @VisibleForTesting
48 static final int MAX_TRIES_ALLOWED = 3;
49
50 public MinidumpUploadService() {
51 super(TAG);
52 setIntentRedelivery(true);
53 }
54
55 @Override
56 public void onCreate() {
57 super.onCreate();
58 if (isMiniDumpCleanNeeded()) {
59 final CrashFileManager crashFileManager =
60 new CrashFileManager(getApplicationContext().getCacheDir());
61 // Cleaning minidumps in a background not to block the Ui thread.
62 // NOTE: {@link CrashFileManager#cleanAllMiniDumps()} is not thread- safe and can
63 // possibly result in race condition by calling from multiple thread s. However, this
64 // should only result in warning messages in logs.
65 new AsyncTask<Void, Void, Void>() {
66 @Override
67 protected Void doInBackground(Void... params) {
68 crashFileManager.cleanAllMiniDumps();
69 return null;
70 }
71 }.execute();
72 }
73 }
74
75 @Override
76 protected void onHandleIntent(Intent intent) {
77 if (intent == null) return;
78 if (ACTION_FIND_LAST.equals(intent.getAction())) {
79 handleFindAndUploadLastCrash(intent);
80 } else if (ACTION_FIND_ALL.equals(intent.getAction())) {
81 handleFindAndUploadAllCrashes();
82 } else if (ACTION_UPLOAD.equals(intent.getAction())) {
83 handleUploadCrash(intent);
84 } else {
85 Log.w(TAG, "Got unknown action from intent: " + intent.getAction());
86 }
87 }
88
89 /**
90 * Creates an intent that when started will find the last created minidump,
91 * and try to upload it.
92 *
93 * @param context the context to use for the intent.
94 * @return an Intent to use to start the service.
95 */
96 public static Intent createFindAndUploadLastCrashIntent(Context context) {
97 Intent intent = new Intent(context, MinidumpUploadService.class);
98 intent.setAction(ACTION_FIND_LAST);
99 return intent;
100 }
101
102 public static void storeBreakpadUploadAttemptsInUma(ChromePreferenceManager pref) {
103 for (int success = pref.getBreakpadUploadSuccessCount(); success > 0; su ccess--) {
104 RecordUserAction.record("MobileBreakpadUploadSuccess");
105 }
106
107 for (int fail = pref.getBreakpadUploadFailCount(); fail > 0; fail--) {
108 RecordUserAction.record("MobileBreakpadUploadFail");
109 }
110
111 pref.setBreakpadUploadSuccessCount(0);
112 pref.setBreakpadUploadFailCount(0);
113 }
114
115 private void handleFindAndUploadLastCrash(Intent intent) {
116 CrashFileManager fileManager = new CrashFileManager(getApplicationContex t().getCacheDir());
117 File[] minidumpFiles = fileManager.getAllMinidumpFilesSorted();
118 if (minidumpFiles.length == 0) {
119 // Try again later. Maybe the minidump hasn't finished being written .
120 Log.d(TAG, "Could not find any crash dumps to upload");
121 return;
122 }
123 File minidumpFile = minidumpFiles[0];
124 File logfile = fileManager.getCrashUploadLogFile();
125 Intent uploadIntent = createUploadIntent(getApplicationContext(), minidu mpFile, logfile);
126 startService(uploadIntent);
127 }
128
129 /**
130 * Creates an intent that when started will find all minidumps, and try to u pload them.
131 *
132 * @param context the context to use for the intent.
133 * @return an Intent to use to start the service.
134 */
135 @VisibleForTesting
136 static Intent createFindAndUploadAllCrashesIntent(Context context) {
137 Intent intent = new Intent(context, MinidumpUploadService.class);
138 intent.setAction(ACTION_FIND_ALL);
139 return intent;
140 }
141
142 private void handleFindAndUploadAllCrashes() {
143 CrashFileManager fileManager = new CrashFileManager(getApplicationContex t().getCacheDir());
144 File[] minidumps = fileManager.getAllMinidumpFiles();
145 File logfile = fileManager.getCrashUploadLogFile();
146 Log.i(TAG, "Attempting to upload accumulated crash dumps.");
147 for (File minidump : minidumps) {
148 Intent uploadIntent = createUploadIntent(getApplicationContext(), mi nidump, logfile);
149 startService(uploadIntent);
150 }
151 }
152
153 /**
154 * Creates an intent that when started will find all minidumps, and try to u pload them.
155 *
156 * @param minidumpFile the minidump file to upload.
157 * @return an Intent to use to start the service.
158 */
159 @VisibleForTesting
160 public static Intent createUploadIntent(Context context, File minidumpFile, File logfile) {
161 Intent intent = new Intent(context, MinidumpUploadService.class);
162 intent.setAction(ACTION_UPLOAD);
163 intent.putExtra(FILE_TO_UPLOAD_KEY, minidumpFile.getAbsolutePath());
164 intent.putExtra(UPLOAD_LOG_KEY, logfile.getAbsolutePath());
165 return intent;
166 }
167
168 private void handleUploadCrash(Intent intent) {
169 String minidumpFileName = intent.getStringExtra(FILE_TO_UPLOAD_KEY);
170 if (minidumpFileName == null || minidumpFileName.isEmpty()) {
171 Log.w(TAG, "Cannot upload crash data since minidump is absent.");
172 return;
173 }
174 File minidumpFile = new File(minidumpFileName);
175 if (!minidumpFile.isFile()) {
176 Log.w(TAG, "Cannot upload crash data since specified minidump "
177 + minidumpFileName + "is not present.");
178 return;
179 }
180 int tries = CrashFileManager.readAttemptNumber(minidumpFileName);
181 if (tries == -1 || tries >= MAX_TRIES_ALLOWED) {
182 ChromePreferenceManager.getInstance(this).incrementBreakpadUploadFai lCount();
183 Log.d(TAG, "Giving up on trying to upload " + minidumpFileName + " a fter "
184 + tries + " attempts");
185 return;
186 }
187
188 String logfileName = intent.getStringExtra(UPLOAD_LOG_KEY);
189 File logfile = new File(logfileName);
190
191 // Try to upload minidump
192 MinidumpUploadCallable minidumpUploadCallable =
193 createMinidumpUploadCallable(minidumpFile, logfile);
194 boolean success = minidumpUploadCallable.call();
195
196 if (success) {
197 ChromePreferenceManager.getInstance(this).incrementBreakpadUploadSuc cessCount();
198 } else {
199 // Unable to upload minidump. Incrementing try number and restarting .
200
201 // Only create another attempt if we have successfully renamed
202 // the file.
203 String newName = CrashFileManager.tryIncrementAttemptNumber(minidump File);
204 tries++;
205 if (newName != null && tries < MAX_TRIES_ALLOWED) {
206 // TODO(nyquist): Do this as an exponential backoff.
207 MinidumpUploadRetry.scheduleRetry(getApplicationContext());
208 } else {
209 Log.w(TAG, "Failed to rename minidump " + minidumpFileName);
210 }
211 }
212 }
213
214 /**
215 * Factory method for creating minidump callables.
216 *
217 * This may be overridden for tests.
218 *
219 * @param minidumpFile the File to upload.
220 * @param logfile the Log file to write to upon successful uploads.
221 * @return a new MinidumpUploadCallable.
222 */
223 @VisibleForTesting
224 MinidumpUploadCallable createMinidumpUploadCallable(File minidumpFile, File logfile) {
225 return new MinidumpUploadCallable(minidumpFile, logfile, getApplicationC ontext());
226 }
227
228 /**
229 * Attempts to upload all minidump files using the given {@link android.con tent.Context}.
230 *
231 * Note that this method is asynchronous. All that is guaranteed is that
232 * upload attempts will be enqueued.
233 *
234 * This method is safe to call from the UI thread.
235 *
236 * @param context Context of the application.
237 */
238 public static void tryUploadAllCrashDumps(Context context) {
239 Intent findAndUploadAllCrashesIntent = createFindAndUploadAllCrashesInte nt(context);
240 context.startService(findAndUploadAllCrashesIntent);
241 }
242
243 /**
244 * Checks whether it is the first time restrictions for cellular uploads sho uld apply. Is used
245 * to determine whether unsent crash uploads should be deleted which should happen only once.
246 */
247 @VisibleForTesting
248 protected boolean isMiniDumpCleanNeeded() {
249 SharedPreferences sharedPreferences =
250 PreferenceManager.getDefaultSharedPreferences(getApplicationCont ext());
251
252 // If cellular upload logic is enabled and the preference used for that is not initialized
253 // then this is the first time that logic is enabled.
254 boolean cleanNeeded =
255 !sharedPreferences.contains(MinidumpUploadCallable.PREF_LAST_UPL OAD_DAY)
256 && PrivacyPreferencesManager.getInstance(getApplicationContext() ).isUploadLimited();
257
258 // Initialize the preference with default value to make sure the above c heck works only
259 // once.
260 if (cleanNeeded) {
261 sharedPreferences.edit().putInt(MinidumpUploadCallable.PREF_LAST_UPL OAD_DAY, 0).apply();
262 }
263 return cleanNeeded;
264 }
265 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698