/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.shell;

import static android.test.MoreAsserts.assertContainsRegex;

import static com.android.shell.ActionSendMultipleConsumerActivity.UI_NAME;
import static com.android.shell.BugreportPrefs.PREFS_BUGREPORT;
import static com.android.shell.BugreportPrefs.STATE_HIDE;
import static com.android.shell.BugreportPrefs.STATE_SHOW;
import static com.android.shell.BugreportPrefs.STATE_UNKNOWN;
import static com.android.shell.BugreportPrefs.getWarningState;
import static com.android.shell.BugreportPrefs.setWarningState;
import static com.android.shell.BugreportProgressService.EXTRA_BUGREPORT;
import static com.android.shell.BugreportProgressService.EXTRA_ID;
import static com.android.shell.BugreportProgressService.EXTRA_MAX;
import static com.android.shell.BugreportProgressService.EXTRA_NAME;
import static com.android.shell.BugreportProgressService.EXTRA_PID;
import static com.android.shell.BugreportProgressService.EXTRA_SCREENSHOT;
import static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_FINISHED;
import static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_STARTED;
import static com.android.shell.BugreportProgressService.POLLING_FREQUENCY;
import static com.android.shell.BugreportProgressService.SCREENSHOT_DELAY_SECONDS;

import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import libcore.io.Streams;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.app.Instrumentation;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.SystemProperties;
import android.service.notification.StatusBarNotification;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObjectNotFoundException;
import android.test.InstrumentationTestCase;
import android.test.suitebuilder.annotation.LargeTest;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Log;

import com.android.shell.ActionSendMultipleConsumerActivity.CustomActionSendMultipleListener;

/**
 * Integration tests for {@link BugreportReceiver}.
 * <p>
 * These tests don't mock any component and rely on external UI components (like the notification
 * bar and activity chooser), which can make them unreliable and slow.
 * <p>
 * The general workflow is:
 * <ul>
 * <li>creates the bug report files
 * <li>generates the BUGREPORT_FINISHED intent
 * <li>emulate user actions to share the intent with a custom activity
 * <li>asserts the extras received by the custom activity
 * </ul>
 * <p>
 * <strong>NOTE</strong>: these tests only work if the device is unlocked.
 */
@LargeTest
public class BugreportReceiverTest extends InstrumentationTestCase {
    private static final String TAG = "BugreportReceiverTest";

    // Timeout for UI operations, in milliseconds.
    private static final int TIMEOUT = (int) POLLING_FREQUENCY * 4;

    // Timeout for when waiting for a screenshot to finish.
    private static final int SAFE_SCREENSHOT_DELAY = SCREENSHOT_DELAY_SECONDS + 10;

    private static final String BUGREPORTS_DIR = "bugreports";
    private static final String BUGREPORT_FILE = "test_bugreport.txt";
    private static final String ZIP_FILE = "test_bugreport.zip";
    private static final String ZIP_FILE2 = "test_bugreport2.zip";
    private static final String SCREENSHOT_FILE = "test_screenshot.png";

    private static final String BUGREPORT_CONTENT = "Dump, might as well dump!\n";
    private static final String SCREENSHOT_CONTENT = "A picture is worth a thousand words!\n";

    private static final int PID = 42;
    private static final int PID2 = 24;
    private static final int ID = 108;
    private static final int ID2 = 801;
    private static final String PROGRESS_PROPERTY = "dumpstate." + PID + ".progress";
    private static final String MAX_PROPERTY = "dumpstate." + PID + ".max";
    private static final String NAME_PROPERTY = "dumpstate." + PID + ".name";
    private static final String NAME = "BUG, Y U NO REPORT?";
    private static final String NAME2 = "A bugreport's life";
    private static final String NEW_NAME = "Bug_Forrest_Bug";
    private static final String NEW_NAME2 = "BugsyReportsy";
    private static final String TITLE = "Wimbugdom Champion 2015";
    private static final String TITLE2 = "Master of the Universe";
    private static final String DESCRIPTION = "One's description...";
    private static final String DESCRIPTION2 = "...is another's treasure.";

    private static final String NO_DESCRIPTION = null;
    private static final String NO_NAME = null;
    private static final String NO_SCREENSHOT = null;
    private static final String NO_TITLE = null;
    private static final int NO_ID = 0;
    private static final boolean RENAMED_SCREENSHOTS = true;
    private static final boolean DIDNT_RENAME_SCREENSHOTS = false;

    private String mDescription;

    private String mPlainTextPath;
    private String mZipPath;
    private String mZipPath2;
    private String mScreenshotPath;

    private Context mContext;
    private UiBot mUiBot;
    private CustomActionSendMultipleListener mListener;

