blob: 3a71632cf1cafde1d29adac21feb55ac049b4c3b [file] [log] [blame]
Felipe Lemee53e85f2015-11-17 17:37:53 -08001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.shell;
18
19import static android.test.MoreAsserts.assertContainsRegex;
Felipe Lemefcca68d2016-04-12 14:00:07 -070020
Felipe Lemee53e85f2015-11-17 17:37:53 -080021import static com.android.shell.ActionSendMultipleConsumerActivity.UI_NAME;
Felipe Lemefcca68d2016-04-12 14:00:07 -070022import static com.android.shell.BugreportPrefs.PREFS_BUGREPORT;
23import static com.android.shell.BugreportPrefs.STATE_HIDE;
24import static com.android.shell.BugreportPrefs.STATE_SHOW;
25import static com.android.shell.BugreportPrefs.STATE_UNKNOWN;
26import static com.android.shell.BugreportPrefs.getWarningState;
27import static com.android.shell.BugreportPrefs.setWarningState;
Felipe Lemeb9238b32015-11-24 17:31:47 -080028import static com.android.shell.BugreportProgressService.EXTRA_BUGREPORT;
Felipe Leme85ae3cf2016-02-24 15:36:50 -080029import static com.android.shell.BugreportProgressService.EXTRA_ID;
Felipe Leme69c02922015-11-24 17:48:05 -080030import static com.android.shell.BugreportProgressService.EXTRA_MAX;
31import static com.android.shell.BugreportProgressService.EXTRA_NAME;
32import static com.android.shell.BugreportProgressService.EXTRA_PID;
Felipe Lemeb9238b32015-11-24 17:31:47 -080033import static com.android.shell.BugreportProgressService.EXTRA_SCREENSHOT;
Felipe Leme69c02922015-11-24 17:48:05 -080034import static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_FINISHED;
35import static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_STARTED;
Felipe Lemed1e0f122015-12-18 16:12:41 -080036import static com.android.shell.BugreportProgressService.SCREENSHOT_DELAY_SECONDS;
Felipe Lemee53e85f2015-11-17 17:37:53 -080037
Felipe Leme47ec8be2016-08-12 15:55:17 -070038import static org.junit.Assert.assertEquals;
39import static org.junit.Assert.assertFalse;
40import static org.junit.Assert.assertNotNull;
41import static org.junit.Assert.assertNull;
42import static org.junit.Assert.assertTrue;
43import static org.junit.Assert.fail;
44
KOUSHIK PANUGANTI390f4c02019-03-13 16:53:33 -070045import android.app.ActivityManager;
46import android.app.ActivityManager.RunningServiceInfo;
47import android.app.Instrumentation;
48import android.app.NotificationManager;
49import android.content.Context;
50import android.content.Intent;
51import android.net.Uri;
52import android.os.Build;
53import android.os.Bundle;
54import android.os.SystemClock;
55import android.os.SystemProperties;
56import android.service.notification.StatusBarNotification;
57import android.support.test.uiautomator.UiDevice;
58import android.support.test.uiautomator.UiObject;
59import android.support.test.uiautomator.UiObjectNotFoundException;
60import android.text.TextUtils;
61import android.text.format.DateUtils;
62import android.util.Log;
63
64import androidx.test.InstrumentationRegistry;
65import androidx.test.filters.LargeTest;
66import androidx.test.runner.AndroidJUnit4;
67
68import com.android.shell.ActionSendMultipleConsumerActivity.CustomActionSendMultipleListener;
69
70import libcore.io.Streams;
71
72import org.junit.After;
73import org.junit.Before;
74import org.junit.Rule;
75import org.junit.Test;
76import org.junit.rules.TestName;
77import org.junit.runner.RunWith;
78
Felipe Lemee53e85f2015-11-17 17:37:53 -080079import java.io.BufferedOutputStream;
80import java.io.BufferedWriter;
81import java.io.ByteArrayOutputStream;
Felipe Lemea0bf0332015-12-11 09:35:03 -080082import java.io.File;
Felipe Lemee53e85f2015-11-17 17:37:53 -080083import java.io.FileOutputStream;
84import java.io.IOException;
85import java.io.InputStream;
86import java.io.OutputStreamWriter;
87import java.io.Writer;
Felipe Lemee86b63b2016-02-08 09:39:50 -080088import java.text.NumberFormat;
Felipe Lemed1e0f122015-12-18 16:12:41 -080089import java.util.ArrayList;
Felipe Lemee53e85f2015-11-17 17:37:53 -080090import java.util.List;
Felipe Lemed1e0f122015-12-18 16:12:41 -080091import java.util.SortedSet;
92import java.util.TreeSet;
Felipe Lemee53e85f2015-11-17 17:37:53 -080093import java.util.zip.ZipEntry;
94import java.util.zip.ZipInputStream;
95import java.util.zip.ZipOutputStream;
96
Felipe Lemee53e85f2015-11-17 17:37:53 -080097/**
98 * Integration tests for {@link BugreportReceiver}.
99 * <p>
100 * These tests don't mock any component and rely on external UI components (like the notification
101 * bar and activity chooser), which can make them unreliable and slow.
102 * <p>
103 * The general workflow is:
104 * <ul>
105 * <li>creates the bug report files
106 * <li>generates the BUGREPORT_FINISHED intent
107 * <li>emulate user actions to share the intent with a custom activity
108 * <li>asserts the extras received by the custom activity
109 * </ul>
110 * <p>
Felipe Leme6bbb6b92015-12-07 17:43:55 -0800111 * <strong>NOTE</strong>: these tests only work if the device is unlocked.
Felipe Lemee53e85f2015-11-17 17:37:53 -0800112 */
Felipe Leme2bfa0852015-12-10 12:43:31 -0800113@LargeTest
Felipe Leme47ec8be2016-08-12 15:55:17 -0700114@RunWith(AndroidJUnit4.class)
115public class BugreportReceiverTest {
Felipe Lemee53e85f2015-11-17 17:37:53 -0800116 private static final String TAG = "BugreportReceiverTest";
117
118 // Timeout for UI operations, in milliseconds.
Felipe Lemefa26a0e2016-10-28 09:32:03 -0700119 private static final int TIMEOUT = (int) (5 * DateUtils.SECOND_IN_MILLIS);
Felipe Lemee53e85f2015-11-17 17:37:53 -0800120
Felipe Lemec4f646772016-01-12 18:12:09 -0800121 // Timeout for when waiting for a screenshot to finish.
122 private static final int SAFE_SCREENSHOT_DELAY = SCREENSHOT_DELAY_SECONDS + 10;
123
Felipe Lemea0bf0332015-12-11 09:35:03 -0800124 private static final String BUGREPORTS_DIR = "bugreports";
Felipe Lemee53e85f2015-11-17 17:37:53 -0800125 private static final String BUGREPORT_FILE = "test_bugreport.txt";
126 private static final String ZIP_FILE = "test_bugreport.zip";
Felipe Leme26288782016-02-25 12:10:43 -0800127 private static final String ZIP_FILE2 = "test_bugreport2.zip";
Felipe Lemea0bf0332015-12-11 09:35:03 -0800128 private static final String SCREENSHOT_FILE = "test_screenshot.png";
Felipe Lemee53e85f2015-11-17 17:37:53 -0800129
130 private static final String BUGREPORT_CONTENT = "Dump, might as well dump!\n";
131 private static final String SCREENSHOT_CONTENT = "A picture is worth a thousand words!\n";
132
Felipe Leme93702ab2015-12-11 13:06:45 -0800133 private static final int PID = 42;
Felipe Leme26288782016-02-25 12:10:43 -0800134 private static final int PID2 = 24;
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800135 private static final int ID = 108;
Felipe Leme26288782016-02-25 12:10:43 -0800136 private static final int ID2 = 801;
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800137 private static final String PROGRESS_PROPERTY = "dumpstate." + PID + ".progress";
138 private static final String MAX_PROPERTY = "dumpstate." + PID + ".max";
139 private static final String NAME_PROPERTY = "dumpstate." + PID + ".name";
Felipe Leme93702ab2015-12-11 13:06:45 -0800140 private static final String NAME = "BUG, Y U NO REPORT?";
Felipe Leme26288782016-02-25 12:10:43 -0800141 private static final String NAME2 = "A bugreport's life";
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800142 private static final String NEW_NAME = "Bug_Forrest_Bug";
Felipe Leme26288782016-02-25 12:10:43 -0800143 private static final String NEW_NAME2 = "BugsyReportsy";
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800144 private static final String TITLE = "Wimbugdom Champion 2015";
Felipe Leme26288782016-02-25 12:10:43 -0800145 private static final String TITLE2 = "Master of the Universe";
146 private static final String DESCRIPTION = "One's description...";
147 private static final String DESCRIPTION2 = "...is another's treasure.";
Felipe Leme4967f732016-01-06 11:38:53 -0800148
149 private static final String NO_DESCRIPTION = null;
150 private static final String NO_NAME = null;
151 private static final String NO_SCREENSHOT = null;
152 private static final String NO_TITLE = null;
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800153 private static final int NO_ID = 0;
Felipe Lemec8e2b602016-01-29 13:55:35 -0800154 private static final boolean RENAMED_SCREENSHOTS = true;
155 private static final boolean DIDNT_RENAME_SCREENSHOTS = false;
Felipe Leme4967f732016-01-06 11:38:53 -0800156
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800157 private String mDescription;
Felipe Leme93702ab2015-12-11 13:06:45 -0800158
Felipe Lemea0bf0332015-12-11 09:35:03 -0800159 private String mPlainTextPath;
160 private String mZipPath;
Felipe Leme26288782016-02-25 12:10:43 -0800161 private String mZipPath2;
Felipe Lemea0bf0332015-12-11 09:35:03 -0800162 private String mScreenshotPath;
163
Felipe Lemee53e85f2015-11-17 17:37:53 -0800164 private Context mContext;
165 private UiBot mUiBot;
166 private CustomActionSendMultipleListener mListener;
167
Felipe Leme47ec8be2016-08-12 15:55:17 -0700168 @Rule public TestName mName = new TestName();
169
170 @Before
171 public void setUp() throws Exception {
Felipe Lemeca5002f2016-08-03 11:51:00 -0700172 Log.i(TAG, getName() + ".setup()");
Felipe Lemee53e85f2015-11-17 17:37:53 -0800173 Instrumentation instrumentation = getInstrumentation();
174 mContext = instrumentation.getTargetContext();
Felipe Lemea86a3012016-07-15 10:40:00 -0700175 mUiBot = new UiBot(instrumentation, TIMEOUT);
Felipe Lemee53e85f2015-11-17 17:37:53 -0800176 mListener = ActionSendMultipleConsumerActivity.getListener(mContext);
Felipe Leme93702ab2015-12-11 13:06:45 -0800177
178 cancelExistingNotifications();
179
Felipe Lemea0bf0332015-12-11 09:35:03 -0800180 mPlainTextPath = getPath(BUGREPORT_FILE);
181 mZipPath = getPath(ZIP_FILE);
Felipe Leme26288782016-02-25 12:10:43 -0800182 mZipPath2 = getPath(ZIP_FILE2);
Felipe Lemea0bf0332015-12-11 09:35:03 -0800183 mScreenshotPath = getPath(SCREENSHOT_FILE);
Felipe Leme93702ab2015-12-11 13:06:45 -0800184 createTextFile(mPlainTextPath, BUGREPORT_CONTENT);
185 createTextFile(mScreenshotPath, SCREENSHOT_CONTENT);
186 createZipFile(mZipPath, BUGREPORT_FILE, BUGREPORT_CONTENT);
Felipe Leme26288782016-02-25 12:10:43 -0800187 createZipFile(mZipPath2, BUGREPORT_FILE, BUGREPORT_CONTENT);
Felipe Leme93702ab2015-12-11 13:06:45 -0800188
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800189 // Creates a multi-line description.
190 StringBuilder sb = new StringBuilder();
191 for (int i = 1; i <= 20; i++) {
192 sb.append("All work and no play makes Shell a dull app!\n");
193 }
194 mDescription = sb.toString();
195
Felipe Lemefcca68d2016-04-12 14:00:07 -0700196 setWarningState(mContext, STATE_HIDE);
Felipe Leme91699af2016-07-28 15:16:55 -0700197
198 mUiBot.turnScreenOn();
Felipe Lemee53e85f2015-11-17 17:37:53 -0800199 }
200
Felipe Leme47ec8be2016-08-12 15:55:17 -0700201 @After
202 public void tearDown() throws Exception {
Felipe Lemeca5002f2016-08-03 11:51:00 -0700203 Log.i(TAG, getName() + ".tearDown()");
Felipe Leme1ac54412016-10-11 09:17:50 -0700204 try {
205 cancelExistingNotifications();
206 } finally {
207 // Collapses just in case, so a failure here does not compromise tests on other classes.
208 mUiBot.collapseStatusBar();
209 }
Felipe Lemeca5002f2016-08-03 11:51:00 -0700210 }
211
Felipe Lemefa26a0e2016-10-28 09:32:03 -0700212 /*
213 * TODO: this test is incomplete because:
214 * - the assertProgressNotification() is not really asserting the progress because the
215 * UI automation API doesn't provide a way to check the notification progress bar value
216 * - it should use the binder object instead of SystemProperties to update progress
217 */
Felipe Leme47ec8be2016-08-12 15:55:17 -0700218 @Test
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800219 public void testProgress() throws Exception {
Felipe Leme93702ab2015-12-11 13:06:45 -0800220 resetProperties();
221 sendBugreportStarted(1000);
Felipe Leme22881292016-01-06 09:57:23 -0800222 waitForScreenshotButtonEnabled(true);
Felipe Leme69c02922015-11-24 17:48:05 -0800223
Felipe Leme9ca5e562016-04-11 10:27:02 -0700224 assertProgressNotification(NAME, 0f);
Felipe Leme69c02922015-11-24 17:48:05 -0800225
Felipe Leme93702ab2015-12-11 13:06:45 -0800226 SystemProperties.set(PROGRESS_PROPERTY, "108");
Felipe Leme9ca5e562016-04-11 10:27:02 -0700227 assertProgressNotification(NAME, 10.80f);
Felipe Leme69c02922015-11-24 17:48:05 -0800228
Felipe Leme9ca5e562016-04-11 10:27:02 -0700229 assertProgressNotification(NAME, 50.00f);
Felipe Leme69c02922015-11-24 17:48:05 -0800230
Felipe Leme3fc44b92016-03-21 17:34:21 -0700231 SystemProperties.set(PROGRESS_PROPERTY, "950");
Felipe Leme9ca5e562016-04-11 10:27:02 -0700232 assertProgressNotification(NAME, 95.00f);
Felipe Leme3fc44b92016-03-21 17:34:21 -0700233
234 // Make sure progress never goes back...
Felipe Leme93702ab2015-12-11 13:06:45 -0800235 SystemProperties.set(MAX_PROPERTY, "2000");
Felipe Leme9ca5e562016-04-11 10:27:02 -0700236 assertProgressNotification(NAME, 95.00f);
Felipe Leme3fc44b92016-03-21 17:34:21 -0700237
238 SystemProperties.set(PROGRESS_PROPERTY, "1000");
Felipe Leme9ca5e562016-04-11 10:27:02 -0700239 assertProgressNotification(NAME, 95.00f);
Felipe Leme3fc44b92016-03-21 17:34:21 -0700240
241 // ...only forward...
242 SystemProperties.set(PROGRESS_PROPERTY, "1902");
Felipe Leme9ca5e562016-04-11 10:27:02 -0700243 assertProgressNotification(NAME, 95.10f);
Felipe Leme3fc44b92016-03-21 17:34:21 -0700244
245 SystemProperties.set(PROGRESS_PROPERTY, "1960");
Felipe Leme9ca5e562016-04-11 10:27:02 -0700246 assertProgressNotification(NAME, 98.00f);
Felipe Leme3fc44b92016-03-21 17:34:21 -0700247
248 // ...but never more than the capped value.
249 SystemProperties.set(PROGRESS_PROPERTY, "2000");
Felipe Leme9ca5e562016-04-11 10:27:02 -0700250 assertProgressNotification(NAME, 99.00f);
Felipe Leme3fc44b92016-03-21 17:34:21 -0700251
252 SystemProperties.set(PROGRESS_PROPERTY, "3000");
Felipe Leme9ca5e562016-04-11 10:27:02 -0700253 assertProgressNotification(NAME, 99.00f);
Felipe Leme69c02922015-11-24 17:48:05 -0800254
Felipe Leme93702ab2015-12-11 13:06:45 -0800255 Bundle extras =
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800256 sendBugreportFinishedAndGetSharedIntent(ID, mPlainTextPath, mScreenshotPath);
257 assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, ZIP_FILE,
Felipe Leme079f8962016-04-18 12:04:23 -0700258 NAME, NO_TITLE, NO_DESCRIPTION, 0, RENAMED_SCREENSHOTS);
Felipe Lemed1e0f122015-12-18 16:12:41 -0800259
260 assertServiceNotRunning();
261 }
262
Felipe Leme47ec8be2016-08-12 15:55:17 -0700263 @Test
Felipe Lemedb313632016-02-25 17:06:58 -0800264 public void testProgress_cancel() throws Exception {
265 resetProperties();
266 sendBugreportStarted(1000);
267 waitForScreenshotButtonEnabled(true);
268
269 final NumberFormat nf = NumberFormat.getPercentInstance();
270 nf.setMinimumFractionDigits(2);
271 nf.setMaximumFractionDigits(2);
272
Felipe Leme9ca5e562016-04-11 10:27:02 -0700273 assertProgressNotification(NAME, 00.00f);
Felipe Lemedb313632016-02-25 17:06:58 -0800274
Felipe Lemea86a3012016-07-15 10:40:00 -0700275 cancelFromNotification();
Felipe Lemedb313632016-02-25 17:06:58 -0800276
277 waitForService(false);
278 }
279
Felipe Leme47ec8be2016-08-12 15:55:17 -0700280 @Test
Felipe Lemed1e0f122015-12-18 16:12:41 -0800281 public void testProgress_takeExtraScreenshot() throws Exception {
282 resetProperties();
283 sendBugreportStarted(1000);
284
285 waitForScreenshotButtonEnabled(true);
286 takeScreenshot();
287 assertScreenshotButtonEnabled(false);
288 waitForScreenshotButtonEnabled(true);
289
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800290 sendBugreportFinished(ID, mPlainTextPath, mScreenshotPath);
Felipe Lemec4f646772016-01-12 18:12:09 -0800291
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800292 Bundle extras = acceptBugreportAndGetSharedIntent(ID);
293 assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, ZIP_FILE,
Felipe Leme079f8962016-04-18 12:04:23 -0700294 NAME, NO_TITLE, NO_DESCRIPTION, 1, RENAMED_SCREENSHOTS);
Felipe Leme69c02922015-11-24 17:48:05 -0800295
Felipe Leme93702ab2015-12-11 13:06:45 -0800296 assertServiceNotRunning();
Felipe Leme69c02922015-11-24 17:48:05 -0800297 }
298
Felipe Leme47ec8be2016-08-12 15:55:17 -0700299 @Test
Felipe Lemec4f646772016-01-12 18:12:09 -0800300 public void testScreenshotFinishesAfterBugreport() throws Exception {
Felipe Lemec4f646772016-01-12 18:12:09 -0800301 resetProperties();
302
303 sendBugreportStarted(1000);
Felipe Leme079f8962016-04-18 12:04:23 -0700304 waitForScreenshotButtonEnabled(true);
305 takeScreenshot();
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800306 sendBugreportFinished(ID, mPlainTextPath, NO_SCREENSHOT);
307 waitShareNotification(ID);
Felipe Lemec4f646772016-01-12 18:12:09 -0800308
309 // There's no indication in the UI about the screenshot finish, so just sleep like a baby...
Felipe Lemeca5002f2016-08-03 11:51:00 -0700310 sleep(SAFE_SCREENSHOT_DELAY * DateUtils.SECOND_IN_MILLIS);
Felipe Lemec4f646772016-01-12 18:12:09 -0800311
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800312 Bundle extras = acceptBugreportAndGetSharedIntent(ID);
313 assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT, ID, PID, ZIP_FILE,
Felipe Lemec8e2b602016-01-29 13:55:35 -0800314 NAME, NO_TITLE, NO_DESCRIPTION, 1, RENAMED_SCREENSHOTS);
Felipe Lemec4f646772016-01-12 18:12:09 -0800315
316 assertServiceNotRunning();
317 }
318
Felipe Leme47ec8be2016-08-12 15:55:17 -0700319 @Test
Felipe Leme4967f732016-01-06 11:38:53 -0800320 public void testProgress_changeDetailsInvalidInput() throws Exception {
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800321 resetProperties();
322 sendBugreportStarted(1000);
Felipe Leme22881292016-01-06 09:57:23 -0800323 waitForScreenshotButtonEnabled(true);
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800324
Felipe Lemeca5002f2016-08-03 11:51:00 -0700325 DetailsUi detailsUi = new DetailsUi(mUiBot, ID, NAME);
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800326
327 // Check initial name.
Felipe Leme26288782016-02-25 12:10:43 -0800328 detailsUi.assertName(NAME);
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800329
330 // Change name - it should have changed system property once focus is changed.
Felipe Leme208b1882016-03-14 18:03:41 -0700331 detailsUi.focusOnName();
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800332 detailsUi.nameField.setText(NEW_NAME);
333 detailsUi.focusAwayFromName();
334 assertPropertyValue(NAME_PROPERTY, NEW_NAME);
335
336 // Cancel the dialog to make sure property was restored.
337 detailsUi.clickCancel();
338 assertPropertyValue(NAME_PROPERTY, NAME);
339
340 // Now try to set an invalid name.
Felipe Lemeca5002f2016-08-03 11:51:00 -0700341 detailsUi.reOpen(NAME);
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800342 detailsUi.nameField.setText("/etc/passwd");
343 detailsUi.clickOk();
344 assertPropertyValue(NAME_PROPERTY, "_etc_passwd");
345
346 // Finally, make the real changes.
Felipe Lemeca5002f2016-08-03 11:51:00 -0700347 detailsUi.reOpen("_etc_passwd");
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800348 detailsUi.nameField.setText(NEW_NAME);
349 detailsUi.titleField.setText(TITLE);
350 detailsUi.descField.setText(mDescription);
351
352 detailsUi.clickOk();
353
354 assertPropertyValue(NAME_PROPERTY, NEW_NAME);
Felipe Leme9ca5e562016-04-11 10:27:02 -0700355 assertProgressNotification(NEW_NAME, 00.00f);
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800356
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800357 Bundle extras = sendBugreportFinishedAndGetSharedIntent(ID, mPlainTextPath,
Felipe Leme65405742017-05-24 11:51:10 -0700358 mScreenshotPath, TITLE);
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800359 assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, TITLE,
Felipe Leme079f8962016-04-18 12:04:23 -0700360 NEW_NAME, TITLE, mDescription, 0, RENAMED_SCREENSHOTS);
Felipe Leme4967f732016-01-06 11:38:53 -0800361
362 assertServiceNotRunning();
363 }
364
Felipe Leme47ec8be2016-08-12 15:55:17 -0700365 @Test
Felipe Lemea86a3012016-07-15 10:40:00 -0700366 public void testProgress_cancelBugClosesDetailsDialog() throws Exception {
367 resetProperties();
368 sendBugreportStarted(1000);
369 waitForScreenshotButtonEnabled(true);
370
Felipe Lemeca5002f2016-08-03 11:51:00 -0700371 DetailsUi detailsUi = new DetailsUi(mUiBot, ID, NAME);
Felipe Lemea86a3012016-07-15 10:40:00 -0700372 detailsUi.assertName(NAME); // Sanity check
373
374 cancelFromNotification();
Felipe Leme1ac54412016-10-11 09:17:50 -0700375 mUiBot.collapseStatusBar();
Felipe Lemea86a3012016-07-15 10:40:00 -0700376
377 assertDetailsUiClosed();
378 assertServiceNotRunning();
379 }
380
Felipe Leme47ec8be2016-08-12 15:55:17 -0700381 @Test
Felipe Leme4967f732016-01-06 11:38:53 -0800382 public void testProgress_changeDetailsPlainBugreport() throws Exception {
383 changeDetailsTest(true);
384 }
385
Felipe Leme47ec8be2016-08-12 15:55:17 -0700386 @Test
Felipe Leme4967f732016-01-06 11:38:53 -0800387 public void testProgress_changeDetailsZippedBugreport() throws Exception {
388 changeDetailsTest(false);
389 }
390
Felipe Lemeca5002f2016-08-03 11:51:00 -0700391 private void changeDetailsTest(boolean plainText) throws Exception {
Felipe Leme4967f732016-01-06 11:38:53 -0800392 resetProperties();
393 sendBugreportStarted(1000);
394 waitForScreenshotButtonEnabled(true);
395
Felipe Lemeca5002f2016-08-03 11:51:00 -0700396 DetailsUi detailsUi = new DetailsUi(mUiBot, ID, NAME);
Felipe Leme4967f732016-01-06 11:38:53 -0800397
398 // Check initial name.
Felipe Leme26288782016-02-25 12:10:43 -0800399 detailsUi.assertName(NAME);
Felipe Leme4967f732016-01-06 11:38:53 -0800400
401 // Change fields.
Felipe Lemeca5002f2016-08-03 11:51:00 -0700402 detailsUi.reOpen(NAME);
Felipe Leme4967f732016-01-06 11:38:53 -0800403 detailsUi.nameField.setText(NEW_NAME);
404 detailsUi.titleField.setText(TITLE);
405 detailsUi.descField.setText(mDescription);
406
407 detailsUi.clickOk();
408
409 assertPropertyValue(NAME_PROPERTY, NEW_NAME);
Felipe Leme9ca5e562016-04-11 10:27:02 -0700410 assertProgressNotification(NEW_NAME, 00.00f);
Felipe Leme4967f732016-01-06 11:38:53 -0800411
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800412 Bundle extras = sendBugreportFinishedAndGetSharedIntent(ID,
Felipe Leme65405742017-05-24 11:51:10 -0700413 plainText? mPlainTextPath : mZipPath, mScreenshotPath, TITLE);
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800414 assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, TITLE,
Felipe Leme079f8962016-04-18 12:04:23 -0700415 NEW_NAME, TITLE, mDescription, 0, RENAMED_SCREENSHOTS);
Felipe Lemec8e2b602016-01-29 13:55:35 -0800416
417 assertServiceNotRunning();
418 }
419
Felipe Leme47ec8be2016-08-12 15:55:17 -0700420 @Test
Felipe Lemedb313632016-02-25 17:06:58 -0800421 public void testProgress_changeJustDetailsTouchingDetails() throws Exception {
422 changeJustDetailsTest(true);
423 }
424
Felipe Leme47ec8be2016-08-12 15:55:17 -0700425 @Test
Felipe Lemedb313632016-02-25 17:06:58 -0800426 public void testProgress_changeJustDetailsTouchingNotification() throws Exception {
427 changeJustDetailsTest(false);
428 }
429
430 private void changeJustDetailsTest(boolean touchDetails) throws Exception {
Felipe Lemec8e2b602016-01-29 13:55:35 -0800431 resetProperties();
432 sendBugreportStarted(1000);
433 waitForScreenshotButtonEnabled(true);
434
Felipe Lemeca5002f2016-08-03 11:51:00 -0700435 DetailsUi detailsUi = new DetailsUi(mUiBot, ID, NAME, touchDetails);
Felipe Lemec8e2b602016-01-29 13:55:35 -0800436
437 detailsUi.nameField.setText("");
438 detailsUi.titleField.setText("");
439 detailsUi.descField.setText(mDescription);
440 detailsUi.clickOk();
441
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800442 Bundle extras = sendBugreportFinishedAndGetSharedIntent(ID, mZipPath, mScreenshotPath);
443 assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, ZIP_FILE,
Felipe Leme079f8962016-04-18 12:04:23 -0700444 NO_NAME, NO_TITLE, mDescription, 0, DIDNT_RENAME_SCREENSHOTS);
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800445
446 assertServiceNotRunning();
447 }
448
Felipe Leme47ec8be2016-08-12 15:55:17 -0700449 @Test
Felipe Leme26288782016-02-25 12:10:43 -0800450 public void testProgress_changeJustDetailsIsClearedOnSecondBugreport() throws Exception {
451 resetProperties();
452 sendBugreportStarted(ID, PID, NAME, 1000);
453 waitForScreenshotButtonEnabled(true);
454
Felipe Lemeca5002f2016-08-03 11:51:00 -0700455 DetailsUi detailsUi = new DetailsUi(mUiBot, ID, NAME);
Felipe Leme26288782016-02-25 12:10:43 -0800456 detailsUi.assertName(NAME);
Felipe Lemebbd91e52016-02-26 16:48:22 -0800457 detailsUi.assertTitle("");
458 detailsUi.assertDescription("");
Felipe Lemeda1fbdd2016-08-03 17:39:01 -0700459 assertTrue("didn't enable name on UI", detailsUi.nameField.isEnabled());
Felipe Leme26288782016-02-25 12:10:43 -0800460 detailsUi.nameField.setText(NEW_NAME);
461 detailsUi.titleField.setText(TITLE);
462 detailsUi.descField.setText(DESCRIPTION);
463 detailsUi.clickOk();
464
465 sendBugreportStarted(ID2, PID2, NAME2, 1000);
466
Felipe Leme5ee846d2016-03-09 10:14:27 -0800467 sendBugreportFinished(ID, mZipPath, mScreenshotPath);
Felipe Leme65405742017-05-24 11:51:10 -0700468 Bundle extras = acceptBugreportAndGetSharedIntent(TITLE);
Felipe Leme26288782016-02-25 12:10:43 -0800469
Felipe Lemeca5002f2016-08-03 11:51:00 -0700470 detailsUi = new DetailsUi(mUiBot, ID2, NAME2);
Felipe Leme26288782016-02-25 12:10:43 -0800471 detailsUi.assertName(NAME2);
Felipe Lemebbd91e52016-02-26 16:48:22 -0800472 detailsUi.assertTitle("");
473 detailsUi.assertDescription("");
Felipe Lemeda1fbdd2016-08-03 17:39:01 -0700474 assertTrue("didn't enable name on UI", detailsUi.nameField.isEnabled());
Felipe Leme26288782016-02-25 12:10:43 -0800475 detailsUi.nameField.setText(NEW_NAME2);
476 detailsUi.titleField.setText(TITLE2);
477 detailsUi.descField.setText(DESCRIPTION2);
478 detailsUi.clickOk();
479
480 // Must use a different zip file otherwise it will fail because zip already contains
481 // title.txt and description.txt entries.
Felipe Leme65405742017-05-24 11:51:10 -0700482 extras = sendBugreportFinishedAndGetSharedIntent(ID2, mZipPath2, NO_SCREENSHOT, TITLE2);
Felipe Leme26288782016-02-25 12:10:43 -0800483 assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT, ID2, PID2, TITLE2,
Felipe Leme079f8962016-04-18 12:04:23 -0700484 NEW_NAME2, TITLE2, DESCRIPTION2, 0, RENAMED_SCREENSHOTS);
Felipe Leme26288782016-02-25 12:10:43 -0800485
486 assertServiceNotRunning();
487 }
488
Felipe Leme22881292016-01-06 09:57:23 -0800489 /**
490 * Tests the scenario where the initial screenshot and dumpstate are finished while the user
491 * is changing the info in the details screen.
492 */
Felipe Leme47ec8be2016-08-12 15:55:17 -0700493 @Test
Felipe Leme22881292016-01-06 09:57:23 -0800494 public void testProgress_bugreportAndScreenshotFinishedWhileChangingDetails() throws Exception {
495 bugreportFinishedWhileChangingDetailsTest(false);
496 }
497
498 /**
499 * Tests the scenario where dumpstate is finished while the user is changing the info in the
500 * details screen, but the initial screenshot finishes afterwards.
501 */
Felipe Leme47ec8be2016-08-12 15:55:17 -0700502 @Test
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800503 public void testProgress_bugreportFinishedWhileChangingDetails() throws Exception {
Felipe Leme22881292016-01-06 09:57:23 -0800504 bugreportFinishedWhileChangingDetailsTest(true);
505 }
506
507 private void bugreportFinishedWhileChangingDetailsTest(boolean waitScreenshot) throws Exception {
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800508 resetProperties();
509 sendBugreportStarted(1000);
Felipe Leme22881292016-01-06 09:57:23 -0800510 if (waitScreenshot) {
511 waitForScreenshotButtonEnabled(true);
512 }
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800513
Felipe Lemeca5002f2016-08-03 11:51:00 -0700514 DetailsUi detailsUi = new DetailsUi(mUiBot, ID, NAME);
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800515
516 // Finish the bugreport while user's still typing the name.
517 detailsUi.nameField.setText(NEW_NAME);
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800518 sendBugreportFinished(ID, mPlainTextPath, mScreenshotPath);
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800519
Felipe Leme22881292016-01-06 09:57:23 -0800520 // Wait until the share notification is received...
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800521 waitShareNotification(ID);
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800522 // ...then close notification bar.
523 mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
524
525 // Make sure UI was updated properly.
526 assertFalse("didn't disable name on UI", detailsUi.nameField.isEnabled());
527 assertEquals("didn't revert name on UI", NAME, detailsUi.nameField.getText().toString());
528
529 // Finish changing other fields.
530 detailsUi.titleField.setText(TITLE);
531 detailsUi.descField.setText(mDescription);
532 detailsUi.clickOk();
533
534 // Finally, share bugreport.
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800535 Bundle extras = acceptBugreportAndGetSharedIntent(ID);
536 assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, TITLE,
Felipe Leme079f8962016-04-18 12:04:23 -0700537 NAME, TITLE, mDescription, 0, RENAMED_SCREENSHOTS);
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800538
539 assertServiceNotRunning();
540 }
541
Felipe Leme47ec8be2016-08-12 15:55:17 -0700542 @Test
Felipe Lemefcca68d2016-04-12 14:00:07 -0700543 public void testBugreportFinished_withWarningFirstTime() throws Exception {
544 bugreportFinishedWithWarningTest(null);
545 }
546
Felipe Leme47ec8be2016-08-12 15:55:17 -0700547 @Test
Felipe Lemefcca68d2016-04-12 14:00:07 -0700548 public void testBugreportFinished_withWarningUnknownState() throws Exception {
549 bugreportFinishedWithWarningTest(STATE_UNKNOWN);
550 }
551
Felipe Leme47ec8be2016-08-12 15:55:17 -0700552 @Test
Felipe Lemefcca68d2016-04-12 14:00:07 -0700553 public void testBugreportFinished_withWarningShowAgain() throws Exception {
554 bugreportFinishedWithWarningTest(STATE_SHOW);
555 }
556
557 private void bugreportFinishedWithWarningTest(Integer propertyState) throws Exception {
558 if (propertyState == null) {
559 // Clear properties
560 mContext.getSharedPreferences(PREFS_BUGREPORT, Context.MODE_PRIVATE)
561 .edit().clear().commit();
562 // Sanity check...
563 assertEquals("Did not reset properties", STATE_UNKNOWN,
564 getWarningState(mContext, STATE_UNKNOWN));
565 } else {
566 setWarningState(mContext, propertyState);
567 }
Felipe Leme6bbb6b92015-12-07 17:43:55 -0800568
569 // Send notification and click on share.
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800570 sendBugreportFinished(NO_ID, mPlainTextPath, null);
Felipe Leme65405742017-05-24 11:51:10 -0700571 mUiBot.clickOnNotification(mContext.getString(R.string.bugreport_finished_title, NO_ID));
Felipe Leme6bbb6b92015-12-07 17:43:55 -0800572
573 // Handle the warning
574 mUiBot.getVisibleObject(mContext.getString(R.string.bugreport_confirm));
Felipe Lemefcca68d2016-04-12 14:00:07 -0700575 // TODO: get ok and dontShowAgain from the dialog reference above
576 UiObject dontShowAgain =
577 mUiBot.getVisibleObject(mContext.getString(R.string.bugreport_confirm_dont_repeat));
578 final boolean firstTime = propertyState == null || propertyState == STATE_UNKNOWN;
579 if (firstTime) {
Jeff Sharkey5ab02432017-06-27 11:01:36 -0600580 if (Build.IS_USER) {
Felipe Lemeaf096712016-04-25 13:36:44 -0700581 assertFalse("Checkbox should NOT be checked by default on user builds",
582 dontShowAgain.isChecked());
583 mUiBot.click(dontShowAgain, "dont-show-again");
584 } else {
585 assertTrue("Checkbox should be checked by default on build type " + Build.TYPE,
586 dontShowAgain.isChecked());
587 }
Felipe Lemefcca68d2016-04-12 14:00:07 -0700588 } else {
589 assertFalse("Checkbox should not be checked", dontShowAgain.isChecked());
590 mUiBot.click(dontShowAgain, "dont-show-again");
591 }
Felipe Leme6bbb6b92015-12-07 17:43:55 -0800592 UiObject ok = mUiBot.getVisibleObject(mContext.getString(com.android.internal.R.string.ok));
593 mUiBot.click(ok, "ok");
594
595 // Share the bugreport.
596 mUiBot.chooseActivity(UI_NAME);
597 Bundle extras = mListener.getExtras();
Felipe Leme4967f732016-01-06 11:38:53 -0800598 assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
Felipe Leme6bbb6b92015-12-07 17:43:55 -0800599
600 // Make sure it's hidden now.
Felipe Lemefcca68d2016-04-12 14:00:07 -0700601 int newState = getWarningState(mContext, STATE_UNKNOWN);
602 assertEquals("Didn't change state", STATE_HIDE, newState);
Felipe Leme6bbb6b92015-12-07 17:43:55 -0800603 }
604
Felipe Leme47ec8be2016-08-12 15:55:17 -0700605 @Test
Felipe Lemec4f646772016-01-12 18:12:09 -0800606 public void testShareBugreportAfterServiceDies() throws Exception {
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800607 sendBugreportFinished(NO_ID, mPlainTextPath, NO_SCREENSHOT);
Felipe Leme69c53e62016-04-15 12:49:34 -0700608 waitForService(false);
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800609 Bundle extras = acceptBugreportAndGetSharedIntent(NO_ID);
Felipe Lemec4f646772016-01-12 18:12:09 -0800610 assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
611 }
612
Felipe Leme47ec8be2016-08-12 15:55:17 -0700613 @Test
Felipe Lemee53e85f2015-11-17 17:37:53 -0800614 public void testBugreportFinished_plainBugreportAndScreenshot() throws Exception {
Felipe Leme93702ab2015-12-11 13:06:45 -0800615 Bundle extras = sendBugreportFinishedAndGetSharedIntent(mPlainTextPath, mScreenshotPath);
Felipe Lemee53e85f2015-11-17 17:37:53 -0800616 assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);
617 }
618
Felipe Leme47ec8be2016-08-12 15:55:17 -0700619 @Test
Felipe Lemee53e85f2015-11-17 17:37:53 -0800620 public void testBugreportFinished_zippedBugreportAndScreenshot() throws Exception {
Felipe Leme93702ab2015-12-11 13:06:45 -0800621 Bundle extras = sendBugreportFinishedAndGetSharedIntent(mZipPath, mScreenshotPath);
Felipe Lemee53e85f2015-11-17 17:37:53 -0800622 assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);
623 }
624
Felipe Leme47ec8be2016-08-12 15:55:17 -0700625 @Test
Felipe Lemee53e85f2015-11-17 17:37:53 -0800626 public void testBugreportFinished_plainBugreportAndNoScreenshot() throws Exception {
Felipe Leme4967f732016-01-06 11:38:53 -0800627 Bundle extras = sendBugreportFinishedAndGetSharedIntent(mPlainTextPath, NO_SCREENSHOT);
628 assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
Felipe Lemee53e85f2015-11-17 17:37:53 -0800629 }
630
Felipe Leme47ec8be2016-08-12 15:55:17 -0700631 @Test
Felipe Lemee53e85f2015-11-17 17:37:53 -0800632 public void testBugreportFinished_zippedBugreportAndNoScreenshot() throws Exception {
Felipe Leme4967f732016-01-06 11:38:53 -0800633 Bundle extras = sendBugreportFinishedAndGetSharedIntent(mZipPath, NO_SCREENSHOT);
634 assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
Felipe Lemee53e85f2015-11-17 17:37:53 -0800635 }
636
637 private void cancelExistingNotifications() {
Felipe Leme2c0f3a32016-08-08 15:39:13 -0700638 // Must kill service first, because notifications from a foreground service cannot be
639 // canceled.
640 killService();
641
Felipe Lemee53e85f2015-11-17 17:37:53 -0800642 NotificationManager nm = NotificationManager.from(mContext);
Felipe Lemeca5002f2016-08-03 11:51:00 -0700643 StatusBarNotification[] activeNotifications = nm.getActiveNotifications();
644 if (activeNotifications.length == 0) {
645 return;
Felipe Lemee53e85f2015-11-17 17:37:53 -0800646 }
Felipe Lemeca5002f2016-08-03 11:51:00 -0700647
648 Log.w(TAG, getName() + ": " + activeNotifications.length + " active notifications");
649
650 nm.cancelAll();
651
652 // Wait a little bit...
653 for (int i = 1; i < 5; i++) {
654 int total = nm.getActiveNotifications().length;
655 if (total == 0) {
656 return;
657 }
658 Log.d(TAG, total + "notifications are still active; sleeping ");
659 nm.cancelAll();
660 sleep(1000);
661 }
662 assertEquals("old notifications were not cancelled", 0, nm.getActiveNotifications().length);
Felipe Lemee53e85f2015-11-17 17:37:53 -0800663 }
664
Felipe Lemea86a3012016-07-15 10:40:00 -0700665 private void cancelFromNotification() {
Felipe Lemeca5002f2016-08-03 11:51:00 -0700666 openProgressNotification(NAME);
Felipe Lemea86a3012016-07-15 10:40:00 -0700667 UiObject cancelButton = mUiBot.getVisibleObject(mContext.getString(
668 com.android.internal.R.string.cancel).toUpperCase());
669 mUiBot.click(cancelButton, "cancel_button");
670 }
671
Felipe Leme9ca5e562016-04-11 10:27:02 -0700672 private void assertProgressNotification(String name, float percent) {
Felipe Lemeca5002f2016-08-03 11:51:00 -0700673 openProgressNotification(name);
Felipe Leme9ca5e562016-04-11 10:27:02 -0700674 // TODO: need a way to get the ProgresBar from the "android:id/progress" UIObject...
Felipe Leme69c02922015-11-24 17:48:05 -0800675 }
676
Felipe Lemeca5002f2016-08-03 11:51:00 -0700677 private UiObject openProgressNotification(String bugreportName) {
678 Log.v(TAG, "Looking for progress notification for '" + bugreportName + "'");
679 return mUiBot.getNotification(bugreportName);
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800680 }
681
Felipe Leme93702ab2015-12-11 13:06:45 -0800682 void resetProperties() {
683 // TODO: call method to remove property instead
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800684 SystemProperties.set(PROGRESS_PROPERTY, "Reset");
685 SystemProperties.set(MAX_PROPERTY, "Reset");
686 SystemProperties.set(NAME_PROPERTY, "Reset");
Felipe Leme93702ab2015-12-11 13:06:45 -0800687 }
688
689 /**
690 * Sends a "bugreport started" intent with the default values.
691 */
Felipe Lemed1e0f122015-12-18 16:12:41 -0800692 private void sendBugreportStarted(int max) throws Exception {
Felipe Leme26288782016-02-25 12:10:43 -0800693 sendBugreportStarted(ID, PID, NAME, max);
694 }
695
696 private void sendBugreportStarted(int id, int pid, String name, int max) throws Exception {
Felipe Leme93702ab2015-12-11 13:06:45 -0800697 Intent intent = new Intent(INTENT_BUGREPORT_STARTED);
Felipe Leme8775eaa2017-02-10 13:06:58 -0800698 intent.setPackage("com.android.shell");
Felipe Lemeec175382016-01-26 18:17:15 -0800699 intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
Felipe Leme26288782016-02-25 12:10:43 -0800700 intent.putExtra(EXTRA_ID, id);
701 intent.putExtra(EXTRA_PID, pid);
702 intent.putExtra(EXTRA_NAME, name);
Felipe Leme93702ab2015-12-11 13:06:45 -0800703 intent.putExtra(EXTRA_MAX, max);
704 mContext.sendBroadcast(intent);
705 }
706
Felipe Lemee53e85f2015-11-17 17:37:53 -0800707 /**
708 * Sends a "bugreport finished" intent and waits for the result.
709 *
Felipe Leme93702ab2015-12-11 13:06:45 -0800710 * @return extras sent in the shared intent.
Felipe Lemee53e85f2015-11-17 17:37:53 -0800711 */
Felipe Leme93702ab2015-12-11 13:06:45 -0800712 private Bundle sendBugreportFinishedAndGetSharedIntent(String bugreportPath,
713 String screenshotPath) {
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800714 return sendBugreportFinishedAndGetSharedIntent(NO_ID, bugreportPath, screenshotPath);
Felipe Leme69c02922015-11-24 17:48:05 -0800715 }
716
Felipe Leme93702ab2015-12-11 13:06:45 -0800717 /**
718 * Sends a "bugreport finished" intent and waits for the result.
719 *
720 * @return extras sent in the shared intent.
721 */
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800722 private Bundle sendBugreportFinishedAndGetSharedIntent(int id, String bugreportPath,
Felipe Leme69c02922015-11-24 17:48:05 -0800723 String screenshotPath) {
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800724 sendBugreportFinished(id, bugreportPath, screenshotPath);
Felipe Lemea43d13932016-04-12 17:28:06 -0700725 return acceptBugreportAndGetSharedIntent(id);
Felipe Leme93702ab2015-12-11 13:06:45 -0800726 }
727
Felipe Leme65405742017-05-24 11:51:10 -0700728 // TODO: document / merge these 3 sendBugreportFinishedAndGetSharedIntent methods
729 private Bundle sendBugreportFinishedAndGetSharedIntent(int id, String bugreportPath,
730 String screenshotPath, String notificationTitle) {
731 sendBugreportFinished(id, bugreportPath, screenshotPath);
732 return acceptBugreportAndGetSharedIntent(notificationTitle);
733 }
734
Felipe Leme93702ab2015-12-11 13:06:45 -0800735 /**
736 * Accepts the notification to share the finished bugreport and waits for the result.
737 *
738 * @return extras sent in the shared intent.
739 */
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800740 private Bundle acceptBugreportAndGetSharedIntent(int id) {
Felipe Leme65405742017-05-24 11:51:10 -0700741 final String notificationTitle = mContext.getString(R.string.bugreport_finished_title, id);
742 return acceptBugreportAndGetSharedIntent(notificationTitle);
743 }
744
745 // TODO: document and/or merge these 2 acceptBugreportAndGetSharedIntent methods
746 private Bundle acceptBugreportAndGetSharedIntent(String notificationTitle) {
747 mUiBot.clickOnNotification(notificationTitle);
Felipe Leme93702ab2015-12-11 13:06:45 -0800748 mUiBot.chooseActivity(UI_NAME);
749 return mListener.getExtras();
750 }
751
752 /**
Felipe Lemec4f646772016-01-12 18:12:09 -0800753 * Waits for the notification to share the finished bugreport.
754 */
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800755 private void waitShareNotification(int id) {
756 mUiBot.getNotification(mContext.getString(R.string.bugreport_finished_title, id));
Felipe Lemec4f646772016-01-12 18:12:09 -0800757 }
758
759 /**
Felipe Leme93702ab2015-12-11 13:06:45 -0800760 * Sends a "bugreport finished" intent.
Felipe Leme93702ab2015-12-11 13:06:45 -0800761 */
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800762 private void sendBugreportFinished(int id, String bugreportPath, String screenshotPath) {
Felipe Leme69c02922015-11-24 17:48:05 -0800763 Intent intent = new Intent(INTENT_BUGREPORT_FINISHED);
Felipe Leme8775eaa2017-02-10 13:06:58 -0800764 intent.setPackage("com.android.shell");
Felipe Lemeec175382016-01-26 18:17:15 -0800765 intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800766 if (id != NO_ID) {
767 intent.putExtra(EXTRA_ID, id);
Felipe Leme69c02922015-11-24 17:48:05 -0800768 }
Felipe Lemee53e85f2015-11-17 17:37:53 -0800769 if (bugreportPath != null) {
770 intent.putExtra(EXTRA_BUGREPORT, bugreportPath);
771 }
772 if (screenshotPath != null) {
773 intent.putExtra(EXTRA_SCREENSHOT, screenshotPath);
774 }
775
776 mContext.sendBroadcast(intent);
Felipe Lemee53e85f2015-11-17 17:37:53 -0800777 }
778
779 /**
Felipe Lemed1e0f122015-12-18 16:12:41 -0800780 * Asserts the proper {@link Intent#ACTION_SEND_MULTIPLE} intent was sent.
Felipe Lemee53e85f2015-11-17 17:37:53 -0800781 */
782 private void assertActionSendMultiple(Bundle extras, String bugreportContent,
783 String screenshotContent) throws IOException {
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800784 assertActionSendMultiple(extras, bugreportContent, screenshotContent, ID, PID, ZIP_FILE,
Felipe Lemec8e2b602016-01-29 13:55:35 -0800785 NO_NAME, NO_TITLE, NO_DESCRIPTION, 0, DIDNT_RENAME_SCREENSHOTS);
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800786 }
787
Felipe Lemed1e0f122015-12-18 16:12:41 -0800788 /**
789 * Asserts the proper {@link Intent#ACTION_SEND_MULTIPLE} intent was sent.
790 *
791 * @param extras extras received in the intent
792 * @param bugreportContent expected content in the bugreport file
793 * @param screenshotContent expected content in the screenshot file (sent by dumpstate), if any
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800794 * @param id emulated dumpstate id
Felipe Lemed1e0f122015-12-18 16:12:41 -0800795 * @param pid emulated dumpstate pid
Felipe Leme4967f732016-01-06 11:38:53 -0800796 * @param name expected subject
797 * @param name bugreport name as provided by the user (or received by dumpstate)
798 * @param title bugreport name as provided by the user
Felipe Lemed1e0f122015-12-18 16:12:41 -0800799 * @param description bugreport description as provided by the user
800 * @param numberScreenshots expected number of screenshots taken by Shell.
Felipe Leme22881292016-01-06 09:57:23 -0800801 * @param renamedScreenshots whether the screenshots are expected to be renamed
Felipe Lemed1e0f122015-12-18 16:12:41 -0800802 */
803 private void assertActionSendMultiple(Bundle extras, String bugreportContent,
Felipe Leme85ae3cf2016-02-24 15:36:50 -0800804 String screenshotContent, int id, int pid, String subject,
Felipe Leme4967f732016-01-06 11:38:53 -0800805 String name, String title, String description,
Felipe Leme22881292016-01-06 09:57:23 -0800806 int numberScreenshots, boolean renamedScreenshots) throws IOException {
Felipe Lemee53e85f2015-11-17 17:37:53 -0800807 String body = extras.getString(Intent.EXTRA_TEXT);
808 assertContainsRegex("missing build info",
809 SystemProperties.get("ro.build.description"), body);
810 assertContainsRegex("missing serial number",
811 SystemProperties.get("ro.serialno"), body);
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800812 if (description != null) {
813 assertContainsRegex("missing description", description, body);
814 }
Felipe Lemee53e85f2015-11-17 17:37:53 -0800815
Felipe Leme4967f732016-01-06 11:38:53 -0800816 assertEquals("wrong subject", subject, extras.getString(Intent.EXTRA_SUBJECT));
Felipe Lemee53e85f2015-11-17 17:37:53 -0800817
818 List<Uri> attachments = extras.getParcelableArrayList(Intent.EXTRA_STREAM);
Felipe Lemed1e0f122015-12-18 16:12:41 -0800819 int expectedNumberScreenshots = numberScreenshots;
820 if (screenshotContent != null) {
821 expectedNumberScreenshots ++; // Add screenshot received by dumpstate
822 }
823 int expectedSize = expectedNumberScreenshots + 1; // All screenshots plus the bugreport file
Felipe Lemec4f646772016-01-12 18:12:09 -0800824 assertEquals("wrong number of attachments (" + attachments + ")",
825 expectedSize, attachments.size());
Felipe Lemee53e85f2015-11-17 17:37:53 -0800826
827 // Need to interact through all attachments, since order is not guaranteed.
Felipe Lemed1e0f122015-12-18 16:12:41 -0800828 Uri zipUri = null;
829 List<Uri> screenshotUris = new ArrayList<>(expectedNumberScreenshots);
Felipe Lemee53e85f2015-11-17 17:37:53 -0800830 for (Uri attachment : attachments) {
831 if (attachment.getPath().endsWith(".zip")) {
832 zipUri = attachment;
833 }
834 if (attachment.getPath().endsWith(".png")) {
Felipe Lemed1e0f122015-12-18 16:12:41 -0800835 screenshotUris.add(attachment);
Felipe Lemee53e85f2015-11-17 17:37:53 -0800836 }
837 }
838 assertNotNull("did not get .zip attachment", zipUri);
839 assertZipContent(zipUri, BUGREPORT_FILE, BUGREPORT_CONTENT);
Felipe Leme4967f732016-01-06 11:38:53 -0800840 if (!TextUtils.isEmpty(title)) {
841 assertZipContent(zipUri, "title.txt", title);
842 }
843 if (!TextUtils.isEmpty(description)) {
844 assertZipContent(zipUri, "description.txt", description);
845 }
Felipe Lemee53e85f2015-11-17 17:37:53 -0800846
Felipe Lemed1e0f122015-12-18 16:12:41 -0800847 // URI of the screenshot taken by dumpstate.
848 Uri externalScreenshotUri = null;
849 SortedSet<String> internalScreenshotNames = new TreeSet<>();
850 for (Uri screenshotUri : screenshotUris) {
851 String screenshotName = screenshotUri.getLastPathSegment();
852 if (screenshotName.endsWith(SCREENSHOT_FILE)) {
853 externalScreenshotUri = screenshotUri;
854 } else {
855 internalScreenshotNames.add(screenshotName);
856 }
Felipe Lemee53e85f2015-11-17 17:37:53 -0800857 }
Felipe Lemed1e0f122015-12-18 16:12:41 -0800858 // Check external screenshot
859 if (screenshotContent != null) {
860 assertNotNull("did not get .png attachment for external screenshot",
861 externalScreenshotUri);
862 assertContent(externalScreenshotUri, SCREENSHOT_CONTENT);
863 } else {
864 assertNull("should not have .png attachment for external screenshot",
865 externalScreenshotUri);
866 }
867 // Check internal screenshots.
868 SortedSet<String> expectedNames = new TreeSet<>();
869 for (int i = 1 ; i <= numberScreenshots; i++) {
Felipe Leme22881292016-01-06 09:57:23 -0800870 String prefix = renamedScreenshots ? name : Integer.toString(pid);
Felipe Lemed1e0f122015-12-18 16:12:41 -0800871 String expectedName = "screenshot-" + prefix + "-" + i + ".png";
872 expectedNames.add(expectedName);
873 }
874 // Ideally we should use MoreAsserts, but the error message in case of failure is not
875 // really useful.
876 assertEquals("wrong names for internal screenshots",
877 expectedNames, internalScreenshotNames);
Felipe Lemee53e85f2015-11-17 17:37:53 -0800878 }
879
880 private void assertContent(Uri uri, String expectedContent) throws IOException {
881 Log.v(TAG, "assertContents(uri=" + uri);
882 try (InputStream is = mContext.getContentResolver().openInputStream(uri)) {
883 String actualContent = new String(Streams.readFully(is));
884 assertEquals("wrong content for '" + uri + "'", expectedContent, actualContent);
885 }
886 }
887
888 private void assertZipContent(Uri uri, String entryName, String expectedContent)
889 throws IOException, IOException {
890 Log.v(TAG, "assertZipEntry(uri=" + uri + ", entryName=" + entryName);
891 try (ZipInputStream zis = new ZipInputStream(mContext.getContentResolver().openInputStream(
892 uri))) {
893 ZipEntry entry;
894 while ((entry = zis.getNextEntry()) != null) {
895 Log.v(TAG, "Zip entry: " + entry.getName());
896 if (entry.getName().equals(entryName)) {
897 ByteArrayOutputStream bos = new ByteArrayOutputStream();
898 Streams.copy(zis, bos);
899 String actualContent = new String(bos.toByteArray(), "UTF-8");
900 bos.close();
901 assertEquals("wrong content for zip entry'" + entryName + "' on '" + uri + "'",
902 expectedContent, actualContent);
903 return;
904 }
905 }
906 }
907 fail("Did not find entry '" + entryName + "' on file '" + uri + "'");
908 }
909
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800910 private void assertPropertyValue(String key, String expectedValue) {
Felipe Lemeca5002f2016-08-03 11:51:00 -0700911 // Since the property is set in a different thread by BugreportProgressService, we need to
912 // poll it a couple times...
913
914 for (int i = 1; i <= 5; i++) {
915 String actualValue = SystemProperties.get(key);
916 if (expectedValue.equals(actualValue)) {
917 return;
918 }
919 Log.d(TAG, "Value of property " + key + " (" + actualValue
920 + ") does not match expected value (" + expectedValue
921 + ") on attempt " + i + ". Sleeping before next attempt...");
922 sleep(1000);
923 }
924 // Final try...
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800925 String actualValue = SystemProperties.get(key);
926 assertEquals("Wrong value for property '" + key + "'", expectedValue, actualValue);
927 }
928
Felipe Leme93702ab2015-12-11 13:06:45 -0800929 private void assertServiceNotRunning() {
930 String service = BugreportProgressService.class.getName();
931 assertFalse("Service '" + service + "' is still running", isServiceRunning(service));
932 }
933
Felipe Lemeba477932015-12-09 11:04:59 -0800934 private boolean isServiceRunning(String name) {
935 ActivityManager manager = (ActivityManager) mContext
936 .getSystemService(Context.ACTIVITY_SERVICE);
937 for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
938 if (service.service.getClassName().equals(name)) {
939 return true;
940 }
941 }
942 return false;
943 }
944
Felipe Lemec4f646772016-01-12 18:12:09 -0800945 private void waitForService(boolean expectRunning) {
946 String service = BugreportProgressService.class.getName();
947 boolean actualRunning;
948 for (int i = 1; i <= 5; i++) {
949 actualRunning = isServiceRunning(service);
950 Log.d(TAG, "Attempt " + i + " to check status of service '"
951 + service + "': expected=" + expectRunning + ", actual= " + actualRunning);
952 if (actualRunning == expectRunning) {
953 return;
954 }
Felipe Lemeca5002f2016-08-03 11:51:00 -0700955 sleep(DateUtils.SECOND_IN_MILLIS);
Felipe Lemec4f646772016-01-12 18:12:09 -0800956 }
Felipe Lemec4f646772016-01-12 18:12:09 -0800957
958 fail("Service status didn't change to " + expectRunning);
959 }
960
Felipe Leme2c0f3a32016-08-08 15:39:13 -0700961 private void killService() {
962 String service = BugreportProgressService.class.getName();
963
964 if (!isServiceRunning(service)) return;
965
966 Log.w(TAG, "Service '" + service + "' is still running, killing it");
967 silentlyExecuteShellCommand("am stopservice com.android.shell/.BugreportProgressService");
968
969 waitForService(false);
970 }
971
972 private void silentlyExecuteShellCommand(String cmd) {
973 Log.w(TAG, "silentlyExecuteShellCommand: '" + cmd + "'");
974 try {
975 UiDevice.getInstance(getInstrumentation()).executeShellCommand(cmd);
976 } catch (IOException e) {
977 Log.w(TAG, "error executing shell comamand '" + cmd + "'", e);
978 }
979 }
980
Felipe Leme26288782016-02-25 12:10:43 -0800981 private void createTextFile(String path, String content) throws IOException {
Felipe Lemee53e85f2015-11-17 17:37:53 -0800982 Log.v(TAG, "createFile(" + path + ")");
983 try (Writer writer = new BufferedWriter(new OutputStreamWriter(
984 new FileOutputStream(path)))) {
985 writer.write(content);
986 }
987 }
988
989 private void createZipFile(String path, String entryName, String content) throws IOException {
990 Log.v(TAG, "createZipFile(" + path + ", " + entryName + ")");
991 try (ZipOutputStream zos = new ZipOutputStream(
992 new BufferedOutputStream(new FileOutputStream(path)))) {
993 ZipEntry entry = new ZipEntry(entryName);
994 zos.putNextEntry(entry);
995 byte[] data = content.getBytes();
996 zos.write(data, 0, data.length);
997 zos.closeEntry();
998 }
999 }
Felipe Lemea0bf0332015-12-11 09:35:03 -08001000
1001 private String getPath(String file) {
Felipe Lemefcca68d2016-04-12 14:00:07 -07001002 final File rootDir = mContext.getFilesDir();
1003 final File dir = new File(rootDir, BUGREPORTS_DIR);
Felipe Lemee2b4f492015-12-11 18:19:26 -08001004 if (!dir.exists()) {
1005 Log.i(TAG, "Creating directory " + dir);
1006 assertTrue("Could not create directory " + dir, dir.mkdir());
1007 }
Felipe Lemea0bf0332015-12-11 09:35:03 -08001008 String path = new File(dir, file).getAbsolutePath();
1009 Log.v(TAG, "Path for '" + file + "': " + path);
1010 return path;
1011 }
Felipe Lemebc73ffc2015-12-11 15:07:14 -08001012
1013 /**
Felipe Lemed1e0f122015-12-18 16:12:41 -08001014 * Gets the notification button used to take a screenshot.
1015 */
1016 private UiObject getScreenshotButton() {
Felipe Lemeca5002f2016-08-03 11:51:00 -07001017 openProgressNotification(NAME);
Felipe Lemed1e0f122015-12-18 16:12:41 -08001018 return mUiBot.getVisibleObject(
1019 mContext.getString(R.string.bugreport_screenshot_action).toUpperCase());
1020 }
1021
1022 /**
1023 * Takes a screenshot using the system notification.
1024 */
1025 private void takeScreenshot() throws Exception {
1026 UiObject screenshotButton = getScreenshotButton();
1027 mUiBot.click(screenshotButton, "screenshot_button");
1028 }
1029
1030 private UiObject waitForScreenshotButtonEnabled(boolean expectedEnabled) throws Exception {
1031 UiObject screenshotButton = getScreenshotButton();
Felipe Lemec4f646772016-01-12 18:12:09 -08001032 int maxAttempts = SAFE_SCREENSHOT_DELAY;
Felipe Lemed1e0f122015-12-18 16:12:41 -08001033 int i = 0;
1034 do {
1035 boolean enabled = screenshotButton.isEnabled();
1036 if (enabled == expectedEnabled) {
1037 return screenshotButton;
1038 }
1039 i++;
1040 Log.v(TAG, "Sleeping for 1 second while waiting for screenshot.enable to be "
1041 + expectedEnabled + " (attempt " + i + ")");
1042 Thread.sleep(DateUtils.SECOND_IN_MILLIS);
1043 } while (i <= maxAttempts);
1044 fail("screenshot.enable didn't change to " + expectedEnabled + " in " + maxAttempts + "s");
1045 return screenshotButton;
1046 }
1047
1048 private void assertScreenshotButtonEnabled(boolean expectedEnabled) throws Exception {
1049 UiObject screenshotButton = getScreenshotButton();
1050 assertEquals("wrong state for screenshot button ", expectedEnabled,
1051 screenshotButton.isEnabled());
1052 }
1053
Felipe Lemea86a3012016-07-15 10:40:00 -07001054 private void assertDetailsUiClosed() {
1055 // TODO: unhardcode resource ids
1056 mUiBot.assertNotVisibleById("android:id/alertTitle");
1057 }
1058
Felipe Leme47ec8be2016-08-12 15:55:17 -07001059 private String getName() {
1060 return mName.getMethodName();
1061 }
1062
1063 private Instrumentation getInstrumentation() {
1064 return InstrumentationRegistry.getInstrumentation();
1065 }
1066
Felipe Lemeca5002f2016-08-03 11:51:00 -07001067 private static void sleep(long ms) {
1068 Log.d(TAG, "sleeping for " + ms + "ms");
1069 SystemClock.sleep(ms);
1070 Log.d(TAG, "woke up");
1071 }
1072
Felipe Lemed1e0f122015-12-18 16:12:41 -08001073 /**
Felipe Lemebc73ffc2015-12-11 15:07:14 -08001074 * Helper class containing the UiObjects present in the bugreport info dialog.
1075 */
1076 private final class DetailsUi {
1077
1078 final UiObject detailsButton;
1079 final UiObject nameField;
1080 final UiObject titleField;
1081 final UiObject descField;
1082 final UiObject okButton;
1083 final UiObject cancelButton;
1084
1085 /**
Felipe Lemeca5002f2016-08-03 11:51:00 -07001086 * Gets the UI objects by opening the progress notification and clicking on DETAILS.
1087 *
1088 * @param id bugreport id
1089 * @param id bugreport name
Felipe Lemebc73ffc2015-12-11 15:07:14 -08001090 */
Felipe Lemeca5002f2016-08-03 11:51:00 -07001091 DetailsUi(UiBot uiBot, int id, String name) throws UiObjectNotFoundException {
1092 this(uiBot, id, name, true);
Felipe Lemedb313632016-02-25 17:06:58 -08001093 }
1094
1095 /**
1096 * Gets the UI objects by opening the progress notification and clicking on DETAILS or in
1097 * the notification itself.
Felipe Lemeca5002f2016-08-03 11:51:00 -07001098 *
1099 * @param id bugreport id
1100 * @param id bugreport name
Felipe Lemedb313632016-02-25 17:06:58 -08001101 */
Felipe Lemeca5002f2016-08-03 11:51:00 -07001102 DetailsUi(UiBot uiBot, int id, String name, boolean clickDetails)
1103 throws UiObjectNotFoundException {
1104 final UiObject notification = openProgressNotification(name);
Felipe Leme26288782016-02-25 12:10:43 -08001105 detailsButton = mUiBot.getVisibleObject(mContext.getString(
1106 R.string.bugreport_info_action).toUpperCase());
1107
Felipe Lemedb313632016-02-25 17:06:58 -08001108 if (clickDetails) {
1109 mUiBot.click(detailsButton, "details_button");
1110 } else {
1111 mUiBot.click(notification, "notification");
1112 }
Felipe Lemebc73ffc2015-12-11 15:07:14 -08001113 // TODO: unhardcode resource ids
Felipe Lemee86b63b2016-02-08 09:39:50 -08001114 UiObject dialogTitle = mUiBot.getVisibleObjectById("android:id/alertTitle");
1115 assertEquals("Wrong title", mContext.getString(R.string.bugreport_info_dialog_title,
Felipe Leme85ae3cf2016-02-24 15:36:50 -08001116 id), dialogTitle.getText().toString());
Felipe Lemebc73ffc2015-12-11 15:07:14 -08001117 nameField = mUiBot.getVisibleObjectById("com.android.shell:id/name");
1118 titleField = mUiBot.getVisibleObjectById("com.android.shell:id/title");
1119 descField = mUiBot.getVisibleObjectById("com.android.shell:id/description");
1120 okButton = mUiBot.getObjectById("android:id/button1");
1121 cancelButton = mUiBot.getObjectById("android:id/button2");
1122 }
1123
Felipe Leme208b1882016-03-14 18:03:41 -07001124 private void assertField(String name, UiObject field, String expected)
1125 throws UiObjectNotFoundException {
1126 String actual = field.getText().toString();
1127 assertEquals("Wrong value on field '" + name + "'", expected, actual);
Felipe Leme26288782016-02-25 12:10:43 -08001128 }
1129
Felipe Leme208b1882016-03-14 18:03:41 -07001130 void assertName(String expected) throws UiObjectNotFoundException {
Felipe Leme26288782016-02-25 12:10:43 -08001131 assertField("name", nameField, expected);
1132 }
1133
Felipe Leme208b1882016-03-14 18:03:41 -07001134 void assertTitle(String expected) throws UiObjectNotFoundException {
Felipe Leme26288782016-02-25 12:10:43 -08001135 assertField("title", titleField, expected);
1136 }
1137
Felipe Leme208b1882016-03-14 18:03:41 -07001138 void assertDescription(String expected) throws UiObjectNotFoundException {
Felipe Leme26288782016-02-25 12:10:43 -08001139 assertField("description", descField, expected);
1140 }
1141
Felipe Lemebc73ffc2015-12-11 15:07:14 -08001142 /**
Felipe Leme208b1882016-03-14 18:03:41 -07001143 * Set focus on the name field so it can be validated once focus is lost.
1144 */
1145 void focusOnName() throws UiObjectNotFoundException {
1146 mUiBot.click(nameField, "name_field");
1147 assertTrue("name_field not focused", nameField.isFocused());
1148 }
1149
1150 /**
Felipe Lemebc73ffc2015-12-11 15:07:14 -08001151 * Takes focus away from the name field so it can be validated.
1152 */
Felipe Leme208b1882016-03-14 18:03:41 -07001153 void focusAwayFromName() throws UiObjectNotFoundException {
Felipe Lemebc73ffc2015-12-11 15:07:14 -08001154 mUiBot.click(titleField, "title_field"); // Change focus.
Felipe Leme208b1882016-03-14 18:03:41 -07001155 assertFalse("name_field is focused", nameField.isFocused());
Felipe Lemebc73ffc2015-12-11 15:07:14 -08001156 }
1157
Felipe Lemeca5002f2016-08-03 11:51:00 -07001158 void reOpen(String name) {
1159 openProgressNotification(name);
Felipe Lemebc73ffc2015-12-11 15:07:14 -08001160 mUiBot.click(detailsButton, "details_button");
Felipe Lemebc73ffc2015-12-11 15:07:14 -08001161 }
1162
1163 void clickOk() {
1164 mUiBot.click(okButton, "details_ok_button");
1165 }
1166
1167 void clickCancel() {
1168 mUiBot.click(cancelButton, "details_cancel_button");
1169 }
1170 }
Felipe Lemee53e85f2015-11-17 17:37:53 -08001171}