Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 45c7d94d authored by Rhed Jao's avatar Rhed Jao
Browse files

Fix BugreportReceiverTest

- Implements a local binder and #onBind in the service to return the
  service instance.
- Mocks BugreportManager in the service to avoid service interacting
  with the dumpstate.
- Fixes dialog name field did not disable after service is finished.
- Fixes screenshot did not remove if the name is empty.
- Extends screenshot delay timeout in tests.
- Fine tune the UiBot to fit new bugreport notification.
- Removes obsolete cases in the tests.

Bug: 143130523
Test: atest BugreportReceiverTest
Change-Id: Iae89206da1d08a10891503869bbbf1ce18d4e31f
parent 65269996
Loading
Loading
Loading
Loading
+54 −12
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Binder;
import android.os.BugreportManager;
import android.os.BugreportManager.BugreportCallback;
import android.os.BugreportManager.BugreportCallback.BugreportErrorCode;
@@ -186,7 +187,7 @@ public class BugreportProgressService extends Service {
    static final int SCREENSHOT_DELAY_SECONDS = 3;

    /** System property where dumpstate stores last triggered bugreport id */
    private static final String PROPERTY_LAST_ID = "dumpstate.last_id";
    static final String PROPERTY_LAST_ID = "dumpstate.last_id";

    private static final String BUGREPORT_SERVICE = "bugreport";

@@ -233,7 +234,7 @@ public class BugreportProgressService extends Service {

    private File mBugreportsDir;

    private BugreportManager mBugreportManager;
    @VisibleForTesting BugreportManager mBugreportManager;

    /**
     * id of the notification used to set service on foreground.
@@ -248,6 +249,11 @@ public class BugreportProgressService extends Service {
     */
    private boolean mTakingScreenshot;

    /**
     * The delay timeout before taking a screenshot.
     */
    @VisibleForTesting int mScreenshotDelaySec = SCREENSHOT_DELAY_SECONDS;

    @GuardedBy("sNotificationBundle")
    private static final Bundle sNotificationBundle = new Bundle();

@@ -282,6 +288,7 @@ public class BugreportProgressService extends Service {
                        mContext.getString(R.string.bugreport_notification_channel),
                        isTv(this) ? NotificationManager.IMPORTANCE_DEFAULT
                                : NotificationManager.IMPORTANCE_LOW));
        mBugreportManager = mContext.getSystemService(BugreportManager.class);
    }

    @Override
