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;
20fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme
21e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport static com.android.shell.ActionSendMultipleConsumerActivity.UI_NAME;
22fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Lemeimport static com.android.shell.BugreportPrefs.PREFS_BUGREPORT;
23fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Lemeimport static com.android.shell.BugreportPrefs.STATE_HIDE;
24fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Lemeimport static com.android.shell.BugreportPrefs.STATE_SHOW;
25fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Lemeimport static com.android.shell.BugreportPrefs.STATE_UNKNOWN;
26fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Lemeimport static com.android.shell.BugreportPrefs.getWarningState;
27fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Lemeimport static com.android.shell.BugreportPrefs.setWarningState;
28b9238b37838d653c38ce4e712421adb61978fc22Felipe Lemeimport static com.android.shell.BugreportProgressService.EXTRA_BUGREPORT;
2985ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Lemeimport static com.android.shell.BugreportProgressService.EXTRA_ID;
3069c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Lemeimport static com.android.shell.BugreportProgressService.EXTRA_MAX;
3169c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Lemeimport static com.android.shell.BugreportProgressService.EXTRA_NAME;
3269c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Lemeimport static com.android.shell.BugreportProgressService.EXTRA_PID;
33b9238b37838d653c38ce4e712421adb61978fc22Felipe Lemeimport static com.android.shell.BugreportProgressService.EXTRA_SCREENSHOT;
3469c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Lemeimport static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_FINISHED;
3569c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Lemeimport static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_STARTED;
363fc44b9a6274254e8d3a53b6b1e245c5f9177229Felipe Lemeimport static com.android.shell.BugreportProgressService.POLLING_FREQUENCY;
37d1e0f12979441733753b538611f6d73e5527c43cFelipe Lemeimport static com.android.shell.BugreportProgressService.SCREENSHOT_DELAY_SECONDS;
38e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
39e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.BufferedOutputStream;
40e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.BufferedWriter;
41e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.ByteArrayOutputStream;
42a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Lemeimport java.io.File;
43e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.FileOutputStream;
44e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.IOException;
45e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.InputStream;
46e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.OutputStreamWriter;
47e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.Writer;
48e86b63bd17da3d347b9392f897e361919655edd6Felipe Lemeimport java.text.NumberFormat;
49d1e0f12979441733753b538611f6d73e5527c43cFelipe Lemeimport java.util.ArrayList;
50e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.util.List;
51d1e0f12979441733753b538611f6d73e5527c43cFelipe Lemeimport java.util.SortedSet;
52d1e0f12979441733753b538611f6d73e5527c43cFelipe Lemeimport java.util.TreeSet;
53e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.util.zip.ZipEntry;
54e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.util.zip.ZipInputStream;
55e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.util.zip.ZipOutputStream;
56e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
57e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport libcore.io.Streams;
58fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme
59ba477939f0ae38926b4b0a6501a2371acc612433Felipe Lemeimport android.app.ActivityManager;
60ba477939f0ae38926b4b0a6501a2371acc612433Felipe Lemeimport android.app.ActivityManager.RunningServiceInfo;
61e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.app.Instrumentation;
62e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.app.NotificationManager;
63e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.content.Context;
64e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.content.Intent;
65e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.net.Uri;
66af096719c0e45a2b7d67e9267b40cffdc16f441aFelipe Lemeimport android.os.Build;
67e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.os.Bundle;
68e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.os.SystemProperties;
69e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.service.notification.StatusBarNotification;
70e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.support.test.uiautomator.UiDevice;
716bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Lemeimport android.support.test.uiautomator.UiObject;
72e86b63bd17da3d347b9392f897e361919655edd6Felipe Lemeimport android.support.test.uiautomator.UiObjectNotFoundException;
73e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.test.InstrumentationTestCase;
742bfa0858a8cb67e19a1c9df8aad0a4da423a52b8Felipe Lemeimport android.test.suitebuilder.annotation.LargeTest;
754967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Lemeimport android.text.TextUtils;
76d1e0f12979441733753b538611f6d73e5527c43cFelipe Lemeimport android.text.format.DateUtils;
77e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.util.Log;
78e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
79e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport com.android.shell.ActionSendMultipleConsumerActivity.CustomActionSendMultipleListener;
80e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
81e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme/**
82e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * Integration tests for {@link BugreportReceiver}.
83e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <p>
84e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * These tests don't mock any component and rely on external UI components (like the notification
85e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * bar and activity chooser), which can make them unreliable and slow.
86e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <p>
87e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * The general workflow is:
88e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <ul>
89e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <li>creates the bug report files
90e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <li>generates the BUGREPORT_FINISHED intent
91e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <li>emulate user actions to share the intent with a custom activity
92e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <li>asserts the extras received by the custom activity
93e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * </ul>
94e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <p>
956bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme * <strong>NOTE</strong>: these tests only work if the device is unlocked.
96e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme */
972bfa0858a8cb67e19a1c9df8aad0a4da423a52b8Felipe Leme@LargeTest
98e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemepublic class BugreportReceiverTest extends InstrumentationTestCase {
99e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String TAG = "BugreportReceiverTest";
100e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
101e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    // Timeout for UI operations, in milliseconds.
1023fc44b9a6274254e8d3a53b6b1e245c5f9177229Felipe Leme    private static final int TIMEOUT = (int) POLLING_FREQUENCY * 4;
103e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
104c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    // Timeout for when waiting for a screenshot to finish.
105c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    private static final int SAFE_SCREENSHOT_DELAY = SCREENSHOT_DELAY_SECONDS + 10;
106c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
107a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme    private static final String BUGREPORTS_DIR = "bugreports";
108e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String BUGREPORT_FILE = "test_bugreport.txt";
109e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String ZIP_FILE = "test_bugreport.zip";
110262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    private static final String ZIP_FILE2 = "test_bugreport2.zip";
111a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme    private static final String SCREENSHOT_FILE = "test_screenshot.png";
112e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
113e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String BUGREPORT_CONTENT = "Dump, might as well dump!\n";
114e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String SCREENSHOT_CONTENT = "A picture is worth a thousand words!\n";
115e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
11693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    private static final int PID = 42;
117262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    private static final int PID2 = 24;
11885ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private static final int ID = 108;
119262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    private static final int ID2 = 801;
12085ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private static final String PROGRESS_PROPERTY = "dumpstate." + PID + ".progress";
12185ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private static final String MAX_PROPERTY = "dumpstate." + PID + ".max";
12285ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private static final String NAME_PROPERTY = "dumpstate." + PID + ".name";
12393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    private static final String NAME = "BUG, Y U NO REPORT?";
124262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    private static final String NAME2 = "A bugreport's life";
125bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    private static final String NEW_NAME = "Bug_Forrest_Bug";
126262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    private static final String NEW_NAME2 = "BugsyReportsy";
127bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    private static final String TITLE = "Wimbugdom Champion 2015";
128262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    private static final String TITLE2 = "Master of the Universe";
129262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    private static final String DESCRIPTION = "One's description...";
130262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    private static final String DESCRIPTION2 = "...is another's treasure.";
1314967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
1324967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    private static final String NO_DESCRIPTION = null;
1334967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    private static final String NO_NAME = null;
1344967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    private static final String NO_SCREENSHOT = null;
1354967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    private static final String NO_TITLE = null;
13685ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private static final int NO_ID = 0;
137c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme    private static final boolean RENAMED_SCREENSHOTS = true;
138c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme    private static final boolean DIDNT_RENAME_SCREENSHOTS = false;
1394967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
140bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    private String mDescription;
14193702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
142a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme    private String mPlainTextPath;
143a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme    private String mZipPath;
144262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    private String mZipPath2;
145a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme    private String mScreenshotPath;
146a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme
147e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private Context mContext;
148e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private UiBot mUiBot;
149e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private CustomActionSendMultipleListener mListener;
150e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
151e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    @Override
152e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    protected void setUp() throws Exception {
153c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        Log.i(TAG, "#### setup() on " + getName());
154e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Instrumentation instrumentation = getInstrumentation();
155e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        mContext = instrumentation.getTargetContext();
156e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        mUiBot = new UiBot(UiDevice.getInstance(instrumentation), TIMEOUT);
157e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        mListener = ActionSendMultipleConsumerActivity.getListener(mContext);
15893702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
15993702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        cancelExistingNotifications();
16093702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
161a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        mPlainTextPath = getPath(BUGREPORT_FILE);
162a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        mZipPath = getPath(ZIP_FILE);
163262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        mZipPath2 = getPath(ZIP_FILE2);
164a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        mScreenshotPath = getPath(SCREENSHOT_FILE);
16593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        createTextFile(mPlainTextPath, BUGREPORT_CONTENT);
16693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        createTextFile(mScreenshotPath, SCREENSHOT_CONTENT);
16793702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        createZipFile(mZipPath, BUGREPORT_FILE, BUGREPORT_CONTENT);
168262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        createZipFile(mZipPath2, BUGREPORT_FILE, BUGREPORT_CONTENT);
16993702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
170bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Creates a multi-line description.
171bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        StringBuilder sb = new StringBuilder();
172bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        for (int i = 1; i <= 20; i++) {
173bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            sb.append("All work and no play makes Shell a dull app!\n");
174bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        }
175bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        mDescription = sb.toString();
176bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
177fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme        setWarningState(mContext, STATE_HIDE);
178e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
179e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
180bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    public void testProgress() throws Exception {
18193702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        resetProperties();
18293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        sendBugreportStarted(1000);
1832288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme        waitForScreenshotButtonEnabled(true);
18469c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
1859ca5e5639048375100acd98a40ad82d8b699c575Felipe Leme        assertProgressNotification(NAME, 0f);
18669c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
18793702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        SystemProperties.set(PROGRESS_PROPERTY, "108");
1889ca5e5639048375100acd98a40ad82d8b699c575Felipe Leme        assertProgressNotification(NAME, 10.80f);
18969c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
1909ca5e5639048375100acd98a40ad82d8b699c575Felipe Leme        assertProgressNotification(NAME, 50.00f);
19169c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
1923fc44b9a6274254e8d3a53b6b1e245c5f9177229Felipe Leme        SystemProperties.set(PROGRESS_PROPERTY, "950");
1939ca5e5639048375100acd98a40ad82d8b699c575Felipe Leme        assertProgressNotification(NAME, 95.00f);
1943fc44b9a6274254e8d3a53b6b1e245c5f9177229Felipe Leme
1953fc44b9a6274254e8d3a53b6b1e245c5f9177229Felipe Leme        // Make sure progress never goes back...
19693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        SystemProperties.set(MAX_PROPERTY, "2000");
1973fc44b9a6274254e8d3a53b6b1e245c5f9177229Felipe Leme        Thread.sleep(POLLING_FREQUENCY + DateUtils.SECOND_IN_MILLIS);
1989ca5e5639048375100acd98a40ad82d8b699c575Felipe Leme        assertProgressNotification(NAME, 95.00f);
1993fc44b9a6274254e8d3a53b6b1e245c5f9177229Felipe Leme
2003fc44b9a6274254e8d3a53b6b1e245c5f9177229Felipe Leme        SystemProperties.set(PROGRESS_PROPERTY, "1000");
2019ca5e5639048375100acd98a40ad82d8b699c575Felipe Leme        assertProgressNotification(NAME, 95.00f);
2023fc44b9a6274254e8d3a53b6b1e245c5f9177229Felipe Leme
2033fc44b9a6274254e8d3a53b6b1e245c5f9177229Felipe Leme        // ...only forward...
2043fc44b9a6274254e8d3a53b6b1e245c5f9177229Felipe Leme        SystemProperties.set(PROGRESS_PROPERTY, "1902");
2059ca5e5639048375100acd98a40ad82d8b699c575Felipe Leme        assertProgressNotification(NAME, 95.10f);
2063fc44b9a6274254e8d3a53b6b1e245c5f9177229Felipe Leme
2073fc44b9a6274254e8d3a53b6b1e245c5f9177229Felipe Leme        SystemProperties.set(PROGRESS_PROPERTY, "1960");
2089ca5e5639048375100acd98a40ad82d8b699c575Felipe Leme        assertProgressNotification(NAME, 98.00f);
2093fc44b9a6274254e8d3a53b6b1e245c5f9177229Felipe Leme
2103fc44b9a6274254e8d3a53b6b1e245c5f9177229Felipe Leme        // ...but never more than the capped value.
2113fc44b9a6274254e8d3a53b6b1e245c5f9177229Felipe Leme        SystemProperties.set(PROGRESS_PROPERTY, "2000");
2129ca5e5639048375100acd98a40ad82d8b699c575Felipe Leme        assertProgressNotification(NAME, 99.00f);
2133fc44b9a6274254e8d3a53b6b1e245c5f9177229Felipe Leme
2143fc44b9a6274254e8d3a53b6b1e245c5f9177229Felipe Leme        SystemProperties.set(PROGRESS_PROPERTY, "3000");
2159ca5e5639048375100acd98a40ad82d8b699c575Felipe Leme        assertProgressNotification(NAME, 99.00f);
216719aaae3c167c2b15525dbe5c7db514a2c0c8269Felipe Leme
21793702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        Bundle extras =
21885ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme                sendBugreportFinishedAndGetSharedIntent(ID, mPlainTextPath, mScreenshotPath);
21985ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, ZIP_FILE,
220079f89614c49364bb907783b008827fbc306dd73Felipe Leme                NAME, NO_TITLE, NO_DESCRIPTION, 0, RENAMED_SCREENSHOTS);
221d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
222d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        assertServiceNotRunning();
223d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    }
224d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
225db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme    public void testProgress_cancel() throws Exception {
226db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        resetProperties();
227db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        sendBugreportStarted(1000);
228db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        waitForScreenshotButtonEnabled(true);
229db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme
230db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        final NumberFormat nf = NumberFormat.getPercentInstance();
231db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        nf.setMinimumFractionDigits(2);
232db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        nf.setMaximumFractionDigits(2);
233db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme
2349ca5e5639048375100acd98a40ad82d8b699c575Felipe Leme        assertProgressNotification(NAME, 00.00f);
235db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme
236db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        openProgressNotification(ID);
237db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        UiObject cancelButton = mUiBot.getVisibleObject(mContext.getString(
238db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme                com.android.internal.R.string.cancel).toUpperCase());
239db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        mUiBot.click(cancelButton, "cancel_button");
240db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme
241db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        waitForService(false);
242db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme    }
243db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme
244d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    public void testProgress_takeExtraScreenshot() throws Exception {
245d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        resetProperties();
246d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        sendBugreportStarted(1000);
247d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
248d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        waitForScreenshotButtonEnabled(true);
249d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        takeScreenshot();
250d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        assertScreenshotButtonEnabled(false);
251d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        waitForScreenshotButtonEnabled(true);
252d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
25385ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        sendBugreportFinished(ID, mPlainTextPath, mScreenshotPath);
254c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
25585ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        Bundle extras = acceptBugreportAndGetSharedIntent(ID);
25685ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, ZIP_FILE,
257079f89614c49364bb907783b008827fbc306dd73Felipe Leme                NAME, NO_TITLE, NO_DESCRIPTION, 1, RENAMED_SCREENSHOTS);
25869c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
25993702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        assertServiceNotRunning();
26069c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme    }
26169c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
262c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    public void testScreenshotFinishesAfterBugreport() throws Exception {
263c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        resetProperties();
264c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
265c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        sendBugreportStarted(1000);
266079f89614c49364bb907783b008827fbc306dd73Felipe Leme        waitForScreenshotButtonEnabled(true);
267079f89614c49364bb907783b008827fbc306dd73Felipe Leme        takeScreenshot();
26885ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        sendBugreportFinished(ID, mPlainTextPath, NO_SCREENSHOT);
26985ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        waitShareNotification(ID);
270c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
271c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        // There's no indication in the UI about the screenshot finish, so just sleep like a baby...
272c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        Thread.sleep(SAFE_SCREENSHOT_DELAY * DateUtils.SECOND_IN_MILLIS);
273c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
27485ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        Bundle extras = acceptBugreportAndGetSharedIntent(ID);
27585ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT, ID, PID, ZIP_FILE,
276c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme                NAME, NO_TITLE, NO_DESCRIPTION, 1, RENAMED_SCREENSHOTS);
277c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
278c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        assertServiceNotRunning();
279c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
280c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
2814967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    public void testProgress_changeDetailsInvalidInput() throws Exception {
282bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        resetProperties();
283bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        sendBugreportStarted(1000);
2842288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme        waitForScreenshotButtonEnabled(true);
285bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
28685ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        DetailsUi detailsUi = new DetailsUi(mUiBot, ID);
287bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
288bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Check initial name.
289262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        detailsUi.assertName(NAME);
290bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
291bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Change name - it should have changed system property once focus is changed.
292208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme        detailsUi.focusOnName();
293bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.nameField.setText(NEW_NAME);
294bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.focusAwayFromName();
295bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertPropertyValue(NAME_PROPERTY, NEW_NAME);
296bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
297bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Cancel the dialog to make sure property was restored.
298bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.clickCancel();
299bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertPropertyValue(NAME_PROPERTY, NAME);
300bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
301bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Now try to set an invalid name.
302bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.reOpen();
303bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.nameField.setText("/etc/passwd");
304bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.clickOk();
305bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertPropertyValue(NAME_PROPERTY, "_etc_passwd");
306bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
307bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Finally, make the real changes.
308bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.reOpen();
309bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.nameField.setText(NEW_NAME);
310bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.titleField.setText(TITLE);
311bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.descField.setText(mDescription);
312bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
313bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.clickOk();
314bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
315bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertPropertyValue(NAME_PROPERTY, NEW_NAME);
3169ca5e5639048375100acd98a40ad82d8b699c575Felipe Leme        assertProgressNotification(NEW_NAME, 00.00f);
317bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
31885ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        Bundle extras = sendBugreportFinishedAndGetSharedIntent(ID, mPlainTextPath,
319bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme                mScreenshotPath);
32085ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, TITLE,
321079f89614c49364bb907783b008827fbc306dd73Felipe Leme                NEW_NAME, TITLE, mDescription, 0, RENAMED_SCREENSHOTS);
3224967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
3234967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertServiceNotRunning();
3244967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    }
3254967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
3264967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    public void testProgress_changeDetailsPlainBugreport() throws Exception {
3274967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        changeDetailsTest(true);
3284967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    }
3294967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
3304967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    public void testProgress_changeDetailsZippedBugreport() throws Exception {
3314967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        changeDetailsTest(false);
3324967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    }
3334967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
3344967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme    public void changeDetailsTest(boolean plainText) throws Exception {
3354967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        resetProperties();
3364967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        sendBugreportStarted(1000);
3374967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        waitForScreenshotButtonEnabled(true);
3384967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
33985ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        DetailsUi detailsUi = new DetailsUi(mUiBot, ID);
3404967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
3414967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        // Check initial name.
342262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        detailsUi.assertName(NAME);
3434967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
3444967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        // Change fields.
3454967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        detailsUi.reOpen();
3464967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        detailsUi.nameField.setText(NEW_NAME);
3474967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        detailsUi.titleField.setText(TITLE);
3484967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        detailsUi.descField.setText(mDescription);
3494967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
3504967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        detailsUi.clickOk();
3514967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
3524967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertPropertyValue(NAME_PROPERTY, NEW_NAME);
3539ca5e5639048375100acd98a40ad82d8b699c575Felipe Leme        assertProgressNotification(NEW_NAME, 00.00f);
3544967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme
35585ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        Bundle extras = sendBugreportFinishedAndGetSharedIntent(ID,
3564967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme                plainText? mPlainTextPath : mZipPath, mScreenshotPath);
35785ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, TITLE,
358079f89614c49364bb907783b008827fbc306dd73Felipe Leme                NEW_NAME, TITLE, mDescription, 0, RENAMED_SCREENSHOTS);
359c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme
360c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme        assertServiceNotRunning();
361c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme    }
362c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme
363db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme    public void testProgress_changeJustDetailsTouchingDetails() throws Exception {
364db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        changeJustDetailsTest(true);
365db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme    }
366db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme
367db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme    public void testProgress_changeJustDetailsTouchingNotification() throws Exception {
368db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        changeJustDetailsTest(false);
369db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme    }
370db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme
371db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme    private void changeJustDetailsTest(boolean touchDetails) throws Exception {
372c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme        resetProperties();
373c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme        sendBugreportStarted(1000);
374c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme        waitForScreenshotButtonEnabled(true);
375c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme
376db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        DetailsUi detailsUi = new DetailsUi(mUiBot, ID, touchDetails);
377c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme
378c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme        detailsUi.nameField.setText("");
379c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme        detailsUi.titleField.setText("");
380c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme        detailsUi.descField.setText(mDescription);
381c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme        detailsUi.clickOk();
382c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme
38385ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        Bundle extras = sendBugreportFinishedAndGetSharedIntent(ID, mZipPath, mScreenshotPath);
38485ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, ZIP_FILE,
385079f89614c49364bb907783b008827fbc306dd73Felipe Leme                NO_NAME, NO_TITLE, mDescription, 0, DIDNT_RENAME_SCREENSHOTS);
386bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
387bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertServiceNotRunning();
388bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    }
389bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
390262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    /*
391262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme     * TODO: this test can be flanky because it relies in the order the notifications are displayed,
392262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme     * since mUiBot gets the first notification.
393262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme     * Ideally, openProgressNotification() should return the whole notification, so DetailsUi
394262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme     * could use it and find children instead, but unfortunately the notification object hierarchy
395262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme     * is too complex and getting it from the notification text object would be to fragile
396262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme     * (for instance, it could require navigating many parents up in the hierarchy).
397262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme     */
398262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    public void testProgress_changeJustDetailsIsClearedOnSecondBugreport() throws Exception {
399262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        resetProperties();
400262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        sendBugreportStarted(ID, PID, NAME, 1000);
401262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        waitForScreenshotButtonEnabled(true);
402262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme
403262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        DetailsUi detailsUi = new DetailsUi(mUiBot, ID);
404262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        detailsUi.assertName(NAME);
405bbd91e58444f092e1080f5a0a746fcd4b21ce113Felipe Leme        detailsUi.assertTitle("");
406bbd91e58444f092e1080f5a0a746fcd4b21ce113Felipe Leme        detailsUi.assertDescription("");
407262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        detailsUi.nameField.setText(NEW_NAME);
408262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        detailsUi.titleField.setText(TITLE);
409262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        detailsUi.descField.setText(DESCRIPTION);
410262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        detailsUi.clickOk();
411262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme
412262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        sendBugreportStarted(ID2, PID2, NAME2, 1000);
413262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme
4145ee846dd18022307341c9808c9aacded2b2f60fdFelipe Leme        sendBugreportFinished(ID, mZipPath, mScreenshotPath);
415a43d139359346ad57604e8335d92de57f3d47171Felipe Leme        Bundle extras = acceptBugreportAndGetSharedIntent(ID);
416262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme
417262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        detailsUi = new DetailsUi(mUiBot, ID2);
418262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        detailsUi.assertName(NAME2);
419bbd91e58444f092e1080f5a0a746fcd4b21ce113Felipe Leme        detailsUi.assertTitle("");
420bbd91e58444f092e1080f5a0a746fcd4b21ce113Felipe Leme        detailsUi.assertDescription("");
421262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        detailsUi.nameField.setText(NEW_NAME2);
422262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        detailsUi.titleField.setText(TITLE2);
423262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        detailsUi.descField.setText(DESCRIPTION2);
424262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        detailsUi.clickOk();
425262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme
426262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        // Must use a different zip file otherwise it will fail because zip already contains
427262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        // title.txt and description.txt entries.
428262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        extras = sendBugreportFinishedAndGetSharedIntent(ID2, mZipPath2, NO_SCREENSHOT);
429262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT, ID2, PID2, TITLE2,
430079f89614c49364bb907783b008827fbc306dd73Felipe Leme                NEW_NAME2, TITLE2, DESCRIPTION2, 0, RENAMED_SCREENSHOTS);
431262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme
432262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        assertServiceNotRunning();
433262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    }
434262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme
4352288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme    /**
4362288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme     * Tests the scenario where the initial screenshot and dumpstate are finished while the user
4372288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme     * is changing the info in the details screen.
4382288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme     */
4392288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme    public void testProgress_bugreportAndScreenshotFinishedWhileChangingDetails() throws Exception {
4402288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme        bugreportFinishedWhileChangingDetailsTest(false);
4412288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme    }
4422288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme
4432288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme    /**
4442288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme     * Tests the scenario where dumpstate is finished while the user is changing the info in the
4452288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme     * details screen, but the initial screenshot finishes afterwards.
4462288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme     */
447bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    public void testProgress_bugreportFinishedWhileChangingDetails() throws Exception {
4482288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme        bugreportFinishedWhileChangingDetailsTest(true);
4492288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme    }
4502288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme
4512288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme    private void bugreportFinishedWhileChangingDetailsTest(boolean waitScreenshot) throws Exception {
452bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        resetProperties();
453bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        sendBugreportStarted(1000);
4542288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme        if (waitScreenshot) {
4552288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme            waitForScreenshotButtonEnabled(true);
4562288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme        }
457bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
45885ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        DetailsUi detailsUi = new DetailsUi(mUiBot, ID);
459bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
460bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Finish the bugreport while user's still typing the name.
461bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.nameField.setText(NEW_NAME);
46285ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        sendBugreportFinished(ID, mPlainTextPath, mScreenshotPath);
463bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
4642288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme        // Wait until the share notification is received...
46585ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        waitShareNotification(ID);
466bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // ...then close notification bar.
467bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
468bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
469bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Make sure UI was updated properly.
470bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertFalse("didn't disable name on UI", detailsUi.nameField.isEnabled());
471bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertEquals("didn't revert name on UI", NAME, detailsUi.nameField.getText().toString());
472bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
473bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Finish changing other fields.
474bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.titleField.setText(TITLE);
475bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.descField.setText(mDescription);
476bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        detailsUi.clickOk();
477bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
478bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        // Finally, share bugreport.
47985ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        Bundle extras = acceptBugreportAndGetSharedIntent(ID);
48085ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, TITLE,
481079f89614c49364bb907783b008827fbc306dd73Felipe Leme                NAME, TITLE, mDescription, 0, RENAMED_SCREENSHOTS);
482bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
483bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertServiceNotRunning();
484bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    }
485bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
486fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme    public void testBugreportFinished_withWarningFirstTime() throws Exception {
487fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme        bugreportFinishedWithWarningTest(null);
488fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme    }
489fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme
490fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme    public void testBugreportFinished_withWarningUnknownState() throws Exception {
491fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme        bugreportFinishedWithWarningTest(STATE_UNKNOWN);
492fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme    }
493fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme
494fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme    public void testBugreportFinished_withWarningShowAgain() throws Exception {
495fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme        bugreportFinishedWithWarningTest(STATE_SHOW);
496fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme    }
497fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme
498fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme    private void bugreportFinishedWithWarningTest(Integer propertyState) throws Exception {
499fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme        if (propertyState == null) {
500fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme            // Clear properties
501fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme            mContext.getSharedPreferences(PREFS_BUGREPORT, Context.MODE_PRIVATE)
502fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme                    .edit().clear().commit();
503fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme            // Sanity check...
504fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme            assertEquals("Did not reset properties", STATE_UNKNOWN,
505fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme                    getWarningState(mContext, STATE_UNKNOWN));
506fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme        } else {
507fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme            setWarningState(mContext, propertyState);
508fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme        }
5096bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
5106bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Send notification and click on share.
51185ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        sendBugreportFinished(NO_ID, mPlainTextPath, null);
51285ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        acceptBugreport(NO_ID);
5136bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
5146bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Handle the warning
5156bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        mUiBot.getVisibleObject(mContext.getString(R.string.bugreport_confirm));
516fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme        // TODO: get ok and dontShowAgain from the dialog reference above
517fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme        UiObject dontShowAgain =
518fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme                mUiBot.getVisibleObject(mContext.getString(R.string.bugreport_confirm_dont_repeat));
519fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme        final boolean firstTime = propertyState == null || propertyState == STATE_UNKNOWN;
520fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme        if (firstTime) {
521af096719c0e45a2b7d67e9267b40cffdc16f441aFelipe Leme            if (Build.TYPE.equals("user")) {
522af096719c0e45a2b7d67e9267b40cffdc16f441aFelipe Leme                assertFalse("Checkbox should NOT be checked by default on user builds",
523af096719c0e45a2b7d67e9267b40cffdc16f441aFelipe Leme                        dontShowAgain.isChecked());
524af096719c0e45a2b7d67e9267b40cffdc16f441aFelipe Leme                mUiBot.click(dontShowAgain, "dont-show-again");
525af096719c0e45a2b7d67e9267b40cffdc16f441aFelipe Leme            } else {
526af096719c0e45a2b7d67e9267b40cffdc16f441aFelipe Leme                assertTrue("Checkbox should be checked by default on build type " + Build.TYPE,
527af096719c0e45a2b7d67e9267b40cffdc16f441aFelipe Leme                        dontShowAgain.isChecked());
528af096719c0e45a2b7d67e9267b40cffdc16f441aFelipe Leme            }
529fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme        } else {
530fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme            assertFalse("Checkbox should not be checked", dontShowAgain.isChecked());
531fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme            mUiBot.click(dontShowAgain, "dont-show-again");
532fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme        }
5336bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        UiObject ok = mUiBot.getVisibleObject(mContext.getString(com.android.internal.R.string.ok));
5346bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        mUiBot.click(ok, "ok");
5356bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
5366bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Share the bugreport.
5376bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        mUiBot.chooseActivity(UI_NAME);
5386bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        Bundle extras = mListener.getExtras();
5394967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
5406bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
5416bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Make sure it's hidden now.
542fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme        int newState = getWarningState(mContext, STATE_UNKNOWN);
543fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme        assertEquals("Didn't change state", STATE_HIDE, newState);
5446bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme    }
5456bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
546c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    public void testShareBugreportAfterServiceDies() throws Exception {
54785ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        sendBugreportFinished(NO_ID, mPlainTextPath, NO_SCREENSHOT);
54869c53e65b941235a8d2e193d5b9a783f7787af0dFelipe Leme        waitForService(false);
54985ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        Bundle extras = acceptBugreportAndGetSharedIntent(NO_ID);
550c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
551c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
552c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
553e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    public void testBugreportFinished_plainBugreportAndScreenshot() throws Exception {
55493702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        Bundle extras = sendBugreportFinishedAndGetSharedIntent(mPlainTextPath, mScreenshotPath);
555e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);
556e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
557e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
558e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    public void testBugreportFinished_zippedBugreportAndScreenshot() throws Exception {
55993702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        Bundle extras = sendBugreportFinishedAndGetSharedIntent(mZipPath, mScreenshotPath);
560e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);
561e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
562e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
563e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    public void testBugreportFinished_plainBugreportAndNoScreenshot() throws Exception {
5644967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        Bundle extras = sendBugreportFinishedAndGetSharedIntent(mPlainTextPath, NO_SCREENSHOT);
5654967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
566e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
567e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
568e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    public void testBugreportFinished_zippedBugreportAndNoScreenshot() throws Exception {
5694967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        Bundle extras = sendBugreportFinishedAndGetSharedIntent(mZipPath, NO_SCREENSHOT);
5704967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
571e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
572e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
573e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void cancelExistingNotifications() {
574e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        NotificationManager nm = NotificationManager.from(mContext);
575e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        for (StatusBarNotification notification : nm.getActiveNotifications()) {
576e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            int id = notification.getId();
577e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            Log.i(TAG, "Canceling existing notification (id=" + id + ")");
578e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            nm.cancel(id);
579e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
580e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
581e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
5829ca5e5639048375100acd98a40ad82d8b699c575Felipe Leme    private void assertProgressNotification(String name, float percent) {
583d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        // TODO: it currently looks for 3 distinct objects, without taking advantage of their
58469c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        // relationship.
58585ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        openProgressNotification(ID);
58669c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        Log.v(TAG, "Looking for progress notification details: '" + name + "-" + percent + "'");
58769c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        mUiBot.getObject(name);
5889ca5e5639048375100acd98a40ad82d8b699c575Felipe Leme        // TODO: need a way to get the ProgresBar from the "android:id/progress" UIObject...
58969c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme    }
59069c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
591db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme    private UiObject openProgressNotification(int id) {
59285ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        String title = mContext.getString(R.string.bugreport_in_progress_title, id);
593bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        Log.v(TAG, "Looking for progress notification title: '" + title + "'");
594db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        return mUiBot.getNotification(title);
595bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    }
596bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
59793702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    void resetProperties() {
59893702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        // TODO: call method to remove property instead
59985ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        SystemProperties.set(PROGRESS_PROPERTY, "Reset");
60085ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        SystemProperties.set(MAX_PROPERTY, "Reset");
60185ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        SystemProperties.set(NAME_PROPERTY, "Reset");
60293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    }
60393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
60493702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    /**
60593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * Sends a "bugreport started" intent with the default values.
60693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     */
607d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    private void sendBugreportStarted(int max) throws Exception {
608262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        sendBugreportStarted(ID, PID, NAME, max);
609262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    }
610262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme
611262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    private void sendBugreportStarted(int id, int pid, String name, int max) throws Exception {
61293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        Intent intent = new Intent(INTENT_BUGREPORT_STARTED);
613ec17538d46a49530ed6efdc2842ee16eaf18b9f6Felipe Leme        intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
614262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        intent.putExtra(EXTRA_ID, id);
615262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        intent.putExtra(EXTRA_PID, pid);
616262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        intent.putExtra(EXTRA_NAME, name);
61793702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        intent.putExtra(EXTRA_MAX, max);
61893702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        mContext.sendBroadcast(intent);
61993702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    }
62093702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
621e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    /**
622e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme     * Sends a "bugreport finished" intent and waits for the result.
623e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme     *
62493702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * @return extras sent in the shared intent.
625e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme     */
62693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    private Bundle sendBugreportFinishedAndGetSharedIntent(String bugreportPath,
62793702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme            String screenshotPath) {
62885ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        return sendBugreportFinishedAndGetSharedIntent(NO_ID, bugreportPath, screenshotPath);
62969c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme    }
63069c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
63193702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    /**
63293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * Sends a "bugreport finished" intent and waits for the result.
63393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     *
63493702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * @return extras sent in the shared intent.
63593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     */
63685ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private Bundle sendBugreportFinishedAndGetSharedIntent(int id, String bugreportPath,
63769c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme            String screenshotPath) {
63885ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        sendBugreportFinished(id, bugreportPath, screenshotPath);
639a43d139359346ad57604e8335d92de57f3d47171Felipe Leme        return acceptBugreportAndGetSharedIntent(id);
64093702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    }
64193702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
64293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    /**
64393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * Accepts the notification to share the finished bugreport and waits for the result.
64493702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     *
64593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * @return extras sent in the shared intent.
64693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     */
64785ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private Bundle acceptBugreportAndGetSharedIntent(int id) {
648a43d139359346ad57604e8335d92de57f3d47171Felipe Leme        acceptBugreport(id);
64993702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        mUiBot.chooseActivity(UI_NAME);
65093702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        return mListener.getExtras();
65193702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    }
65293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
65393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    /**
654c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme     * Waits for the notification to share the finished bugreport.
655c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme     */
65685ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private void waitShareNotification(int id) {
65785ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        mUiBot.getNotification(mContext.getString(R.string.bugreport_finished_title, id));
658c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
659c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
660c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    /**
66193702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * Accepts the notification to share the finished bugreport.
66293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     */
66385ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private void acceptBugreport(int id) {
664a43d139359346ad57604e8335d92de57f3d47171Felipe Leme        mUiBot.clickOnNotification(mContext.getString(R.string.bugreport_finished_title, id));
66593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    }
66693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
66793702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    /**
66893702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     * Sends a "bugreport finished" intent.
66993702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme     */
67085ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme    private void sendBugreportFinished(int id, String bugreportPath, String screenshotPath) {
67169c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        Intent intent = new Intent(INTENT_BUGREPORT_FINISHED);
672ec17538d46a49530ed6efdc2842ee16eaf18b9f6Felipe Leme        intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
67385ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        if (id != NO_ID) {
67485ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme            intent.putExtra(EXTRA_ID, id);
67569c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        }
676e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        if (bugreportPath != null) {
677e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            intent.putExtra(EXTRA_BUGREPORT, bugreportPath);
678e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
679e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        if (screenshotPath != null) {
680e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            intent.putExtra(EXTRA_SCREENSHOT, screenshotPath);
681e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
682e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
683e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        mContext.sendBroadcast(intent);
684e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
685e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
686e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    /**
687d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * Asserts the proper {@link Intent#ACTION_SEND_MULTIPLE} intent was sent.
688e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme     */
689e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void assertActionSendMultiple(Bundle extras, String bugreportContent,
690e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            String screenshotContent) throws IOException {
69185ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        assertActionSendMultiple(extras, bugreportContent, screenshotContent, ID, PID, ZIP_FILE,
692c8e2b6092c0fbf87e71f81fd2cffbb29ff8d9039Felipe Leme                NO_NAME, NO_TITLE, NO_DESCRIPTION, 0, DIDNT_RENAME_SCREENSHOTS);
693bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    }
694bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
695d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    /**
696d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * Asserts the proper {@link Intent#ACTION_SEND_MULTIPLE} intent was sent.
697d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     *
698d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * @param extras extras received in the intent
699d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * @param bugreportContent expected content in the bugreport file
700d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * @param screenshotContent expected content in the screenshot file (sent by dumpstate), if any
70185ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme     * @param id emulated dumpstate id
702d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * @param pid emulated dumpstate pid
7034967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme     * @param name expected subject
7044967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme     * @param name bugreport name as provided by the user (or received by dumpstate)
7054967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme     * @param title bugreport name as provided by the user
706d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * @param description bugreport description as provided by the user
707d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * @param numberScreenshots expected number of screenshots taken by Shell.
7082288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme     * @param renamedScreenshots whether the screenshots are expected to be renamed
709d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     */
710d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    private void assertActionSendMultiple(Bundle extras, String bugreportContent,
71185ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme            String screenshotContent, int id, int pid, String subject,
7124967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme            String name, String title, String description,
7132288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme            int numberScreenshots, boolean renamedScreenshots) throws IOException {
714e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        String body = extras.getString(Intent.EXTRA_TEXT);
715e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertContainsRegex("missing build info",
716e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                SystemProperties.get("ro.build.description"), body);
717e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertContainsRegex("missing serial number",
718e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                SystemProperties.get("ro.serialno"), body);
719bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        if (description != null) {
720bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            assertContainsRegex("missing description", description, body);
721bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        }
722e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
7234967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        assertEquals("wrong subject", subject, extras.getString(Intent.EXTRA_SUBJECT));
724e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
725e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        List<Uri> attachments = extras.getParcelableArrayList(Intent.EXTRA_STREAM);
726d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        int expectedNumberScreenshots = numberScreenshots;
727d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        if (screenshotContent != null) {
728d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            expectedNumberScreenshots ++; // Add screenshot received by dumpstate
729d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        }
730d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        int expectedSize = expectedNumberScreenshots + 1; // All screenshots plus the bugreport file
731c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        assertEquals("wrong number of attachments (" + attachments + ")",
732c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme                expectedSize, attachments.size());
733e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
734e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        // Need to interact through all attachments, since order is not guaranteed.
735d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        Uri zipUri = null;
736d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        List<Uri> screenshotUris = new ArrayList<>(expectedNumberScreenshots);
737e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        for (Uri attachment : attachments) {
738e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            if (attachment.getPath().endsWith(".zip")) {
739e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                zipUri = attachment;
740e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            }
741e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            if (attachment.getPath().endsWith(".png")) {
742d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                screenshotUris.add(attachment);
743e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            }
744e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
745e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertNotNull("did not get .zip attachment", zipUri);
746e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertZipContent(zipUri, BUGREPORT_FILE, BUGREPORT_CONTENT);
7474967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        if (!TextUtils.isEmpty(title)) {
7484967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme            assertZipContent(zipUri, "title.txt", title);
7494967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        }
7504967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        if (!TextUtils.isEmpty(description)) {
7514967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme            assertZipContent(zipUri, "description.txt", description);
7524967f737d9906e3d5c9bf3a0584a7b7cf83b5a8cFelipe Leme        }
753e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
754d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        // URI of the screenshot taken by dumpstate.
755d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        Uri externalScreenshotUri = null;
756d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        SortedSet<String> internalScreenshotNames = new TreeSet<>();
757d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        for (Uri screenshotUri : screenshotUris) {
758d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            String screenshotName = screenshotUri.getLastPathSegment();
759d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            if (screenshotName.endsWith(SCREENSHOT_FILE)) {
760d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                externalScreenshotUri = screenshotUri;
761d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            } else {
762d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                internalScreenshotNames.add(screenshotName);
763d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            }
764d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        }
765d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        // Check external screenshot
766e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        if (screenshotContent != null) {
767d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            assertNotNull("did not get .png attachment for external screenshot",
768d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                    externalScreenshotUri);
769d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            assertContent(externalScreenshotUri, SCREENSHOT_CONTENT);
770e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        } else {
771d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            assertNull("should not have .png attachment for external screenshot",
772d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                    externalScreenshotUri);
773d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        }
774d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        // Check internal screenshots.
775d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        SortedSet<String> expectedNames = new TreeSet<>();
776d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        for (int i = 1 ; i <= numberScreenshots; i++) {
7772288129d5208cd26ab41191db69a418d15ead9eeFelipe Leme            String prefix = renamedScreenshots  ? name : Integer.toString(pid);
778d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            String expectedName = "screenshot-" + prefix + "-" + i + ".png";
779d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            expectedNames.add(expectedName);
780e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
781d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        // Ideally we should use MoreAsserts, but the error message in case of failure is not
782d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        // really useful.
783d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        assertEquals("wrong names for internal screenshots",
784d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                expectedNames, internalScreenshotNames);
785e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
786e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
787e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void assertContent(Uri uri, String expectedContent) throws IOException {
788e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Log.v(TAG, "assertContents(uri=" + uri);
789e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        try (InputStream is = mContext.getContentResolver().openInputStream(uri)) {
790e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            String actualContent = new String(Streams.readFully(is));
791e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            assertEquals("wrong content for '" + uri + "'", expectedContent, actualContent);
792e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
793e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
794e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
795e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void assertZipContent(Uri uri, String entryName, String expectedContent)
796e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            throws IOException, IOException {
797e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Log.v(TAG, "assertZipEntry(uri=" + uri + ", entryName=" + entryName);
798e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        try (ZipInputStream zis = new ZipInputStream(mContext.getContentResolver().openInputStream(
799e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                uri))) {
800e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            ZipEntry entry;
801e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            while ((entry = zis.getNextEntry()) != null) {
802e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                Log.v(TAG, "Zip entry: " + entry.getName());
803e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                if (entry.getName().equals(entryName)) {
804e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
805e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    Streams.copy(zis, bos);
806e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    String actualContent = new String(bos.toByteArray(), "UTF-8");
807e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    bos.close();
808e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    assertEquals("wrong content for zip entry'" + entryName + "' on '" + uri + "'",
809e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                            expectedContent, actualContent);
810e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    return;
811e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                }
812e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            }
813e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
814e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        fail("Did not find entry '" + entryName + "' on file '" + uri + "'");
815e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
816e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
817bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    private void assertPropertyValue(String key, String expectedValue) {
818bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        String actualValue = SystemProperties.get(key);
819bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        assertEquals("Wrong value for property '" + key + "'", expectedValue, actualValue);
820bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    }
821bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
82293702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    private void assertServiceNotRunning() {
82393702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        String service = BugreportProgressService.class.getName();
82493702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme        assertFalse("Service '" + service + "' is still running", isServiceRunning(service));
82593702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme    }
82693702abf6e9a87079e81c46c82d8c3954a426759Felipe Leme
827ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme    private boolean isServiceRunning(String name) {
828ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme        ActivityManager manager = (ActivityManager) mContext
829ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme                .getSystemService(Context.ACTIVITY_SERVICE);
830ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme        for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
831ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme            if (service.service.getClassName().equals(name)) {
832ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme                return true;
833ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme            }
834ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme        }
835ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme        return false;
836ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme    }
837ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme
838c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    private void waitForService(boolean expectRunning) {
839c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        String service = BugreportProgressService.class.getName();
840c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        boolean actualRunning;
841c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        for (int i = 1; i <= 5; i++) {
842c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            actualRunning = isServiceRunning(service);
843c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            Log.d(TAG, "Attempt " + i + " to check status of service '"
844c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme                    + service + "': expected=" + expectRunning + ", actual= " + actualRunning);
845c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            if (actualRunning == expectRunning) {
846c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme                return;
847c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            }
848c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            try {
849c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme                Thread.sleep(DateUtils.SECOND_IN_MILLIS);
850c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            } catch (InterruptedException e) {
851c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme                Log.w(TAG, "thread interrupted");
852c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme                Thread.currentThread().interrupt();
853c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme            }
854c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        }
855c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
856c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        fail("Service status didn't change to " + expectRunning);
857c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme    }
858c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme
859262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme    private void createTextFile(String path, String content) throws IOException {
860e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Log.v(TAG, "createFile(" + path + ")");
861e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        try (Writer writer = new BufferedWriter(new OutputStreamWriter(
862e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                new FileOutputStream(path)))) {
863e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            writer.write(content);
864e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
865e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
866e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
867e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void createZipFile(String path, String entryName, String content) throws IOException {
868e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Log.v(TAG, "createZipFile(" + path + ", " + entryName + ")");
869e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        try (ZipOutputStream zos = new ZipOutputStream(
870e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                new BufferedOutputStream(new FileOutputStream(path)))) {
871e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            ZipEntry entry = new ZipEntry(entryName);
872e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            zos.putNextEntry(entry);
873e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            byte[] data = content.getBytes();
874e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            zos.write(data, 0, data.length);
875e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            zos.closeEntry();
876e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
877e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
878a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme
879a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme    private String getPath(String file) {
880fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme        final File rootDir = mContext.getFilesDir();
881fcca68dfb137c061952d23e1873e995e6bcf172dFelipe Leme        final File dir = new File(rootDir, BUGREPORTS_DIR);
882e2b4f49795b4f23fa563a0ffb9986b49aee7f9beFelipe Leme        if (!dir.exists()) {
883e2b4f49795b4f23fa563a0ffb9986b49aee7f9beFelipe Leme            Log.i(TAG, "Creating directory " + dir);
884e2b4f49795b4f23fa563a0ffb9986b49aee7f9beFelipe Leme            assertTrue("Could not create directory " + dir, dir.mkdir());
885e2b4f49795b4f23fa563a0ffb9986b49aee7f9beFelipe Leme        }
886a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        String path = new File(dir, file).getAbsolutePath();
887a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        Log.v(TAG, "Path for '" + file + "': " + path);
888a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme        return path;
889a0bf0336f0b6ff39cd90aabe0eb48b022d008ed6Felipe Leme    }
890bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
891bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    /**
892d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * Gets the notification button used to take a screenshot.
893d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     */
894d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    private UiObject getScreenshotButton() {
89585ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        openProgressNotification(ID);
896d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        return mUiBot.getVisibleObject(
897d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                mContext.getString(R.string.bugreport_screenshot_action).toUpperCase());
898d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    }
899d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
900d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    /**
901d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     * Takes a screenshot using the system notification.
902d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme     */
903d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    private void takeScreenshot() throws Exception {
904d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        UiObject screenshotButton = getScreenshotButton();
905d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        mUiBot.click(screenshotButton, "screenshot_button");
906d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    }
907d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
908d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    private UiObject waitForScreenshotButtonEnabled(boolean expectedEnabled) throws Exception {
909d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        UiObject screenshotButton = getScreenshotButton();
910c4f6467702e308844ef0769ba17dcb7b7b32a9e6Felipe Leme        int maxAttempts = SAFE_SCREENSHOT_DELAY;
911d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        int i = 0;
912d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        do {
913d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            boolean enabled = screenshotButton.isEnabled();
914d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            if (enabled == expectedEnabled) {
915d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                return screenshotButton;
916d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            }
917d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            i++;
918d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            Log.v(TAG, "Sleeping for 1 second while waiting for screenshot.enable to be "
919d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                    + expectedEnabled + " (attempt " + i + ")");
920d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme            Thread.sleep(DateUtils.SECOND_IN_MILLIS);
921d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        } while (i <= maxAttempts);
922d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        fail("screenshot.enable didn't change to " + expectedEnabled + " in " + maxAttempts + "s");
923d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        return screenshotButton;
924d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    }
925d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
926d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    private void assertScreenshotButtonEnabled(boolean expectedEnabled) throws Exception {
927d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        UiObject screenshotButton = getScreenshotButton();
928d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme        assertEquals("wrong state for screenshot button ", expectedEnabled,
929d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme                screenshotButton.isEnabled());
930d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    }
931d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme
932d1e0f12979441733753b538611f6d73e5527c43cFelipe Leme    /**
933bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme     * Helper class containing the UiObjects present in the bugreport info dialog.
934bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme     */
935bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    private final class DetailsUi {
936bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
937bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        final UiObject detailsButton;
938bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        final UiObject nameField;
939bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        final UiObject titleField;
940bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        final UiObject descField;
941bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        final UiObject okButton;
942bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        final UiObject cancelButton;
943bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
944bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        /**
945bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme         * Gets the UI objects by opening the progress notification and clicking DETAILS.
946bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme         */
94785ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme        DetailsUi(UiBot uiBot, int id) throws UiObjectNotFoundException {
948db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme            this(uiBot, id, true);
949db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        }
950db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme
951db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        /**
952db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme         * Gets the UI objects by opening the progress notification and clicking on DETAILS or in
953db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme         * the notification itself.
954db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme         */
955db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme        DetailsUi(UiBot uiBot, int id, boolean clickDetails) throws UiObjectNotFoundException {
956db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme            UiObject notification = openProgressNotification(id);
957262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme            detailsButton = mUiBot.getVisibleObject(mContext.getString(
958262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme                    R.string.bugreport_info_action).toUpperCase());
959262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme
960db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme            if (clickDetails) {
961db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme                mUiBot.click(detailsButton, "details_button");
962db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme            } else {
963db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme                mUiBot.click(notification, "notification");
964db31363aa9670dbbc5837af7a04bdd8012493fd7Felipe Leme            }
965bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            // TODO: unhardcode resource ids
966e86b63bd17da3d347b9392f897e361919655edd6Felipe Leme            UiObject dialogTitle = mUiBot.getVisibleObjectById("android:id/alertTitle");
967e86b63bd17da3d347b9392f897e361919655edd6Felipe Leme            assertEquals("Wrong title", mContext.getString(R.string.bugreport_info_dialog_title,
96885ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme                    id), dialogTitle.getText().toString());
969bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            nameField = mUiBot.getVisibleObjectById("com.android.shell:id/name");
970bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            titleField = mUiBot.getVisibleObjectById("com.android.shell:id/title");
971bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            descField = mUiBot.getVisibleObjectById("com.android.shell:id/description");
972bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            okButton = mUiBot.getObjectById("android:id/button1");
973bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            cancelButton = mUiBot.getObjectById("android:id/button2");
974bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        }
975bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
976208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme        private void assertField(String name, UiObject field, String expected)
977208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme                throws UiObjectNotFoundException {
978208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme            String actual = field.getText().toString();
979208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme            assertEquals("Wrong value on field '" + name + "'", expected, actual);
980262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        }
981262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme
982208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme        void assertName(String expected) throws UiObjectNotFoundException {
983262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme            assertField("name", nameField, expected);
984262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        }
985262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme
986208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme        void assertTitle(String expected) throws UiObjectNotFoundException {
987262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme            assertField("title", titleField, expected);
988262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        }
989262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme
990208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme        void assertDescription(String expected) throws UiObjectNotFoundException {
991262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme            assertField("description", descField, expected);
992262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme        }
993262887834c7938b7a7bbbd7ef026b5965d6412fcFelipe Leme
994bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        /**
995208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme         * Set focus on the name field so it can be validated once focus is lost.
996208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme         */
997208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme        void focusOnName() throws UiObjectNotFoundException {
998208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme            mUiBot.click(nameField, "name_field");
999208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme            assertTrue("name_field not focused", nameField.isFocused());
1000208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme        }
1001208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme
1002208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme        /**
1003bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme         * Takes focus away from the name field so it can be validated.
1004bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme         */
1005208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme        void focusAwayFromName() throws UiObjectNotFoundException {
1006bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            mUiBot.click(titleField, "title_field"); // Change focus.
1007bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            mUiBot.pressBack(); // Dismiss keyboard.
1008208b1881ae924cd0c2bed326555e4aa18424d927Felipe Leme            assertFalse("name_field is focused", nameField.isFocused());
1009bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        }
1010bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
1011bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        void reOpen() {
101285ae3cf46ad66d71e5a29a93e89a0f569d74288bFelipe Leme            openProgressNotification(ID);
1013bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            mUiBot.click(detailsButton, "details_button");
1014bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        }
1015bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
1016bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        void clickOk() {
1017bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            mUiBot.click(okButton, "details_ok_button");
1018bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        }
1019bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme
1020bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        void clickCancel() {
1021bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme            mUiBot.click(cancelButton, "details_cancel_button");
1022bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme        }
1023bc73ffc06fd2b5b30802cc7e8874a986626b897dFelipe Leme    }
1024e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme}
1025