Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a106554c authored by Felipe Leme's avatar Felipe Leme Committed by Android (Google) Code Review
Browse files

Merge "Changed BugReportReceiver to send zipped bugreports." into mnc-dev

parents 7f92f067 55beae09
Loading
Loading
Loading
Loading
+118 −22
Original line number Diff line number Diff line
@@ -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();
@@ -140,6 +135,107 @@ public class BugreportReceiver extends BroadcastReceiver {
        return intent;
    }

    /**
     * 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.
     */