Refactoring: pulled ServiceHandler methods to its parent class.

Now ServiceHandler only have 2 methods:

- handleMessage(): part of its interface.
- poll(): delegates work to parent, but sends a delayed message
  so it keeps polling.

Also changed hardcoded "N/A" to a resource.

BUG: 25794470
Change-Id: I486fff46c1532685bfd6f5903349d14e55059219
This commit is contained in:
Felipe Leme
2015-12-04 12:15:30 -08:00
parent 719aaae3c1
commit 923afa9fe1
2 changed files with 181 additions and 168 deletions

View File

@@ -39,4 +39,7 @@
<!-- Toast message sent when the bugreport file could be read. -->
<string name="bugreport_unreadable_text">Bug report file could not be read</string>
<!-- Title for bug reports received from dumpstate without a name. [CHAR LIMIT=30]-->
<string name="bugreport_unnamed">unnamed</string>
</resources>

View File

@@ -180,13 +180,13 @@ public class BugreportProgressService extends Service {
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
pollProgress();
poll();
}
@Override
public void handleMessage(Message msg) {
if (msg.what == MSG_POLL) {
pollProgress();
poll();
return;
}
@@ -243,181 +243,191 @@ public class BugreportProgressService extends Service {
}
/**
* Creates the {@link BugreportInfo} for a process and issue a system notification to
* indicate its progress.
*
* @return whether it succeeded or not.
*/
private boolean startProgress(String name, int pid, int max) {
if (name == null) {
Log.w(TAG, "Missing " + EXTRA_NAME + " on start intent");
name = "N/A";
}
if (pid == -1) {
Log.e(TAG, "Missing " + EXTRA_PID + " on start intent");
return false;
}
if (max <= 0) {
Log.e(TAG, "Invalid value for extra " + EXTRA_MAX + ": " + max);
return false;
}
final BugreportInfo info = new BugreportInfo(getApplicationContext(), pid, name, max);
synchronized (mProcesses) {
if (mProcesses.indexOfKey(pid) >= 0) {
Log.w(TAG, "PID " + pid + " already watched");
} else {
mProcesses.put(info.pid, info);
}
}
updateProgress(info);
return true;
}
/**
* Updates the system notification for a given bug report.
*/
private void updateProgress(BugreportInfo info) {
if (info.max <= 0 || info.progress < 0 || info.name == null) {
Log.e(TAG, "Invalid progress values for " + info);
return;
}
final Context context = getApplicationContext();
final NumberFormat nf = NumberFormat.getPercentInstance();
nf.setMinimumFractionDigits(2);
nf.setMaximumFractionDigits(2);
final String percentText = nf.format((double) info.progress / info.max);
final Intent cancelIntent = new Intent(context, BugreportReceiver.class);
cancelIntent.setAction(INTENT_BUGREPORT_CANCEL);
cancelIntent.putExtra(EXTRA_PID, info.pid);
final Action cancelAction = new Action.Builder(null,
context.getString(com.android.internal.R.string.cancel),
PendingIntent.getBroadcast(context, info.pid, cancelIntent,
PendingIntent.FLAG_CANCEL_CURRENT)).build();
final String title = context.getString(R.string.bugreport_in_progress_title);
final Notification notification = new Notification.Builder(context)
.setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
.setContentTitle(title)
.setTicker(title)
.setContentText(info.name)
.setContentInfo(percentText)
.setProgress(info.max, info.progress, false)
.setOngoing(true)
.setLocalOnly(true)
.setColor(context.getColor(
com.android.internal.R.color.system_notification_accent_color))
.addAction(cancelAction)
.build();
NotificationManager.from(context).notify(TAG, info.pid, notification);
}
/**
* Finalizes the progress on a given process and sends the finished intent.
*/
private void stopProgress(int pid, Intent intent) {
synchronized (mProcesses) {
if (mProcesses.indexOfKey(pid) < 0) {
Log.w(TAG, "PID not watched: " + pid);
} else {
mProcesses.remove(pid);
}
stopSelfWhenDone();
}
if (DEBUG) Log.v(TAG, "stopProgress(" + pid + "): cancel notification");
NotificationManager.from(getApplicationContext()).cancel(TAG, pid);
if (intent != null) {
// Bug report finished fine: send a new, different notification.
if (DEBUG) Log.v(TAG, "stopProgress(" + pid + "): finish bug report");
onBugreportFinished(pid, intent);
}
}
/**
* Cancels a bugreport upon user's request.
*/
private void cancel(int pid) {
Log.i(TAG, "Cancelling PID " + pid + " on user's request");
SystemProperties.set(CTL_STOP, BUGREPORT_SERVICE);
stopProgress(pid, null);
}
/**
* Poll {@link SystemProperties} to get the progress on each monitored process.
*/
private void pollProgress() {
synchronized (mProcesses) {
if (mProcesses.size() == 0) {
Log.d(TAG, "No process to poll progress.");
}
for (int i = 0; i < mProcesses.size(); i++) {
final int pid = mProcesses.keyAt(i);
final String progressKey = DUMPSTATE_PREFIX + pid + PROGRESS_SUFFIX;
final int progress = SystemProperties.getInt(progressKey, 0);
if (progress == 0) {
Log.v(TAG, "System property " + progressKey + " is not set yet");
continue;
}
final int max = SystemProperties.getInt(DUMPSTATE_PREFIX + pid + MAX_SUFFIX, 0);
final BugreportInfo info = mProcesses.valueAt(i);
final boolean maxChanged = max > 0 && max != info.max;
final boolean progressChanged = progress > 0 && progress != info.progress;
if (progressChanged || maxChanged) {
if (progressChanged) {
if (DEBUG) Log.v(TAG, "Updating progress for PID " + pid + " from "
+ info.progress + " to " + progress);
info.progress = progress;
}
if (maxChanged) {
Log.i(TAG, "Updating max progress for PID " + pid + " from " + info.max
+ " to " + max);
info.max = max;
}
info.lastUpdate = System.currentTimeMillis();
updateProgress(info);
} else {
long inactiveTime = System.currentTimeMillis() - info.lastUpdate;
if (inactiveTime >= INACTIVITY_TIMEOUT) {
Log.w(TAG, "No progress update for process " + pid + " since "
+ info.getFormattedLastUpdate());
stopProgress(info.pid, null);
}
}
}
private void poll() {
if (pollProgress()) {
// Keep polling...
sendEmptyMessageDelayed(MSG_POLL, POLLING_FREQUENCY);
}
}
}
/**
* Finishes the service when it's not monitoring any more processes.
*/
private void stopSelfWhenDone() {
synchronized (mProcesses) {
if (mProcesses.size() > 0) {
if (DEBUG) Log.v(TAG, "Staying alive, waiting for pids " + mProcesses);
return;
}
Log.v(TAG, "No more pids to handle, shutting down");
stopSelf();
}
/**
* Creates the {@link BugreportInfo} for a process and issue a system notification to
* indicate its progress.
*
* @return whether it succeeded or not.
*/
private boolean startProgress(String name, int pid, int max) {
if (name == null) {
Log.w(TAG, "Missing " + EXTRA_NAME + " on start intent");
}
if (pid == -1) {
Log.e(TAG, "Missing " + EXTRA_PID + " on start intent");
return false;
}
if (max <= 0) {
Log.e(TAG, "Invalid value for extra " + EXTRA_MAX + ": " + max);
return false;
}
private void onBugreportFinished(int pid, Intent intent) {
final Context context = getApplicationContext();
final Configuration conf = context.getResources().getConfiguration();
final File bugreportFile = getFileExtra(intent, EXTRA_BUGREPORT);
final File screenshotFile = getFileExtra(intent, EXTRA_SCREENSHOT);
if ((conf.uiMode & Configuration.UI_MODE_TYPE_MASK) != Configuration.UI_MODE_TYPE_WATCH) {
triggerLocalNotification(context, pid, bugreportFile, screenshotFile);
final BugreportInfo info = new BugreportInfo(getApplicationContext(), pid, name, max);
synchronized (mProcesses) {
if (mProcesses.indexOfKey(pid) >= 0) {
Log.w(TAG, "PID " + pid + " already watched");
} else {
mProcesses.put(info.pid, info);
}
}
updateProgress(info);
return true;
}
/**
* Updates the system notification for a given bug report.
*/
private void updateProgress(BugreportInfo info) {
if (info.max <= 0 || info.progress < 0) {
Log.e(TAG, "Invalid progress values for " + info);
return;
}
final Context context = getApplicationContext();
final NumberFormat nf = NumberFormat.getPercentInstance();
nf.setMinimumFractionDigits(2);
nf.setMaximumFractionDigits(2);
final String percentText = nf.format((double) info.progress / info.max);
final Intent cancelIntent = new Intent(context, BugreportReceiver.class);
cancelIntent.setAction(INTENT_BUGREPORT_CANCEL);
cancelIntent.putExtra(EXTRA_PID, info.pid);
final Action cancelAction = new Action.Builder(null,
context.getString(com.android.internal.R.string.cancel),
PendingIntent.getBroadcast(context, info.pid, cancelIntent,
PendingIntent.FLAG_CANCEL_CURRENT)).build();
final String title = context.getString(R.string.bugreport_in_progress_title);
final String name =
info.name != null ? info.name : context.getString(R.string.bugreport_unnamed);
final Notification notification = new Notification.Builder(context)
.setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
.setContentTitle(title)
.setTicker(title)
.setContentText(name)
.setContentInfo(percentText)
.setProgress(info.max, info.progress, false)
.setOngoing(true)
.setLocalOnly(true)
.setColor(context.getColor(
com.android.internal.R.color.system_notification_accent_color))
.addAction(cancelAction)
.build();
NotificationManager.from(context).notify(TAG, info.pid, notification);
}
/**
* Finalizes the progress on a given process and sends the finished intent.
*/
private void stopProgress(int pid, Intent intent) {
synchronized (mProcesses) {
if (mProcesses.indexOfKey(pid) < 0) {
Log.w(TAG, "PID not watched: " + pid);
} else {
mProcesses.remove(pid);
}
stopSelfWhenDone();
}
if (DEBUG) Log.v(TAG, "stopProgress(" + pid + "): cancel notification");
NotificationManager.from(getApplicationContext()).cancel(TAG, pid);
if (intent != null) {
// Bug report finished fine: send a new, different notification.
if (DEBUG) Log.v(TAG, "stopProgress(" + pid + "): finish bug report");
onBugreportFinished(pid, intent);
}
}
/**
* Cancels a bugreport upon user's request.
*/
private void cancel(int pid) {
Log.i(TAG, "Cancelling PID " + pid + " on user's request");
SystemProperties.set(CTL_STOP, BUGREPORT_SERVICE);
stopProgress(pid, null);
}
/**
* Poll {@link SystemProperties} to get the progress on each monitored process.
*
* @return whether it should keep polling.
*/
private boolean pollProgress() {
synchronized (mProcesses) {
if (mProcesses.size() == 0) {
Log.d(TAG, "No process to poll progress.");
}
for (int i = 0; i < mProcesses.size(); i++) {
final int pid = mProcesses.keyAt(i);
final String progressKey = DUMPSTATE_PREFIX + pid + PROGRESS_SUFFIX;
final int progress = SystemProperties.getInt(progressKey, 0);
if (progress == 0) {
Log.v(TAG, "System property " + progressKey + " is not set yet");
continue;
}
final int max = SystemProperties.getInt(DUMPSTATE_PREFIX + pid + MAX_SUFFIX, 0);
final BugreportInfo info = mProcesses.valueAt(i);
final boolean maxChanged = max > 0 && max != info.max;
final boolean progressChanged = progress > 0 && progress != info.progress;
if (progressChanged || maxChanged) {
if (progressChanged) {
if (DEBUG) Log.v(TAG, "Updating progress for PID " + pid + " from "
+ info.progress + " to " + progress);
info.progress = progress;
}
if (maxChanged) {
Log.i(TAG, "Updating max progress for PID " + pid + " from " + info.max
+ " to " + max);
info.max = max;
}
info.lastUpdate = System.currentTimeMillis();
updateProgress(info);
} else {
long inactiveTime = System.currentTimeMillis() - info.lastUpdate;
if (inactiveTime >= INACTIVITY_TIMEOUT) {
Log.w(TAG, "No progress update for process " + pid + " since "
+ info.getFormattedLastUpdate());
stopProgress(info.pid, null);
}
}
}
return true;
}
}
/**
* Finishes the service when it's not monitoring any more processes.
*/
private void stopSelfWhenDone() {
synchronized (mProcesses) {
if (mProcesses.size() > 0) {
if (DEBUG) Log.v(TAG, "Staying alive, waiting for pids " + mProcesses);
return;
}
Log.v(TAG, "No more pids to handle, shutting down");
stopSelf();
}
}
private void onBugreportFinished(int pid, Intent intent) {
final Context context = getApplicationContext();
final Configuration conf = context.getResources().getConfiguration();
final File bugreportFile = getFileExtra(intent, EXTRA_BUGREPORT);
final File screenshotFile = getFileExtra(intent, EXTRA_SCREENSHOT);
if ((conf.uiMode & Configuration.UI_MODE_TYPE_MASK) != Configuration.UI_MODE_TYPE_WATCH) {
triggerLocalNotification(context, pid, bugreportFile, screenshotFile);
}
}
/**