summaryrefslogtreecommitdiffstats
path: root/packages/Shell
diff options
context:
space:
mode:
authorFelipe Leme <felipeal@google.com>2015-06-01 12:21:46 -0700
committerFelipe Leme <felipeal@google.com>2015-06-16 09:05:22 -0700
commit55beae09e57f987e23f8737d25c611a34fd7fc81 (patch)
tree82052c53c3f61b66eb5b6f86380adba2bbb05d32 /packages/Shell
parent242b9c4eee9d42d02fd2259ffe2124234653aaf2 (diff)
downloadframeworks_base-55beae09e57f987e23f8737d25c611a34fd7fc81.zip
frameworks_base-55beae09e57f987e23f8737d25c611a34fd7fc81.tar.gz
frameworks_base-55beae09e57f987e23f8737d25c611a34fd7fc81.tar.bz2
Changed BugReportReceiver to send zipped bugreports.
When BugReporterReceiver receives a android.permission.DUMP, it will handle the bugreport file (extra android.intent.extra.BUGREPORT) depending on its format: - If it's a plain-text file (extension .txt), it will create a zip file with the plain-text report renamed as bugreport.txt. - If there is an error creating the zip file, the plain-text bugreport will be sent instead. - If it's not a plain-text file, it fill send the file as is (so if 'dumpstate' is later changed to generate a zipped file directly, nothing has to be done here). Note that only the bugreport itself is included in the zip file, the screenshot is still sent separately (extra android.intent.extra.SCREENSHOT), so the receiver of the bugreport intent can display a screenshot thumbnail without unzipping the other file (which is useful when sending the bugreport through GMail, for example). BUG: 20447313 BUG: 21868658 Change-Id: I3fa1e0c89190bfe6fa5c418f0f01ce1fb376f537
Diffstat (limited to 'packages/Shell')
-rw-r--r--packages/Shell/src/com/android/shell/BugreportReceiver.java140
1 files changed, 118 insertions, 22 deletions
diff --git a/packages/Shell/src/com/android/shell/BugreportReceiver.java b/packages/Shell/src/com/android/shell/BugreportReceiver.java
index e1bfc43..d299d66 100644
--- a/packages/Shell/src/com/android/shell/BugreportReceiver.java
+++ b/packages/Shell/src/com/android/shell/BugreportReceiver.java
@@ -33,11 +33,22 @@ import android.os.FileUtils;
import android.os.SystemProperties;
import android.support.v4.content.FileProvider;
import android.text.format.DateUtils;
+import android.util.Log;
import android.util.Patterns;
import com.google.android.collect.Lists;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
import java.util.ArrayList;
/**
@@ -73,30 +84,14 @@ public class BugreportReceiver extends BroadcastReceiver {
final Uri bugreportUri = FileProvider.getUriForFile(context, AUTHORITY, bugreportFile);
final Uri screenshotUri = FileProvider.getUriForFile(context, AUTHORITY, screenshotFile);
- Intent sendIntent = buildSendIntent(context, bugreportUri, screenshotUri);
- Intent notifIntent;
-
- // Send through warning dialog by default
- if (getWarningState(context, STATE_SHOW) == STATE_SHOW) {
- notifIntent = buildWarningIntent(context, sendIntent);
+ boolean isPlainText = bugreportFile.getName().toLowerCase().endsWith(".txt");
+ if (!isPlainText) {
+ // Already zipped, send it right away.
+ sendBugreportNotification(context, bugreportFile, screenshotFile);
} else {
- notifIntent = sendIntent;
+ // Asynchronously zip the file first, then send it.
+ sendZippedBugreportNotification(context, bugreportFile, screenshotFile);
}
- notifIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
- final Notification.Builder builder = new Notification.Builder(context)
- .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
- .setContentTitle(context.getString(R.string.bugreport_finished_title))
- .setTicker(context.getString(R.string.bugreport_finished_title))
- .setContentText(context.getString(R.string.bugreport_finished_text))
- .setContentIntent(PendingIntent.getActivity(
- context, 0, notifIntent, PendingIntent.FLAG_CANCEL_CURRENT))
- .setAutoCancel(true)
- .setLocalOnly(true)
- .setColor(context.getColor(
- com.android.internal.R.color.system_notification_accent_color));
-
- NotificationManager.from(context).notify(TAG, 0, builder.build());
// Clean up older bugreports in background
final PendingResult result = goAsync();
@@ -141,6 +136,107 @@ public class BugreportReceiver extends BroadcastReceiver {
}
/**
+ * Sends a bugreport notitication.
+ */
+ private static void sendBugreportNotification(Context context, File bugreportFile,
+ File screenshotFile) {
+ // Files are kept on private storage, so turn into Uris that we can
+ // grant temporary permissions for.
+ final Uri bugreportUri = FileProvider.getUriForFile(context, AUTHORITY, bugreportFile);
+ final Uri screenshotUri = FileProvider.getUriForFile(context, AUTHORITY, screenshotFile);
+
+ Intent sendIntent = buildSendIntent(context, bugreportUri, screenshotUri);
+ Intent notifIntent;
+
+ // Send through warning dialog by default
+ if (getWarningState(context, STATE_SHOW) == STATE_SHOW) {
+ notifIntent = buildWarningIntent(context, sendIntent);
+ } else {
+ notifIntent = sendIntent;
+ }
+ notifIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ final Notification.Builder builder = new Notification.Builder(context)
+ .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
+ .setContentTitle(context.getString(R.string.bugreport_finished_title))
+ .setTicker(context.getString(R.string.bugreport_finished_title))
+ .setContentText(context.getString(R.string.bugreport_finished_text))
+ .setContentIntent(PendingIntent.getActivity(
+ context, 0, notifIntent, PendingIntent.FLAG_CANCEL_CURRENT))
+ .setAutoCancel(true)
+ .setLocalOnly(true)
+ .setColor(context.getColor(
+ com.android.internal.R.color.system_notification_accent_color));
+
+ NotificationManager.from(context).notify(TAG, 0, builder.build());
+ }
+
+ /**
+ * Sends a zipped bugreport notification.
+ */
+ private static void sendZippedBugreportNotification(final Context context,
+ final File bugreportFile, final File screenshotFile) {
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ File zippedFile = zipBugreport(bugreportFile);
+ sendBugreportNotification(context, zippedFile, screenshotFile);
+ return null;
+ }
+ }.execute();
+ }
+
+ /**
+ * Zips a bugreport file, returning the path to the new file (or to the
+ * original in case of failure).
+ */
+ private static File zipBugreport(File bugreportFile) {
+ byte[] bytes = read(bugreportFile);
+ if (bytes == null) {
+ // Could not read bugreport, return original.
+ return bugreportFile;
+ }
+ String bugreportPath = bugreportFile.getAbsolutePath();
+ String zippedPath = bugreportPath.replace(".txt", ".zip");
+ Log.v(TAG, "zipping " + bugreportPath + " as " + zippedPath);
+ File bugreportZippedFile = new File(zippedPath);
+ try (ZipOutputStream zos = new ZipOutputStream(
+ new BufferedOutputStream(new FileOutputStream(bugreportZippedFile)))) {
+ ZipEntry entry = new ZipEntry("bugreport.txt");
+ zos.putNextEntry(entry);
+ zos.write(bytes);
+ zos.closeEntry();
+ // Delete old file;
+ boolean deleted = bugreportFile.delete();
+ if (deleted) {
+ Log.v(TAG, "deleted original bugreport (" + bugreportPath + ")");
+ } else {
+ Log.e(TAG, "could not delete original bugreport (" + bugreportPath + ")");
+ }
+ return bugreportZippedFile;
+ } catch (IOException e) {
+ Log.e(TAG, "exception zipping file " + zippedPath, e);
+ return bugreportFile; // Return original.
+ }
+ }
+
+ /** Returns the content of file, or {@code null} in case of error. */
+ private static byte[] read(File file) {
+ try (ByteArrayOutputStream output = new ByteArrayOutputStream();
+ InputStream input = new FileInputStream(file)) {
+ byte[] buffer = new byte[4096];
+ int read = 0;
+ while ((read = input.read(buffer)) != -1) {
+ output.write(buffer, 0, read);
+ }
+ return output.toByteArray();
+ } catch (IOException e) {
+ Log.e(TAG, "IOException reading " + file.getAbsolutePath(), e);
+ return null;
+ }
+ }
+
+ /**
* Find the best matching {@link Account} based on build properties.
*/
private static Account findSendToAccount(Context context) {