BugreportReceiverTest.java revision c4f6467702e308844ef0769ba17dcb7b7b32a9e6
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;
2269c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Lemeimport static com.android.shell.BugreportProgressService.EXTRA_MAX;
2369c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Lemeimport static com.android.shell.BugreportProgressService.EXTRA_NAME;
2469c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Lemeimport static com.android.shell.BugreportProgressService.EXTRA_PID;
25b9238b37838d653c38ce4e712421adb61978fc22Felipe Lemeimport static com.android.shell.BugreportProgressService.EXTRA_SCREENSHOT;
2669c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Lemeimport static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_FINISHED;
2769c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Lemeimport static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_STARTED;
28d1e0f12979441733753b538611f6d73e5527c43cFelipe Lemeimport static com.android.shell.BugreportProgressService.SCREENSHOT_DELAY_SECONDS;
29e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
30e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.BufferedOutputStream;
31e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.BufferedWriter;
32e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.ByteArrayOutputStream;
33a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Lemeimport java.io.File;
34e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.FileOutputStream;
35e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.IOException;
36e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.InputStream;
37e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.OutputStreamWriter;
38e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.Writer;
39d1e0f12979441733753b538611f6d73e5527c43cFelipe Lemeimport java.util.ArrayList;
40e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.util.List;
41d1e0f12979441733753b538611f6d73e5527c43cFelipe Lemeimport java.util.SortedSet;
42d1e0f12979441733753b538611f6d73e5527c43cFelipe Lemeimport java.util.TreeSet;
43e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.util.zip.ZipEntry;
44e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.util.zip.ZipInputStream;
45e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.util.zip.ZipOutputStream;
46e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
47e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport libcore.io.Streams;
48ba477939f0ae38926b4b0a6501a2371acc612433Felipe Lemeimport android.app.ActivityManager;
49ba477939f0ae38926b4b0a6501a2371acc612433Felipe Lemeimport android.app.ActivityManager.RunningServiceInfo;
50e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.app.Instrumentation;
51e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.app.NotificationManager;
52e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.content.Context;
53a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Lemeimport android.content.ContextWrapper;
54e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.content.Intent;
55e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.net.Uri;
56e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.os.Bundle;
57e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.os.SystemProperties;
58e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.service.notification.StatusBarNotification;
59e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.support.test.uiautomator.UiDevice;
606bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Lemeimport android.support.test.uiautomator.UiObject;
61e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.test.InstrumentationTestCase;
622bfa0858a8cb67e19a1c9df8aad0a4da423a52b8Felipe Lemeimport android.test.suitebuilder.annotation.LargeTest;
634967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Lemeimport android.text.TextUtils;
64d1e0f12979441733753b538611f6d73e5527c43cFelipe Lemeimport android.text.format.DateUtils;
65e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.util.Log;
66e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
67e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport com.android.shell.ActionSendMultipleConsumerActivity.CustomActionSendMultipleListener;
68c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Lemeimport com.android.shell.BugreportProgressService;
69e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
70e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme/**
71e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * Integration tests for {@link BugreportReceiver}.
72e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <p>
73e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * These tests don't mock any component and rely on external UI components (like the notification
74e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * bar and activity chooser), which can make them unreliable and slow.
75e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <p>
76e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * The general workflow is:
77e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <ul>
78e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <li>creates the bug report files
79e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <li>generates the BUGREPORT_FINISHED intent
80e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <li>emulate user actions to share the intent with a custom activity
81e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <li>asserts the extras received by the custom activity
82e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * </ul>
83e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <p>
846bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme * <strong>NOTE</strong>: these tests only work if the device is unlocked.
85e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme */
862bfa0858a8cb67e19a1c9df8aad0a4da423a52b8Felipe Leme@LargeTest
87e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemepublic class BugreportReceiverTest extends InstrumentationTestCase {
88e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String TAG = "BugreportReceiverTest";
89e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
90e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    // Timeout for UI operations, in milliseconds.
9146d47911ea8bbbe0b8d7a6029b80da6b1eb94393Felipe Leme    private static final int TIMEOUT = (int) BugreportProgressService.POLLING_FREQUENCY * 4;
92e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
93c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    // Timeout for when waiting for a screenshot to finish.
94c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    private static final int SAFE_SCREENSHOT_DELAY = SCREENSHOT_DELAY_SECONDS + 10;
95c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
96a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme    private static final String BUGREPORTS_DIR = "bugreports";
97e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String BUGREPORT_FILE = "test_bugreport.txt";
98e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String ZIP_FILE = "test_bugreport.zip";
99a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme    private static final String SCREENSHOT_FILE = "test_screenshot.png";
100e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
101e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String BUGREPORT_CONTENT = "Dump, might as well dump!\n";
102e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String SCREENSHOT_CONTENT = "A picture is worth a thousand words!\n";
103e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
10493702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    private static final int PID = 42;
10593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    private static final String PROGRESS_PROPERTY = "dumpstate.42.progress";
10693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    private static final String MAX_PROPERTY = "dumpstate.42.max";
107bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    private static final String NAME_PROPERTY = "dumpstate.42.name";
10893702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    private static final String NAME = "BUG, Y U NO REPORT?";
109bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    private static final String NEW_NAME = "Bug_Forrest_Bug";
110bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    private static final String TITLE = "Wimbugdom Champion 2015";
1114967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
1124967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    private static final String NO_DESCRIPTION = null;
1134967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    private static final String NO_NAME = null;
1144967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    private static final String NO_SCREENSHOT = null;
1154967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    private static final String NO_TITLE = null;
116c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    private static final Integer NO_PID = null;
1174967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
118bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    private String mDescription;
11993702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
120a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme    private String mPlainTextPath;
121a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme    private String mZipPath;
122a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme    private String mScreenshotPath;
123a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme
124e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private Context mContext;
125e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private UiBot mUiBot;
126e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private CustomActionSendMultipleListener mListener;
127e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
128e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    @Override
129e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    protected void setUp() throws Exception {
130c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        Log.i(TAG, "#### setup() on " + getName());
131e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Instrumentation instrumentation = getInstrumentation();
132e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        mContext = instrumentation.getTargetContext();
133e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        mUiBot = new UiBot(UiDevice.getInstance(instrumentation), TIMEOUT);
134e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        mListener = ActionSendMultipleConsumerActivity.getListener(mContext);
13593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
13693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        cancelExistingNotifications();
13793702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
138a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        mPlainTextPath = getPath(BUGREPORT_FILE);
139a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        mZipPath = getPath(ZIP_FILE);
140a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        mScreenshotPath = getPath(SCREENSHOT_FILE);
14193702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        createTextFile(mPlainTextPath, BUGREPORT_CONTENT);
14293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        createTextFile(mScreenshotPath, SCREENSHOT_CONTENT);
14393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        createZipFile(mZipPath, BUGREPORT_FILE, BUGREPORT_CONTENT);
14493702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
145bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Creates a multi-line description.
146bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        StringBuilder sb = new StringBuilder();
147bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        for (int i = 1; i <= 20; i++) {
148bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            sb.append("All work and no play makes Shell a dull app!\n");
149bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        }
150bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        mDescription = sb.toString();
151bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
1526bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        BugreportPrefs.setWarningState(mContext, BugreportPrefs.STATE_HIDE);
153e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
154e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
155bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    public void testProgress() throws Exception {
15693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        resetProperties();
15793702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        sendBugreportStarted(1000);
1582288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme        waitForScreenshotButtonEnabled(true);
15969c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
16093702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        assertProgressNotification(NAME, "0.00%");
16169c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
16293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        SystemProperties.set(PROGRESS_PROPERTY, "108");
16393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        assertProgressNotification(NAME, "10.80%");
16469c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
16593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        SystemProperties.set(PROGRESS_PROPERTY, "500");
16693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        assertProgressNotification(NAME, "50.00%");
16769c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
16893702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        SystemProperties.set(MAX_PROPERTY, "2000");
16993702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        assertProgressNotification(NAME, "25.00%");
170719aaae3c167c2b15525dbe5c7db514a2c0c8269Felipe Leme
17193702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        Bundle extras =
17293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme                sendBugreportFinishedAndGetSharedIntent(PID, mPlainTextPath, mScreenshotPath);
173c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, PID, ZIP_FILE,
1744967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme                NAME, NO_TITLE, NO_DESCRIPTION, 1, true);
175d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
176d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        assertServiceNotRunning();
177d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    }
178d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
179d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    public void testProgress_takeExtraScreenshot() throws Exception {
180c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        takeExtraScreenshotTest(false);
181c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
182c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
183c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    public void testProgress_takeExtraScreenshotServiceDiesAfterScreenshotTaken() throws Exception {
184c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        takeExtraScreenshotTest(true);
185c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
186c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
187c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    private void takeExtraScreenshotTest(boolean serviceDies) throws Exception {
188d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        resetProperties();
189d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        sendBugreportStarted(1000);
190d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
191d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        waitForScreenshotButtonEnabled(true);
192d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        takeScreenshot();
193d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        assertScreenshotButtonEnabled(false);
194d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        waitForScreenshotButtonEnabled(true);
195d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
196c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        sendBugreportFinished(PID, mPlainTextPath, mScreenshotPath);
197c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
198c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        if (serviceDies) {
199c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            waitShareNotification();
200c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            killService();
201c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        }
202c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
203c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        Bundle extras = acceptBugreportAndGetSharedIntent();
204c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, PID, ZIP_FILE,
2054967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme                NAME, NO_TITLE, NO_DESCRIPTION, 2, true);
20669c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
20793702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        assertServiceNotRunning();
20869c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme    }
20969c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
210c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    public void testScreenshotFinishesAfterBugreport() throws Exception {
211c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        screenshotFinishesAfterBugreportTest(false);
212c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
213c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
214c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    public void testScreenshotFinishesAfterBugreportAndServiceDiesBeforeSharing() throws Exception {
215c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        screenshotFinishesAfterBugreportTest(true);
216c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
217c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
218c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    private void screenshotFinishesAfterBugreportTest(boolean serviceDies) throws Exception {
219c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        resetProperties();
220c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
221c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        sendBugreportStarted(1000);
222c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        sendBugreportFinished(PID, mPlainTextPath, NO_SCREENSHOT);
223c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        waitShareNotification();
224c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
225c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        // There's no indication in the UI about the screenshot finish, so just sleep like a baby...
226c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        Thread.sleep(SAFE_SCREENSHOT_DELAY * DateUtils.SECOND_IN_MILLIS);
227c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
228c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        if (serviceDies) {
229c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            killService();
230c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        }
231c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
232c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        Bundle extras = acceptBugreportAndGetSharedIntent();
233c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT, PID, ZIP_FILE,
234c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme                NAME, NO_TITLE, NO_DESCRIPTION, 1, true);
235c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
236c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        assertServiceNotRunning();
237c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
238c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
2394967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    public void testProgress_changeDetailsInvalidInput() throws Exception {
2404967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
241bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        resetProperties();
242bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        sendBugreportStarted(1000);
2432288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme        waitForScreenshotButtonEnabled(true);
244bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
245bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        DetailsUi detailsUi = new DetailsUi(mUiBot);
246bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
247bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Check initial name.
248bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        String actualName = detailsUi.nameField.getText().toString();
249bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertEquals("Wrong value on field 'name'", NAME, actualName);
250bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
251bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Change name - it should have changed system property once focus is changed.
252bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.nameField.setText(NEW_NAME);
253bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.focusAwayFromName();
254bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertPropertyValue(NAME_PROPERTY, NEW_NAME);
255bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
256bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Cancel the dialog to make sure property was restored.
257bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.clickCancel();
258bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertPropertyValue(NAME_PROPERTY, NAME);
259bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
260bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Now try to set an invalid name.
261bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.reOpen();
262bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.nameField.setText("/etc/passwd");
263bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.clickOk();
264bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertPropertyValue(NAME_PROPERTY, "_etc_passwd");
265bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
266bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Finally, make the real changes.
267bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.reOpen();
268bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.nameField.setText(NEW_NAME);
269bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.titleField.setText(TITLE);
270bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.descField.setText(mDescription);
271bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
272bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.clickOk();
273bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
274bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertPropertyValue(NAME_PROPERTY, NEW_NAME);
275bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertProgressNotification(NEW_NAME, "0.00%");
276bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
277bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        Bundle extras = sendBugreportFinishedAndGetSharedIntent(PID, mPlainTextPath,
278bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme                mScreenshotPath);
279c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, PID, TITLE,
2804967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme                NEW_NAME, TITLE, mDescription, 1, true);
2814967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
2824967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertServiceNotRunning();
2834967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    }
2844967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
2854967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    public void testProgress_changeDetailsPlainBugreport() throws Exception {
2864967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        changeDetailsTest(true);
2874967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    }
2884967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
2894967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    public void testProgress_changeDetailsZippedBugreport() throws Exception {
2904967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        changeDetailsTest(false);
2914967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    }
2924967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
2934967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    public void changeDetailsTest(boolean plainText) throws Exception {
2944967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
2954967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        resetProperties();
2964967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        sendBugreportStarted(1000);
2974967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        waitForScreenshotButtonEnabled(true);
2984967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
2994967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        DetailsUi detailsUi = new DetailsUi(mUiBot);
3004967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
3014967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        // Check initial name.
3024967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        String actualName = detailsUi.nameField.getText().toString();
3034967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertEquals("Wrong value on field 'name'", NAME, actualName);
3044967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
3054967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        // Change fields.
3064967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        detailsUi.reOpen();
3074967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        detailsUi.nameField.setText(NEW_NAME);
3084967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        detailsUi.titleField.setText(TITLE);
3094967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        detailsUi.descField.setText(mDescription);
3104967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
3114967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        detailsUi.clickOk();
3124967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
3134967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertPropertyValue(NAME_PROPERTY, NEW_NAME);
3144967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertProgressNotification(NEW_NAME, "0.00%");
3154967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
3164967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        Bundle extras = sendBugreportFinishedAndGetSharedIntent(PID,
3174967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme                plainText? mPlainTextPath : mZipPath, mScreenshotPath);
318c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, PID, TITLE,
3194967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme                NEW_NAME, TITLE, mDescription, 1, true);
320bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
321bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertServiceNotRunning();
322bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    }
323bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
3242288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme    /**
3252288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme     * Tests the scenario where the initial screenshot and dumpstate are finished while the user
3262288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme     * is changing the info in the details screen.
3272288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme     */
3282288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme    public void testProgress_bugreportAndScreenshotFinishedWhileChangingDetails() throws Exception {
3292288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme        bugreportFinishedWhileChangingDetailsTest(false);
3302288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme    }
3312288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme
3322288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme    /**
3332288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme     * Tests the scenario where dumpstate is finished while the user is changing the info in the
3342288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme     * details screen, but the initial screenshot finishes afterwards.
3352288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme     */
336bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    public void testProgress_bugreportFinishedWhileChangingDetails() throws Exception {
3372288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme        bugreportFinishedWhileChangingDetailsTest(true);
3382288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme    }
3392288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme
3402288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme    private void bugreportFinishedWhileChangingDetailsTest(boolean waitScreenshot) throws Exception {
341bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        resetProperties();
342bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        sendBugreportStarted(1000);
3432288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme        if (waitScreenshot) {
3442288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme            waitForScreenshotButtonEnabled(true);
3452288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme        }
346bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
347bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        DetailsUi detailsUi = new DetailsUi(mUiBot);
348bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
349bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Finish the bugreport while user's still typing the name.
350bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.nameField.setText(NEW_NAME);
351bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        sendBugreportFinished(PID, mPlainTextPath, mScreenshotPath);
352bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
3532288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme        // Wait until the share notification is received...
354bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        mUiBot.getNotification(mContext.getString(R.string.bugreport_finished_title));
355bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // ...then close notification bar.
356bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
357bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
358bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Make sure UI was updated properly.
359bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertFalse("didn't disable name on UI", detailsUi.nameField.isEnabled());
360bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertEquals("didn't revert name on UI", NAME, detailsUi.nameField.getText().toString());
361bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
362bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Finish changing other fields.
363bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.titleField.setText(TITLE);
364bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.descField.setText(mDescription);
365bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.clickOk();
366bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
367bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Finally, share bugreport.
368bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        Bundle extras = acceptBugreportAndGetSharedIntent();
369c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, PID, TITLE,
370c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme                NAME, TITLE, mDescription, 1, true);
371bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
372bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertServiceNotRunning();
373bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    }
374bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
3756bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme    public void testBugreportFinished_withWarning() throws Exception {
3766bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Explicitly shows the warning.
3776bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        BugreportPrefs.setWarningState(mContext, BugreportPrefs.STATE_SHOW);
3786bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
3796bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Send notification and click on share.
380c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        sendBugreportFinished(NO_PID, mPlainTextPath, null);
38193702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        acceptBugreport();
3826bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
3836bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Handle the warning
3846bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        mUiBot.getVisibleObject(mContext.getString(R.string.bugreport_confirm));
3856bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // TODO: get ok and showMessageAgain from the dialog reference above
3866bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        UiObject showMessageAgain =
3876bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme                mUiBot.getVisibleObject(mContext.getString(R.string.bugreport_confirm_repeat));
3886bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        mUiBot.click(showMessageAgain, "show-message-again");
3896bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        UiObject ok = mUiBot.getVisibleObject(mContext.getString(com.android.internal.R.string.ok));
3906bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        mUiBot.click(ok, "ok");
3916bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
3926bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Share the bugreport.
3936bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        mUiBot.chooseActivity(UI_NAME);
3946bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        Bundle extras = mListener.getExtras();
3954967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
3966bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
3976bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Make sure it's hidden now.
3986bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        int newState = BugreportPrefs.getWarningState(mContext, BugreportPrefs.STATE_UNKNOWN);
3996bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        assertEquals("Didn't change state", BugreportPrefs.STATE_HIDE, newState);
4006bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme    }
4016bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
402c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    public void testShareBugreportAfterServiceDies() throws Exception {
403c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        sendBugreportFinished(NO_PID, mPlainTextPath, NO_SCREENSHOT);
404c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        killService();
405c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        Bundle extras = acceptBugreportAndGetSharedIntent();
406c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
407c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
408c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
409e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    public void testBugreportFinished_plainBugreportAndScreenshot() throws Exception {
41093702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        Bundle extras = sendBugreportFinishedAndGetSharedIntent(mPlainTextPath, mScreenshotPath);
411e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);
412e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
413e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
414e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    public void testBugreportFinished_zippedBugreportAndScreenshot() throws Exception {
41593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        Bundle extras = sendBugreportFinishedAndGetSharedIntent(mZipPath, mScreenshotPath);
416e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);
417e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
418e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
419e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    public void testBugreportFinished_plainBugreportAndNoScreenshot() throws Exception {
4204967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        Bundle extras = sendBugreportFinishedAndGetSharedIntent(mPlainTextPath, NO_SCREENSHOT);
4214967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
422e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
423e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
424e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    public void testBugreportFinished_zippedBugreportAndNoScreenshot() throws Exception {
4254967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        Bundle extras = sendBugreportFinishedAndGetSharedIntent(mZipPath, NO_SCREENSHOT);
4264967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
427e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
428e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
429e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void cancelExistingNotifications() {
430e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        NotificationManager nm = NotificationManager.from(mContext);
431e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        for (StatusBarNotification notification : nm.getActiveNotifications()) {
432e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            int id = notification.getId();
433e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            Log.i(TAG, "Canceling existing notification (id=" + id + ")");
434e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            nm.cancel(id);
435e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
436e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
437e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
43869c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme    private void assertProgressNotification(String name, String percent) {
439d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        // TODO: it currently looks for 3 distinct objects, without taking advantage of their
44069c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        // relationship.
441bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        openProgressNotification();
44269c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        Log.v(TAG, "Looking for progress notification details: '" + name + "-" + percent + "'");
44369c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        mUiBot.getObject(name);
44469c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        mUiBot.getObject(percent);
44569c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme    }
44669c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
447bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    private void openProgressNotification() {
448bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        String title = mContext.getString(R.string.bugreport_in_progress_title);
449bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        Log.v(TAG, "Looking for progress notification title: '" + title + "'");
450bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        mUiBot.getNotification(title);
451bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    }
452bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
45393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    void resetProperties() {
45493702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        // TODO: call method to remove property instead
45593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        SystemProperties.set(PROGRESS_PROPERTY, "0");
45693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        SystemProperties.set(MAX_PROPERTY, "0");
45793702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    }
45893702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
45993702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    /**
46093702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * Sends a "bugreport started" intent with the default values.
46193702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     */
462d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    private void sendBugreportStarted(int max) throws Exception {
46393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        Intent intent = new Intent(INTENT_BUGREPORT_STARTED);
46493702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        intent.putExtra(EXTRA_PID, PID);
46593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        intent.putExtra(EXTRA_NAME, NAME);
46693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        intent.putExtra(EXTRA_MAX, max);
46793702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        mContext.sendBroadcast(intent);
46893702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    }
46993702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
470e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    /**
471e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme     * Sends a "bugreport finished" intent and waits for the result.
472e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme     *
47393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * @return extras sent in the shared intent.
474e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme     */
47593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    private Bundle sendBugreportFinishedAndGetSharedIntent(String bugreportPath,
47693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme            String screenshotPath) {
47793702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        return sendBugreportFinishedAndGetSharedIntent(null, bugreportPath, screenshotPath);
47869c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme    }
47969c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
48093702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    /**
48193702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * Sends a "bugreport finished" intent and waits for the result.
48293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     *
48393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * @return extras sent in the shared intent.
48493702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     */
48593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    private Bundle sendBugreportFinishedAndGetSharedIntent(Integer pid, String bugreportPath,
48669c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme            String screenshotPath) {
48793702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        sendBugreportFinished(pid, bugreportPath, screenshotPath);
48893702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        return acceptBugreportAndGetSharedIntent();
48993702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    }
49093702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
49193702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    /**
49293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * Accepts the notification to share the finished bugreport and waits for the result.
49393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     *
49493702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * @return extras sent in the shared intent.
49593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     */
49693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    private Bundle acceptBugreportAndGetSharedIntent() {
49793702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        acceptBugreport();
49893702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        mUiBot.chooseActivity(UI_NAME);
49993702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        return mListener.getExtras();
50093702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    }
50193702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
50293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    /**
503c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme     * Waits for the notification to share the finished bugreport.
504c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme     */
505c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    private void waitShareNotification() {
506c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        mUiBot.getNotification(mContext.getString(R.string.bugreport_finished_title));
507c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
508c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
509c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    /**
51093702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * Accepts the notification to share the finished bugreport.
51193702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     */
51293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    private void acceptBugreport() {
51393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        mUiBot.clickOnNotification(mContext.getString(R.string.bugreport_finished_title));
51493702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    }
51593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
51693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    /**
51793702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * Sends a "bugreport finished" intent.
51893702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     */
51993702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    private void sendBugreportFinished(Integer pid, String bugreportPath, String screenshotPath) {
52069c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        Intent intent = new Intent(INTENT_BUGREPORT_FINISHED);
52169c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        if (pid != null) {
52269c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme            intent.putExtra(EXTRA_PID, pid);
52369c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        }
524e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        if (bugreportPath != null) {
525e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            intent.putExtra(EXTRA_BUGREPORT, bugreportPath);
526e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
527e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        if (screenshotPath != null) {
528e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            intent.putExtra(EXTRA_SCREENSHOT, screenshotPath);
529e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
530e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
531e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        mContext.sendBroadcast(intent);
532e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
533e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
534e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    /**
535d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * Asserts the proper {@link Intent#ACTION_SEND_MULTIPLE} intent was sent.
536e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme     */
537e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void assertActionSendMultiple(Bundle extras, String bugreportContent,
538e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            String screenshotContent) throws IOException {
5394967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertActionSendMultiple(extras, bugreportContent, screenshotContent, PID, ZIP_FILE,
5404967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme                NO_NAME, NO_TITLE, NO_DESCRIPTION, 0, false);
541bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    }
542bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
543d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    /**
544d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * Asserts the proper {@link Intent#ACTION_SEND_MULTIPLE} intent was sent.
545d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     *
546d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * @param extras extras received in the intent
547d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * @param bugreportContent expected content in the bugreport file
548d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * @param screenshotContent expected content in the screenshot file (sent by dumpstate), if any
549d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * @param pid emulated dumpstate pid
5504967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme     * @param name expected subject
5514967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme     * @param name bugreport name as provided by the user (or received by dumpstate)
5524967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme     * @param title bugreport name as provided by the user
553d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * @param description bugreport description as provided by the user
554d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * @param numberScreenshots expected number of screenshots taken by Shell.
5552288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme     * @param renamedScreenshots whether the screenshots are expected to be renamed
556d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     */
557d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    private void assertActionSendMultiple(Bundle extras, String bugreportContent,
5584967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme            String screenshotContent, int pid, String subject,
5594967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme            String name, String title, String description,
5602288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme            int numberScreenshots, boolean renamedScreenshots) throws IOException {
561e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        String body = extras.getString(Intent.EXTRA_TEXT);
562e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertContainsRegex("missing build info",
563e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                SystemProperties.get("ro.build.description"), body);
564e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertContainsRegex("missing serial number",
565e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                SystemProperties.get("ro.serialno"), body);
566bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        if (description != null) {
567bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            assertContainsRegex("missing description", description, body);
568bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        }
569e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
5704967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertEquals("wrong subject", subject, extras.getString(Intent.EXTRA_SUBJECT));
571e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
572e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        List<Uri> attachments = extras.getParcelableArrayList(Intent.EXTRA_STREAM);
573d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        int expectedNumberScreenshots = numberScreenshots;
574d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        if (screenshotContent != null) {
575d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            expectedNumberScreenshots ++; // Add screenshot received by dumpstate
576d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        }
577d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        int expectedSize = expectedNumberScreenshots + 1; // All screenshots plus the bugreport file
578c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        assertEquals("wrong number of attachments (" + attachments + ")",
579c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme                expectedSize, attachments.size());
580e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
581e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        // Need to interact through all attachments, since order is not guaranteed.
582d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        Uri zipUri = null;
583d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        List<Uri> screenshotUris = new ArrayList<>(expectedNumberScreenshots);
584e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        for (Uri attachment : attachments) {
585e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            if (attachment.getPath().endsWith(".zip")) {
586e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                zipUri = attachment;
587e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            }
588e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            if (attachment.getPath().endsWith(".png")) {
589d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                screenshotUris.add(attachment);
590e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            }
591e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
592e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertNotNull("did not get .zip attachment", zipUri);
593e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertZipContent(zipUri, BUGREPORT_FILE, BUGREPORT_CONTENT);
5944967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        if (!TextUtils.isEmpty(title)) {
5954967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme            assertZipContent(zipUri, "title.txt", title);
5964967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        }
5974967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        if (!TextUtils.isEmpty(description)) {
5984967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme            assertZipContent(zipUri, "description.txt", description);
5994967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        }
600e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
601d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        // URI of the screenshot taken by dumpstate.
602d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        Uri externalScreenshotUri = null;
603d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        SortedSet<String> internalScreenshotNames = new TreeSet<>();
604d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        for (Uri screenshotUri : screenshotUris) {
605d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            String screenshotName = screenshotUri.getLastPathSegment();
606d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            if (screenshotName.endsWith(SCREENSHOT_FILE)) {
607d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                externalScreenshotUri = screenshotUri;
608d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            } else {
609d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                internalScreenshotNames.add(screenshotName);
610d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            }
611d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        }
612d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        // Check external screenshot
613e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        if (screenshotContent != null) {
614d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            assertNotNull("did not get .png attachment for external screenshot",
615d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                    externalScreenshotUri);
616d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            assertContent(externalScreenshotUri, SCREENSHOT_CONTENT);
617e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        } else {
618d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            assertNull("should not have .png attachment for external screenshot",
619d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                    externalScreenshotUri);
620d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        }
621d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        // Check internal screenshots.
622d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        SortedSet<String> expectedNames = new TreeSet<>();
623d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        for (int i = 1 ; i <= numberScreenshots; i++) {
6242288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme            String prefix = renamedScreenshots  ? name : Integer.toString(pid);
625d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            String expectedName = "screenshot-" + prefix + "-" + i + ".png";
626d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            expectedNames.add(expectedName);
627e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
628d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        // Ideally we should use MoreAsserts, but the error message in case of failure is not
629d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        // really useful.
630d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        assertEquals("wrong names for internal screenshots",
631d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                expectedNames, internalScreenshotNames);
632e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
633e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
634e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void assertContent(Uri uri, String expectedContent) throws IOException {
635e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Log.v(TAG, "assertContents(uri=" + uri);
636e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        try (InputStream is = mContext.getContentResolver().openInputStream(uri)) {
637e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            String actualContent = new String(Streams.readFully(is));
638e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            assertEquals("wrong content for '" + uri + "'", expectedContent, actualContent);
639e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
640e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
641e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
642e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void assertZipContent(Uri uri, String entryName, String expectedContent)
643e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            throws IOException, IOException {
644e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Log.v(TAG, "assertZipEntry(uri=" + uri + ", entryName=" + entryName);
645e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        try (ZipInputStream zis = new ZipInputStream(mContext.getContentResolver().openInputStream(
646e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                uri))) {
647e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            ZipEntry entry;
648e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            while ((entry = zis.getNextEntry()) != null) {
649e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                Log.v(TAG, "Zip entry: " + entry.getName());
650e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                if (entry.getName().equals(entryName)) {
651e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
652e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    Streams.copy(zis, bos);
653e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    String actualContent = new String(bos.toByteArray(), "UTF-8");
654e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    bos.close();
655e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    assertEquals("wrong content for zip entry'" + entryName + "' on '" + uri + "'",
656e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                            expectedContent, actualContent);
657e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    return;
658e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                }
659e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            }
660e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
661e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        fail("Did not find entry '" + entryName + "' on file '" + uri + "'");
662e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
663e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
664bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    private void assertPropertyValue(String key, String expectedValue) {
665bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        String actualValue = SystemProperties.get(key);
666bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertEquals("Wrong value for property '" + key + "'", expectedValue, actualValue);
667bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    }
668bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
66993702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    private void assertServiceNotRunning() {
67093702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        String service = BugreportProgressService.class.getName();
67193702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        assertFalse("Service '" + service + "' is still running", isServiceRunning(service));
67293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    }
67393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
674c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    private void killService() {
675c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        waitForService(true);
676c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        Log.v(TAG, "Stopping service");
677c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        boolean stopped = mContext.stopService(new Intent(mContext, BugreportProgressService.class));
678c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        Log.d(TAG, "stopService returned " + stopped);
679c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        waitForService(false);
680c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        assertServiceNotRunning();  // Sanity check.
681c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
682c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
683ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme    private boolean isServiceRunning(String name) {
684ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme        ActivityManager manager = (ActivityManager) mContext
685ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme                .getSystemService(Context.ACTIVITY_SERVICE);
686ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme        for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
687ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme            if (service.service.getClassName().equals(name)) {
688ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme                return true;
689ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme            }
690ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme        }
691ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme        return false;
692ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme    }
693ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme
694c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    private void waitForService(boolean expectRunning) {
695c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        String service = BugreportProgressService.class.getName();
696c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        boolean actualRunning;
697c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        for (int i = 1; i <= 5; i++) {
698c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            actualRunning = isServiceRunning(service);
699c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            Log.d(TAG, "Attempt " + i + " to check status of service '"
700c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme                    + service + "': expected=" + expectRunning + ", actual= " + actualRunning);
701c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            if (actualRunning == expectRunning) {
702c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme                return;
703c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            }
704c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            try {
705c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme                Thread.sleep(DateUtils.SECOND_IN_MILLIS);
706c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            } catch (InterruptedException e) {
707c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme                Log.w(TAG, "thread interrupted");
708c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme                Thread.currentThread().interrupt();
709c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            }
710c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        }
711c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        if (!expectRunning) {
712c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            // Typically happens when service is waiting for a screenshot to finish.
713c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            Log.w(TAG, "Service didn't stop; try to kill it again");
714c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            killService();
715c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            return;
716c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        }
717c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
718c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        fail("Service status didn't change to " + expectRunning);
719c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
720c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
721e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static void createTextFile(String path, String content) throws IOException {
722e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Log.v(TAG, "createFile(" + path + ")");
723e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        try (Writer writer = new BufferedWriter(new OutputStreamWriter(
724e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                new FileOutputStream(path)))) {
725e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            writer.write(content);
726e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
727e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
728e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
729e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void createZipFile(String path, String entryName, String content) throws IOException {
730e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Log.v(TAG, "createZipFile(" + path + ", " + entryName + ")");
731e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        try (ZipOutputStream zos = new ZipOutputStream(
732e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                new BufferedOutputStream(new FileOutputStream(path)))) {
733e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            ZipEntry entry = new ZipEntry(entryName);
734e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            zos.putNextEntry(entry);
735e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            byte[] data = content.getBytes();
736e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            zos.write(data, 0, data.length);
737e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            zos.closeEntry();
738e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
739e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
740a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme
741a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme    private String getPath(String file) {
742a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        File rootDir = new ContextWrapper(mContext).getFilesDir();
743a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        File dir = new File(rootDir, BUGREPORTS_DIR);
744e2b4f49795b4f23fa563a0ffb9986b49aee7f9beFelipe Leme        if (!dir.exists()) {
745e2b4f49795b4f23fa563a0ffb9986b49aee7f9beFelipe Leme            Log.i(TAG, "Creating directory " + dir);
746e2b4f49795b4f23fa563a0ffb9986b49aee7f9beFelipe Leme            assertTrue("Could not create directory " + dir, dir.mkdir());
747e2b4f49795b4f23fa563a0ffb9986b49aee7f9beFelipe Leme        }
748a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        String path = new File(dir, file).getAbsolutePath();
749a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        Log.v(TAG, "Path for '" + file + "': " + path);
750a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        return path;
751a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme    }
752bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
753bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    /**
754d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * Gets the notification button used to take a screenshot.
755d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     */
756d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    private UiObject getScreenshotButton() {
757d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        openProgressNotification();
758d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        return mUiBot.getVisibleObject(
759d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                mContext.getString(R.string.bugreport_screenshot_action).toUpperCase());
760d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    }
761d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
762d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    /**
763d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * Takes a screenshot using the system notification.
764d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     */
765d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    private void takeScreenshot() throws Exception {
766d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        UiObject screenshotButton = getScreenshotButton();
767d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        mUiBot.click(screenshotButton, "screenshot_button");
768d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    }
769d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
770d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    private UiObject waitForScreenshotButtonEnabled(boolean expectedEnabled) throws Exception {
771d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        UiObject screenshotButton = getScreenshotButton();
772c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        int maxAttempts = SAFE_SCREENSHOT_DELAY;
773d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        int i = 0;
774d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        do {
775d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            boolean enabled = screenshotButton.isEnabled();
776d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            if (enabled == expectedEnabled) {
777d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                return screenshotButton;
778d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            }
779d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            i++;
780d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            Log.v(TAG, "Sleeping for 1 second while waiting for screenshot.enable to be "
781d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                    + expectedEnabled + " (attempt " + i + ")");
782d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            Thread.sleep(DateUtils.SECOND_IN_MILLIS);
783d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        } while (i <= maxAttempts);
784d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        fail("screenshot.enable didn't change to " + expectedEnabled + " in " + maxAttempts + "s");
785d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        return screenshotButton;
786d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    }
787d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
788d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    private void assertScreenshotButtonEnabled(boolean expectedEnabled) throws Exception {
789d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        UiObject screenshotButton = getScreenshotButton();
790d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        assertEquals("wrong state for screenshot button ", expectedEnabled,
791d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                screenshotButton.isEnabled());
792d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    }
793d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
794d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    /**
795bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme     * Helper class containing the UiObjects present in the bugreport info dialog.
796bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme     */
797bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    private final class DetailsUi {
798bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
799bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        final UiObject detailsButton;
800bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        final UiObject nameField;
801bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        final UiObject titleField;
802bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        final UiObject descField;
803bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        final UiObject okButton;
804bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        final UiObject cancelButton;
805bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
806bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        /**
807bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme         * Gets the UI objects by opening the progress notification and clicking DETAILS.
808bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme         */
809bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        DetailsUi(UiBot uiBot) {
810bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            openProgressNotification();
811bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            detailsButton = mUiBot.getVisibleObject(
812bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme                    mContext.getString(R.string.bugreport_info_action).toUpperCase());
813bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            mUiBot.click(detailsButton, "details_button");
814bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            // TODO: unhardcode resource ids
815bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            nameField = mUiBot.getVisibleObjectById("com.android.shell:id/name");
816bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            titleField = mUiBot.getVisibleObjectById("com.android.shell:id/title");
817bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            descField = mUiBot.getVisibleObjectById("com.android.shell:id/description");
818bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            okButton = mUiBot.getObjectById("android:id/button1");
819bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            cancelButton = mUiBot.getObjectById("android:id/button2");
820bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        }
821bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
822bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        /**
823bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme         * Takes focus away from the name field so it can be validated.
824bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme         */
825bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        void focusAwayFromName() {
826bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            mUiBot.click(titleField, "title_field"); // Change focus.
827bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            mUiBot.pressBack(); // Dismiss keyboard.
828bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        }
829bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
830bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        void reOpen() {
831bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            openProgressNotification();
832bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            mUiBot.click(detailsButton, "details_button");
833bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
834bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        }
835bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
836bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        void clickOk() {
837bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            mUiBot.click(okButton, "details_ok_button");
838bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        }
839bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
840bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        void clickCancel() {
841bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            mUiBot.click(cancelButton, "details_cancel_button");
842bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        }
843bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    }
844e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme}
845