@@ -305,7 +312,7 @@ public class BugreportProgressService extends Service {

    @Override
    public IBinder onBind(Intent intent) {
        return null;
        return new LocalBinder();
    }

    @Override
@@ -375,6 +382,7 @@ public class BugreportProgressService extends Service {
            mInfo.renameScreenshots();
            synchronized (mLock) {
                sendBugreportFinishedBroadcastLocked();
                mMainThreadHandler.post(() -> mInfoDialog.onBugreportFinished(mInfo));
            }
        }

@@ -624,8 +632,6 @@ public class BugreportProgressService extends Service {
            }
        }

        mBugreportManager = (BugreportManager) mContext.getSystemService(
                Context.BUGREPORT_SERVICE);
        final Executor executor = ActivityThread.currentActivityThread().getExecutor();

        Log.i(TAG, "bugreport type = " + bugreportType
@@ -885,12 +891,12 @@ public class BugreportProgressService extends Service {
        collapseNotificationBar();
        final String msg = mContext.getResources()
                .getQuantityString(com.android.internal.R.plurals.bugreport_countdown,
                        SCREENSHOT_DELAY_SECONDS, SCREENSHOT_DELAY_SECONDS);
                        mScreenshotDelaySec, mScreenshotDelaySec);
        Log.i(TAG, msg);
        // Show a toast just once, otherwise it might be captured in the screenshot.
        Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show();

        takeScreenshot(id, SCREENSHOT_DELAY_SECONDS);
        takeScreenshot(id, mScreenshotDelaySec);
    }

    /**
@@ -1619,6 +1625,16 @@ public class BugreportProgressService extends Service {
                || c == '_' || c == '-';
    }

    /**
     * A local binder with interface to return an instance of BugreportProgressService for the
     * purpose of testing.
     */
    final class LocalBinder extends Binder {
        @VisibleForTesting BugreportProgressService getService() {
            return BugreportProgressService.this;
        }
    }

    /**
     * Helper class encapsulating the UI elements and logic used to display a dialog where user
     * can change the details of a bugreport.
@@ -1748,6 +1764,22 @@ public class BugreportProgressService extends Service {
            }
        }

        /**
         * Notifies the dialog that the bugreport has finished so it disables the {@code name}
         * field.
         * <p>Once the bugreport is finished dumpstate has already generated the final files, so
         * changing the name would have no effect.
         */
        void onBugreportFinished(BugreportInfo info) {
            if (mId == info.id && mInfoName != null) {
                mInfoName.setEnabled(false);
                mInfoName.setText(null);
                if (!TextUtils.isEmpty(info.getName())) {
                    mInfoName.setText(info.getName());
                }
            }
        }

        void cancel() {
            if (mDialog != null) {
                mDialog.cancel();
@@ -1992,12 +2024,21 @@ public class BugreportProgressService extends Service {
                Log.i(TAG, "Deleting empty bugreport file: " + bugreportFile);
                bugreportFile.delete();
            }
            for (File file : screenshotFiles) {
                if (file.length() == 0) {
            deleteEmptyScreenshots();
        }

        /**
         * Deletes empty screenshot files.
         */
        private void deleteEmptyScreenshots() {
            screenshotFiles.removeIf(file -> {
                final long length = file.length();
                if (length == 0) {
                    Log.i(TAG, "Deleting empty screenshot file: " + file);
                    file.delete();
                }
            }
                return length == 0;
            });
        }

        /**
@@ -2005,7 +2046,8 @@ public class BugreportProgressService extends Service {
         * {@code initialName} if user has changed it.
         */
        void renameScreenshots() {
            if (TextUtils.isEmpty(name)) {
            deleteEmptyScreenshots();
            if (TextUtils.isEmpty(name) || screenshotFiles.isEmpty()) {
                return;
            }
            final List<File> renamedFiles = new ArrayList<>(screenshotFiles.size());
+246 −392

File changed.

Preview size limit exceeded, changes collapsed.

+59 −2
Original line number Diff line number Diff line
@@ -18,17 +18,23 @@ package com.android.shell;

import android.app.Instrumentation;
import android.app.StatusBarManager;
import android.os.SystemClock;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.UiObjectNotFoundException;
import android.support.test.uiautomator.UiSelector;
import android.support.test.uiautomator.Until;
import android.text.format.DateUtils;
import android.util.Log;

import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;

import java.util.List;

/**
 * A helper class for UI-related testing tasks.
 */
@@ -36,6 +42,9 @@ final class UiBot {

    private static final String TAG = "UiBot";
    private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
    private static final String ANDROID_PACKAGE = "android";

    private static final long SHORT_UI_TIMEOUT_MS = (3 * DateUtils.SECOND_IN_MILLIS);

    private final Instrumentation mInstrumentation;
    private final UiDevice mDevice;
@@ -48,9 +57,9 @@ final class UiBot {
    }

    /**
     * Opens the system notification and gets a given notification.
     * Opens the system notification and gets a UiObject with the text.
     *
     * @param text Notificaton's text as displayed by the UI.
     * @param text Notification's text as displayed by the UI.
     * @return notification object.
     */
    public UiObject getNotification(String text) {
@@ -62,6 +71,43 @@ final class UiBot {
        return getObject(text);
    }

    /**
     * Opens the system notification and gets a notification containing the text.
     *
     * @param text Notification's text as displayed by the UI.
     * @return notification object.
     */
    public UiObject2 getNotification2(String text) {
        boolean opened = mDevice.openNotification();
        Log.v(TAG, "openNotification(): " + opened);
        final UiObject2 notificationScroller = mDevice.wait(Until.findObject(
                By.res(SYSTEMUI_PACKAGE, "notification_stack_scroller")), mTimeout);
        assertNotNull("could not get notification stack scroller", notificationScroller);
        final List<UiObject2> notificationList = notificationScroller.getChildren();
        for (UiObject2 notification: notificationList) {
            final UiObject2 notificationText = notification.findObject(By.textContains(text));
            if (notificationText != null) {
                return notification;
            }
        }
        return null;
    }

    /**
     * Expands the notification.
     *
     * @param notification The notification object returned by {@link #getNotification2(String)}.
     */
    public void expandNotification(UiObject2 notification) {
        final UiObject2 expandBtn =  notification.findObject(
                By.res(ANDROID_PACKAGE, "expand_button"));
        if (expandBtn.getContentDescription().equals("Collapse")) {
            return;
        }
        expandBtn.click();
        mDevice.waitForIdle();
    }

    public void collapseStatusBar() throws Exception {
        // TODO: mDevice should provide such method..
        StatusBarManager sbm =
@@ -162,6 +208,12 @@ final class UiBot {
     */
    public void chooseActivity(String name) {
        // It uses an intent chooser now, so just getting the activity by text is enough...
        final String share = mInstrumentation.getContext().getString(
                com.android.internal.R.string.share);
        boolean gotIt = mDevice.wait(Until.hasObject(By.text(share)), mTimeout);
        assertTrue("could not get share activity (" + share + ")", gotIt);
        swipeUp();
        SystemClock.sleep(SHORT_UI_TIMEOUT_MS);
        UiObject activity = getObject(name);
        click(activity, name);
    }
@@ -173,6 +225,11 @@ final class UiBot {
    public void turnScreenOn() throws Exception {
        mDevice.executeShellCommand("input keyevent KEYCODE_WAKEUP");
        mDevice.executeShellCommand("wm dismiss-keyguard");
        mDevice.waitForIdle();
    }

    public void swipeUp() {
        mDevice.swipe(mDevice.getDisplayWidth() / 2, mDevice.getDisplayHeight() * 3 / 4,
                mDevice.getDisplayWidth() / 2, 0, 30);
    }
}