Merge "Split bugreport identifier into id and pid." into nyc-dev

This commit is contained in:
Felipe Leme
2016-02-12 00:40:40 +00:00
committed by Android (Google) Code Review

View File

@@ -88,8 +88,8 @@ import android.widget.Toast;
* <p> * <p>
* The workflow is: * The workflow is:
* <ol> * <ol>
* <li>When {@code dumpstate} starts, it sends a {@code BUGREPORT_STARTED} with its pid and the * <li>When {@code dumpstate} starts, it sends a {@code BUGREPORT_STARTED} with a sequential id,
* estimated total effort. * its pid, and the estimated total effort.
* <li>{@link BugreportReceiver} receives the intent and delegates it to this service. * <li>{@link BugreportReceiver} receives the intent and delegates it to this service.
* <li>Upon start, this service: * <li>Upon start, this service:
* <ol> * <ol>
@@ -132,6 +132,7 @@ public class BugreportProgressService extends Service {
static final String EXTRA_BUGREPORT = "android.intent.extra.BUGREPORT"; static final String EXTRA_BUGREPORT = "android.intent.extra.BUGREPORT";
static final String EXTRA_SCREENSHOT = "android.intent.extra.SCREENSHOT"; static final String EXTRA_SCREENSHOT = "android.intent.extra.SCREENSHOT";
static final String EXTRA_ID = "android.intent.extra.ID";
static final String EXTRA_PID = "android.intent.extra.PID"; static final String EXTRA_PID = "android.intent.extra.PID";
static final String EXTRA_MAX = "android.intent.extra.MAX"; static final String EXTRA_MAX = "android.intent.extra.MAX";
static final String EXTRA_NAME = "android.intent.extra.NAME"; static final String EXTRA_NAME = "android.intent.extra.NAME";
@@ -177,7 +178,7 @@ public class BugreportProgressService extends Service {
*/ */
private static final String SCREENSHOT_DIR = "bugreports"; private static final String SCREENSHOT_DIR = "bugreports";
/** Managed dumpstate processes (keyed by pid) */ /** Managed dumpstate processes (keyed by id) */
private final SparseArray<BugreportInfo> mProcesses = new SparseArray<>(); private final SparseArray<BugreportInfo> mProcesses = new SparseArray<>();
private Context mContext; private Context mContext;
@@ -222,7 +223,7 @@ public class BugreportProgressService extends Service {
} }
// If service is killed it cannot be recreated because it would not know which // If service is killed it cannot be recreated because it would not know which
// dumpstate PIDs it would have to watch. // dumpstate IDs it would have to watch.
return START_NOT_STICKY; return START_NOT_STICKY;
} }
@@ -299,38 +300,41 @@ public class BugreportProgressService extends Service {
} }
final String action = intent.getAction(); final String action = intent.getAction();
final int pid = intent.getIntExtra(EXTRA_PID, 0); final int pid = intent.getIntExtra(EXTRA_PID, 0);
// TODO: temporarily using pid as id until test cases and dumpstate are changed.
final int id = intent.getIntExtra(EXTRA_ID, pid);
final int max = intent.getIntExtra(EXTRA_MAX, -1); final int max = intent.getIntExtra(EXTRA_MAX, -1);
final String name = intent.getStringExtra(EXTRA_NAME); final String name = intent.getStringExtra(EXTRA_NAME);
if (DEBUG) Log.v(TAG, "action: " + action + ", name: " + name + ", pid: " + pid if (DEBUG)
+ ", max: "+ max); Log.v(TAG, "action: " + action + ", name: " + name + ", id: " + id + ", pid: "
+ pid + ", max: " + max);
switch (action) { switch (action) {
case INTENT_BUGREPORT_STARTED: case INTENT_BUGREPORT_STARTED:
if (!startProgress(name, pid, max)) { if (!startProgress(name, id, pid, max)) {
stopSelfWhenDone(); stopSelfWhenDone();
return; return;
} }
poll(); poll();
break; break;
case INTENT_BUGREPORT_FINISHED: case INTENT_BUGREPORT_FINISHED:
if (pid == 0) { if (id == 0) {
// Shouldn't happen, unless BUGREPORT_FINISHED is received from a legacy, // Shouldn't happen, unless BUGREPORT_FINISHED is received from a legacy,
// out-of-sync dumpstate process. // out-of-sync dumpstate process.
Log.w(TAG, "Missing " + EXTRA_PID + " on intent " + intent); Log.w(TAG, "Missing " + EXTRA_ID + " on intent " + intent);
} }
onBugreportFinished(pid, intent); onBugreportFinished(id, intent);
break; break;
case INTENT_BUGREPORT_INFO_LAUNCH: case INTENT_BUGREPORT_INFO_LAUNCH:
launchBugreportInfoDialog(pid); launchBugreportInfoDialog(id);
break; break;
case INTENT_BUGREPORT_SCREENSHOT: case INTENT_BUGREPORT_SCREENSHOT:
takeScreenshot(pid, true); takeScreenshot(id, true);
break; break;
case INTENT_BUGREPORT_SHARE: case INTENT_BUGREPORT_SHARE:
shareBugreport(pid, (BugreportInfo) intent.getParcelableExtra(EXTRA_INFO)); shareBugreport(id, (BugreportInfo) intent.getParcelableExtra(EXTRA_INFO));
break; break;
case INTENT_BUGREPORT_CANCEL: case INTENT_BUGREPORT_CANCEL:
cancel(pid); cancel(id);
break; break;
default: default:
Log.w(TAG, "Unsupported intent: " + action); Log.w(TAG, "Unsupported intent: " + action);
@@ -367,10 +371,10 @@ public class BugreportProgressService extends Service {
} }
} }
private BugreportInfo getInfo(int pid) { private BugreportInfo getInfo(int id) {
final BugreportInfo info = mProcesses.get(pid); final BugreportInfo info = mProcesses.get(id);
if (info == null) { if (info == null) {
Log.w(TAG, "Not monitoring process with PID " + pid); Log.w(TAG, "Not monitoring process with ID " + id);
} }
return info; return info;
} }
@@ -381,10 +385,14 @@ public class BugreportProgressService extends Service {
* *
* @return whether it succeeded or not. * @return whether it succeeded or not.
*/ */
private boolean startProgress(String name, int pid, int max) { private boolean startProgress(String name, int id, int pid, int max) {
if (name == null) { if (name == null) {
Log.w(TAG, "Missing " + EXTRA_NAME + " on start intent"); Log.w(TAG, "Missing " + EXTRA_NAME + " on start intent");
} }
if (id == -1) {
Log.e(TAG, "Missing " + EXTRA_ID + " on start intent");
return false;
}
if (pid == -1) { if (pid == -1) {
Log.e(TAG, "Missing " + EXTRA_PID + " on start intent"); Log.e(TAG, "Missing " + EXTRA_PID + " on start intent");
return false; return false;
@@ -394,14 +402,14 @@ public class BugreportProgressService extends Service {
return false; return false;
} }
final BugreportInfo info = new BugreportInfo(mContext, pid, name, max); final BugreportInfo info = new BugreportInfo(mContext, id, pid, name, max);
if (mProcesses.indexOfKey(pid) >= 0) { if (mProcesses.indexOfKey(id) >= 0) {
Log.w(TAG, "PID " + pid + " already watched"); Log.w(TAG, "ID " + id + " already watched");
} else { } else {
mProcesses.put(info.pid, info); mProcesses.put(info.id, info);
} }
// Take initial screenshot. // Take initial screenshot.
takeScreenshot(pid, false); takeScreenshot(id, false);
updateProgress(info); updateProgress(info);
return true; return true;
} }
@@ -423,22 +431,22 @@ public class BugreportProgressService extends Service {
com.android.internal.R.string.cancel), newCancelIntent(mContext, info)).build(); com.android.internal.R.string.cancel), newCancelIntent(mContext, info)).build();
final Intent infoIntent = new Intent(mContext, BugreportProgressService.class); final Intent infoIntent = new Intent(mContext, BugreportProgressService.class);
infoIntent.setAction(INTENT_BUGREPORT_INFO_LAUNCH); infoIntent.setAction(INTENT_BUGREPORT_INFO_LAUNCH);
infoIntent.putExtra(EXTRA_PID, info.pid); infoIntent.putExtra(EXTRA_ID, info.id);
final Action infoAction = new Action.Builder(null, final Action infoAction = new Action.Builder(null,
mContext.getString(R.string.bugreport_info_action), mContext.getString(R.string.bugreport_info_action),
PendingIntent.getService(mContext, info.pid, infoIntent, PendingIntent.getService(mContext, info.id, infoIntent,
PendingIntent.FLAG_UPDATE_CURRENT)).build(); PendingIntent.FLAG_UPDATE_CURRENT)).build();
final Intent screenshotIntent = new Intent(mContext, BugreportProgressService.class); final Intent screenshotIntent = new Intent(mContext, BugreportProgressService.class);
screenshotIntent.setAction(INTENT_BUGREPORT_SCREENSHOT); screenshotIntent.setAction(INTENT_BUGREPORT_SCREENSHOT);
screenshotIntent.putExtra(EXTRA_PID, info.pid); screenshotIntent.putExtra(EXTRA_ID, info.id);
PendingIntent screenshotPendingIntent = mTakingScreenshot ? null : PendingIntent PendingIntent screenshotPendingIntent = mTakingScreenshot ? null : PendingIntent
.getService(mContext, info.pid, screenshotIntent, .getService(mContext, info.id, screenshotIntent,
PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent.FLAG_UPDATE_CURRENT);
final Action screenshotAction = new Action.Builder(null, final Action screenshotAction = new Action.Builder(null,
mContext.getString(R.string.bugreport_screenshot_action), mContext.getString(R.string.bugreport_screenshot_action),
screenshotPendingIntent).build(); screenshotPendingIntent).build();
final String title = mContext.getString(R.string.bugreport_in_progress_title, info.pid); final String title = mContext.getString(R.string.bugreport_in_progress_title, info.id);
final String name = final String name =
info.name != null ? info.name : mContext.getString(R.string.bugreport_unnamed); info.name != null ? info.name : mContext.getString(R.string.bugreport_unnamed);
@@ -464,8 +472,8 @@ public class BugreportProgressService extends Service {
+ info + ")"); + info + ")");
return; return;
} }
Log.v(TAG, "Sending 'Progress' notification for pid " + info.pid + ": " + percentText); Log.v(TAG, "Sending 'Progress' notification for id " + info.id + ": " + percentText);
NotificationManager.from(mContext).notify(TAG, info.pid, notification); NotificationManager.from(mContext).notify(TAG, info.id, notification);
} }
/** /**
@@ -474,38 +482,38 @@ public class BugreportProgressService extends Service {
private static PendingIntent newCancelIntent(Context context, BugreportInfo info) { private static PendingIntent newCancelIntent(Context context, BugreportInfo info) {
final Intent intent = new Intent(INTENT_BUGREPORT_CANCEL); final Intent intent = new Intent(INTENT_BUGREPORT_CANCEL);
intent.setClass(context, BugreportProgressService.class); intent.setClass(context, BugreportProgressService.class);
intent.putExtra(EXTRA_PID, info.pid); intent.putExtra(EXTRA_ID, info.id);
return PendingIntent.getService(context, info.pid, intent, return PendingIntent.getService(context, info.id, intent,
PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent.FLAG_UPDATE_CURRENT);
} }
/** /**
* Finalizes the progress on a given bugreport and cancel its notification. * Finalizes the progress on a given bugreport and cancel its notification.
*/ */
private void stopProgress(int pid) { private void stopProgress(int id) {
if (mProcesses.indexOfKey(pid) < 0) { if (mProcesses.indexOfKey(id) < 0) {
Log.w(TAG, "PID not watched: " + pid); Log.w(TAG, "ID not watched: " + id);
} else { } else {
Log.d(TAG, "Removing PID " + pid); Log.d(TAG, "Removing ID " + id);
mProcesses.remove(pid); mProcesses.remove(id);
} }
stopSelfWhenDone(); stopSelfWhenDone();
Log.v(TAG, "stopProgress(" + pid + "): cancel notification"); Log.v(TAG, "stopProgress(" + id + "): cancel notification");
NotificationManager.from(mContext).cancel(TAG, pid); NotificationManager.from(mContext).cancel(TAG, id);
} }
/** /**
* Cancels a bugreport upon user's request. * Cancels a bugreport upon user's request.
*/ */
private void cancel(int pid) { private void cancel(int id) {
Log.v(TAG, "cancel: pid=" + pid); Log.v(TAG, "cancel: ID=" + id);
final BugreportInfo info = getInfo(pid); final BugreportInfo info = getInfo(id);
if (info != null && !info.finished) { if (info != null && !info.finished) {
Log.i(TAG, "Cancelling bugreport service (pid=" + pid + ") on user's request"); Log.i(TAG, "Cancelling bugreport service (ID=" + id + ") on user's request");
setSystemProperty(CTL_STOP, BUGREPORT_SERVICE); setSystemProperty(CTL_STOP, BUGREPORT_SERVICE);
deleteScreenshots(info); deleteScreenshots(info);
} }
stopProgress(pid); stopProgress(id);
} }
/** /**
@@ -522,14 +530,15 @@ public class BugreportProgressService extends Service {
for (int i = 0; i < total; i++) { for (int i = 0; i < total; i++) {
final BugreportInfo info = mProcesses.valueAt(i); final BugreportInfo info = mProcesses.valueAt(i);
if (info == null) { if (info == null) {
Log.wtf(TAG, "pollProgress(): null info at index " + i + "(pid = " Log.wtf(TAG, "pollProgress(): null info at index " + i + "(ID = "
+ mProcesses.keyAt(i) + ")"); + mProcesses.keyAt(i) + ")");
continue; continue;
} }
final int pid = info.pid; final int pid = info.pid;
final int id = info.id;
if (info.finished) { if (info.finished) {
if (DEBUG) Log.v(TAG, "Skipping finished process " + pid); if (DEBUG) Log.v(TAG, "Skipping finished process " + pid + "(id: " + id + ")");
continue; continue;
} }
activeProcesses++; activeProcesses++;
@@ -544,13 +553,13 @@ public class BugreportProgressService extends Service {
if (progressChanged || maxChanged) { if (progressChanged || maxChanged) {
if (progressChanged) { if (progressChanged) {
if (DEBUG) Log.v(TAG, "Updating progress for PID " + pid + " from " if (DEBUG) Log.v(TAG, "Updating progress for PID " + pid + "(id: " + id
+ info.progress + " to " + progress); + ") from " + info.progress + " to " + progress);
info.progress = progress; info.progress = progress;
} }
if (maxChanged) { if (maxChanged) {
Log.i(TAG, "Updating max progress for PID " + pid + " from " + info.max Log.i(TAG, "Updating max progress for PID " + pid + "(id: " + id
+ " to " + max); + ") from " + info.max + " to " + max);
info.max = max; info.max = max;
} }
info.lastUpdate = System.currentTimeMillis(); info.lastUpdate = System.currentTimeMillis();
@@ -558,9 +567,9 @@ public class BugreportProgressService extends Service {
} else { } else {
long inactiveTime = System.currentTimeMillis() - info.lastUpdate; long inactiveTime = System.currentTimeMillis() - info.lastUpdate;
if (inactiveTime >= INACTIVITY_TIMEOUT) { if (inactiveTime >= INACTIVITY_TIMEOUT) {
Log.w(TAG, "No progress update for process " + pid + " since " Log.w(TAG, "No progress update for PID " + pid + " since "
+ info.getFormattedLastUpdate()); + info.getFormattedLastUpdate());
stopProgress(info.pid); stopProgress(info.id);
} }
} }
} }
@@ -572,19 +581,16 @@ public class BugreportProgressService extends Service {
* Fetches a {@link BugreportInfo} for a given process and launches a dialog where the user can * Fetches a {@link BugreportInfo} for a given process and launches a dialog where the user can
* change its values. * change its values.
*/ */
private void launchBugreportInfoDialog(int pid) { private void launchBugreportInfoDialog(int id) {
// Copy values so it doesn't lock mProcesses while UI is being updated // Copy values so it doesn't lock mProcesses while UI is being updated
final String name, title, description; final String name, title, description;
final BugreportInfo info = getInfo(pid); final BugreportInfo info = getInfo(id);
if (info == null) { if (info == null) {
return; return;
} }
name = info.name;
title = info.title;
description = info.description;
collapseNotificationBar(); collapseNotificationBar();
mInfoDialog.initialize(mContext, pid, name, title, description); mInfoDialog.initialize(mContext, info);
} }
/** /**
@@ -597,7 +603,7 @@ public class BugreportProgressService extends Service {
* Typical usage is delaying when taken from the notification action, and taking it right away * Typical usage is delaying when taken from the notification action, and taking it right away
* upon receiving a {@link #INTENT_BUGREPORT_STARTED}. * upon receiving a {@link #INTENT_BUGREPORT_STARTED}.
*/ */
private void takeScreenshot(int pid, boolean delayed) { private void takeScreenshot(int id, boolean delayed) {
setTakingScreenshot(true); setTakingScreenshot(true);
if (delayed) { if (delayed) {
collapseNotificationBar(); collapseNotificationBar();
@@ -608,28 +614,28 @@ public class BugreportProgressService extends Service {
// Show a toast just once, otherwise it might be captured in the screenshot. // Show a toast just once, otherwise it might be captured in the screenshot.
Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show(); Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show();
takeScreenshot(pid, SCREENSHOT_DELAY_SECONDS); takeScreenshot(id, SCREENSHOT_DELAY_SECONDS);
} else { } else {
takeScreenshot(pid, 0); takeScreenshot(id, 0);
} }
} }
/** /**
* Takes a screenshot after {@code delay} seconds. * Takes a screenshot after {@code delay} seconds.
*/ */
private void takeScreenshot(int pid, int delay) { private void takeScreenshot(int id, int delay) {
if (delay > 0) { if (delay > 0) {
Log.d(TAG, "Taking screenshot for " + pid + " in " + delay + " seconds"); Log.d(TAG, "Taking screenshot for " + id + " in " + delay + " seconds");
final Message msg = mMainHandler.obtainMessage(); final Message msg = mMainHandler.obtainMessage();
msg.what = MSG_DELAYED_SCREENSHOT; msg.what = MSG_DELAYED_SCREENSHOT;
msg.arg1 = pid; msg.arg1 = id;
msg.arg2 = delay - 1; msg.arg2 = delay - 1;
mMainHandler.sendMessageDelayed(msg, DateUtils.SECOND_IN_MILLIS); mMainHandler.sendMessageDelayed(msg, DateUtils.SECOND_IN_MILLIS);
return; return;
} }
// It's time to take the screenshot: let the proper thread handle it // It's time to take the screenshot: let the proper thread handle it
final BugreportInfo info = getInfo(pid); final BugreportInfo info = getInfo(id);
if (info == null) { if (info == null) {
return; return;
} }
@@ -638,7 +644,7 @@ public class BugreportProgressService extends Service {
final Message requestMsg = new Message(); final Message requestMsg = new Message();
requestMsg.what = MSG_SCREENSHOT_REQUEST; requestMsg.what = MSG_SCREENSHOT_REQUEST;
requestMsg.arg1 = pid; requestMsg.arg1 = id;
requestMsg.obj = screenshotPath; requestMsg.obj = screenshotPath;
mScreenshotHandler.sendMessage(requestMsg); mScreenshotHandler.sendMessage(requestMsg);
} }
@@ -715,30 +721,30 @@ public class BugreportProgressService extends Service {
*/ */
private void stopSelfWhenDone() { private void stopSelfWhenDone() {
if (mProcesses.size() > 0) { if (mProcesses.size() > 0) {
if (DEBUG) Log.v(TAG, "Staying alive, waiting for pids " + mProcesses); if (DEBUG) Log.d(TAG, "Staying alive, waiting for IDs " + mProcesses);
return; return;
} }
Log.v(TAG, "No more pids to handle, shutting down"); Log.v(TAG, "No more processes to handle, shutting down");
stopSelf(); stopSelf();
} }
/** /**
* Handles the BUGREPORT_FINISHED intent sent by {@code dumpstate}. * Handles the BUGREPORT_FINISHED intent sent by {@code dumpstate}.
*/ */
private void onBugreportFinished(int pid, Intent intent) { private void onBugreportFinished(int id, Intent intent) {
final File bugreportFile = getFileExtra(intent, EXTRA_BUGREPORT); final File bugreportFile = getFileExtra(intent, EXTRA_BUGREPORT);
if (bugreportFile == null) { if (bugreportFile == null) {
// Should never happen, dumpstate always set the file. // Should never happen, dumpstate always set the file.
Log.wtf(TAG, "Missing " + EXTRA_BUGREPORT + " on intent " + intent); Log.wtf(TAG, "Missing " + EXTRA_BUGREPORT + " on intent " + intent);
return; return;
} }
mInfoDialog.onBugreportFinished(pid); mInfoDialog.onBugreportFinished(id);
BugreportInfo info = getInfo(pid); BugreportInfo info = getInfo(id);
if (info == null) { if (info == null) {
// Happens when BUGREPORT_FINISHED was received without a BUGREPORT_STARTED first. // Happens when BUGREPORT_FINISHED was received without a BUGREPORT_STARTED first.
Log.v(TAG, "Creating info for untracked pid " + pid); Log.v(TAG, "Creating info for untracked ID " + id);
info = new BugreportInfo(mContext, pid); info = new BugreportInfo(mContext, id);
mProcesses.put(pid, info); mProcesses.put(id, info);
} }
info.renameScreenshots(mScreenshotsDir); info.renameScreenshots(mScreenshotsDir);
info.bugreportFile = bugreportFile; info.bugreportFile = bugreportFile;
@@ -765,7 +771,7 @@ public class BugreportProgressService extends Service {
if (!info.bugreportFile.exists() || !info.bugreportFile.canRead()) { if (!info.bugreportFile.exists() || !info.bugreportFile.canRead()) {
Log.e(TAG, "Could not read bugreport file " + info.bugreportFile); Log.e(TAG, "Could not read bugreport file " + info.bugreportFile);
Toast.makeText(context, R.string.bugreport_unreadable_text, Toast.LENGTH_LONG).show(); Toast.makeText(context, R.string.bugreport_unreadable_text, Toast.LENGTH_LONG).show();
stopProgress(info.pid); stopProgress(info.id);
return; return;
} }
@@ -837,12 +843,12 @@ public class BugreportProgressService extends Service {
* Shares the bugreport upon user's request by issuing a {@link Intent#ACTION_SEND_MULTIPLE} * Shares the bugreport upon user's request by issuing a {@link Intent#ACTION_SEND_MULTIPLE}
* intent, but issuing a warning dialog the first time. * intent, but issuing a warning dialog the first time.
*/ */
private void shareBugreport(int pid, BugreportInfo sharedInfo) { private void shareBugreport(int id, BugreportInfo sharedInfo) {
BugreportInfo info = getInfo(pid); BugreportInfo info = getInfo(id);
if (info == null) { if (info == null) {
// Service was terminated but notification persisted // Service was terminated but notification persisted
info = sharedInfo; info = sharedInfo;
Log.d(TAG, "shareBugreport(): no info for PID " + pid + " on managed processes (" Log.d(TAG, "shareBugreport(): no info for ID " + id + " on managed processes ("
+ mProcesses + "), using info from intent instead (" + info + ")"); + mProcesses + "), using info from intent instead (" + info + ")");
} }
@@ -863,7 +869,7 @@ public class BugreportProgressService extends Service {
mContext.startActivity(notifIntent); mContext.startActivity(notifIntent);
// ... and stop watching this process. // ... and stop watching this process.
stopProgress(pid); stopProgress(id);
} }
/** /**
@@ -877,16 +883,16 @@ public class BugreportProgressService extends Service {
final Intent shareIntent = new Intent(INTENT_BUGREPORT_SHARE); final Intent shareIntent = new Intent(INTENT_BUGREPORT_SHARE);
shareIntent.setClass(context, BugreportProgressService.class); shareIntent.setClass(context, BugreportProgressService.class);
shareIntent.setAction(INTENT_BUGREPORT_SHARE); shareIntent.setAction(INTENT_BUGREPORT_SHARE);
shareIntent.putExtra(EXTRA_PID, info.pid); shareIntent.putExtra(EXTRA_ID, info.id);
shareIntent.putExtra(EXTRA_INFO, info); shareIntent.putExtra(EXTRA_INFO, info);
final String title = context.getString(R.string.bugreport_finished_title, info.pid); final String title = context.getString(R.string.bugreport_finished_title, info.id);
final Notification.Builder builder = new Notification.Builder(context) final Notification.Builder builder = new Notification.Builder(context)
.setSmallIcon(com.android.internal.R.drawable.stat_sys_adb) .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
.setContentTitle(title) .setContentTitle(title)
.setTicker(title) .setTicker(title)
.setContentText(context.getString(R.string.bugreport_finished_text)) .setContentText(context.getString(R.string.bugreport_finished_text))
.setContentIntent(PendingIntent.getService(context, info.pid, shareIntent, .setContentIntent(PendingIntent.getService(context, info.id, shareIntent,
PendingIntent.FLAG_UPDATE_CURRENT)) PendingIntent.FLAG_UPDATE_CURRENT))
.setDeleteIntent(newCancelIntent(context, info)) .setDeleteIntent(newCancelIntent(context, info))
.setLocalOnly(true) .setLocalOnly(true)
@@ -897,8 +903,8 @@ public class BugreportProgressService extends Service {
builder.setContentInfo(info.name); builder.setContentInfo(info.name);
} }
Log.v(TAG, "Sending 'Share' notification for pid " + info.pid + ": " + title); Log.v(TAG, "Sending 'Share' notification for ID " + info.id + ": " + title);
NotificationManager.from(context).notify(TAG, info.pid, builder.build()); NotificationManager.from(context).notify(TAG, info.id, builder.build());
} }
/** /**
@@ -906,7 +912,7 @@ public class BugreportProgressService extends Service {
* finishes - at this point there is nothing to be done other than waiting, hence it has no * finishes - at this point there is nothing to be done other than waiting, hence it has no
* pending action. * pending action.
*/ */
private static void sendBugreportBeingUpdatedNotification(Context context, int pid) { private static void sendBugreportBeingUpdatedNotification(Context context, int id) {
final String title = context.getString(R.string.bugreport_updating_title); final String title = context.getString(R.string.bugreport_updating_title);
final Notification.Builder builder = new Notification.Builder(context) final Notification.Builder builder = new Notification.Builder(context)
.setSmallIcon(com.android.internal.R.drawable.stat_sys_adb) .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
@@ -916,8 +922,8 @@ public class BugreportProgressService extends Service {
.setLocalOnly(true) .setLocalOnly(true)
.setColor(context.getColor( .setColor(context.getColor(
com.android.internal.R.color.system_notification_accent_color)); com.android.internal.R.color.system_notification_accent_color));
Log.v(TAG, "Sending 'Updating zip' notification for pid " + pid + ": " + title); Log.v(TAG, "Sending 'Updating zip' notification for ID " + id + ": " + title);
NotificationManager.from(context).notify(TAG, pid, builder.build()); NotificationManager.from(context).notify(TAG, id, builder.build());
} }
/** /**
@@ -985,7 +991,7 @@ public class BugreportProgressService extends Service {
// It's not possible to add a new entry into an existing file, so we need to create a new // It's not possible to add a new entry into an existing file, so we need to create a new
// zip, copy all entries, then rename it. // zip, copy all entries, then rename it.
sendBugreportBeingUpdatedNotification(context, info.pid); // ...and that takes time sendBugreportBeingUpdatedNotification(context, info.id); // ...and that takes time
final File dir = info.bugreportFile.getParentFile(); final File dir = info.bugreportFile.getParentFile();
final File tmpZip = new File(dir, "tmp-" + info.bugreportFile.getName()); final File tmpZip = new File(dir, "tmp-" + info.bugreportFile.getName());
Log.d(TAG, "Writing temporary zip file (" + tmpZip + ") with title and/or description"); Log.d(TAG, "Writing temporary zip file (" + tmpZip + ") with title and/or description");
@@ -1113,8 +1119,8 @@ public class BugreportProgressService extends Service {
/** /**
* Updates the user-provided details of a bugreport. * Updates the user-provided details of a bugreport.
*/ */
private void updateBugreportInfo(int pid, String name, String title, String description) { private void updateBugreportInfo(int id, String name, String title, String description) {
final BugreportInfo info = getInfo(pid); final BugreportInfo info = getInfo(id);
if (info == null) { if (info == null) {
return; return;
} }
@@ -1179,6 +1185,7 @@ public class BugreportProgressService extends Service {
private EditText mInfoDescription; private EditText mInfoDescription;
private AlertDialog mDialog; private AlertDialog mDialog;
private Button mOkButton; private Button mOkButton;
private int mId;
private int mPid; private int mPid;
/** /**
@@ -1207,8 +1214,7 @@ public class BugreportProgressService extends Service {
/** /**
* Sets its internal state and displays the dialog. * Sets its internal state and displays the dialog.
*/ */
private void initialize(Context context, int pid, String name, String title, private void initialize(Context context, BugreportInfo info) {
String description) {
// First initializes singleton. // First initializes singleton.
if (mDialog == null) { if (mDialog == null) {
@SuppressLint("InflateParams") @SuppressLint("InflateParams")
@@ -1232,7 +1238,7 @@ public class BugreportProgressService extends Service {
mDialog = new AlertDialog.Builder(context) mDialog = new AlertDialog.Builder(context)
.setView(view) .setView(view)
.setTitle(context.getString(R.string.bugreport_info_dialog_title, pid)) .setTitle(context.getString(R.string.bugreport_info_dialog_title, info.id))
.setCancelable(false) .setCancelable(false)
.setPositiveButton(context.getString(com.android.internal.R.string.ok), .setPositiveButton(context.getString(com.android.internal.R.string.ok),
null) null)
@@ -1258,16 +1264,17 @@ public class BugreportProgressService extends Service {
} }
// Then set fields. // Then set fields.
mSavedName = mTempName = name; mSavedName = mTempName = info.name;
mPid = pid; mId = info.id;
if (!TextUtils.isEmpty(name)) { mPid = info.pid;
mInfoName.setText(name); if (!TextUtils.isEmpty(info.name)) {
mInfoName.setText(info.name);
} }
if (!TextUtils.isEmpty(title)) { if (!TextUtils.isEmpty(info.title)) {
mInfoTitle.setText(title); mInfoTitle.setText(info.title);
} }
if (!TextUtils.isEmpty(description)) { if (!TextUtils.isEmpty(info.description)) {
mInfoDescription.setText(description); mInfoDescription.setText(info.description);
} }
// And finally display it. // And finally display it.
@@ -1290,7 +1297,7 @@ public class BugreportProgressService extends Service {
final String title = mInfoTitle.getText().toString(); final String title = mInfoTitle.getText().toString();
final String description = mInfoDescription.getText().toString(); final String description = mInfoDescription.getText().toString();
updateBugreportInfo(mPid, name, title, description); updateBugreportInfo(mId, name, title, description);
mDialog.dismiss(); mDialog.dismiss();
} }
}); });
@@ -1328,7 +1335,7 @@ public class BugreportProgressService extends Service {
// Must update system property for the cases where dumpstate finishes // Must update system property for the cases where dumpstate finishes
// while the user is still entering other fields (like title or // while the user is still entering other fields (like title or
// description) // description)
setBugreportNameProperty(mPid, name); setBugreportNameProperty(mId, name);
} }
/** /**
@@ -1337,7 +1344,7 @@ public class BugreportProgressService extends Service {
* <p>Once the bugreport is finished dumpstate has already generated the final files, so * <p>Once the bugreport is finished dumpstate has already generated the final files, so
* changing the name would have no effect. * changing the name would have no effect.
*/ */
private void onBugreportFinished(int pid) { private void onBugreportFinished(int id) {
if (mInfoName != null) { if (mInfoName != null) {
mInfoName.setEnabled(false); mInfoName.setEnabled(false);
mInfoName.setText(mSavedName); mInfoName.setText(mSavedName);
@@ -1352,6 +1359,11 @@ public class BugreportProgressService extends Service {
private static final class BugreportInfo implements Parcelable { private static final class BugreportInfo implements Parcelable {
private final Context context; private final Context context;
/**
* Sequential, user-friendly id used to identify the bugreport.
*/
final int id;
/** /**
* {@code pid} of the {@code dumpstate} process generating the bugreport. * {@code pid} of the {@code dumpstate} process generating the bugreport.
*/ */
@@ -1426,8 +1438,9 @@ public class BugreportProgressService extends Service {
/** /**
* Constructor for tracked bugreports - typically called upon receiving BUGREPORT_STARTED. * Constructor for tracked bugreports - typically called upon receiving BUGREPORT_STARTED.
*/ */
BugreportInfo(Context context, int pid, String name, int max) { BugreportInfo(Context context, int id, int pid, String name, int max) {
this.context = context; this.context = context;
this.id = id;
this.pid = pid; this.pid = pid;
this.name = name; this.name = name;
this.max = max; this.max = max;
@@ -1437,8 +1450,8 @@ public class BugreportProgressService extends Service {
* Constructor for untracked bugreports - typically called upon receiving BUGREPORT_FINISHED * Constructor for untracked bugreports - typically called upon receiving BUGREPORT_FINISHED
* without a previous call to BUGREPORT_STARTED. * without a previous call to BUGREPORT_STARTED.
*/ */
BugreportInfo(Context context, int pid) { BugreportInfo(Context context, int id) {
this(context, pid, null, 0); this(context, id, id, null, 0);
this.finished = true; this.finished = true;
} }
@@ -1494,7 +1507,7 @@ public class BugreportProgressService extends Service {
@Override @Override
public String toString() { public String toString() {
final float percent = ((float) progress * 100 / max); final float percent = ((float) progress * 100 / max);
return "pid: " + pid + ", name: " + name + ", finished: " + finished return "id: " + id + ", pid: " + pid + ", name: " + name + ", finished: " + finished
+ "\n\ttitle: " + title + "\n\tdescription: " + description + "\n\ttitle: " + title + "\n\tdescription: " + description
+ "\n\tfile: " + bugreportFile + "\n\tscreenshots: " + screenshotFiles + "\n\tfile: " + bugreportFile + "\n\tscreenshots: " + screenshotFiles
+ "\n\tprogress: " + progress + "/" + max + "(" + percent + ")" + "\n\tprogress: " + progress + "/" + max + "(" + percent + ")"
@@ -1506,6 +1519,7 @@ public class BugreportProgressService extends Service {
// Parcelable contract // Parcelable contract
protected BugreportInfo(Parcel in) { protected BugreportInfo(Parcel in) {
context = null; context = null;
id = in.readInt();
pid = in.readInt(); pid = in.readInt();
name = in.readString(); name = in.readString();
title = in.readString(); title = in.readString();
@@ -1527,6 +1541,7 @@ public class BugreportProgressService extends Service {
@Override @Override
public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeInt(pid); dest.writeInt(pid);
dest.writeString(name); dest.writeString(name);
dest.writeString(title); dest.writeString(title);