    @Override
    protected void setUp() throws Exception {
        Log.i(TAG, "#### setup() on " + getName());
        Instrumentation instrumentation = getInstrumentation();
        mContext = instrumentation.getTargetContext();
        mUiBot = new UiBot(UiDevice.getInstance(instrumentation), TIMEOUT);
        mListener = ActionSendMultipleConsumerActivity.getListener(mContext);

        cancelExistingNotifications();

        mPlainTextPath = getPath(BUGREPORT_FILE);
        mZipPath = getPath(ZIP_FILE);
        mZipPath2 = getPath(ZIP_FILE2);
        mScreenshotPath = getPath(SCREENSHOT_FILE);
        createTextFile(mPlainTextPath, BUGREPORT_CONTENT);
        createTextFile(mScreenshotPath, SCREENSHOT_CONTENT);
        createZipFile(mZipPath, BUGREPORT_FILE, BUGREPORT_CONTENT);
        createZipFile(mZipPath2, BUGREPORT_FILE, BUGREPORT_CONTENT);

        // Creates a multi-line description.
        StringBuilder sb = new StringBuilder();
        for (int i = 1; i <= 20; i++) {
            sb.append("All work and no play makes Shell a dull app!\n");
        }
        mDescription = sb.toString();

        setWarningState(mContext, STATE_HIDE);
    }

    public void testProgress() throws Exception {
        resetProperties();
        sendBugreportStarted(1000);
        waitForScreenshotButtonEnabled(true);

        assertProgressNotification(NAME, 0f);

        SystemProperties.set(PROGRESS_PROPERTY, "108");
        assertProgressNotification(NAME, 10.80f);

        assertProgressNotification(NAME, 50.00f);

        SystemProperties.set(PROGRESS_PROPERTY, "950");
        assertProgressNotification(NAME, 95.00f);

        // Make sure progress never goes back...
        SystemProperties.set(MAX_PROPERTY, "2000");
        Thread.sleep(POLLING_FREQUENCY + DateUtils.SECOND_IN_MILLIS);
        assertProgressNotification(NAME, 95.00f);

        SystemProperties.set(PROGRESS_PROPERTY, "1000");
        assertProgressNotification(NAME, 95.00f);

        // ...only forward...
        SystemProperties.set(PROGRESS_PROPERTY, "1902");
        assertProgressNotification(NAME, 95.10f);

        SystemProperties.set(PROGRESS_PROPERTY, "1960");
        assertProgressNotification(NAME, 98.00f);

        // ...but never more than the capped value.
        SystemProperties.set(PROGRESS_PROPERTY, "2000");
        assertProgressNotification(NAME, 99.00f);

        SystemProperties.set(PROGRESS_PROPERTY, "3000");
        assertProgressNotification(NAME, 99.00f);

        Bundle extras =
                sendBugreportFinishedAndGetSharedIntent(ID, mPlainTextPath, mScreenshotPath);
        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, ZIP_FILE,
                NAME, NO_TITLE, NO_DESCRIPTION, 0, RENAMED_SCREENSHOTS);

