am 1d882baf: am 0fe3f871: am a106554c: Merge "Changed BugReportReceiver to send zipped bugreports." into mnc-dev

* commit '1d882bafc7dc855951ba980529560b48f95e4fb3':
  Changed BugReportReceiver to send zipped bugreports.
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.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 @@
         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 @@
     }
 
     /**
+     * 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) {