BugreportReceiverTest.java revision ba477939f0ae38926b4b0a6501a2371acc612433
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;
56e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.util.Log;
57e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
58e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport com.android.shell.ActionSendMultipleConsumerActivity.CustomActionSendMultipleListener;
59e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
60e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme/**
61e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * Integration tests for {@link BugreportReceiver}.
62e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <p>
63e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * These tests don't mock any component and rely on external UI components (like the notification
64e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * bar and activity chooser), which can make them unreliable and slow.
65e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <p>
66e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * The general workflow is:
67e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <ul>
68e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <li>creates the bug report files
69e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <li>generates the BUGREPORT_FINISHED intent
70e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <li>emulate user actions to share the intent with a custom activity
71e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <li>asserts the extras received by the custom activity
72e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * </ul>
73e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * <p>
746bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme * <strong>NOTE</strong>: these tests only work if the device is unlocked.
75e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme */
76e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemepublic class BugreportReceiverTest extends InstrumentationTestCase {
77e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
78e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String TAG = "BugreportReceiverTest";
79e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
80e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    // Timeout for UI operations, in milliseconds.
81e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final int TIMEOUT = 1000;
82e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
83e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String ROOT_DIR = "/data/data/com.android.shell/files/bugreports";
84e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String BUGREPORT_FILE = "test_bugreport.txt";
85e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String ZIP_FILE = "test_bugreport.zip";
86e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String PLAIN_TEXT_PATH = ROOT_DIR + "/" + BUGREPORT_FILE;
87e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String ZIP_PATH = ROOT_DIR + "/" + ZIP_FILE;
88e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String SCREENSHOT_PATH = ROOT_DIR + "/test_screenshot.png";
89e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
90e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String BUGREPORT_CONTENT = "Dump, might as well dump!\n";
91e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static final String SCREENSHOT_CONTENT = "A picture is worth a thousand words!\n";
92e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
93e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private Context mContext;
94e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private UiBot mUiBot;
95e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private CustomActionSendMultipleListener mListener;
96e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
97e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    @Override
98e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    protected void setUp() throws Exception {
99e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Instrumentation instrumentation = getInstrumentation();
100e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        mContext = instrumentation.getTargetContext();
101e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        mUiBot = new UiBot(UiDevice.getInstance(instrumentation), TIMEOUT);
102e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        mListener = ActionSendMultipleConsumerActivity.getListener(mContext);
103e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        cancelExistingNotifications();
1046bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        BugreportPrefs.setWarningState(mContext, BugreportPrefs.STATE_HIDE);
105e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
106e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
10769c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme    public void testFullWorkflow() throws Exception {
10869c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        final String name = "BUG, Y U NO REPORT?";
10969c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        // TODO: call method to remove property instead
110719aaae3c167c2b15525dbe5c7db514a2c0c8269Felipe Leme        SystemProperties.set("dumpstate.42.progress", "0");
111719aaae3c167c2b15525dbe5c7db514a2c0c8269Felipe Leme        SystemProperties.set("dumpstate.42.max", "0");
11269c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
11369c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        Intent intent = new Intent(INTENT_BUGREPORT_STARTED);
11469c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        intent.putExtra(EXTRA_PID, 42);
11569c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        intent.putExtra(EXTRA_NAME, name);
11669c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        intent.putExtra(EXTRA_MAX, 1000);
11769c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        mContext.sendBroadcast(intent);
11869c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
11969c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        assertProgressNotification(name, "0.00%");
12069c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
12169c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        SystemProperties.set("dumpstate.42.progress", "108");
12269c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        assertProgressNotification(name, "10.80%");
12369c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
12469c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        SystemProperties.set("dumpstate.42.progress", "500");
12569c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        assertProgressNotification(name, "50.00%");
12669c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
127719aaae3c167c2b15525dbe5c7db514a2c0c8269Felipe Leme        SystemProperties.set("dumpstate.42.max", "2000");
128719aaae3c167c2b15525dbe5c7db514a2c0c8269Felipe Leme        assertProgressNotification(name, "25.00%");
129719aaae3c167c2b15525dbe5c7db514a2c0c8269Felipe Leme
13069c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        createTextFile(PLAIN_TEXT_PATH, BUGREPORT_CONTENT);
13169c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        createTextFile(SCREENSHOT_PATH, SCREENSHOT_CONTENT);
13269c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        Bundle extras = sendBugreportFinishedIntent(42, PLAIN_TEXT_PATH, SCREENSHOT_PATH);
13369c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);
13469c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
135ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme        String service = BugreportProgressService.class.getName();
136ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme        assertFalse("Service '" + service + "' is still running", isServiceRunning(service));
13769c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme    }
13869c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
1396bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme    public void testBugreportFinished_withWarning() throws Exception {
1406bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Explicitly shows the warning.
1416bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        BugreportPrefs.setWarningState(mContext, BugreportPrefs.STATE_SHOW);
1426bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
1436bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Send notification and click on share.
1446bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        createTextFile(PLAIN_TEXT_PATH, BUGREPORT_CONTENT);
1456bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        Intent intent = new Intent(INTENT_BUGREPORT_FINISHED);
1466bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        intent.putExtra(EXTRA_BUGREPORT, PLAIN_TEXT_PATH);
1476bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        mContext.sendBroadcast(intent);
1486bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        mUiBot.clickOnNotification(mContext.getString(R.string.bugreport_finished_title));
1496bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
1506bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Handle the warning
1516bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        mUiBot.getVisibleObject(mContext.getString(R.string.bugreport_confirm));
1526bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // TODO: get ok and showMessageAgain from the dialog reference above
1536bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        UiObject showMessageAgain =
1546bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme                mUiBot.getVisibleObject(mContext.getString(R.string.bugreport_confirm_repeat));
1556bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        mUiBot.click(showMessageAgain, "show-message-again");
1566bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        UiObject ok = mUiBot.getVisibleObject(mContext.getString(com.android.internal.R.string.ok));
1576bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        mUiBot.click(ok, "ok");
1586bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
1596bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Share the bugreport.
1606bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        mUiBot.chooseActivity(UI_NAME);
1616bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        Bundle extras = mListener.getExtras();
1626bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, null);
1636bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
1646bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        // Make sure it's hidden now.
1656bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        int newState = BugreportPrefs.getWarningState(mContext, BugreportPrefs.STATE_UNKNOWN);
1666bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme        assertEquals("Didn't change state", BugreportPrefs.STATE_HIDE, newState);
1676bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme    }
1686bbb6b9caf0e91afa11421e6d64a95a9ee4ca26eFelipe Leme
169e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    public void testBugreportFinished_plainBugreportAndScreenshot() throws Exception {
170e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        createTextFile(PLAIN_TEXT_PATH, BUGREPORT_CONTENT);
171e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        createTextFile(SCREENSHOT_PATH, SCREENSHOT_CONTENT);
172e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Bundle extras = sendBugreportFinishedIntent(PLAIN_TEXT_PATH, SCREENSHOT_PATH);
173e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);
174e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
175e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
176e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    public void testBugreportFinished_zippedBugreportAndScreenshot() throws Exception {
177e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        createZipFile(ZIP_PATH, BUGREPORT_FILE, BUGREPORT_CONTENT);
178e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        createTextFile(SCREENSHOT_PATH, SCREENSHOT_CONTENT);
179e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Bundle extras = sendBugreportFinishedIntent(ZIP_PATH, SCREENSHOT_PATH);
180e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);
181e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
182e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
183e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    public void testBugreportFinished_plainBugreportAndNoScreenshot() throws Exception {
184e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        createTextFile(PLAIN_TEXT_PATH, BUGREPORT_CONTENT);
185e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Bundle extras = sendBugreportFinishedIntent(PLAIN_TEXT_PATH, null);
186e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, null);
187e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
188e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
189e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    public void testBugreportFinished_zippedBugreportAndNoScreenshot() throws Exception {
190e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        createZipFile(ZIP_PATH, BUGREPORT_FILE, BUGREPORT_CONTENT);
191e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Bundle extras = sendBugreportFinishedIntent(ZIP_PATH, null);
192e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertActionSendMultiple(extras, BUGREPORT_CONTENT, null);
193e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
194e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
195e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void cancelExistingNotifications() {
196e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        NotificationManager nm = NotificationManager.from(mContext);
197e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        for (StatusBarNotification notification : nm.getActiveNotifications()) {
198e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            int id = notification.getId();
199e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            Log.i(TAG, "Canceling existing notification (id=" + id + ")");
200e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            nm.cancel(id);
201e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
202e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
203e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
20469c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme    private void assertProgressNotification(String name, String percent) {
20569c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        // TODO: it current looks for 3 distinct objects, without taking advantage of their
20669c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        // relationship.
20769c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        String title = mContext.getString(R.string.bugreport_in_progress_title);
20869c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        Log.v(TAG, "Looking for progress notification title: '" + title+ "'");
20969c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        mUiBot.getNotification(title);
21069c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        Log.v(TAG, "Looking for progress notification details: '" + name + "-" + percent + "'");
21169c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        mUiBot.getObject(name);
21269c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        mUiBot.getObject(percent);
21369c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme    }
21469c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
215e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    /**
216e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme     * Sends a "bugreport finished" intent and waits for the result.
217e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme     *
218e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme     * @return extras sent to the bugreport finished consumer.
219e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme     */
220e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private Bundle sendBugreportFinishedIntent(String bugreportPath, String screenshotPath) {
22169c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        return sendBugreportFinishedIntent(null, bugreportPath, screenshotPath);
22269c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme    }
22369c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme
22469c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme    private Bundle sendBugreportFinishedIntent(Integer pid, String bugreportPath,
22569c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme            String screenshotPath) {
22669c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        Intent intent = new Intent(INTENT_BUGREPORT_FINISHED);
22769c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        if (pid != null) {
22869c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme            intent.putExtra(EXTRA_PID, pid);
22969c0292affe8be51e10afb2dbf58f0133918a2c3Felipe Leme        }
230e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        if (bugreportPath != null) {
231e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            intent.putExtra(EXTRA_BUGREPORT, bugreportPath);
232e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
233e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        if (screenshotPath != null) {
234e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            intent.putExtra(EXTRA_SCREENSHOT, screenshotPath);
235e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
236e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
237e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        mContext.sendBroadcast(intent);
238e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
239e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        mUiBot.clickOnNotification(mContext.getString(R.string.bugreport_finished_title));
240e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        mUiBot.chooseActivity(UI_NAME);
241e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        return mListener.getExtras();
242e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
243e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
244e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    /**
245e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme     * Asserts the proper ACTION_SEND_MULTIPLE intent was sent.
246e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme     */
247e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void assertActionSendMultiple(Bundle extras, String bugreportContent,
248e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            String screenshotContent) throws IOException {
249e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        String body = extras.getString(Intent.EXTRA_TEXT);
250e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertContainsRegex("missing build info",
251e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                SystemProperties.get("ro.build.description"), body);
252e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertContainsRegex("missing serial number",
253e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                SystemProperties.get("ro.serialno"), body);
254e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
255e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertEquals("wrong subject", ZIP_FILE, extras.getString(Intent.EXTRA_SUBJECT));
256e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
257e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        List<Uri> attachments = extras.getParcelableArrayList(Intent.EXTRA_STREAM);
258e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        int expectedSize = screenshotContent != null ? 2 : 1;
259e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertEquals("wrong number of attachments", expectedSize, attachments.size());
260e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
261e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        // Need to interact through all attachments, since order is not guaranteed.
262e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Uri zipUri = null, screenshotUri = null;
263e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        for (Uri attachment : attachments) {
264e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            if (attachment.getPath().endsWith(".zip")) {
265e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                zipUri = attachment;
266e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            }
267e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            if (attachment.getPath().endsWith(".png")) {
268e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                screenshotUri = attachment;
269e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            }
270e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
271e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertNotNull("did not get .zip attachment", zipUri);
272e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        assertZipContent(zipUri, BUGREPORT_FILE, BUGREPORT_CONTENT);
273e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
274e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        if (screenshotContent != null) {
275e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            assertNotNull("did not get .png attachment", screenshotUri);
276e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            assertContent(screenshotUri, SCREENSHOT_CONTENT);
277e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        } else {
278e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            assertNull("should not have .png attachment", screenshotUri);
279e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
280e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
281e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
282e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void assertContent(Uri uri, String expectedContent) throws IOException {
283e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Log.v(TAG, "assertContents(uri=" + uri);
284e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        try (InputStream is = mContext.getContentResolver().openInputStream(uri)) {
285e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            String actualContent = new String(Streams.readFully(is));
286e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            assertEquals("wrong content for '" + uri + "'", expectedContent, actualContent);
287e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
288e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
289e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
290e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void assertZipContent(Uri uri, String entryName, String expectedContent)
291e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            throws IOException, IOException {
292e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Log.v(TAG, "assertZipEntry(uri=" + uri + ", entryName=" + entryName);
293e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        try (ZipInputStream zis = new ZipInputStream(mContext.getContentResolver().openInputStream(
294e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                uri))) {
295e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            ZipEntry entry;
296e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            while ((entry = zis.getNextEntry()) != null) {
297e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                Log.v(TAG, "Zip entry: " + entry.getName());
298e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                if (entry.getName().equals(entryName)) {
299e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
300e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    Streams.copy(zis, bos);
301e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    String actualContent = new String(bos.toByteArray(), "UTF-8");
302e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    bos.close();
303e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    assertEquals("wrong content for zip entry'" + entryName + "' on '" + uri + "'",
304e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                            expectedContent, actualContent);
305e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                    return;
306e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                }
307e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            }
308e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
309e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        fail("Did not find entry '" + entryName + "' on file '" + uri + "'");
310e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
311e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
312ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme    private boolean isServiceRunning(String name) {
313ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme        ActivityManager manager = (ActivityManager) mContext
314ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme                .getSystemService(Context.ACTIVITY_SERVICE);
315ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme        for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
316ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme            if (service.service.getClassName().equals(name)) {
317ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme                return true;
318ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme            }
319ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme        }
320ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme        return false;
321ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme    }
322ba477939f0ae38926b4b0a6501a2371acc612433Felipe Leme
323e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private static void createTextFile(String path, String content) throws IOException {
324e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Log.v(TAG, "createFile(" + path + ")");
325e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        try (Writer writer = new BufferedWriter(new OutputStreamWriter(
326e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                new FileOutputStream(path)))) {
327e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            writer.write(content);
328e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
329e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
330e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme
331e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    private void createZipFile(String path, String entryName, String content) throws IOException {
332e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        Log.v(TAG, "createZipFile(" + path + ", " + entryName + ")");
333e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        try (ZipOutputStream zos = new ZipOutputStream(
334e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme                new BufferedOutputStream(new FileOutputStream(path)))) {
335e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            ZipEntry entry = new ZipEntry(entryName);
336e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            zos.putNextEntry(entry);
337e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            byte[] data = content.getBytes();
338e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            zos.write(data, 0, data.length);
339e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme            zos.closeEntry();
340e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme        }
341e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme    }
342e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme}
343