        assertServiceNotRunning();
    }

    public void testProgress_cancel() throws Exception {
        resetProperties();
        sendBugreportStarted(1000);
        waitForScreenshotButtonEnabled(true);

        final NumberFormat nf = NumberFormat.getPercentInstance();
        nf.setMinimumFractionDigits(2);
        nf.setMaximumFractionDigits(2);

        assertProgressNotification(NAME, 00.00f);

        openProgressNotification(ID);
        UiObject cancelButton = mUiBot.getVisibleObject(mContext.getString(
                com.android.internal.R.string.cancel).toUpperCase());
        mUiBot.click(cancelButton, "cancel_button");

        waitForService(false);
    }

    public void testProgress_takeExtraScreenshot() throws Exception {
        resetProperties();
        sendBugreportStarted(1000);

        waitForScreenshotButtonEnabled(true);
        takeScreenshot();
        assertScreenshotButtonEnabled(false);
        waitForScreenshotButtonEnabled(true);

        sendBugreportFinished(ID, mPlainTextPath, mScreenshotPath);

        Bundle extras = acceptBugreportAndGetSharedIntent(ID);
        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, ZIP_FILE,
                NAME, NO_TITLE, NO_DESCRIPTION, 1, RENAMED_SCREENSHOTS);

        assertServiceNotRunning();
    }

    public void testScreenshotFinishesAfterBugreport() throws Exception {
        resetProperties();

        sendBugreportStarted(1000);
        waitForScreenshotButtonEnabled(true);
        takeScreenshot();
        sendBugreportFinished(ID, mPlainTextPath, NO_SCREENSHOT);
        waitShareNotification(ID);

        // There's no indication in the UI about the screenshot finish, so just sleep like a baby...
        Thread.sleep(SAFE_SCREENSHOT_DELAY * DateUtils.SECOND_IN_MILLIS);

        Bundle extras = acceptBugreportAndGetSharedIntent(ID);
        assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT, ID, PID, ZIP_FILE,
                NAME, NO_TITLE, NO_DESCRIPTION, 1, RENAMED_SCREENSHOTS);

        assertServiceNotRunning();
    }

    public void testProgress_changeDetailsInvalidInput() throws Exception {
        resetProperties();
        sendBugreportStarted(1000);
        waitForScreenshotButtonEnabled(true);

        DetailsUi detailsUi = new DetailsUi(mUiBot, ID);

        // Check initial name.
        detailsUi.assertName(NAME);

        // Change name - it should have changed system property once focus is changed.
        detailsUi.focusOnName();
        detailsUi.nameField.setText(NEW_NAME);
        detailsUi.focusAwayFromName();
        assertPropertyValue(NAME_PROPERTY, NEW_NAME);

        // Cancel the dialog to make sure property was restored.
        detailsUi.clickCancel();
        assertPropertyValue(NAME_PROPERTY, NAME);

        // Now try to set an invalid name.
        detailsUi.reOpen();
        detailsUi.nameField.setText("/etc/passwd");
        detailsUi.clickOk();
        assertPropertyValue(NAME_PROPERTY, "_etc_passwd");

        // Finally, make the real changes.
        detailsUi.reOpen();
        detailsUi.nameField.setText(NEW_NAME);
        detailsUi.titleField.setText(TITLE);
        detailsUi.descField.setText(mDescription);

        detailsUi.clickOk();

        assertPropertyValue(NAME_PROPERTY, NEW_NAME);
        assertProgressNotification(NEW_NAME, 00.00f);

        Bundle extras = sendBugreportFinishedAndGetSharedIntent(ID, mPlainTextPath,
                mScreenshotPath);
        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, TITLE,
                NEW_NAME, TITLE, mDescription, 0, RENAMED_SCREENSHOTS);

        assertServiceNotRunning();
    }

    public void testProgress_changeDetailsPlainBugreport() throws Exception {
        changeDetailsTest(true);
    }

    public void testProgress_changeDetailsZippedBugreport() throws Exception {
        changeDetailsTest(false);
    }

    public void changeDetailsTest(boolean plainText) throws Exception {
        resetProperties();
        sendBugreportStarted(1000);
        waitForScreenshotButtonEnabled(true);

        DetailsUi detailsUi = new DetailsUi(mUiBot, ID);

        // Check initial name.
        detailsUi.assertName(NAME);

        // Change fields.
        detailsUi.reOpen();
        detailsUi.nameField.setText(NEW_NAME);
        detailsUi.titleField.setText(TITLE);
        detailsUi.descField.setText(mDescription);

        detailsUi.clickOk();

        assertPropertyValue(NAME_PROPERTY, NEW_NAME);
        assertProgressNotification(NEW_NAME, 00.00f);

        Bundle extras = sendBugreportFinishedAndGetSharedIntent(ID,
                plainText? mPlainTextPath : mZipPath, mScreenshotPath);
        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, TITLE,
                NEW_NAME, TITLE, mDescription, 0, RENAMED_SCREENSHOTS);

        assertServiceNotRunning();
    }

    public void testProgress_changeJustDetailsTouchingDetails() throws Exception {
        changeJustDetailsTest(true);
    }

    public void testProgress_changeJustDetailsTouchingNotification() throws Exception {
        changeJustDetailsTest(false);
    }

    private void changeJustDetailsTest(boolean touchDetails) throws Exception {
        resetProperties();
        sendBugreportStarted(1000);
        waitForScreenshotButtonEnabled(true);

        DetailsUi detailsUi = new DetailsUi(mUiBot, ID, touchDetails);

        detailsUi.nameField.setText("");
        detailsUi.titleField.setText("");
        detailsUi.descField.setText(mDescription);
        detailsUi.clickOk();

        Bundle extras = sendBugreportFinishedAndGetSharedIntent(ID, mZipPath, mScreenshotPath);
        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, ZIP_FILE,
                NO_NAME, NO_TITLE, mDescription, 0, DIDNT_RENAME_SCREENSHOTS);

        assertServiceNotRunning();
    }

    /*
     * TODO: this test can be flanky because it relies in the order the notifications are displayed,
     * since mUiBot gets the first notification.
     * Ideally, openProgressNotification() should return the whole notification, so DetailsUi
     * could use it and find children instead, but unfortunately the notification object hierarchy
     * is too complex and getting it from the notification text object would be to fragile
     * (for instance, it could require navigating many parents up in the hierarchy).
     */
    public void testProgress_changeJustDetailsIsClearedOnSecondBugreport() throws Exception {
        resetProperties();
        sendBugreportStarted(ID, PID, NAME, 1000);
        waitForScreenshotButtonEnabled(true);

        DetailsUi detailsUi = new DetailsUi(mUiBot, ID);
        detailsUi.assertName(NAME);
        detailsUi.assertTitle("");
        detailsUi.assertDescription("");
        detailsUi.nameField.setText(NEW_NAME);
        detailsUi.titleField.setText(TITLE);
        detailsUi.descField.setText(DESCRIPTION);
        detailsUi.clickOk();

        sendBugreportStarted(ID2, PID2, NAME2, 1000);

        sendBugreportFinished(ID, mZipPath, mScreenshotPath);
        Bundle extras = acceptBugreportAndGetSharedIntent(ID);

        detailsUi = new DetailsUi(mUiBot, ID2);
        detailsUi.assertName(NAME2);
        detailsUi.assertTitle("");
        detailsUi.assertDescription("");
        detailsUi.nameField.setText(NEW_NAME2);
        detailsUi.titleField.setText(TITLE2);
        detailsUi.descField.setText(DESCRIPTION2);
        detailsUi.clickOk();

        // Must use a different zip file otherwise it will fail because zip already contains
        // title.txt and description.txt entries.
        extras = sendBugreportFinishedAndGetSharedIntent(ID2, mZipPath2, NO_SCREENSHOT);
        assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT, ID2, PID2, TITLE2,
                NEW_NAME2, TITLE2, DESCRIPTION2, 0, RENAMED_SCREENSHOTS);

        assertServiceNotRunning();
    }

    /**
     * Tests the scenario where the initial screenshot and dumpstate are finished while the user
     * is changing the info in the details screen.
     */
    public void testProgress_bugreportAndScreenshotFinishedWhileChangingDetails() throws Exception {
        bugreportFinishedWhileChangingDetailsTest(false);
    }

    /**
     * Tests the scenario where dumpstate is finished while the user is changing the info in the
     * details screen, but the initial screenshot finishes afterwards.
     */
    public void testProgress_bugreportFinishedWhileChangingDetails() throws Exception {
        bugreportFinishedWhileChangingDetailsTest(true);
    }

    private void bugreportFinishedWhileChangingDetailsTest(boolean waitScreenshot) throws Exception {
        resetProperties();
        sendBugreportStarted(1000);
        if (waitScreenshot) {
            waitForScreenshotButtonEnabled(true);
        }

        DetailsUi detailsUi = new DetailsUi(mUiBot, ID);

        // Finish the bugreport while user's still typing the name.
        detailsUi.nameField.setText(NEW_NAME);
        sendBugreportFinished(ID, mPlainTextPath, mScreenshotPath);

        // Wait until the share notification is received...
        waitShareNotification(ID);
        // ...then close notification bar.
        mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));

        // Make sure UI was updated properly.
        assertFalse("didn't disable name on UI", detailsUi.nameField.isEnabled());
        assertEquals("didn't revert name on UI", NAME, detailsUi.nameField.getText().toString());

        // Finish changing other fields.
        detailsUi.titleField.setText(TITLE);
        detailsUi.descField.setText(mDescription);
        detailsUi.clickOk();

        // Finally, share bugreport.
        Bundle extras = acceptBugreportAndGetSharedIntent(ID);
        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, TITLE,
                NAME, TITLE, mDescription, 0, RENAMED_SCREENSHOTS);

        assertServiceNotRunning();
    }

    public void testBugreportFinished_withWarningFirstTime() throws Exception {
        bugreportFinishedWithWarningTest(null);
    }

    public void testBugreportFinished_withWarningUnknownState() throws Exception {
        bugreportFinishedWithWarningTest(STATE_UNKNOWN);
    }

    public void testBugreportFinished_withWarningShowAgain() throws Exception {
        bugreportFinishedWithWarningTest(STATE_SHOW);
    }

    private void bugreportFinishedWithWarningTest(Integer propertyState) throws Exception {
        if (propertyState == null) {
            // Clear properties
            mContext.getSharedPreferences(PREFS_BUGREPORT, Context.MODE_PRIVATE)
                    .edit().clear().commit();
            // Sanity check...
            assertEquals("Did not reset properties", STATE_UNKNOWN,
                    getWarningState(mContext, STATE_UNKNOWN));
        } else {
            setWarningState(mContext, propertyState);
        }

        // Send notification and click on share.
        sendBugreportFinished(NO_ID, mPlainTextPath, null);
        acceptBugreport(NO_ID);

        // Handle the warning
        mUiBot.getVisibleObject(mContext.getString(R.string.bugreport_confirm));
        // TODO: get ok and dontShowAgain from the dialog reference above
        UiObject dontShowAgain =
                mUiBot.getVisibleObject(mContext.getString(R.string.bugreport_confirm_dont_repeat));
        final boolean firstTime = propertyState == null || propertyState == STATE_UNKNOWN;
        if (firstTime) {
            if (Build.TYPE.equals("user")) {
                assertFalse("Checkbox should NOT be checked by default on user builds",
                        dontShowAgain.isChecked());
                mUiBot.click(dontShowAgain, "dont-show-again");
            } else {
                assertTrue("Checkbox should be checked by default on build type " + Build.TYPE,
                        dontShowAgain.isChecked());
            }
        } else {
            assertFalse("Checkbox should not be checked", dontShowAgain.isChecked());
            mUiBot.click(dontShowAgain, "dont-show-again");
        }
        UiObject ok = mUiBot.getVisibleObject(mContext.getString(com.android.internal.R.string.ok));
        mUiBot.click(ok, "ok");

        // Share the bugreport.
        mUiBot.chooseActivity(UI_NAME);
        Bundle extras = mListener.getExtras();
        assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);

        // Make sure it's hidden now.
        int newState = getWarningState(mContext, STATE_UNKNOWN);
        assertEquals("Didn't change state", STATE_HIDE, newState);
    }

    public void testShareBugreportAfterServiceDies() throws Exception {
        sendBugreportFinished(NO_ID, mPlainTextPath, NO_SCREENSHOT);
        waitForService(false);
        Bundle extras = acceptBugreportAndGetSharedIntent(NO_ID);
        assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
    }

    public void testBugreportFinished_plainBugreportAndScreenshot() throws Exception {
        Bundle extras = sendBugreportFinishedAndGetSharedIntent(mPlainTextPath, mScreenshotPath);
        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);
    }

    public void testBugreportFinished_zippedBugreportAndScreenshot() throws Exception {
        Bundle extras = sendBugreportFinishedAndGetSharedIntent(mZipPath, mScreenshotPath);
        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);
    }

    public void testBugreportFinished_plainBugreportAndNoScreenshot() throws Exception {
        Bundle extras = sendBugreportFinishedAndGetSharedIntent(mPlainTextPath, NO_SCREENSHOT);
        assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
    }

    public void testBugreportFinished_zippedBugreportAndNoScreenshot() throws Exception {
        Bundle extras = sendBugreportFinishedAndGetSharedIntent(mZipPath, NO_SCREENSHOT);
        assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
    }

    private void cancelExistingNotifications() {
        NotificationManager nm = NotificationManager.from(mContext);
        for (StatusBarNotification notification : nm.getActiveNotifications()) {
            int id = notification.getId();
            Log.i(TAG, "Canceling existing notification (id=" + id + ")");
            nm.cancel(id);
        }
    }

    private void assertProgressNotification(String name, float percent) {
        // TODO: it currently looks for 3 distinct objects, without taking advantage of their
        // relationship.
        openProgressNotification(ID);
        Log.v(TAG, "Looking for progress notification details: '" + name + "-" + percent + "'");
        mUiBot.getObject(name);
        // TODO: need a way to get the ProgresBar from the "android:id/progress" UIObject...
    }

    private UiObject openProgressNotification(int id) {
        String title = mContext.getString(R.string.bugreport_in_progress_title, id);
        Log.v(TAG, "Looking for progress notification title: '" + title + "'");
        return mUiBot.getNotification(title);
    }

    void resetProperties() {
        // TODO: call method to remove property instead
        SystemProperties.set(PROGRESS_PROPERTY, "Reset");
        SystemProperties.set(MAX_PROPERTY, "Reset");
        SystemProperties.set(NAME_PROPERTY, "Reset");
    }

    /**
     * Sends a "bugreport started" intent with the default values.
     */
    private void sendBugreportStarted(int max) throws Exception {
        sendBugreportStarted(ID, PID, NAME, max);
    }

    private void sendBugreportStarted(int id, int pid, String name, int max) throws Exception {
        Intent intent = new Intent(INTENT_BUGREPORT_STARTED);
        intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
        intent.putExtra(EXTRA_ID, id);
        intent.putExtra(EXTRA_PID, pid);
        intent.putExtra(EXTRA_NAME, name);
        intent.putExtra(EXTRA_MAX, max);
        mContext.sendBroadcast(intent);
    }

    /**
     * Sends a "bugreport finished" intent and waits for the result.
     *
     * @return extras sent in the shared intent.
     */
    private Bundle sendBugreportFinishedAndGetSharedIntent(String bugreportPath,
            String screenshotPath) {
        return sendBugreportFinishedAndGetSharedIntent(NO_ID, bugreportPath, screenshotPath);
    }

    /**
     * Sends a "bugreport finished" intent and waits for the result.
     *
     * @return extras sent in the shared intent.
     */
    private Bundle sendBugreportFinishedAndGetSharedIntent(int id, String bugreportPath,
            String screenshotPath) {
        sendBugreportFinished(id, bugreportPath, screenshotPath);
        return acceptBugreportAndGetSharedIntent(id);
    }

    /**
     * Accepts the notification to share the finished bugreport and waits for the result.
     *
     * @return extras sent in the shared intent.
     */
    private Bundle acceptBugreportAndGetSharedIntent(int id) {
        acceptBugreport(id);
        mUiBot.chooseActivity(UI_NAME);
        return mListener.getExtras();
    }

    /**
     * Waits for the notification to share the finished bugreport.
     */
    private void waitShareNotification(int id) {
        mUiBot.getNotification(mContext.getString(R.string.bugreport_finished_title, id));
    }

    /**
     * Accepts the notification to share the finished bugreport.
     */
    private void acceptBugreport(int id) {
        mUiBot.clickOnNotification(mContext.getString(R.string.bugreport_finished_title, id));
    }

    /**
     * Sends a "bugreport finished" intent.
     */
    private void sendBugreportFinished(int id, String bugreportPath, String screenshotPath) {
        Intent intent = new Intent(INTENT_BUGREPORT_FINISHED);
        intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
        if (id != NO_ID) {
            intent.putExtra(EXTRA_ID, id);
        }
        if (bugreportPath != null) {
            intent.putExtra(EXTRA_BUGREPORT, bugreportPath);
        }
        if (screenshotPath != null) {
            intent.putExtra(EXTRA_SCREENSHOT, screenshotPath);
        }

        mContext.sendBroadcast(intent);
    }

    /**
     * Asserts the proper {@link Intent#ACTION_SEND_MULTIPLE} intent was sent.
     */
    private void assertActionSendMultiple(Bundle extras, String bugreportContent,
            String screenshotContent) throws IOException {
        assertActionSendMultiple(extras, bugreportContent, screenshotContent, ID, PID, ZIP_FILE,
                NO_NAME, NO_TITLE, NO_DESCRIPTION, 0, DIDNT_RENAME_SCREENSHOTS);
    }

    /**
     * Asserts the proper {@link Intent#ACTION_SEND_MULTIPLE} intent was sent.
     *
     * @param extras extras received in the intent
     * @param bugreportContent expected content in the bugreport file
     * @param screenshotContent expected content in the screenshot file (sent by dumpstate), if any
     * @param id emulated dumpstate id
     * @param pid emulated dumpstate pid
     * @param name expected subject
     * @param name bugreport name as provided by the user (or received by dumpstate)
     * @param title bugreport name as provided by the user
     * @param description bugreport description as provided by the user
     * @param numberScreenshots expected number of screenshots taken by Shell.
     * @param renamedScreenshots whether the screenshots are expected to be renamed
     */
    private void assertActionSendMultiple(Bundle extras, String bugreportContent,
            String screenshotContent, int id, int pid, String subject,
            String name, String title, String description,
            int numberScreenshots, boolean renamedScreenshots) throws IOException {
        String body = extras.getString(Intent.EXTRA_TEXT);
        assertContainsRegex("missing build info",
                SystemProperties.get("ro.build.description"), body);
        assertContainsRegex("missing serial number",
                SystemProperties.get("ro.serialno"), body);
        if (description != null) {
            assertContainsRegex("missing description", description, body);
        }

        assertEquals("wrong subject", subject, extras.getString(Intent.EXTRA_SUBJECT));

        List<Uri> attachments = extras.getParcelableArrayList(Intent.EXTRA_STREAM);
        int expectedNumberScreenshots = numberScreenshots;
        if (screenshotContent != null) {
            expectedNumberScreenshots ++; // Add screenshot received by dumpstate
        }
        int expectedSize = expectedNumberScreenshots + 1; // All screenshots plus the bugreport file
        assertEquals("wrong number of attachments (" + attachments + ")",
                expectedSize, attachments.size());

        // Need to interact through all attachments, since order is not guaranteed.
        Uri zipUri = null;
        List<Uri> screenshotUris = new ArrayList<>(expectedNumberScreenshots);
        for (Uri attachment : attachments) {
            if (attachment.getPath().endsWith(".zip")) {
                zipUri = attachment;
            }
            if (attachment.getPath().endsWith(".png")) {
                screenshotUris.add(attachment);
            }
        }
        assertNotNull("did not get .zip attachment", zipUri);
        assertZipContent(zipUri, BUGREPORT_FILE, BUGREPORT_CONTENT);
        if (!TextUtils.isEmpty(title)) {
            assertZipContent(zipUri, "title.txt", title);
        }
        if (!TextUtils.isEmpty(description)) {
            assertZipContent(zipUri, "description.txt", description);
        }

        // URI of the screenshot taken by dumpstate.
        Uri externalScreenshotUri = null;
        SortedSet<String> internalScreenshotNames = new TreeSet<>();
        for (Uri screenshotUri : screenshotUris) {
            String screenshotName = screenshotUri.getLastPathSegment();
            if (screenshotName.endsWith(SCREENSHOT_FILE)) {
                externalScreenshotUri = screenshotUri;
            } else {
                internalScreenshotNames.add(screenshotName);
            }
        }
        // Check external screenshot
        if (screenshotContent != null) {
            assertNotNull("did not get .png attachment for external screenshot",
                    externalScreenshotUri);
            assertContent(externalScreenshotUri, SCREENSHOT_CONTENT);
        } else {
            assertNull("should not have .png attachment for external screenshot",
                    externalScreenshotUri);
        }
        // Check internal screenshots.
        SortedSet<String> expectedNames = new TreeSet<>();
        for (int i = 1 ; i <= numberScreenshots; i++) {
            String prefix = renamedScreenshots  ? name : Integer.toString(pid);
            String expectedName = "screenshot-" + prefix + "-" + i + ".png";
            expectedNames.add(expectedName);
        }
        // Ideally we should use MoreAsserts, but the error message in case of failure is not
        // really useful.
        assertEquals("wrong names for internal screenshots",
                expectedNames, internalScreenshotNames);
    }

    private void assertContent(Uri uri, String expectedContent) throws IOException {
        Log.v(TAG, "assertContents(uri=" + uri);
        try (InputStream is = mContext.getContentResolver().openInputStream(uri)) {
            String actualContent = new String(Streams.readFully(is));
            assertEquals("wrong content for '" + uri + "'", expectedContent, actualContent);
        }
    }

    private void assertZipContent(Uri uri, String entryName, String expectedContent)
            throws IOException, IOException {
        Log.v(TAG, "assertZipEntry(uri=" + uri + ", entryName=" + entryName);
        try (ZipInputStream zis = new ZipInputStream(mContext.getContentResolver().openInputStream(
                uri))) {
            ZipEntry entry;
            while ((entry = zis.getNextEntry()) != null) {
                Log.v(TAG, "Zip entry: " + entry.getName());
                if (entry.getName().equals(entryName)) {
                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
                    Streams.copy(zis, bos);
                    String actualContent = new String(bos.toByteArray(), "UTF-8");
                    bos.close();
                    assertEquals("wrong content for zip entry'" + entryName + "' on '" + uri + "'",
                            expectedContent, actualContent);
                    return;
                }
            }
        }
        fail("Did not find entry '" + entryName + "' on file '" + uri + "'");
    }

    private void assertPropertyValue(String key, String expectedValue) {
        String actualValue = SystemProperties.get(key);
        assertEquals("Wrong value for property '" + key + "'", expectedValue, actualValue);
    }

    private void assertServiceNotRunning() {
        String service = BugreportProgressService.class.getName();
        assertFalse("Service '" + service + "' is still running", isServiceRunning(service));
    }

    private boolean isServiceRunning(String name) {
        ActivityManager manager = (ActivityManager) mContext
                .getSystemService(Context.ACTIVITY_SERVICE);
        for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
            if (service.service.getClassName().equals(name)) {
                return true;
            }
        }
        return false;
    }

    private void waitForService(boolean expectRunning) {
        String service = BugreportProgressService.class.getName();
        boolean actualRunning;
        for (int i = 1; i <= 5; i++) {
            actualRunning = isServiceRunning(service);
            Log.d(TAG, "Attempt " + i + " to check status of service '"
                    + service + "': expected=" + expectRunning + ", actual= " + actualRunning);
            if (actualRunning == expectRunning) {
                return;
            }
            try {
                Thread.sleep(DateUtils.SECOND_IN_MILLIS);
            } catch (InterruptedException e) {
                Log.w(TAG, "thread interrupted");
                Thread.currentThread().interrupt();
            }
        }

        fail("Service status didn't change to " + expectRunning);
    }

    private void createTextFile(String path, String content) throws IOException {
        Log.v(TAG, "createFile(" + path + ")");
        try (Writer writer = new BufferedWriter(new OutputStreamWriter(
                new FileOutputStream(path)))) {
            writer.write(content);
        }
    }

    private void createZipFile(String path, String entryName, String content) throws IOException {
        Log.v(TAG, "createZipFile(" + path + ", " + entryName + ")");
        try (ZipOutputStream zos = new ZipOutputStream(
                new BufferedOutputStream(new FileOutputStream(path)))) {
            ZipEntry entry = new ZipEntry(entryName);
            zos.putNextEntry(entry);
            byte[] data = content.getBytes();
            zos.write(data, 0, data.length);
            zos.closeEntry();
        }
    }

    private String getPath(String file) {
        final File rootDir = mContext.getFilesDir();
        final File dir = new File(rootDir, BUGREPORTS_DIR);
        if (!dir.exists()) {
            Log.i(TAG, "Creating directory " + dir);
            assertTrue("Could not create directory " + dir, dir.mkdir());
        }
        String path = new File(dir, file).getAbsolutePath();
        Log.v(TAG, "Path for '" + file + "': " + path);
        return path;
    }

    /**
     * Gets the notification button used to take a screenshot.
     */
    private UiObject getScreenshotButton() {
        openProgressNotification(ID);
        return mUiBot.getVisibleObject(
                mContext.getString(R.string.bugreport_screenshot_action).toUpperCase());
    }

    /**
     * Takes a screenshot using the system notification.
     */
    private void takeScreenshot() throws Exception {
        UiObject screenshotButton = getScreenshotButton();
        mUiBot.click(screenshotButton, "screenshot_button");
    }

    private UiObject waitForScreenshotButtonEnabled(boolean expectedEnabled) throws Exception {
        UiObject screenshotButton = getScreenshotButton();
        int maxAttempts = SAFE_SCREENSHOT_DELAY;
        int i = 0;
        do {
            boolean enabled = screenshotButton.isEnabled();
            if (enabled == expectedEnabled) {
                return screenshotButton;
            }
            i++;
            Log.v(TAG, "Sleeping for 1 second while waiting for screenshot.enable to be "
                    + expectedEnabled + " (attempt " + i + ")");
            Thread.sleep(DateUtils.SECOND_IN_MILLIS);
        } while (i <= maxAttempts);
        fail("screenshot.enable didn't change to " + expectedEnabled + " in " + maxAttempts + "s");
        return screenshotButton;
    }

    private void assertScreenshotButtonEnabled(boolean expectedEnabled) throws Exception {
        UiObject screenshotButton = getScreenshotButton();
        assertEquals("wrong state for screenshot button ", expectedEnabled,
                screenshotButton.isEnabled());
    }

    /**
     * Helper class containing the UiObjects present in the bugreport info dialog.
     */
    private final class DetailsUi {

        final UiObject detailsButton;
        final UiObject nameField;
        final UiObject titleField;
        final UiObject descField;
        final UiObject okButton;
        final UiObject cancelButton;

        /**
         * Gets the UI objects by opening the progress notification and clicking DETAILS.
         */
        DetailsUi(UiBot uiBot, int id) throws UiObjectNotFoundException {
            this(uiBot, id, true);
        }

        /**
         * Gets the UI objects by opening the progress notification and clicking on DETAILS or in
         * the notification itself.
         */
        DetailsUi(UiBot uiBot, int id, boolean clickDetails) throws UiObjectNotFoundException {
            UiObject notification = openProgressNotification(id);
            detailsButton = mUiBot.getVisibleObject(mContext.getString(
                    R.string.bugreport_info_action).toUpperCase());

            if (clickDetails) {
                mUiBot.click(detailsButton, "details_button");
            } else {
                mUiBot.click(notification, "notification");
            }
            // TODO: unhardcode resource ids
            UiObject dialogTitle = mUiBot.getVisibleObjectById("android:id/alertTitle");
            assertEquals("Wrong title", mContext.getString(R.string.bugreport_info_dialog_title,
                    id), dialogTitle.getText().toString());
            nameField = mUiBot.getVisibleObjectById("com.android.shell:id/name");
            titleField = mUiBot.getVisibleObjectById("com.android.shell:id/title");
            descField = mUiBot.getVisibleObjectById("com.android.shell:id/description");
            okButton = mUiBot.getObjectById("android:id/button1");
            cancelButton = mUiBot.getObjectById("android:id/button2");
        }

        private void assertField(String name, UiObject field, String expected)
                throws UiObjectNotFoundException {
            String actual = field.getText().toString();
            assertEquals("Wrong value on field '" + name + "'", expected, actual);
        }

        void assertName(String expected) throws UiObjectNotFoundException {
            assertField("name", nameField, expected);
        }

        void assertTitle(String expected) throws UiObjectNotFoundException {
            assertField("title", titleField, expected);
        }

        void assertDescription(String expected) throws UiObjectNotFoundException {
            assertField("description", descField, expected);
        }

        /**
         * Set focus on the name field so it can be validated once focus is lost.
         */
        void focusOnName() throws UiObjectNotFoundException {
            mUiBot.click(nameField, "name_field");
            assertTrue("name_field not focused", nameField.isFocused());
        }

        /**
         * Takes focus away from the name field so it can be validated.
         */
        void focusAwayFromName() throws UiObjectNotFoundException {
            mUiBot.click(titleField, "title_field"); // Change focus.
            mUiBot.pressBack(); // Dismiss keyboard.
            assertFalse("name_field is focused", nameField.isFocused());
        }

        void reOpen() {
            openProgressNotification(ID);
            mUiBot.click(detailsButton, "details_button");
        }

        void clickOk() {
            mUiBot.click(okButton, "details_ok_button");
        }

        void clickCancel() {
            mUiBot.click(cancelButton, "details_cancel_button");
        }
    }
}
