BugreportReceiverTest.java revision 85ae3cf46ad66d71e5a29a93e89a0f569d74288b
1e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme/*
2e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * Copyright (C) 2015 The Android Open Source Project
3e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme *
4e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * Licensed under the Apache License, Version 2.0 (the "License");
5e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * you may not use this file except in compliance with the License.
6e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * You may obtain a copy of the License at
7e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme *
8e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme *      http://www.apache.org/licenses/LICENSE-2.0
9e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme *
10e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * Unless required by applicable law or agreed to in writing, software
11e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * distributed under the License is distributed on an "AS IS" BASIS,
12e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * See the License for the specific language governing permissions and
14e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * limitations under the License.
15e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme */
16e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
17e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemepackage com.android.shell;
18e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
19e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport static android.test.MoreAsserts.assertContainsRegex;
20e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport static com.android.shell.ActionSendMultipleConsumerActivity.UI_NAME;
21b9238b37838d653c38ce4e712421adb61978fc22Felipe Lemeimport static com.android.shell.BugreportProgressService.EXTRA_BUGREPORT;
2285ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Lemeimport static com.android.shell.BugreportProgressService.EXTRA_ID;
2369c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Lemeimport static com.android.shell.BugreportProgressService.EXTRA_MAX;
2469c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Lemeimport static com.android.shell.BugreportProgressService.EXTRA_NAME;
2569c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Lemeimport static com.android.shell.BugreportProgressService.EXTRA_PID;
26b9238b37838d653c38ce4e712421adb61978fc22Felipe Lemeimport static com.android.shell.BugreportProgressService.EXTRA_SCREENSHOT;
2769c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Lemeimport static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_FINISHED;
2869c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Lemeimport static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_STARTED;
29d1e0f12979441733753b538611f6d73e5527c43cFelipe Lemeimport static com.android.shell.BugreportProgressService.SCREENSHOT_DELAY_SECONDS;
30e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
31e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.BufferedOutputStream;
32e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.BufferedWriter;
33e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.ByteArrayOutputStream;
34a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Lemeimport java.io.File;
35e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.FileOutputStream;
36e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.IOException;
37e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.InputStream;
38e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.OutputStreamWriter;
39e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.Writer;
40e86b63bd17da3d347b9392f897e361919655edd6Felipe Lemeimport java.text.NumberFormat;
41d1e0f12979441733753b538611f6d73e5527c43cFelipe Lemeimport java.util.ArrayList;
42e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.util.List;
43d1e0f12979441733753b538611f6d73e5527c43cFelipe Lemeimport java.util.SortedSet;
44d1e0f12979441733753b538611f6d73e5527c43cFelipe Lemeimport java.util.TreeSet;
45e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.util.zip.ZipEntry;
46e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.util.zip.ZipInputStream;
47e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.util.zip.ZipOutputStream;
48e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
49e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport libcore.io.Streams;
5085ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme
51ba477939f0ae38926b4b0a6501a2371acc612433Felipe Lemeimport android.app.ActivityManager;
52ba477939f0ae38926b4b0a6501a2371acc612433Felipe Lemeimport android.app.ActivityManager.RunningServiceInfo;
53e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.app.Instrumentation;
54e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.app.NotificationManager;
55e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.content.Context;
56a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Lemeimport android.content.ContextWrapper;
57e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.content.Intent;
58e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.net.Uri;
59e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.os.Bundle;
60e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.os.SystemProperties;
61e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.service.notification.StatusBarNotification;
62e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.support.test.uiautomator.UiDevice;
636bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Lemeimport android.support.test.uiautomator.UiObject;
64e86b63bd17da3d347b9392f897e361919655edd6Felipe Lemeimport android.support.test.uiautomator.UiObjectNotFoundException;
65e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.test.InstrumentationTestCase;
662bfa0858a8cb67e19a1c9df8aad0a4da423a52b8Felipe Lemeimport android.test.suitebuilder.annotation.LargeTest;
674967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Lemeimport android.text.TextUtils;
68d1e0f12979441733753b538611f6d73e5527c43cFelipe Lemeimport android.text.format.DateUtils;
69e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.util.Log;
70e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
71e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport com.android.shell.ActionSendMultipleConsumerActivity.CustomActionSendMultipleListener;
72c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Lemeimport com.android.shell.BugreportProgressService;
73e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
74e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme/**
75e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * Integration tests for {@link BugreportReceiver}.
76e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <p>
77e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * These tests don't mock any component and rely on external UI components (like the notification
78e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * bar and activity chooser), which can make them unreliable and slow.
79e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <p>
80e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * The general workflow is:
81e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <ul>
82e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <li>creates the bug report files
83e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <li>generates the BUGREPORT_FINISHED intent
84e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <li>emulate user actions to share the intent with a custom activity
85e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <li>asserts the extras received by the custom activity
86e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * </ul>
87e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <p>
886bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme * <strong>NOTE</strong>: these tests only work if the device is unlocked.
89e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme */
902bfa0858a8cb67e19a1c9df8aad0a4da423a52b8Felipe Leme@LargeTest
91e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemepublic class BugreportReceiverTest extends InstrumentationTestCase {
92e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String TAG = "BugreportReceiverTest";
93e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
94e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    // Timeout for UI operations, in milliseconds.
9546d47911ea8bbbe0b8d7a6029b80da6b1eb94393Felipe Leme    private static final int TIMEOUT = (int) BugreportProgressService.POLLING_FREQUENCY * 4;
96e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
97c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    // Timeout for when waiting for a screenshot to finish.
98c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    private static final int SAFE_SCREENSHOT_DELAY = SCREENSHOT_DELAY_SECONDS + 10;
99c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
100a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme    private static final String BUGREPORTS_DIR = "bugreports";
101e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String BUGREPORT_FILE = "test_bugreport.txt";
102e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String ZIP_FILE = "test_bugreport.zip";
103a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme    private static final String SCREENSHOT_FILE = "test_screenshot.png";
104e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
105e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String BUGREPORT_CONTENT = "Dump, might as well dump!\n";
106e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String SCREENSHOT_CONTENT = "A picture is worth a thousand words!\n";
107e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
10893702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    private static final int PID = 42;
10985ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private static final int ID = 108;
11085ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private static final String PROGRESS_PROPERTY = "dumpstate." + PID + ".progress";
11185ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private static final String MAX_PROPERTY = "dumpstate." + PID + ".max";
11285ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private static final String NAME_PROPERTY = "dumpstate." + PID + ".name";
11393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    private static final String NAME = "BUG, Y U NO REPORT?";
114bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    private static final String NEW_NAME = "Bug_Forrest_Bug";
115bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    private static final String TITLE = "Wimbugdom Champion 2015";
1164967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
1174967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    private static final String NO_DESCRIPTION = null;
1184967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    private static final String NO_NAME = null;
1194967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    private static final String NO_SCREENSHOT = null;
1204967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    private static final String NO_TITLE = null;
12185ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private static final int NO_ID = 0;
122c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme    private static final boolean RENAMED_SCREENSHOTS = true;
123c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme    private static final boolean DIDNT_RENAME_SCREENSHOTS = false;
1244967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
125bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    private String mDescription;
12693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
127a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme    private String mPlainTextPath;
128a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme    private String mZipPath;
129a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme    private String mScreenshotPath;
130a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme
131e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private Context mContext;
132e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private UiBot mUiBot;
133e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private CustomActionSendMultipleListener mListener;
134e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
135e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    @Override
136e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    protected void setUp() throws Exception {
137c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        Log.i(TAG, "#### setup() on " + getName());
138e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Instrumentation instrumentation = getInstrumentation();
139e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        mContext = instrumentation.getTargetContext();
140e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        mUiBot = new UiBot(UiDevice.getInstance(instrumentation), TIMEOUT);
141e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        mListener = ActionSendMultipleConsumerActivity.getListener(mContext);
14293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
14393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        cancelExistingNotifications();
14493702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
145a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        mPlainTextPath = getPath(BUGREPORT_FILE);
146a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        mZipPath = getPath(ZIP_FILE);
147a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        mScreenshotPath = getPath(SCREENSHOT_FILE);
14893702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        createTextFile(mPlainTextPath, BUGREPORT_CONTENT);
14993702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        createTextFile(mScreenshotPath, SCREENSHOT_CONTENT);
15093702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        createZipFile(mZipPath, BUGREPORT_FILE, BUGREPORT_CONTENT);
15193702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
152bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Creates a multi-line description.
153bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        StringBuilder sb = new StringBuilder();
154bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        for (int i = 1; i <= 20; i++) {
155bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            sb.append("All work and no play makes Shell a dull app!\n");
156bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        }
157bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        mDescription = sb.toString();
158bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
1596bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        BugreportPrefs.setWarningState(mContext, BugreportPrefs.STATE_HIDE);
160e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
161e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
162bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    public void testProgress() throws Exception {
16393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        resetProperties();
16493702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        sendBugreportStarted(1000);
1652288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme        waitForScreenshotButtonEnabled(true);
16669c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
167e86b63bd17da3d347b9392f897e361919655edd6Felipe Leme        final NumberFormat nf = NumberFormat.getPercentInstance();
168e86b63bd17da3d347b9392f897e361919655edd6Felipe Leme        nf.setMinimumFractionDigits(2);
169e86b63bd17da3d347b9392f897e361919655edd6Felipe Leme        nf.setMaximumFractionDigits(2);
170e86b63bd17da3d347b9392f897e361919655edd6Felipe Leme
171e86b63bd17da3d347b9392f897e361919655edd6Felipe Leme        assertProgressNotification(NAME, nf.format(0));
17269c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
17393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        SystemProperties.set(PROGRESS_PROPERTY, "108");
174e86b63bd17da3d347b9392f897e361919655edd6Felipe Leme        assertProgressNotification(NAME, nf.format(0.108));
17569c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
17693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        SystemProperties.set(PROGRESS_PROPERTY, "500");
177e86b63bd17da3d347b9392f897e361919655edd6Felipe Leme        assertProgressNotification(NAME, nf.format(0.50));
17869c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
17993702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        SystemProperties.set(MAX_PROPERTY, "2000");
180e86b63bd17da3d347b9392f897e361919655edd6Felipe Leme        assertProgressNotification(NAME, nf.format(0.25));
181719aaae3c167c2b15525dbe5c7db514a2c0c8269Felipe Leme
18293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        Bundle extras =
18385ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme                sendBugreportFinishedAndGetSharedIntent(ID, mPlainTextPath, mScreenshotPath);
18485ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, ZIP_FILE,
185c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme                NAME, NO_TITLE, NO_DESCRIPTION, 1, RENAMED_SCREENSHOTS);
186d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
187d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        assertServiceNotRunning();
188d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    }
189d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
190d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    public void testProgress_takeExtraScreenshot() throws Exception {
191c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        takeExtraScreenshotTest(false);
192c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
193c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
194c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    public void testProgress_takeExtraScreenshotServiceDiesAfterScreenshotTaken() throws Exception {
195c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        takeExtraScreenshotTest(true);
196c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
197c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
198c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    private void takeExtraScreenshotTest(boolean serviceDies) throws Exception {
199d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        resetProperties();
200d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        sendBugreportStarted(1000);
201d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
202d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        waitForScreenshotButtonEnabled(true);
203d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        takeScreenshot();
204d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        assertScreenshotButtonEnabled(false);
205d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        waitForScreenshotButtonEnabled(true);
206d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
20785ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        sendBugreportFinished(ID, mPlainTextPath, mScreenshotPath);
208c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
209c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        if (serviceDies) {
21085ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme            waitShareNotification(ID);
211c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            killService();
212c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        }
213c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
21485ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        Bundle extras = acceptBugreportAndGetSharedIntent(ID);
21585ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, ZIP_FILE,
216c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme                NAME, NO_TITLE, NO_DESCRIPTION, 2, RENAMED_SCREENSHOTS);
21769c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
21893702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        assertServiceNotRunning();
21969c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme    }
22069c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
221c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    public void testScreenshotFinishesAfterBugreport() throws Exception {
222c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        screenshotFinishesAfterBugreportTest(false);
223c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
224c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
225c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    public void testScreenshotFinishesAfterBugreportAndServiceDiesBeforeSharing() throws Exception {
226c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        screenshotFinishesAfterBugreportTest(true);
227c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
228c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
229c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    private void screenshotFinishesAfterBugreportTest(boolean serviceDies) throws Exception {
230c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        resetProperties();
231c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
232c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        sendBugreportStarted(1000);
23385ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        sendBugreportFinished(ID, mPlainTextPath, NO_SCREENSHOT);
23485ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        waitShareNotification(ID);
235c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
236c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        // There's no indication in the UI about the screenshot finish, so just sleep like a baby...
237c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        Thread.sleep(SAFE_SCREENSHOT_DELAY * DateUtils.SECOND_IN_MILLIS);
238c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
239c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        if (serviceDies) {
240c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            killService();
241c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        }
242c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
24385ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        Bundle extras = acceptBugreportAndGetSharedIntent(ID);
24485ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT, ID, PID, ZIP_FILE,
245c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme                NAME, NO_TITLE, NO_DESCRIPTION, 1, RENAMED_SCREENSHOTS);
246c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
247c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        assertServiceNotRunning();
248c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
249c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
2504967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    public void testProgress_changeDetailsInvalidInput() throws Exception {
251bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        resetProperties();
252bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        sendBugreportStarted(1000);
2532288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme        waitForScreenshotButtonEnabled(true);
254bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
25585ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        DetailsUi detailsUi = new DetailsUi(mUiBot, ID);
256bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
257bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Check initial name.
258bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        String actualName = detailsUi.nameField.getText().toString();
259bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertEquals("Wrong value on field 'name'", NAME, actualName);
260bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
261bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Change name - it should have changed system property once focus is changed.
262bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.nameField.setText(NEW_NAME);
263bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.focusAwayFromName();
264bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertPropertyValue(NAME_PROPERTY, NEW_NAME);
265bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
266bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Cancel the dialog to make sure property was restored.
267bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.clickCancel();
268bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertPropertyValue(NAME_PROPERTY, NAME);
269bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
270bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Now try to set an invalid name.
271bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.reOpen();
272bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.nameField.setText("/etc/passwd");
273bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.clickOk();
274bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertPropertyValue(NAME_PROPERTY, "_etc_passwd");
275bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
276bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Finally, make the real changes.
277bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.reOpen();
278bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.nameField.setText(NEW_NAME);
279bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.titleField.setText(TITLE);
280bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.descField.setText(mDescription);
281bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
282bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.clickOk();
283bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
284bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertPropertyValue(NAME_PROPERTY, NEW_NAME);
285bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertProgressNotification(NEW_NAME, "0.00%");
286bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
28785ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        Bundle extras = sendBugreportFinishedAndGetSharedIntent(ID, mPlainTextPath,
288bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme                mScreenshotPath);
28985ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, TITLE,
290c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme                NEW_NAME, TITLE, mDescription, 1, RENAMED_SCREENSHOTS);
2914967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
2924967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertServiceNotRunning();
2934967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    }
2944967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
2954967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    public void testProgress_changeDetailsPlainBugreport() throws Exception {
2964967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        changeDetailsTest(true);
2974967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    }
2984967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
2994967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    public void testProgress_changeDetailsZippedBugreport() throws Exception {
3004967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        changeDetailsTest(false);
3014967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    }
3024967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
3034967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    public void changeDetailsTest(boolean plainText) throws Exception {
3044967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        resetProperties();
3054967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        sendBugreportStarted(1000);
3064967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        waitForScreenshotButtonEnabled(true);
3074967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
30885ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        DetailsUi detailsUi = new DetailsUi(mUiBot, ID);
3094967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
3104967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        // Check initial name.
3114967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        String actualName = detailsUi.nameField.getText().toString();
3124967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertEquals("Wrong value on field 'name'", NAME, actualName);
3134967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
3144967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        // Change fields.
3154967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        detailsUi.reOpen();
3164967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        detailsUi.nameField.setText(NEW_NAME);
3174967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        detailsUi.titleField.setText(TITLE);
3184967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        detailsUi.descField.setText(mDescription);
3194967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
3204967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        detailsUi.clickOk();
3214967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
3224967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertPropertyValue(NAME_PROPERTY, NEW_NAME);
3234967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertProgressNotification(NEW_NAME, "0.00%");
3244967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
32585ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        Bundle extras = sendBugreportFinishedAndGetSharedIntent(ID,
3264967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme                plainText? mPlainTextPath : mZipPath, mScreenshotPath);
32785ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, TITLE,
328c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme                NEW_NAME, TITLE, mDescription, 1, RENAMED_SCREENSHOTS);
329c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme
330c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme        assertServiceNotRunning();
331c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme    }
332c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme
333c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme    public void testProgress_changeJustDetails() throws Exception {
334c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme        resetProperties();
335c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme        sendBugreportStarted(1000);
336c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme        waitForScreenshotButtonEnabled(true);
337c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme
33885ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        DetailsUi detailsUi = new DetailsUi(mUiBot, ID);
339c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme
340c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme        detailsUi.nameField.setText("");
341c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme        detailsUi.titleField.setText("");
342c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme        detailsUi.descField.setText(mDescription);
343c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme        detailsUi.clickOk();
344c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme
34585ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        Bundle extras = sendBugreportFinishedAndGetSharedIntent(ID, mZipPath, mScreenshotPath);
34685ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, ZIP_FILE,
347c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme                NO_NAME, NO_TITLE, mDescription, 1, DIDNT_RENAME_SCREENSHOTS);
348bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
349bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertServiceNotRunning();
350bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    }
351bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
3522288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme    /**
3532288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme     * Tests the scenario where the initial screenshot and dumpstate are finished while the user
3542288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme     * is changing the info in the details screen.
3552288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme     */
3562288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme    public void testProgress_bugreportAndScreenshotFinishedWhileChangingDetails() throws Exception {
3572288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme        bugreportFinishedWhileChangingDetailsTest(false);
3582288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme    }
3592288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme
3602288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme    /**
3612288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme     * Tests the scenario where dumpstate is finished while the user is changing the info in the
3622288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme     * details screen, but the initial screenshot finishes afterwards.
3632288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme     */
364bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    public void testProgress_bugreportFinishedWhileChangingDetails() throws Exception {
3652288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme        bugreportFinishedWhileChangingDetailsTest(true);
3662288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme    }
3672288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme
3682288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme    private void bugreportFinishedWhileChangingDetailsTest(boolean waitScreenshot) throws Exception {
369bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        resetProperties();
370bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        sendBugreportStarted(1000);
3712288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme        if (waitScreenshot) {
3722288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme            waitForScreenshotButtonEnabled(true);
3732288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme        }
374bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
37585ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        DetailsUi detailsUi = new DetailsUi(mUiBot, ID);
376bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
377bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Finish the bugreport while user's still typing the name.
378bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.nameField.setText(NEW_NAME);
37985ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        sendBugreportFinished(ID, mPlainTextPath, mScreenshotPath);
380bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
3812288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme        // Wait until the share notification is received...
38285ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        waitShareNotification(ID);
383bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // ...then close notification bar.
384bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
385bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
386bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Make sure UI was updated properly.
387bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertFalse("didn't disable name on UI", detailsUi.nameField.isEnabled());
388bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertEquals("didn't revert name on UI", NAME, detailsUi.nameField.getText().toString());
389bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
390bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Finish changing other fields.
391bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.titleField.setText(TITLE);
392bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.descField.setText(mDescription);
393bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.clickOk();
394bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
395bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Finally, share bugreport.
39685ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        Bundle extras = acceptBugreportAndGetSharedIntent(ID);
39785ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, TITLE,
398c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme                NAME, TITLE, mDescription, 1, RENAMED_SCREENSHOTS);
399bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
400bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertServiceNotRunning();
401bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    }
402bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
4036bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme    public void testBugreportFinished_withWarning() throws Exception {
4046bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Explicitly shows the warning.
4056bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        BugreportPrefs.setWarningState(mContext, BugreportPrefs.STATE_SHOW);
4066bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
4076bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Send notification and click on share.
40885ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        sendBugreportFinished(NO_ID, mPlainTextPath, null);
40985ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        acceptBugreport(NO_ID);
4106bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
4116bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Handle the warning
4126bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        mUiBot.getVisibleObject(mContext.getString(R.string.bugreport_confirm));
4136bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // TODO: get ok and showMessageAgain from the dialog reference above
4146bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        UiObject showMessageAgain =
4156bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme                mUiBot.getVisibleObject(mContext.getString(R.string.bugreport_confirm_repeat));
4166bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        mUiBot.click(showMessageAgain, "show-message-again");
4176bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        UiObject ok = mUiBot.getVisibleObject(mContext.getString(com.android.internal.R.string.ok));
4186bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        mUiBot.click(ok, "ok");
4196bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
4206bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Share the bugreport.
4216bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        mUiBot.chooseActivity(UI_NAME);
4226bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        Bundle extras = mListener.getExtras();
4234967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
4246bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
4256bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Make sure it's hidden now.
4266bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        int newState = BugreportPrefs.getWarningState(mContext, BugreportPrefs.STATE_UNKNOWN);
4276bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        assertEquals("Didn't change state", BugreportPrefs.STATE_HIDE, newState);
4286bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme    }
4296bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
430c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    public void testShareBugreportAfterServiceDies() throws Exception {
43185ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        sendBugreportFinished(NO_ID, mPlainTextPath, NO_SCREENSHOT);
432c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        killService();
43385ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        Bundle extras = acceptBugreportAndGetSharedIntent(NO_ID);
434c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
435c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
436c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
437e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    public void testBugreportFinished_plainBugreportAndScreenshot() throws Exception {
43893702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        Bundle extras = sendBugreportFinishedAndGetSharedIntent(mPlainTextPath, mScreenshotPath);
439e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);
440e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
441e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
442e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    public void testBugreportFinished_zippedBugreportAndScreenshot() throws Exception {
44393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        Bundle extras = sendBugreportFinishedAndGetSharedIntent(mZipPath, mScreenshotPath);
444e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);
445e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
446e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
447e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    public void testBugreportFinished_plainBugreportAndNoScreenshot() throws Exception {
4484967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        Bundle extras = sendBugreportFinishedAndGetSharedIntent(mPlainTextPath, NO_SCREENSHOT);
4494967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
450e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
451e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
452e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    public void testBugreportFinished_zippedBugreportAndNoScreenshot() throws Exception {
4534967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        Bundle extras = sendBugreportFinishedAndGetSharedIntent(mZipPath, NO_SCREENSHOT);
4544967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
455e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
456e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
457e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void cancelExistingNotifications() {
458e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        NotificationManager nm = NotificationManager.from(mContext);
459e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        for (StatusBarNotification notification : nm.getActiveNotifications()) {
460e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            int id = notification.getId();
461e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            Log.i(TAG, "Canceling existing notification (id=" + id + ")");
462e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            nm.cancel(id);
463e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
464e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
465e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
46669c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme    private void assertProgressNotification(String name, String percent) {
467d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        // TODO: it currently looks for 3 distinct objects, without taking advantage of their
46869c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        // relationship.
46985ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        openProgressNotification(ID);
47069c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        Log.v(TAG, "Looking for progress notification details: '" + name + "-" + percent + "'");
47169c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        mUiBot.getObject(name);
47269c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        mUiBot.getObject(percent);
47369c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme    }
47469c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
47585ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private void openProgressNotification(int id) {
47685ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        String title = mContext.getString(R.string.bugreport_in_progress_title, id);
477bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        Log.v(TAG, "Looking for progress notification title: '" + title + "'");
478bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        mUiBot.getNotification(title);
479bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    }
480bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
48193702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    void resetProperties() {
48293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        // TODO: call method to remove property instead
48385ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        SystemProperties.set(PROGRESS_PROPERTY, "Reset");
48485ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        SystemProperties.set(MAX_PROPERTY, "Reset");
48585ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        SystemProperties.set(NAME_PROPERTY, "Reset");
48693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    }
48793702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
48893702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    /**
48993702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * Sends a "bugreport started" intent with the default values.
49093702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     */
491d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    private void sendBugreportStarted(int max) throws Exception {
49293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        Intent intent = new Intent(INTENT_BUGREPORT_STARTED);
493ec17538d46a49530ed6efdc2842ee16eaf18b9f6Felipe Leme        intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
49485ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        intent.putExtra(EXTRA_ID, ID);
49593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        intent.putExtra(EXTRA_PID, PID);
49693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        intent.putExtra(EXTRA_NAME, NAME);
49793702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        intent.putExtra(EXTRA_MAX, max);
49893702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        mContext.sendBroadcast(intent);
49993702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    }
50093702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
501e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    /**
502e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme     * Sends a "bugreport finished" intent and waits for the result.
503e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme     *
50493702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * @return extras sent in the shared intent.
505e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme     */
50693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    private Bundle sendBugreportFinishedAndGetSharedIntent(String bugreportPath,
50793702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme            String screenshotPath) {
50885ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        return sendBugreportFinishedAndGetSharedIntent(NO_ID, bugreportPath, screenshotPath);
50969c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme    }
51069c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
51193702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    /**
51293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * Sends a "bugreport finished" intent and waits for the result.
51393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     *
51493702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * @return extras sent in the shared intent.
51593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     */
51685ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private Bundle sendBugreportFinishedAndGetSharedIntent(int id, String bugreportPath,
51769c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme            String screenshotPath) {
51885ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        sendBugreportFinished(id, bugreportPath, screenshotPath);
51985ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        return acceptBugreportAndGetSharedIntent(id);
52093702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    }
52193702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
52293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    /**
52393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * Accepts the notification to share the finished bugreport and waits for the result.
52493702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     *
52593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * @return extras sent in the shared intent.
52693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     */
52785ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private Bundle acceptBugreportAndGetSharedIntent(int id) {
52885ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        acceptBugreport(id);
52993702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        mUiBot.chooseActivity(UI_NAME);
53093702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        return mListener.getExtras();
53193702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    }
53293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
53393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    /**
534c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme     * Waits for the notification to share the finished bugreport.
535c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme     */
53685ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private void waitShareNotification(int id) {
53785ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        mUiBot.getNotification(mContext.getString(R.string.bugreport_finished_title, id));
538c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
539c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
540c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    /**
54193702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * Accepts the notification to share the finished bugreport.
54293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     */
54385ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private void acceptBugreport(int id) {
54485ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        mUiBot.clickOnNotification(mContext.getString(R.string.bugreport_finished_title, id));
54593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    }
54693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
54793702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    /**
54893702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * Sends a "bugreport finished" intent.
54993702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     */
55085ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private void sendBugreportFinished(int id, String bugreportPath, String screenshotPath) {
55169c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        Intent intent = new Intent(INTENT_BUGREPORT_FINISHED);
552ec17538d46a49530ed6efdc2842ee16eaf18b9f6Felipe Leme        intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
55385ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        if (id != NO_ID) {
55485ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme            intent.putExtra(EXTRA_ID, id);
55569c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        }
556e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        if (bugreportPath != null) {
557e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            intent.putExtra(EXTRA_BUGREPORT, bugreportPath);
558e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
559e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        if (screenshotPath != null) {
560e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            intent.putExtra(EXTRA_SCREENSHOT, screenshotPath);
561e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
562e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
563e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        mContext.sendBroadcast(intent);
564e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
565e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
566e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    /**
567d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * Asserts the proper {@link Intent#ACTION_SEND_MULTIPLE} intent was sent.
568e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme     */
569e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void assertActionSendMultiple(Bundle extras, String bugreportContent,
570e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            String screenshotContent) throws IOException {
57185ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        assertActionSendMultiple(extras, bugreportContent, screenshotContent, ID, PID, ZIP_FILE,
572c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme                NO_NAME, NO_TITLE, NO_DESCRIPTION, 0, DIDNT_RENAME_SCREENSHOTS);
573bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    }
574bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
575d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    /**
576d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * Asserts the proper {@link Intent#ACTION_SEND_MULTIPLE} intent was sent.
577d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     *
578d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * @param extras extras received in the intent
579d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * @param bugreportContent expected content in the bugreport file
580d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * @param screenshotContent expected content in the screenshot file (sent by dumpstate), if any
58185ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme     * @param id emulated dumpstate id
582d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * @param pid emulated dumpstate pid
5834967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme     * @param name expected subject
5844967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme     * @param name bugreport name as provided by the user (or received by dumpstate)
5854967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme     * @param title bugreport name as provided by the user
586d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * @param description bugreport description as provided by the user
587d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * @param numberScreenshots expected number of screenshots taken by Shell.
5882288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme     * @param renamedScreenshots whether the screenshots are expected to be renamed
589d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     */
590d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    private void assertActionSendMultiple(Bundle extras, String bugreportContent,
59185ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme            String screenshotContent, int id, int pid, String subject,
5924967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme            String name, String title, String description,
5932288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme            int numberScreenshots, boolean renamedScreenshots) throws IOException {
594e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        String body = extras.getString(Intent.EXTRA_TEXT);
595e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertContainsRegex("missing build info",
596e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                SystemProperties.get("ro.build.description"), body);
597e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertContainsRegex("missing serial number",
598e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                SystemProperties.get("ro.serialno"), body);
599bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        if (description != null) {
600bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            assertContainsRegex("missing description", description, body);
601bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        }
602e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
6034967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertEquals("wrong subject", subject, extras.getString(Intent.EXTRA_SUBJECT));
604e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
605e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        List<Uri> attachments = extras.getParcelableArrayList(Intent.EXTRA_STREAM);
606d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        int expectedNumberScreenshots = numberScreenshots;
607d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        if (screenshotContent != null) {
608d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            expectedNumberScreenshots ++; // Add screenshot received by dumpstate
609d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        }
610d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        int expectedSize = expectedNumberScreenshots + 1; // All screenshots plus the bugreport file
611c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        assertEquals("wrong number of attachments (" + attachments + ")",
612c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme                expectedSize, attachments.size());
613e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
614e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        // Need to interact through all attachments, since order is not guaranteed.
615d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        Uri zipUri = null;
616d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        List<Uri> screenshotUris = new ArrayList<>(expectedNumberScreenshots);
617e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        for (Uri attachment : attachments) {
618e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            if (attachment.getPath().endsWith(".zip")) {
619e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                zipUri = attachment;
620e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            }
621e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            if (attachment.getPath().endsWith(".png")) {
622d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                screenshotUris.add(attachment);
623e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            }
624e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
625e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertNotNull("did not get .zip attachment", zipUri);
626e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertZipContent(zipUri, BUGREPORT_FILE, BUGREPORT_CONTENT);
6274967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        if (!TextUtils.isEmpty(title)) {
6284967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme            assertZipContent(zipUri, "title.txt", title);
6294967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        }
6304967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        if (!TextUtils.isEmpty(description)) {
6314967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme            assertZipContent(zipUri, "description.txt", description);
6324967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        }
633e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
634d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        // URI of the screenshot taken by dumpstate.
635d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        Uri externalScreenshotUri = null;
636d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        SortedSet<String> internalScreenshotNames = new TreeSet<>();
637d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        for (Uri screenshotUri : screenshotUris) {
638d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            String screenshotName = screenshotUri.getLastPathSegment();
639d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            if (screenshotName.endsWith(SCREENSHOT_FILE)) {
640d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                externalScreenshotUri = screenshotUri;
641d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            } else {
642d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                internalScreenshotNames.add(screenshotName);
643d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            }
644d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        }
645d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        // Check external screenshot
646e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        if (screenshotContent != null) {
647d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            assertNotNull("did not get .png attachment for external screenshot",
648d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                    externalScreenshotUri);
649d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            assertContent(externalScreenshotUri, SCREENSHOT_CONTENT);
650e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        } else {
651d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            assertNull("should not have .png attachment for external screenshot",
652d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                    externalScreenshotUri);
653d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        }
654d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        // Check internal screenshots.
655d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        SortedSet<String> expectedNames = new TreeSet<>();
656d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        for (int i = 1 ; i <= numberScreenshots; i++) {
6572288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme            String prefix = renamedScreenshots  ? name : Integer.toString(pid);
658d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            String expectedName = "screenshot-" + prefix + "-" + i + ".png";
659d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            expectedNames.add(expectedName);
660e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
661d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        // Ideally we should use MoreAsserts, but the error message in case of failure is not
662d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        // really useful.
663d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        assertEquals("wrong names for internal screenshots",
664d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                expectedNames, internalScreenshotNames);
665e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
666e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
667e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void assertContent(Uri uri, String expectedContent) throws IOException {
668e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Log.v(TAG, "assertContents(uri=" + uri);
669e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        try (InputStream is = mContext.getContentResolver().openInputStream(uri)) {
670e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            String actualContent = new String(Streams.readFully(is));
671e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            assertEquals("wrong content for '" + uri + "'", expectedContent, actualContent);
672e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
673e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
674e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
675e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void assertZipContent(Uri uri, String entryName, String expectedContent)
676e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            throws IOException, IOException {
677e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Log.v(TAG, "assertZipEntry(uri=" + uri + ", entryName=" + entryName);
678e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        try (ZipInputStream zis = new ZipInputStream(mContext.getContentResolver().openInputStream(
679e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                uri))) {
680e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            ZipEntry entry;
681e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            while ((entry = zis.getNextEntry()) != null) {
682e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                Log.v(TAG, "Zip entry: " + entry.getName());
683e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                if (entry.getName().equals(entryName)) {
684e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
685e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    Streams.copy(zis, bos);
686e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    String actualContent = new String(bos.toByteArray(), "UTF-8");
687e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    bos.close();
688e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    assertEquals("wrong content for zip entry'" + entryName + "' on '" + uri + "'",
689e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                            expectedContent, actualContent);
690e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    return;
691e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                }
692e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            }
693e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
694e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        fail("Did not find entry '" + entryName + "' on file '" + uri + "'");
695e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
696e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
697bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    private void assertPropertyValue(String key, String expectedValue) {
698bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        String actualValue = SystemProperties.get(key);
699bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertEquals("Wrong value for property '" + key + "'", expectedValue, actualValue);
700bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    }
701bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
70293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    private void assertServiceNotRunning() {
70393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        String service = BugreportProgressService.class.getName();
70493702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        assertFalse("Service '" + service + "' is still running", isServiceRunning(service));
70593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    }
70693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
707c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    private void killService() {
708c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        waitForService(true);
709c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        Log.v(TAG, "Stopping service");
710c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        boolean stopped = mContext.stopService(new Intent(mContext, BugreportProgressService.class));
711c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        Log.d(TAG, "stopService returned " + stopped);
712c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        waitForService(false);
713c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        assertServiceNotRunning();  // Sanity check.
714c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
715c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
716ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme    private boolean isServiceRunning(String name) {
717ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme        ActivityManager manager = (ActivityManager) mContext
718ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme                .getSystemService(Context.ACTIVITY_SERVICE);
719ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme        for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
720ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme            if (service.service.getClassName().equals(name)) {
721ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme                return true;
722ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme            }
723ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme        }
724ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme        return false;
725ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme    }
726ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme
727c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    private void waitForService(boolean expectRunning) {
728c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        String service = BugreportProgressService.class.getName();
729c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        boolean actualRunning;
730c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        for (int i = 1; i <= 5; i++) {
731c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            actualRunning = isServiceRunning(service);
732c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            Log.d(TAG, "Attempt " + i + " to check status of service '"
733c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme                    + service + "': expected=" + expectRunning + ", actual= " + actualRunning);
734c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            if (actualRunning == expectRunning) {
735c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme                return;
736c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            }
737c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            try {
738c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme                Thread.sleep(DateUtils.SECOND_IN_MILLIS);
739c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            } catch (InterruptedException e) {
740c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme                Log.w(TAG, "thread interrupted");
741c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme                Thread.currentThread().interrupt();
742c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            }
743c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        }
744c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        if (!expectRunning) {
745c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            // Typically happens when service is waiting for a screenshot to finish.
746c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            Log.w(TAG, "Service didn't stop; try to kill it again");
747c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            killService();
748c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            return;
749c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        }
750c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
751c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        fail("Service status didn't change to " + expectRunning);
752c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
753c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
754e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static void createTextFile(String path, String content) throws IOException {
755e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Log.v(TAG, "createFile(" + path + ")");
756e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        try (Writer writer = new BufferedWriter(new OutputStreamWriter(
757e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                new FileOutputStream(path)))) {
758e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            writer.write(content);
759e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
760e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
761e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
762e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void createZipFile(String path, String entryName, String content) throws IOException {
763e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Log.v(TAG, "createZipFile(" + path + ", " + entryName + ")");
764e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        try (ZipOutputStream zos = new ZipOutputStream(
765e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                new BufferedOutputStream(new FileOutputStream(path)))) {
766e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            ZipEntry entry = new ZipEntry(entryName);
767e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            zos.putNextEntry(entry);
768e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            byte[] data = content.getBytes();
769e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            zos.write(data, 0, data.length);
770e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            zos.closeEntry();
771e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
772e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
773a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme
774a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme    private String getPath(String file) {
775a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        File rootDir = new ContextWrapper(mContext).getFilesDir();
776a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        File dir = new File(rootDir, BUGREPORTS_DIR);
777e2b4f49795b4f23fa563a0ffb9986b49aee7f9beFelipe Leme        if (!dir.exists()) {
778e2b4f49795b4f23fa563a0ffb9986b49aee7f9beFelipe Leme            Log.i(TAG, "Creating directory " + dir);
779e2b4f49795b4f23fa563a0ffb9986b49aee7f9beFelipe Leme            assertTrue("Could not create directory " + dir, dir.mkdir());
780e2b4f49795b4f23fa563a0ffb9986b49aee7f9beFelipe Leme        }
781a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        String path = new File(dir, file).getAbsolutePath();
782a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        Log.v(TAG, "Path for '" + file + "': " + path);
783a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        return path;
784a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme    }
785bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
786bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    /**
787d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * Gets the notification button used to take a screenshot.
788d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     */
789d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    private UiObject getScreenshotButton() {
79085ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        openProgressNotification(ID);
791d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        return mUiBot.getVisibleObject(
792d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                mContext.getString(R.string.bugreport_screenshot_action).toUpperCase());
793d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    }
794d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
795d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    /**
796d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * Takes a screenshot using the system notification.
797d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     */
798d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    private void takeScreenshot() throws Exception {
799d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        UiObject screenshotButton = getScreenshotButton();
800d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        mUiBot.click(screenshotButton, "screenshot_button");
801d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    }
802d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
803d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    private UiObject waitForScreenshotButtonEnabled(boolean expectedEnabled) throws Exception {
804d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        UiObject screenshotButton = getScreenshotButton();
805c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        int maxAttempts = SAFE_SCREENSHOT_DELAY;
806d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        int i = 0;
807d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        do {
808d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            boolean enabled = screenshotButton.isEnabled();
809d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            if (enabled == expectedEnabled) {
810d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                return screenshotButton;
811d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            }
812d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            i++;
813d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            Log.v(TAG, "Sleeping for 1 second while waiting for screenshot.enable to be "
814d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                    + expectedEnabled + " (attempt " + i + ")");
815d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            Thread.sleep(DateUtils.SECOND_IN_MILLIS);
816d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        } while (i <= maxAttempts);
817d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        fail("screenshot.enable didn't change to " + expectedEnabled + " in " + maxAttempts + "s");
818d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        return screenshotButton;
819d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    }
820d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
821d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    private void assertScreenshotButtonEnabled(boolean expectedEnabled) throws Exception {
822d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        UiObject screenshotButton = getScreenshotButton();
823d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        assertEquals("wrong state for screenshot button ", expectedEnabled,
824d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                screenshotButton.isEnabled());
825d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    }
826d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
827d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    /**
828bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme     * Helper class containing the UiObjects present in the bugreport info dialog.
829bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme     */
830bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    private final class DetailsUi {
831bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
832bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        final UiObject detailsButton;
833bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        final UiObject nameField;
834bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        final UiObject titleField;
835bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        final UiObject descField;
836bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        final UiObject okButton;
837bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        final UiObject cancelButton;
838bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
839bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        /**
840bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme         * Gets the UI objects by opening the progress notification and clicking DETAILS.
841bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme         */
84285ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        DetailsUi(UiBot uiBot, int id) throws UiObjectNotFoundException {
84385ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme            openProgressNotification(id);
844bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            detailsButton = mUiBot.getVisibleObject(
845bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme                    mContext.getString(R.string.bugreport_info_action).toUpperCase());
846bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            mUiBot.click(detailsButton, "details_button");
847bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            // TODO: unhardcode resource ids
848e86b63bd17da3d347b9392f897e361919655edd6Felipe Leme            UiObject dialogTitle = mUiBot.getVisibleObjectById("android:id/alertTitle");
849e86b63bd17da3d347b9392f897e361919655edd6Felipe Leme            assertEquals("Wrong title", mContext.getString(R.string.bugreport_info_dialog_title,
85085ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme                    id), dialogTitle.getText().toString());
851bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            nameField = mUiBot.getVisibleObjectById("com.android.shell:id/name");
852bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            titleField = mUiBot.getVisibleObjectById("com.android.shell:id/title");
853bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            descField = mUiBot.getVisibleObjectById("com.android.shell:id/description");
854bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            okButton = mUiBot.getObjectById("android:id/button1");
855bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            cancelButton = mUiBot.getObjectById("android:id/button2");
856bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        }
857bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
858bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        /**
859bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme         * Takes focus away from the name field so it can be validated.
860bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme         */
861bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        void focusAwayFromName() {
862bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            mUiBot.click(titleField, "title_field"); // Change focus.
863bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            mUiBot.pressBack(); // Dismiss keyboard.
864bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        }
865bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
866bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        void reOpen() {
86785ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme            openProgressNotification(ID);
868bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            mUiBot.click(detailsButton, "details_button");
869bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
870bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        }
871bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
872bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        void clickOk() {
873bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            mUiBot.click(okButton, "details_ok_button");
874bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        }
875bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
876bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        void clickCancel() {
877bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            mUiBot.click(cancelButton, "details_cancel_button");
878bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        }
879bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    }
880e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme}
881