BugreportReceiverTest.java revision 2bfa0858a8cb67e19a1c9df8aad0a4da423a52b8
1e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme/*
2e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * Copyright (C) 2015 The Android Open Source Project
3e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme *
4e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * Licensed under the Apache License, Version 2.0 (the "License");
5e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * you may not use this file except in compliance with the License.
6e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * You may obtain a copy of the License at
7e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme *
8e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme *      http://www.apache.org/licenses/LICENSE-2.0
9e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme *
10e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * Unless required by applicable law or agreed to in writing, software
11e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * distributed under the License is distributed on an "AS IS" BASIS,
12e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * See the License for the specific language governing permissions and
14e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * limitations under the License.
15e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme */
16e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
17e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemepackage com.android.shell;
18e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
19e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport static android.test.MoreAsserts.assertContainsRegex;
20e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport static com.android.shell.ActionSendMultipleConsumerActivity.UI_NAME;
21b9238b37838d653c38ce4e712421adb61978fc22Felipe Lemeimport static com.android.shell.BugreportProgressService.EXTRA_BUGREPORT;
2269c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Lemeimport static com.android.shell.BugreportProgressService.EXTRA_MAX;
2369c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Lemeimport static com.android.shell.BugreportProgressService.EXTRA_NAME;
2469c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Lemeimport static com.android.shell.BugreportProgressService.EXTRA_PID;
25b9238b37838d653c38ce4e712421adb61978fc22Felipe Lemeimport static com.android.shell.BugreportProgressService.EXTRA_SCREENSHOT;
2669c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Lemeimport static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_FINISHED;
2769c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Lemeimport static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_STARTED;
28e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
29e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.BufferedOutputStream;
30e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.BufferedWriter;
31e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.ByteArrayOutputStream;
32e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.FileOutputStream;
33e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.IOException;
34e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.InputStream;
35e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.OutputStreamWriter;
36e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.io.Writer;
37e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.util.List;
38e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.util.zip.ZipEntry;
39e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.util.zip.ZipInputStream;
40e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport java.util.zip.ZipOutputStream;
41e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
42e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport libcore.io.Streams;
43ba477939f0ae38926b4b0a6501a2371acc612433Felipe Lemeimport android.app.ActivityManager;
44ba477939f0ae38926b4b0a6501a2371acc612433Felipe Lemeimport android.app.ActivityManager.RunningServiceInfo;
45e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.app.Instrumentation;
46e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.app.NotificationManager;
47e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.content.Context;
48e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.content.Intent;
49e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.net.Uri;
50e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.os.Bundle;
51e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.os.SystemProperties;
52e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.service.notification.StatusBarNotification;
53e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.support.test.uiautomator.UiDevice;
546bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Lemeimport android.support.test.uiautomator.UiObject;
55e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.test.InstrumentationTestCase;
562bfa0858a8cb67e19a1c9df8aad0a4da423a52b8Felipe Lemeimport android.test.suitebuilder.annotation.LargeTest;
57e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.util.Log;
58e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
59e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport com.android.shell.ActionSendMultipleConsumerActivity.CustomActionSendMultipleListener;
60e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
61e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme/**
62e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * Integration tests for {@link BugreportReceiver}.
63e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <p>
64e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * These tests don't mock any component and rely on external UI components (like the notification
65e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * bar and activity chooser), which can make them unreliable and slow.
66e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <p>
67e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * The general workflow is:
68e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <ul>
69e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <li>creates the bug report files
70e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <li>generates the BUGREPORT_FINISHED intent
71e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <li>emulate user actions to share the intent with a custom activity
72e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <li>asserts the extras received by the custom activity
73e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * </ul>
74e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <p>
756bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme * <strong>NOTE</strong>: these tests only work if the device is unlocked.
76e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme */
772bfa0858a8cb67e19a1c9df8aad0a4da423a52b8Felipe Leme@LargeTest
78e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemepublic class BugreportReceiverTest extends InstrumentationTestCase {
79e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
80e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String TAG = "BugreportReceiverTest";
81e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
82e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    // Timeout for UI operations, in milliseconds.
83e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final int TIMEOUT = 1000;
84e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
85e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String ROOT_DIR = "/data/data/com.android.shell/files/bugreports";
86e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String BUGREPORT_FILE = "test_bugreport.txt";
87e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String ZIP_FILE = "test_bugreport.zip";
88e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String PLAIN_TEXT_PATH = ROOT_DIR + "/" + BUGREPORT_FILE;
89e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String ZIP_PATH = ROOT_DIR + "/" + ZIP_FILE;
90e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String SCREENSHOT_PATH = ROOT_DIR + "/test_screenshot.png";
91e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
92e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String BUGREPORT_CONTENT = "Dump, might as well dump!\n";
93e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String SCREENSHOT_CONTENT = "A picture is worth a thousand words!\n";
94e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
95e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private Context mContext;
96e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private UiBot mUiBot;
97e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private CustomActionSendMultipleListener mListener;
98e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
99e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    @Override
100e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    protected void setUp() throws Exception {
101e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Instrumentation instrumentation = getInstrumentation();
102e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        mContext = instrumentation.getTargetContext();
103e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        mUiBot = new UiBot(UiDevice.getInstance(instrumentation), TIMEOUT);
104e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        mListener = ActionSendMultipleConsumerActivity.getListener(mContext);
105e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        cancelExistingNotifications();
1066bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        BugreportPrefs.setWarningState(mContext, BugreportPrefs.STATE_HIDE);
107e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
108e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
10969c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme    public void testFullWorkflow() throws Exception {
11069c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        final String name = "BUG, Y U NO REPORT?";
11169c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        // TODO: call method to remove property instead
112719aaae3c167c2b15525dbe5c7db514a2c0c8269Felipe Leme        SystemProperties.set("dumpstate.42.progress", "0");
113719aaae3c167c2b15525dbe5c7db514a2c0c8269Felipe Leme        SystemProperties.set("dumpstate.42.max", "0");
11469c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
11569c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        Intent intent = new Intent(INTENT_BUGREPORT_STARTED);
11669c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        intent.putExtra(EXTRA_PID, 42);
11769c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        intent.putExtra(EXTRA_NAME, name);
11869c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        intent.putExtra(EXTRA_MAX, 1000);
11969c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        mContext.sendBroadcast(intent);
12069c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
12169c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        assertProgressNotification(name, "0.00%");
12269c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
12369c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        SystemProperties.set("dumpstate.42.progress", "108");
12469c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        assertProgressNotification(name, "10.80%");
12569c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
12669c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        SystemProperties.set("dumpstate.42.progress", "500");
12769c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        assertProgressNotification(name, "50.00%");
12869c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
129719aaae3c167c2b15525dbe5c7db514a2c0c8269Felipe Leme        SystemProperties.set("dumpstate.42.max", "2000");
130719aaae3c167c2b15525dbe5c7db514a2c0c8269Felipe Leme        assertProgressNotification(name, "25.00%");
131719aaae3c167c2b15525dbe5c7db514a2c0c8269Felipe Leme
13269c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        createTextFile(PLAIN_TEXT_PATH, BUGREPORT_CONTENT);
13369c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        createTextFile(SCREENSHOT_PATH, SCREENSHOT_CONTENT);
13469c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        Bundle extras = sendBugreportFinishedIntent(42, PLAIN_TEXT_PATH, SCREENSHOT_PATH);
13569c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);
13669c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
137ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme        String service = BugreportProgressService.class.getName();
138ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme        assertFalse("Service '" + service + "' is still running", isServiceRunning(service));
13969c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme    }
14069c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
1416bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme    public void testBugreportFinished_withWarning() throws Exception {
1426bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Explicitly shows the warning.
1436bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        BugreportPrefs.setWarningState(mContext, BugreportPrefs.STATE_SHOW);
1446bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
1456bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Send notification and click on share.
1466bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        createTextFile(PLAIN_TEXT_PATH, BUGREPORT_CONTENT);
1476bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        Intent intent = new Intent(INTENT_BUGREPORT_FINISHED);
1486bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        intent.putExtra(EXTRA_BUGREPORT, PLAIN_TEXT_PATH);
1496bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        mContext.sendBroadcast(intent);
1506bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        mUiBot.clickOnNotification(mContext.getString(R.string.bugreport_finished_title));
1516bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
1526bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Handle the warning
1536bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        mUiBot.getVisibleObject(mContext.getString(R.string.bugreport_confirm));
1546bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // TODO: get ok and showMessageAgain from the dialog reference above
1556bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        UiObject showMessageAgain =
1566bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme                mUiBot.getVisibleObject(mContext.getString(R.string.bugreport_confirm_repeat));
1576bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        mUiBot.click(showMessageAgain, "show-message-again");
1586bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        UiObject ok = mUiBot.getVisibleObject(mContext.getString(com.android.internal.R.string.ok));
1596bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        mUiBot.click(ok, "ok");
1606bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
1616bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Share the bugreport.
1626bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        mUiBot.chooseActivity(UI_NAME);
1636bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        Bundle extras = mListener.getExtras();
1646bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, null);
1656bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
1666bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Make sure it's hidden now.
1676bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        int newState = BugreportPrefs.getWarningState(mContext, BugreportPrefs.STATE_UNKNOWN);
1686bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        assertEquals("Didn't change state", BugreportPrefs.STATE_HIDE, newState);
1696bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme    }
1706bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
171e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    public void testBugreportFinished_plainBugreportAndScreenshot() throws Exception {
172e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        createTextFile(PLAIN_TEXT_PATH, BUGREPORT_CONTENT);
173e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        createTextFile(SCREENSHOT_PATH, SCREENSHOT_CONTENT);
174e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Bundle extras = sendBugreportFinishedIntent(PLAIN_TEXT_PATH, SCREENSHOT_PATH);
175e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);
176e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
177e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
178e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    public void testBugreportFinished_zippedBugreportAndScreenshot() throws Exception {
179e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        createZipFile(ZIP_PATH, BUGREPORT_FILE, BUGREPORT_CONTENT);
180e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        createTextFile(SCREENSHOT_PATH, SCREENSHOT_CONTENT);
181e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Bundle extras = sendBugreportFinishedIntent(ZIP_PATH, SCREENSHOT_PATH);
182e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);
183e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
184e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
185e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    public void testBugreportFinished_plainBugreportAndNoScreenshot() throws Exception {
186e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        createTextFile(PLAIN_TEXT_PATH, BUGREPORT_CONTENT);
187e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Bundle extras = sendBugreportFinishedIntent(PLAIN_TEXT_PATH, null);
188e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, null);
189e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
190e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
191e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    public void testBugreportFinished_zippedBugreportAndNoScreenshot() throws Exception {
192e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        createZipFile(ZIP_PATH, BUGREPORT_FILE, BUGREPORT_CONTENT);
193e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Bundle extras = sendBugreportFinishedIntent(ZIP_PATH, null);
194e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, null);
195e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
196e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
197e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void cancelExistingNotifications() {
198e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        NotificationManager nm = NotificationManager.from(mContext);
199e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        for (StatusBarNotification notification : nm.getActiveNotifications()) {
200e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            int id = notification.getId();
201e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            Log.i(TAG, "Canceling existing notification (id=" + id + ")");
202e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            nm.cancel(id);
203e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
204e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
205e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
20669c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme    private void assertProgressNotification(String name, String percent) {
20769c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        // TODO: it current looks for 3 distinct objects, without taking advantage of their
20869c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        // relationship.
20969c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        String title = mContext.getString(R.string.bugreport_in_progress_title);
21069c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        Log.v(TAG, "Looking for progress notification title: '" + title+ "'");
21169c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        mUiBot.getNotification(title);
21269c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        Log.v(TAG, "Looking for progress notification details: '" + name + "-" + percent + "'");
21369c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        mUiBot.getObject(name);
21469c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        mUiBot.getObject(percent);
21569c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme    }
21669c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
217e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    /**
218e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme     * Sends a "bugreport finished" intent and waits for the result.
219e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme     *
220e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme     * @return extras sent to the bugreport finished consumer.
221e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme     */
222e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private Bundle sendBugreportFinishedIntent(String bugreportPath, String screenshotPath) {
22369c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        return sendBugreportFinishedIntent(null, bugreportPath, screenshotPath);
22469c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme    }
22569c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
22669c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme    private Bundle sendBugreportFinishedIntent(Integer pid, String bugreportPath,
22769c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme            String screenshotPath) {
22869c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        Intent intent = new Intent(INTENT_BUGREPORT_FINISHED);
22969c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        if (pid != null) {
23069c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme            intent.putExtra(EXTRA_PID, pid);
23169c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        }
232e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        if (bugreportPath != null) {
233e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            intent.putExtra(EXTRA_BUGREPORT, bugreportPath);
234e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
235e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        if (screenshotPath != null) {
236e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            intent.putExtra(EXTRA_SCREENSHOT, screenshotPath);
237e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
238e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
239e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        mContext.sendBroadcast(intent);
240e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
241e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        mUiBot.clickOnNotification(mContext.getString(R.string.bugreport_finished_title));
242e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        mUiBot.chooseActivity(UI_NAME);
243e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        return mListener.getExtras();
244e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
245e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
246e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    /**
247e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme     * Asserts the proper ACTION_SEND_MULTIPLE intent was sent.
248e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme     */
249e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void assertActionSendMultiple(Bundle extras, String bugreportContent,
250e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            String screenshotContent) throws IOException {
251e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        String body = extras.getString(Intent.EXTRA_TEXT);
252e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertContainsRegex("missing build info",
253e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                SystemProperties.get("ro.build.description"), body);
254e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertContainsRegex("missing serial number",
255e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                SystemProperties.get("ro.serialno"), body);
256e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
257e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertEquals("wrong subject", ZIP_FILE, extras.getString(Intent.EXTRA_SUBJECT));
258e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
259e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        List<Uri> attachments = extras.getParcelableArrayList(Intent.EXTRA_STREAM);
260e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        int expectedSize = screenshotContent != null ? 2 : 1;
261e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertEquals("wrong number of attachments", expectedSize, attachments.size());
262e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
263e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        // Need to interact through all attachments, since order is not guaranteed.
264e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Uri zipUri = null, screenshotUri = null;
265e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        for (Uri attachment : attachments) {
266e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            if (attachment.getPath().endsWith(".zip")) {
267e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                zipUri = attachment;
268e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            }
269e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            if (attachment.getPath().endsWith(".png")) {
270e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                screenshotUri = attachment;
271e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            }
272e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
273e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertNotNull("did not get .zip attachment", zipUri);
274e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertZipContent(zipUri, BUGREPORT_FILE, BUGREPORT_CONTENT);
275e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
276e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        if (screenshotContent != null) {
277e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            assertNotNull("did not get .png attachment", screenshotUri);
278e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            assertContent(screenshotUri, SCREENSHOT_CONTENT);
279e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        } else {
280e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            assertNull("should not have .png attachment", screenshotUri);
281e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
282e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
283e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
284e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void assertContent(Uri uri, String expectedContent) throws IOException {
285e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Log.v(TAG, "assertContents(uri=" + uri);
286e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        try (InputStream is = mContext.getContentResolver().openInputStream(uri)) {
287e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            String actualContent = new String(Streams.readFully(is));
288e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            assertEquals("wrong content for '" + uri + "'", expectedContent, actualContent);
289e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
290e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
291e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
292e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void assertZipContent(Uri uri, String entryName, String expectedContent)
293e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            throws IOException, IOException {
294e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Log.v(TAG, "assertZipEntry(uri=" + uri + ", entryName=" + entryName);
295e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        try (ZipInputStream zis = new ZipInputStream(mContext.getContentResolver().openInputStream(
296e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                uri))) {
297e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            ZipEntry entry;
298e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            while ((entry = zis.getNextEntry()) != null) {
299e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                Log.v(TAG, "Zip entry: " + entry.getName());
300e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                if (entry.getName().equals(entryName)) {
301e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
302e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    Streams.copy(zis, bos);
303e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    String actualContent = new String(bos.toByteArray(), "UTF-8");
304e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    bos.close();
305e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    assertEquals("wrong content for zip entry'" + entryName + "' on '" + uri + "'",
306e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                            expectedContent, actualContent);
307e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    return;
308e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                }
309e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            }
310e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
311e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        fail("Did not find entry '" + entryName + "' on file '" + uri + "'");
312e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
313e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
314ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme    private boolean isServiceRunning(String name) {
315ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme        ActivityManager manager = (ActivityManager) mContext
316ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme                .getSystemService(Context.ACTIVITY_SERVICE);
317ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme        for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
318ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme            if (service.service.getClassName().equals(name)) {
319ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme                return true;
320ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme            }
321ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme        }
322ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme        return false;
323ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme    }
324ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme
325e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static void createTextFile(String path, String content) throws IOException {
326e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Log.v(TAG, "createFile(" + path + ")");
327e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        try (Writer writer = new BufferedWriter(new OutputStreamWriter(
328e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                new FileOutputStream(path)))) {
329e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            writer.write(content);
330e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
331e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
332e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
333e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void createZipFile(String path, String entryName, String content) throws IOException {
334e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Log.v(TAG, "createZipFile(" + path + ", " + entryName + ")");
335e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        try (ZipOutputStream zos = new ZipOutputStream(
336e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                new BufferedOutputStream(new FileOutputStream(path)))) {
337e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            ZipEntry entry = new ZipEntry(entryName);
338e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            zos.putNextEntry(entry);
339e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            byte[] data = content.getBytes();
340e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            zos.write(data, 0, data.length);
341e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            zos.closeEntry();
342e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
343e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
344e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme}
345