BugreportReceiverTest.java revision 208b1881ae924cd0c2bed326555e4aa18424d927
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;
50ba477939f0ae38926b4b0a6501a2371acc612433Felipe Lemeimport android.app.ActivityManager;
51ba477939f0ae38926b4b0a6501a2371acc612433Felipe Lemeimport android.app.ActivityManager.RunningServiceInfo;
52e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.app.Instrumentation;
53e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.app.NotificationManager;
54e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.content.Context;
55a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Lemeimport android.content.ContextWrapper;
56e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.content.Intent;
57e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.net.Uri;
58e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.os.Bundle;
59e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.os.SystemProperties;
60e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.service.notification.StatusBarNotification;
61e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.support.test.uiautomator.UiDevice;
626bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Lemeimport android.support.test.uiautomator.UiObject;
63e86b63bd17da3d347b9392f897e361919655edd6Felipe Lemeimport android.support.test.uiautomator.UiObjectNotFoundException;
64262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Lemeimport android.support.test.uiautomator.UiSelector;
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";
103262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    private static final String ZIP_FILE2 = "test_bugreport2.zip";
104a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme    private static final String SCREENSHOT_FILE = "test_screenshot.png";
105e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
106e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String BUGREPORT_CONTENT = "Dump, might as well dump!\n";
107e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String SCREENSHOT_CONTENT = "A picture is worth a thousand words!\n";
108e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
10993702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    private static final int PID = 42;
110262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    private static final int PID2 = 24;
11185ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private static final int ID = 108;
112262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    private static final int ID2 = 801;
11385ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private static final String PROGRESS_PROPERTY = "dumpstate." + PID + ".progress";
11485ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private static final String MAX_PROPERTY = "dumpstate." + PID + ".max";
11585ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private static final String NAME_PROPERTY = "dumpstate." + PID + ".name";
11693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    private static final String NAME = "BUG, Y U NO REPORT?";
117262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    private static final String NAME2 = "A bugreport's life";
118bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    private static final String NEW_NAME = "Bug_Forrest_Bug";
119262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    private static final String NEW_NAME2 = "BugsyReportsy";
120bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    private static final String TITLE = "Wimbugdom Champion 2015";
121262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    private static final String TITLE2 = "Master of the Universe";
122262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    private static final String DESCRIPTION = "One's description...";
123262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    private static final String DESCRIPTION2 = "...is another's treasure.";
1244967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
1254967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    private static final String NO_DESCRIPTION = null;
1264967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    private static final String NO_NAME = null;
1274967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    private static final String NO_SCREENSHOT = null;
1284967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    private static final String NO_TITLE = null;
12985ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private static final int NO_ID = 0;
130c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme    private static final boolean RENAMED_SCREENSHOTS = true;
131c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme    private static final boolean DIDNT_RENAME_SCREENSHOTS = false;
1324967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
1335ee846dd18022307341c9808c9aacded2b2f60fdFelipe Leme    private static final boolean PENDING_SCREENSHOT = true;
1345ee846dd18022307341c9808c9aacded2b2f60fdFelipe Leme    private static final boolean NOT_PENDING_SCREENSHOT = false;
1355ee846dd18022307341c9808c9aacded2b2f60fdFelipe Leme
136bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    private String mDescription;
13793702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
138a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme    private String mPlainTextPath;
139a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme    private String mZipPath;
140262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    private String mZipPath2;
141a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme    private String mScreenshotPath;
142a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme
143e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private Context mContext;
144e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private UiBot mUiBot;
145e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private CustomActionSendMultipleListener mListener;
146e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
147e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    @Override
148e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    protected void setUp() throws Exception {
149c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        Log.i(TAG, "#### setup() on " + getName());
150e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Instrumentation instrumentation = getInstrumentation();
151e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        mContext = instrumentation.getTargetContext();
152e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        mUiBot = new UiBot(UiDevice.getInstance(instrumentation), TIMEOUT);
153e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        mListener = ActionSendMultipleConsumerActivity.getListener(mContext);
15493702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
15593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        cancelExistingNotifications();
15693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
157a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        mPlainTextPath = getPath(BUGREPORT_FILE);
158a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        mZipPath = getPath(ZIP_FILE);
159262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        mZipPath2 = getPath(ZIP_FILE2);
160a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        mScreenshotPath = getPath(SCREENSHOT_FILE);
16193702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        createTextFile(mPlainTextPath, BUGREPORT_CONTENT);
16293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        createTextFile(mScreenshotPath, SCREENSHOT_CONTENT);
16393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        createZipFile(mZipPath, BUGREPORT_FILE, BUGREPORT_CONTENT);
164262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        createZipFile(mZipPath2, BUGREPORT_FILE, BUGREPORT_CONTENT);
16593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
166bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Creates a multi-line description.
167bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        StringBuilder sb = new StringBuilder();
168bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        for (int i = 1; i <= 20; i++) {
169bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            sb.append("All work and no play makes Shell a dull app!\n");
170bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        }
171bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        mDescription = sb.toString();
172bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
1736bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        BugreportPrefs.setWarningState(mContext, BugreportPrefs.STATE_HIDE);
174e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
175e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
176bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    public void testProgress() throws Exception {
17793702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        resetProperties();
17893702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        sendBugreportStarted(1000);
1792288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme        waitForScreenshotButtonEnabled(true);
18069c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
181e86b63bd17da3d347b9392f897e361919655edd6Felipe Leme        final NumberFormat nf = NumberFormat.getPercentInstance();
182e86b63bd17da3d347b9392f897e361919655edd6Felipe Leme        nf.setMinimumFractionDigits(2);
183e86b63bd17da3d347b9392f897e361919655edd6Felipe Leme        nf.setMaximumFractionDigits(2);
184e86b63bd17da3d347b9392f897e361919655edd6Felipe Leme
185e86b63bd17da3d347b9392f897e361919655edd6Felipe Leme        assertProgressNotification(NAME, nf.format(0));
18669c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
18793702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        SystemProperties.set(PROGRESS_PROPERTY, "108");
188e86b63bd17da3d347b9392f897e361919655edd6Felipe Leme        assertProgressNotification(NAME, nf.format(0.108));
18969c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
19093702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        SystemProperties.set(PROGRESS_PROPERTY, "500");
191e86b63bd17da3d347b9392f897e361919655edd6Felipe Leme        assertProgressNotification(NAME, nf.format(0.50));
19269c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
19393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        SystemProperties.set(MAX_PROPERTY, "2000");
194e86b63bd17da3d347b9392f897e361919655edd6Felipe Leme        assertProgressNotification(NAME, nf.format(0.25));
195719aaae3c167c2b15525dbe5c7db514a2c0c8269Felipe Leme
19693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        Bundle extras =
19785ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme                sendBugreportFinishedAndGetSharedIntent(ID, mPlainTextPath, mScreenshotPath);
19885ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, ZIP_FILE,
199c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme                NAME, NO_TITLE, NO_DESCRIPTION, 1, RENAMED_SCREENSHOTS);
200d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
201d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        assertServiceNotRunning();
202d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    }
203d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
204db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme    public void testProgress_cancel() throws Exception {
205db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        resetProperties();
206db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        sendBugreportStarted(1000);
207db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        waitForScreenshotButtonEnabled(true);
208db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme
209db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        final NumberFormat nf = NumberFormat.getPercentInstance();
210db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        nf.setMinimumFractionDigits(2);
211db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        nf.setMaximumFractionDigits(2);
212db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme
213db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        assertProgressNotification(NAME, nf.format(0));
214db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme
215db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        openProgressNotification(ID);
216db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        UiObject cancelButton = mUiBot.getVisibleObject(mContext.getString(
217db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme                com.android.internal.R.string.cancel).toUpperCase());
218db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        mUiBot.click(cancelButton, "cancel_button");
219db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme
220db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        waitForService(false);
221db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme    }
222db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme
223d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    public void testProgress_takeExtraScreenshot() throws Exception {
224c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        takeExtraScreenshotTest(false);
225c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
226c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
227c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    public void testProgress_takeExtraScreenshotServiceDiesAfterScreenshotTaken() throws Exception {
228c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        takeExtraScreenshotTest(true);
229c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
230c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
231c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    private void takeExtraScreenshotTest(boolean serviceDies) throws Exception {
232d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        resetProperties();
233d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        sendBugreportStarted(1000);
234d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
235d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        waitForScreenshotButtonEnabled(true);
236d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        takeScreenshot();
237d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        assertScreenshotButtonEnabled(false);
238d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        waitForScreenshotButtonEnabled(true);
239d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
24085ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        sendBugreportFinished(ID, mPlainTextPath, mScreenshotPath);
241c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
242c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        if (serviceDies) {
24385ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme            waitShareNotification(ID);
244c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            killService();
245c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        }
246c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
24785ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        Bundle extras = acceptBugreportAndGetSharedIntent(ID);
24885ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, ZIP_FILE,
249c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme                NAME, NO_TITLE, NO_DESCRIPTION, 2, RENAMED_SCREENSHOTS);
25069c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
25193702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        assertServiceNotRunning();
25269c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme    }
25369c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
254c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    public void testScreenshotFinishesAfterBugreport() throws Exception {
255c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        screenshotFinishesAfterBugreportTest(false);
256c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
257c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
258c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    public void testScreenshotFinishesAfterBugreportAndServiceDiesBeforeSharing() throws Exception {
259c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        screenshotFinishesAfterBugreportTest(true);
260c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
261c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
262c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    private void screenshotFinishesAfterBugreportTest(boolean serviceDies) throws Exception {
263c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        resetProperties();
264c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
265c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        sendBugreportStarted(1000);
26685ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        sendBugreportFinished(ID, mPlainTextPath, NO_SCREENSHOT);
26785ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        waitShareNotification(ID);
268c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
269c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        // There's no indication in the UI about the screenshot finish, so just sleep like a baby...
270c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        Thread.sleep(SAFE_SCREENSHOT_DELAY * DateUtils.SECOND_IN_MILLIS);
271c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
272c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        if (serviceDies) {
273c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            killService();
274c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        }
275c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
27685ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        Bundle extras = acceptBugreportAndGetSharedIntent(ID);
27785ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT, ID, PID, ZIP_FILE,
278c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme                NAME, NO_TITLE, NO_DESCRIPTION, 1, RENAMED_SCREENSHOTS);
279c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
280c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        assertServiceNotRunning();
281c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
282c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
2834967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    public void testProgress_changeDetailsInvalidInput() throws Exception {
284bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        resetProperties();
285bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        sendBugreportStarted(1000);
2862288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme        waitForScreenshotButtonEnabled(true);
287bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
28885ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        DetailsUi detailsUi = new DetailsUi(mUiBot, ID);
289bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
290bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Check initial name.
291262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        detailsUi.assertName(NAME);
292bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
293bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Change name - it should have changed system property once focus is changed.
294208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme        detailsUi.focusOnName();
295bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.nameField.setText(NEW_NAME);
296bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.focusAwayFromName();
297bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertPropertyValue(NAME_PROPERTY, NEW_NAME);
298bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
299bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Cancel the dialog to make sure property was restored.
300bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.clickCancel();
301bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertPropertyValue(NAME_PROPERTY, NAME);
302bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
303bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Now try to set an invalid name.
304bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.reOpen();
305bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.nameField.setText("/etc/passwd");
306bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.clickOk();
307bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertPropertyValue(NAME_PROPERTY, "_etc_passwd");
308bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
309bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Finally, make the real changes.
310bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.reOpen();
311bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.nameField.setText(NEW_NAME);
312bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.titleField.setText(TITLE);
313bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.descField.setText(mDescription);
314bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
315bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.clickOk();
316bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
317bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertPropertyValue(NAME_PROPERTY, NEW_NAME);
318bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertProgressNotification(NEW_NAME, "0.00%");
319bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
32085ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        Bundle extras = sendBugreportFinishedAndGetSharedIntent(ID, mPlainTextPath,
321bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme                mScreenshotPath);
32285ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, TITLE,
323c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme                NEW_NAME, TITLE, mDescription, 1, RENAMED_SCREENSHOTS);
3244967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
3254967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertServiceNotRunning();
3264967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    }
3274967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
3284967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    public void testProgress_changeDetailsPlainBugreport() throws Exception {
3294967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        changeDetailsTest(true);
3304967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    }
3314967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
3324967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    public void testProgress_changeDetailsZippedBugreport() throws Exception {
3334967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        changeDetailsTest(false);
3344967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    }
3354967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
3364967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    public void changeDetailsTest(boolean plainText) throws Exception {
3374967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        resetProperties();
3384967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        sendBugreportStarted(1000);
3394967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        waitForScreenshotButtonEnabled(true);
3404967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
34185ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        DetailsUi detailsUi = new DetailsUi(mUiBot, ID);
3424967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
3434967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        // Check initial name.
344262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        detailsUi.assertName(NAME);
3454967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
3464967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        // Change fields.
3474967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        detailsUi.reOpen();
3484967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        detailsUi.nameField.setText(NEW_NAME);
3494967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        detailsUi.titleField.setText(TITLE);
3504967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        detailsUi.descField.setText(mDescription);
3514967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
3524967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        detailsUi.clickOk();
3534967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
3544967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertPropertyValue(NAME_PROPERTY, NEW_NAME);
3554967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertProgressNotification(NEW_NAME, "0.00%");
3564967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
35785ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        Bundle extras = sendBugreportFinishedAndGetSharedIntent(ID,
3584967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme                plainText? mPlainTextPath : mZipPath, mScreenshotPath);
35985ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, TITLE,
360c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme                NEW_NAME, TITLE, mDescription, 1, RENAMED_SCREENSHOTS);
361c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme
362c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme        assertServiceNotRunning();
363c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme    }
364c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme
365db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme    public void testProgress_changeJustDetailsTouchingDetails() throws Exception {
366db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        changeJustDetailsTest(true);
367db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme    }
368db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme
369db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme    public void testProgress_changeJustDetailsTouchingNotification() throws Exception {
370db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        changeJustDetailsTest(false);
371db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme    }
372db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme
373db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme    private void changeJustDetailsTest(boolean touchDetails) throws Exception {
374c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme        resetProperties();
375c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme        sendBugreportStarted(1000);
376c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme        waitForScreenshotButtonEnabled(true);
377c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme
378db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        DetailsUi detailsUi = new DetailsUi(mUiBot, ID, touchDetails);
379c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme
380c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme        detailsUi.nameField.setText("");
381c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme        detailsUi.titleField.setText("");
382c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme        detailsUi.descField.setText(mDescription);
383c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme        detailsUi.clickOk();
384c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme
38585ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        Bundle extras = sendBugreportFinishedAndGetSharedIntent(ID, mZipPath, mScreenshotPath);
38685ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, ZIP_FILE,
387c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme                NO_NAME, NO_TITLE, mDescription, 1, DIDNT_RENAME_SCREENSHOTS);
388bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
389bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertServiceNotRunning();
390bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    }
391bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
392262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    /*
393262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme     * TODO: this test can be flanky because it relies in the order the notifications are displayed,
394262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme     * since mUiBot gets the first notification.
395262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme     * Ideally, openProgressNotification() should return the whole notification, so DetailsUi
396262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme     * could use it and find children instead, but unfortunately the notification object hierarchy
397262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme     * is too complex and getting it from the notification text object would be to fragile
398262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme     * (for instance, it could require navigating many parents up in the hierarchy).
399262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme     */
400262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    public void testProgress_changeJustDetailsIsClearedOnSecondBugreport() throws Exception {
401262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        resetProperties();
402262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        sendBugreportStarted(ID, PID, NAME, 1000);
403262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        waitForScreenshotButtonEnabled(true);
404262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme
405262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        DetailsUi detailsUi = new DetailsUi(mUiBot, ID);
406262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        detailsUi.assertName(NAME);
407bbd91e58444f092e1080f5a0a746fcd4b21ce113Felipe Leme        detailsUi.assertTitle("");
408bbd91e58444f092e1080f5a0a746fcd4b21ce113Felipe Leme        detailsUi.assertDescription("");
409262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        detailsUi.nameField.setText(NEW_NAME);
410262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        detailsUi.titleField.setText(TITLE);
411262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        detailsUi.descField.setText(DESCRIPTION);
412262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        detailsUi.clickOk();
413262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme
414262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        sendBugreportStarted(ID2, PID2, NAME2, 1000);
415262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme
4165ee846dd18022307341c9808c9aacded2b2f60fdFelipe Leme        sendBugreportFinished(ID, mZipPath, mScreenshotPath);
4175ee846dd18022307341c9808c9aacded2b2f60fdFelipe Leme        Bundle extras = acceptBugreportAndGetSharedIntent(ID, PENDING_SCREENSHOT);
418262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme
419262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        detailsUi = new DetailsUi(mUiBot, ID2);
420262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        detailsUi.assertName(NAME2);
421bbd91e58444f092e1080f5a0a746fcd4b21ce113Felipe Leme        detailsUi.assertTitle("");
422bbd91e58444f092e1080f5a0a746fcd4b21ce113Felipe Leme        detailsUi.assertDescription("");
423262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        detailsUi.nameField.setText(NEW_NAME2);
424262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        detailsUi.titleField.setText(TITLE2);
425262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        detailsUi.descField.setText(DESCRIPTION2);
426262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        detailsUi.clickOk();
427262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme
428262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        // Must use a different zip file otherwise it will fail because zip already contains
429262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        // title.txt and description.txt entries.
430262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        extras = sendBugreportFinishedAndGetSharedIntent(ID2, mZipPath2, NO_SCREENSHOT);
431262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT, ID2, PID2, TITLE2,
432262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme                NEW_NAME2, TITLE2, DESCRIPTION2, 1, RENAMED_SCREENSHOTS);
433262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme
434262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        assertServiceNotRunning();
435262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    }
436262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme
4372288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme    /**
4382288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme     * Tests the scenario where the initial screenshot and dumpstate are finished while the user
4392288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme     * is changing the info in the details screen.
4402288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme     */
4412288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme    public void testProgress_bugreportAndScreenshotFinishedWhileChangingDetails() throws Exception {
4422288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme        bugreportFinishedWhileChangingDetailsTest(false);
4432288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme    }
4442288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme
4452288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme    /**
4462288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme     * Tests the scenario where dumpstate is finished while the user is changing the info in the
4472288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme     * details screen, but the initial screenshot finishes afterwards.
4482288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme     */
449bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    public void testProgress_bugreportFinishedWhileChangingDetails() throws Exception {
4502288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme        bugreportFinishedWhileChangingDetailsTest(true);
4512288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme    }
4522288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme
4532288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme    private void bugreportFinishedWhileChangingDetailsTest(boolean waitScreenshot) throws Exception {
454bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        resetProperties();
455bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        sendBugreportStarted(1000);
4562288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme        if (waitScreenshot) {
4572288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme            waitForScreenshotButtonEnabled(true);
4582288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme        }
459bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
46085ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        DetailsUi detailsUi = new DetailsUi(mUiBot, ID);
461bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
462bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Finish the bugreport while user's still typing the name.
463bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.nameField.setText(NEW_NAME);
46485ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        sendBugreportFinished(ID, mPlainTextPath, mScreenshotPath);
465bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
4662288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme        // Wait until the share notification is received...
46785ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        waitShareNotification(ID);
468bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // ...then close notification bar.
469bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
470bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
471bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Make sure UI was updated properly.
472bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertFalse("didn't disable name on UI", detailsUi.nameField.isEnabled());
473bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertEquals("didn't revert name on UI", NAME, detailsUi.nameField.getText().toString());
474bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
475bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Finish changing other fields.
476bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.titleField.setText(TITLE);
477bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.descField.setText(mDescription);
478bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.clickOk();
479bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
480bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Finally, share bugreport.
48185ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        Bundle extras = acceptBugreportAndGetSharedIntent(ID);
48285ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, TITLE,
483c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme                NAME, TITLE, mDescription, 1, RENAMED_SCREENSHOTS);
484bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
485bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertServiceNotRunning();
486bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    }
487bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
4886bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme    public void testBugreportFinished_withWarning() throws Exception {
4896bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Explicitly shows the warning.
4906bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        BugreportPrefs.setWarningState(mContext, BugreportPrefs.STATE_SHOW);
4916bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
4926bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Send notification and click on share.
49385ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        sendBugreportFinished(NO_ID, mPlainTextPath, null);
49485ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        acceptBugreport(NO_ID);
4956bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
4966bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Handle the warning
4976bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        mUiBot.getVisibleObject(mContext.getString(R.string.bugreport_confirm));
4986bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // TODO: get ok and showMessageAgain from the dialog reference above
4996bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        UiObject showMessageAgain =
5006bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme                mUiBot.getVisibleObject(mContext.getString(R.string.bugreport_confirm_repeat));
5016bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        mUiBot.click(showMessageAgain, "show-message-again");
5026bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        UiObject ok = mUiBot.getVisibleObject(mContext.getString(com.android.internal.R.string.ok));
5036bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        mUiBot.click(ok, "ok");
5046bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
5056bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Share the bugreport.
5066bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        mUiBot.chooseActivity(UI_NAME);
5076bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        Bundle extras = mListener.getExtras();
5084967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
5096bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
5106bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Make sure it's hidden now.
5116bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        int newState = BugreportPrefs.getWarningState(mContext, BugreportPrefs.STATE_UNKNOWN);
5126bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        assertEquals("Didn't change state", BugreportPrefs.STATE_HIDE, newState);
5136bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme    }
5146bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
515c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    public void testShareBugreportAfterServiceDies() throws Exception {
51685ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        sendBugreportFinished(NO_ID, mPlainTextPath, NO_SCREENSHOT);
517c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        killService();
51885ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        Bundle extras = acceptBugreportAndGetSharedIntent(NO_ID);
519c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
520c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
521c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
522e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    public void testBugreportFinished_plainBugreportAndScreenshot() throws Exception {
52393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        Bundle extras = sendBugreportFinishedAndGetSharedIntent(mPlainTextPath, mScreenshotPath);
524e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);
525e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
526e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
527e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    public void testBugreportFinished_zippedBugreportAndScreenshot() throws Exception {
52893702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        Bundle extras = sendBugreportFinishedAndGetSharedIntent(mZipPath, mScreenshotPath);
529e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);
530e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
531e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
532e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    public void testBugreportFinished_plainBugreportAndNoScreenshot() throws Exception {
5334967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        Bundle extras = sendBugreportFinishedAndGetSharedIntent(mPlainTextPath, NO_SCREENSHOT);
5344967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
535e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
536e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
537e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    public void testBugreportFinished_zippedBugreportAndNoScreenshot() throws Exception {
5384967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        Bundle extras = sendBugreportFinishedAndGetSharedIntent(mZipPath, NO_SCREENSHOT);
5394967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
540e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
541e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
542e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void cancelExistingNotifications() {
543e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        NotificationManager nm = NotificationManager.from(mContext);
544e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        for (StatusBarNotification notification : nm.getActiveNotifications()) {
545e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            int id = notification.getId();
546e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            Log.i(TAG, "Canceling existing notification (id=" + id + ")");
547e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            nm.cancel(id);
548e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
549e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
550e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
55169c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme    private void assertProgressNotification(String name, String percent) {
552d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        // TODO: it currently looks for 3 distinct objects, without taking advantage of their
55369c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        // relationship.
55485ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        openProgressNotification(ID);
55569c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        Log.v(TAG, "Looking for progress notification details: '" + name + "-" + percent + "'");
55669c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        mUiBot.getObject(name);
55769c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        mUiBot.getObject(percent);
55869c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme    }
55969c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
560db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme    private UiObject openProgressNotification(int id) {
56185ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        String title = mContext.getString(R.string.bugreport_in_progress_title, id);
562bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        Log.v(TAG, "Looking for progress notification title: '" + title + "'");
563db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        return mUiBot.getNotification(title);
564bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    }
565bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
56693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    void resetProperties() {
56793702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        // TODO: call method to remove property instead
56885ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        SystemProperties.set(PROGRESS_PROPERTY, "Reset");
56985ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        SystemProperties.set(MAX_PROPERTY, "Reset");
57085ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        SystemProperties.set(NAME_PROPERTY, "Reset");
57193702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    }
57293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
57393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    /**
57493702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * Sends a "bugreport started" intent with the default values.
57593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     */
576d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    private void sendBugreportStarted(int max) throws Exception {
577262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        sendBugreportStarted(ID, PID, NAME, max);
578262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    }
579262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme
580262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    private void sendBugreportStarted(int id, int pid, String name, int max) throws Exception {
58193702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        Intent intent = new Intent(INTENT_BUGREPORT_STARTED);
582ec17538d46a49530ed6efdc2842ee16eaf18b9f6Felipe Leme        intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
583262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        intent.putExtra(EXTRA_ID, id);
584262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        intent.putExtra(EXTRA_PID, pid);
585262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        intent.putExtra(EXTRA_NAME, name);
58693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        intent.putExtra(EXTRA_MAX, max);
58793702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        mContext.sendBroadcast(intent);
58893702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    }
58993702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
590e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    /**
591e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme     * Sends a "bugreport finished" intent and waits for the result.
592e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme     *
59393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * @return extras sent in the shared intent.
594e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme     */
59593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    private Bundle sendBugreportFinishedAndGetSharedIntent(String bugreportPath,
59693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme            String screenshotPath) {
59785ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        return sendBugreportFinishedAndGetSharedIntent(NO_ID, bugreportPath, screenshotPath);
59869c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme    }
59969c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
60093702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    /**
60193702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * Sends a "bugreport finished" intent and waits for the result.
60293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     *
60393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * @return extras sent in the shared intent.
60493702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     */
60585ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private Bundle sendBugreportFinishedAndGetSharedIntent(int id, String bugreportPath,
60669c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme            String screenshotPath) {
60785ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        sendBugreportFinished(id, bugreportPath, screenshotPath);
6085ee846dd18022307341c9808c9aacded2b2f60fdFelipe Leme        return acceptBugreportAndGetSharedIntent(id, NOT_PENDING_SCREENSHOT);
60993702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    }
61093702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
61193702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    /**
61293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * Accepts the notification to share the finished bugreport and waits for the result.
61393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     *
61493702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * @return extras sent in the shared intent.
61593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     */
61685ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private Bundle acceptBugreportAndGetSharedIntent(int id) {
6175ee846dd18022307341c9808c9aacded2b2f60fdFelipe Leme        return acceptBugreportAndGetSharedIntent(id, NOT_PENDING_SCREENSHOT);
6185ee846dd18022307341c9808c9aacded2b2f60fdFelipe Leme    }
6195ee846dd18022307341c9808c9aacded2b2f60fdFelipe Leme
6205ee846dd18022307341c9808c9aacded2b2f60fdFelipe Leme    private Bundle acceptBugreportAndGetSharedIntent(int id, boolean pendingScreenshot) {
6215ee846dd18022307341c9808c9aacded2b2f60fdFelipe Leme        acceptBugreport(id, pendingScreenshot);
62293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        mUiBot.chooseActivity(UI_NAME);
62393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        return mListener.getExtras();
62493702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    }
62593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
62693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    /**
627c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme     * Waits for the notification to share the finished bugreport.
628c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme     */
62985ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private void waitShareNotification(int id) {
63085ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        mUiBot.getNotification(mContext.getString(R.string.bugreport_finished_title, id));
631c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
632c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
633c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    /**
63493702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * Accepts the notification to share the finished bugreport.
63593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     */
63685ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private void acceptBugreport(int id) {
6375ee846dd18022307341c9808c9aacded2b2f60fdFelipe Leme        acceptBugreport(id, NOT_PENDING_SCREENSHOT);
6385ee846dd18022307341c9808c9aacded2b2f60fdFelipe Leme    }
6395ee846dd18022307341c9808c9aacded2b2f60fdFelipe Leme
6405ee846dd18022307341c9808c9aacded2b2f60fdFelipe Leme    private void acceptBugreport(int id, boolean pendingScreenshot) {
6415ee846dd18022307341c9808c9aacded2b2f60fdFelipe Leme        final int res = pendingScreenshot ? R.string.bugreport_finished_pending_screenshot_title
6425ee846dd18022307341c9808c9aacded2b2f60fdFelipe Leme                : R.string.bugreport_finished_title;
6435ee846dd18022307341c9808c9aacded2b2f60fdFelipe Leme        mUiBot.clickOnNotification(mContext.getString(res, id));
64493702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    }
64593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
64693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    /**
64793702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * Sends a "bugreport finished" intent.
64893702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     */
64985ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private void sendBugreportFinished(int id, String bugreportPath, String screenshotPath) {
65069c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        Intent intent = new Intent(INTENT_BUGREPORT_FINISHED);
651ec17538d46a49530ed6efdc2842ee16eaf18b9f6Felipe Leme        intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
65285ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        if (id != NO_ID) {
65385ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme            intent.putExtra(EXTRA_ID, id);
65469c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        }
655e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        if (bugreportPath != null) {
656e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            intent.putExtra(EXTRA_BUGREPORT, bugreportPath);
657e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
658e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        if (screenshotPath != null) {
659e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            intent.putExtra(EXTRA_SCREENSHOT, screenshotPath);
660e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
661e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
662e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        mContext.sendBroadcast(intent);
663e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
664e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
665e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    /**
666d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * Asserts the proper {@link Intent#ACTION_SEND_MULTIPLE} intent was sent.
667e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme     */
668e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void assertActionSendMultiple(Bundle extras, String bugreportContent,
669e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            String screenshotContent) throws IOException {
67085ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        assertActionSendMultiple(extras, bugreportContent, screenshotContent, ID, PID, ZIP_FILE,
671c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme                NO_NAME, NO_TITLE, NO_DESCRIPTION, 0, DIDNT_RENAME_SCREENSHOTS);
672bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    }
673bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
674d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    /**
675d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * Asserts the proper {@link Intent#ACTION_SEND_MULTIPLE} intent was sent.
676d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     *
677d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * @param extras extras received in the intent
678d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * @param bugreportContent expected content in the bugreport file
679d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * @param screenshotContent expected content in the screenshot file (sent by dumpstate), if any
68085ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme     * @param id emulated dumpstate id
681d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * @param pid emulated dumpstate pid
6824967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme     * @param name expected subject
6834967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme     * @param name bugreport name as provided by the user (or received by dumpstate)
6844967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme     * @param title bugreport name as provided by the user
685d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * @param description bugreport description as provided by the user
686d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * @param numberScreenshots expected number of screenshots taken by Shell.
6872288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme     * @param renamedScreenshots whether the screenshots are expected to be renamed
688d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     */
689d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    private void assertActionSendMultiple(Bundle extras, String bugreportContent,
69085ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme            String screenshotContent, int id, int pid, String subject,
6914967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme            String name, String title, String description,
6922288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme            int numberScreenshots, boolean renamedScreenshots) throws IOException {
693e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        String body = extras.getString(Intent.EXTRA_TEXT);
694e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertContainsRegex("missing build info",
695e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                SystemProperties.get("ro.build.description"), body);
696e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertContainsRegex("missing serial number",
697e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                SystemProperties.get("ro.serialno"), body);
698bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        if (description != null) {
699bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            assertContainsRegex("missing description", description, body);
700bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        }
701e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
7024967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertEquals("wrong subject", subject, extras.getString(Intent.EXTRA_SUBJECT));
703e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
704e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        List<Uri> attachments = extras.getParcelableArrayList(Intent.EXTRA_STREAM);
705d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        int expectedNumberScreenshots = numberScreenshots;
706d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        if (screenshotContent != null) {
707d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            expectedNumberScreenshots ++; // Add screenshot received by dumpstate
708d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        }
709d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        int expectedSize = expectedNumberScreenshots + 1; // All screenshots plus the bugreport file
710c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        assertEquals("wrong number of attachments (" + attachments + ")",
711c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme                expectedSize, attachments.size());
712e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
713e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        // Need to interact through all attachments, since order is not guaranteed.
714d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        Uri zipUri = null;
715d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        List<Uri> screenshotUris = new ArrayList<>(expectedNumberScreenshots);
716e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        for (Uri attachment : attachments) {
717e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            if (attachment.getPath().endsWith(".zip")) {
718e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                zipUri = attachment;
719e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            }
720e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            if (attachment.getPath().endsWith(".png")) {
721d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                screenshotUris.add(attachment);
722e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            }
723e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
724e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertNotNull("did not get .zip attachment", zipUri);
725e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertZipContent(zipUri, BUGREPORT_FILE, BUGREPORT_CONTENT);
7264967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        if (!TextUtils.isEmpty(title)) {
7274967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme            assertZipContent(zipUri, "title.txt", title);
7284967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        }
7294967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        if (!TextUtils.isEmpty(description)) {
7304967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme            assertZipContent(zipUri, "description.txt", description);
7314967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        }
732e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
733d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        // URI of the screenshot taken by dumpstate.
734d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        Uri externalScreenshotUri = null;
735d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        SortedSet<String> internalScreenshotNames = new TreeSet<>();
736d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        for (Uri screenshotUri : screenshotUris) {
737d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            String screenshotName = screenshotUri.getLastPathSegment();
738d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            if (screenshotName.endsWith(SCREENSHOT_FILE)) {
739d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                externalScreenshotUri = screenshotUri;
740d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            } else {
741d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                internalScreenshotNames.add(screenshotName);
742d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            }
743d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        }
744d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        // Check external screenshot
745e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        if (screenshotContent != null) {
746d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            assertNotNull("did not get .png attachment for external screenshot",
747d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                    externalScreenshotUri);
748d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            assertContent(externalScreenshotUri, SCREENSHOT_CONTENT);
749e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        } else {
750d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            assertNull("should not have .png attachment for external screenshot",
751d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                    externalScreenshotUri);
752d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        }
753d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        // Check internal screenshots.
754d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        SortedSet<String> expectedNames = new TreeSet<>();
755d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        for (int i = 1 ; i <= numberScreenshots; i++) {
7562288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme            String prefix = renamedScreenshots  ? name : Integer.toString(pid);
757d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            String expectedName = "screenshot-" + prefix + "-" + i + ".png";
758d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            expectedNames.add(expectedName);
759e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
760d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        // Ideally we should use MoreAsserts, but the error message in case of failure is not
761d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        // really useful.
762d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        assertEquals("wrong names for internal screenshots",
763d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                expectedNames, internalScreenshotNames);
764e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
765e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
766e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void assertContent(Uri uri, String expectedContent) throws IOException {
767e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Log.v(TAG, "assertContents(uri=" + uri);
768e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        try (InputStream is = mContext.getContentResolver().openInputStream(uri)) {
769e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            String actualContent = new String(Streams.readFully(is));
770e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            assertEquals("wrong content for '" + uri + "'", expectedContent, actualContent);
771e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
772e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
773e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
774e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void assertZipContent(Uri uri, String entryName, String expectedContent)
775e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            throws IOException, IOException {
776e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Log.v(TAG, "assertZipEntry(uri=" + uri + ", entryName=" + entryName);
777e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        try (ZipInputStream zis = new ZipInputStream(mContext.getContentResolver().openInputStream(
778e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                uri))) {
779e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            ZipEntry entry;
780e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            while ((entry = zis.getNextEntry()) != null) {
781e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                Log.v(TAG, "Zip entry: " + entry.getName());
782e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                if (entry.getName().equals(entryName)) {
783e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
784e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    Streams.copy(zis, bos);
785e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    String actualContent = new String(bos.toByteArray(), "UTF-8");
786e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    bos.close();
787e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    assertEquals("wrong content for zip entry'" + entryName + "' on '" + uri + "'",
788e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                            expectedContent, actualContent);
789e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    return;
790e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                }
791e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            }
792e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
793e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        fail("Did not find entry '" + entryName + "' on file '" + uri + "'");
794e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
795e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
796bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    private void assertPropertyValue(String key, String expectedValue) {
797bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        String actualValue = SystemProperties.get(key);
798bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertEquals("Wrong value for property '" + key + "'", expectedValue, actualValue);
799bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    }
800bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
80193702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    private void assertServiceNotRunning() {
80293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        String service = BugreportProgressService.class.getName();
80393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        assertFalse("Service '" + service + "' is still running", isServiceRunning(service));
80493702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    }
80593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
806c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    private void killService() {
807c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        waitForService(true);
808c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        Log.v(TAG, "Stopping service");
809c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        boolean stopped = mContext.stopService(new Intent(mContext, BugreportProgressService.class));
810c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        Log.d(TAG, "stopService returned " + stopped);
811c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        waitForService(false);
812c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        assertServiceNotRunning();  // Sanity check.
813c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
814c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
815ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme    private boolean isServiceRunning(String name) {
816ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme        ActivityManager manager = (ActivityManager) mContext
817ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme                .getSystemService(Context.ACTIVITY_SERVICE);
818ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme        for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
819ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme            if (service.service.getClassName().equals(name)) {
820ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme                return true;
821ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme            }
822ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme        }
823ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme        return false;
824ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme    }
825ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme
826c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    private void waitForService(boolean expectRunning) {
827c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        String service = BugreportProgressService.class.getName();
828c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        boolean actualRunning;
829c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        for (int i = 1; i <= 5; i++) {
830c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            actualRunning = isServiceRunning(service);
831c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            Log.d(TAG, "Attempt " + i + " to check status of service '"
832c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme                    + service + "': expected=" + expectRunning + ", actual= " + actualRunning);
833c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            if (actualRunning == expectRunning) {
834c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme                return;
835c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            }
836c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            try {
837c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme                Thread.sleep(DateUtils.SECOND_IN_MILLIS);
838c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            } catch (InterruptedException e) {
839c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme                Log.w(TAG, "thread interrupted");
840c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme                Thread.currentThread().interrupt();
841c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            }
842c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        }
843c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        if (!expectRunning) {
844c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            // Typically happens when service is waiting for a screenshot to finish.
845c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            Log.w(TAG, "Service didn't stop; try to kill it again");
846c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            killService();
847c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            return;
848c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        }
849c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
850c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        fail("Service status didn't change to " + expectRunning);
851c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
852c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
853262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    private void createTextFile(String path, String content) throws IOException {
854e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Log.v(TAG, "createFile(" + path + ")");
855e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        try (Writer writer = new BufferedWriter(new OutputStreamWriter(
856e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                new FileOutputStream(path)))) {
857e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            writer.write(content);
858e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
859e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
860e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
861e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void createZipFile(String path, String entryName, String content) throws IOException {
862e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Log.v(TAG, "createZipFile(" + path + ", " + entryName + ")");
863e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        try (ZipOutputStream zos = new ZipOutputStream(
864e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                new BufferedOutputStream(new FileOutputStream(path)))) {
865e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            ZipEntry entry = new ZipEntry(entryName);
866e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            zos.putNextEntry(entry);
867e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            byte[] data = content.getBytes();
868e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            zos.write(data, 0, data.length);
869e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            zos.closeEntry();
870e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
871e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
872a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme
873a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme    private String getPath(String file) {
874a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        File rootDir = new ContextWrapper(mContext).getFilesDir();
875a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        File dir = new File(rootDir, BUGREPORTS_DIR);
876e2b4f49795b4f23fa563a0ffb9986b49aee7f9beFelipe Leme        if (!dir.exists()) {
877e2b4f49795b4f23fa563a0ffb9986b49aee7f9beFelipe Leme            Log.i(TAG, "Creating directory " + dir);
878e2b4f49795b4f23fa563a0ffb9986b49aee7f9beFelipe Leme            assertTrue("Could not create directory " + dir, dir.mkdir());
879e2b4f49795b4f23fa563a0ffb9986b49aee7f9beFelipe Leme        }
880a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        String path = new File(dir, file).getAbsolutePath();
881a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        Log.v(TAG, "Path for '" + file + "': " + path);
882a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        return path;
883a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme    }
884bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
885bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    /**
886d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * Gets the notification button used to take a screenshot.
887d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     */
888d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    private UiObject getScreenshotButton() {
88985ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        openProgressNotification(ID);
890d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        return mUiBot.getVisibleObject(
891d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                mContext.getString(R.string.bugreport_screenshot_action).toUpperCase());
892d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    }
893d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
894d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    /**
895d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * Takes a screenshot using the system notification.
896d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     */
897d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    private void takeScreenshot() throws Exception {
898d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        UiObject screenshotButton = getScreenshotButton();
899d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        mUiBot.click(screenshotButton, "screenshot_button");
900d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    }
901d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
902d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    private UiObject waitForScreenshotButtonEnabled(boolean expectedEnabled) throws Exception {
903d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        UiObject screenshotButton = getScreenshotButton();
904c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        int maxAttempts = SAFE_SCREENSHOT_DELAY;
905d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        int i = 0;
906d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        do {
907d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            boolean enabled = screenshotButton.isEnabled();
908d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            if (enabled == expectedEnabled) {
909d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                return screenshotButton;
910d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            }
911d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            i++;
912d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            Log.v(TAG, "Sleeping for 1 second while waiting for screenshot.enable to be "
913d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                    + expectedEnabled + " (attempt " + i + ")");
914d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            Thread.sleep(DateUtils.SECOND_IN_MILLIS);
915d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        } while (i <= maxAttempts);
916d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        fail("screenshot.enable didn't change to " + expectedEnabled + " in " + maxAttempts + "s");
917d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        return screenshotButton;
918d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    }
919d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
920d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    private void assertScreenshotButtonEnabled(boolean expectedEnabled) throws Exception {
921d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        UiObject screenshotButton = getScreenshotButton();
922d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        assertEquals("wrong state for screenshot button ", expectedEnabled,
923d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                screenshotButton.isEnabled());
924d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    }
925d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
926d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    /**
927bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme     * Helper class containing the UiObjects present in the bugreport info dialog.
928bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme     */
929bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    private final class DetailsUi {
930bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
931bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        final UiObject detailsButton;
932bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        final UiObject nameField;
933bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        final UiObject titleField;
934bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        final UiObject descField;
935bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        final UiObject okButton;
936bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        final UiObject cancelButton;
937bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
938bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        /**
939bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme         * Gets the UI objects by opening the progress notification and clicking DETAILS.
940bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme         */
94185ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        DetailsUi(UiBot uiBot, int id) throws UiObjectNotFoundException {
942db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme            this(uiBot, id, true);
943db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        }
944db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme
945db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        /**
946db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme         * Gets the UI objects by opening the progress notification and clicking on DETAILS or in
947db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme         * the notification itself.
948db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme         */
949db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        DetailsUi(UiBot uiBot, int id, boolean clickDetails) throws UiObjectNotFoundException {
950db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme            UiObject notification = openProgressNotification(id);
951262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme            detailsButton = mUiBot.getVisibleObject(mContext.getString(
952262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme                    R.string.bugreport_info_action).toUpperCase());
953262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme
954db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme            if (clickDetails) {
955db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme                mUiBot.click(detailsButton, "details_button");
956db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme            } else {
957db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme                mUiBot.click(notification, "notification");
958db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme            }
959bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            // TODO: unhardcode resource ids
960e86b63bd17da3d347b9392f897e361919655edd6Felipe Leme            UiObject dialogTitle = mUiBot.getVisibleObjectById("android:id/alertTitle");
961e86b63bd17da3d347b9392f897e361919655edd6Felipe Leme            assertEquals("Wrong title", mContext.getString(R.string.bugreport_info_dialog_title,
96285ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme                    id), dialogTitle.getText().toString());
963bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            nameField = mUiBot.getVisibleObjectById("com.android.shell:id/name");
964bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            titleField = mUiBot.getVisibleObjectById("com.android.shell:id/title");
965bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            descField = mUiBot.getVisibleObjectById("com.android.shell:id/description");
966bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            okButton = mUiBot.getObjectById("android:id/button1");
967bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            cancelButton = mUiBot.getObjectById("android:id/button2");
968bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        }
969bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
970208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme        private void assertField(String name, UiObject field, String expected)
971208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme                throws UiObjectNotFoundException {
972208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme            String actual = field.getText().toString();
973208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme            assertEquals("Wrong value on field '" + name + "'", expected, actual);
974262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        }
975262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme
976208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme        void assertName(String expected) throws UiObjectNotFoundException {
977262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme            assertField("name", nameField, expected);
978262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        }
979262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme
980208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme        void assertTitle(String expected) throws UiObjectNotFoundException {
981262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme            assertField("title", titleField, expected);
982262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        }
983262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme
984208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme        void assertDescription(String expected) throws UiObjectNotFoundException {
985262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme            assertField("description", descField, expected);
986262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        }
987262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme
988bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        /**
989208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme         * Set focus on the name field so it can be validated once focus is lost.
990208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme         */
991208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme        void focusOnName() throws UiObjectNotFoundException {
992208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme            mUiBot.click(nameField, "name_field");
993208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme            assertTrue("name_field not focused", nameField.isFocused());
994208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme        }
995208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme
996208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme        /**
997bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme         * Takes focus away from the name field so it can be validated.
998bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme         */
999208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme        void focusAwayFromName() throws UiObjectNotFoundException {
1000bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            mUiBot.click(titleField, "title_field"); // Change focus.
1001bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            mUiBot.pressBack(); // Dismiss keyboard.
1002208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme            assertFalse("name_field is focused", nameField.isFocused());
1003bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        }
1004bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
1005bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        void reOpen() {
100685ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme            openProgressNotification(ID);
1007bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            mUiBot.click(detailsButton, "details_button");
1008bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        }
1009bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
1010bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        void clickOk() {
1011bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            mUiBot.click(okButton, "details_ok_button");
1012bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        }
1013bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
1014bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        void clickCancel() {
1015bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            mUiBot.click(cancelButton, "details_cancel_button");
1016bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        }
1017bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    }
1018e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme}
1019