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

Commit 9579d829 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Remove headsUpCommon, simplifies some code, adds tests" into qt-r1-bubbles-dev

parents 508b57ba c55b4122
Loading
Loading
Loading
Loading
+3 −2
Original line number Original line Diff line number Diff line
@@ -47,6 +47,7 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationFilter;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.collection.NotificationData;
import com.android.systemui.statusbar.notification.collection.NotificationData;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.DozeParameters;
@@ -217,8 +218,8 @@ public class SystemUIFactory {
    @Singleton
    @Singleton
    @Provides
    @Provides
    public NotificationInterruptionStateProvider provideNotificationInterruptionStateProvider(
    public NotificationInterruptionStateProvider provideNotificationInterruptionStateProvider(
            Context context) {
            Context context, NotificationFilter filter, StatusBarStateController controller) {
        return new NotificationInterruptionStateProvider(context);
        return new NotificationInterruptionStateProvider(context, filter, controller);
    }
    }


    @Singleton
    @Singleton
+94 −71
Original line number Original line Diff line number Diff line
@@ -23,7 +23,6 @@ import android.app.NotificationManager;
import android.content.Context;
import android.content.Context;
import android.database.ContentObserver;
import android.database.ContentObserver;
import android.hardware.display.AmbientDisplayConfiguration;
import android.hardware.display.AmbientDisplayConfiguration;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager;
@@ -32,7 +31,6 @@ import android.provider.Settings;
import android.service.dreams.DreamService;
import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
import android.service.dreams.IDreamManager;
import android.service.notification.StatusBarNotification;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import android.util.Log;
import android.util.Log;


import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
@@ -41,9 +39,10 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.HeadsUpManager;


import javax.inject.Inject;

/**
/**
 * Provides heads-up and pulsing state for notification entries.
 * Provides heads-up and pulsing state for notification entries.
 */
 */
@@ -54,9 +53,8 @@ public class NotificationInterruptionStateProvider {
    private static final boolean ENABLE_HEADS_UP = true;
    private static final boolean ENABLE_HEADS_UP = true;
    private static final String SETTING_HEADS_UP_TICKER = "ticker_gets_heads_up";
    private static final String SETTING_HEADS_UP_TICKER = "ticker_gets_heads_up";


    private final StatusBarStateController mStatusBarStateController =
    private final StatusBarStateController mStatusBarStateController;
            Dependency.get(StatusBarStateController.class);
    private final NotificationFilter mNotificationFilter;
    private final NotificationFilter mNotificationFilter = Dependency.get(NotificationFilter.class);
    private final AmbientDisplayConfiguration mAmbientDisplayConfiguration;
    private final AmbientDisplayConfiguration mAmbientDisplayConfiguration;


    private final Context mContext;
    private final Context mContext;
@@ -64,7 +62,6 @@ public class NotificationInterruptionStateProvider {
    private final IDreamManager mDreamManager;
    private final IDreamManager mDreamManager;


    private NotificationPresenter mPresenter;
    private NotificationPresenter mPresenter;
    private ShadeController mShadeController;
    private HeadsUpManager mHeadsUpManager;
    private HeadsUpManager mHeadsUpManager;
    private HeadsUpSuppressor mHeadsUpSuppressor;
    private HeadsUpSuppressor mHeadsUpSuppressor;


@@ -73,12 +70,16 @@ public class NotificationInterruptionStateProvider {
    protected boolean mUseHeadsUp = false;
    protected boolean mUseHeadsUp = false;
    private boolean mDisableNotificationAlerts;
    private boolean mDisableNotificationAlerts;


    public NotificationInterruptionStateProvider(Context context) {
    @Inject
    public NotificationInterruptionStateProvider(Context context, NotificationFilter filter,
            StatusBarStateController stateController) {
        this(context,
        this(context,
                (PowerManager) context.getSystemService(Context.POWER_SERVICE),
                (PowerManager) context.getSystemService(Context.POWER_SERVICE),
                IDreamManager.Stub.asInterface(
                IDreamManager.Stub.asInterface(
                        ServiceManager.checkService(DreamService.DREAM_SERVICE)),
                        ServiceManager.checkService(DreamService.DREAM_SERVICE)),
                new AmbientDisplayConfiguration(context));
                new AmbientDisplayConfiguration(context),
                filter,
                stateController);
    }
    }


    @VisibleForTesting
    @VisibleForTesting
@@ -86,11 +87,15 @@ public class NotificationInterruptionStateProvider {
            Context context,
            Context context,
            PowerManager powerManager,
            PowerManager powerManager,
            IDreamManager dreamManager,
            IDreamManager dreamManager,
            AmbientDisplayConfiguration ambientDisplayConfiguration) {
            AmbientDisplayConfiguration ambientDisplayConfiguration,
            NotificationFilter notificationFilter,
            StatusBarStateController statusBarStateController) {
        mContext = context;
        mContext = context;
        mPowerManager = powerManager;
        mPowerManager = powerManager;
        mDreamManager = dreamManager;
        mDreamManager = dreamManager;
        mAmbientDisplayConfiguration = ambientDisplayConfiguration;
        mAmbientDisplayConfiguration = ambientDisplayConfiguration;
        mNotificationFilter = notificationFilter;
        mStatusBarStateController = statusBarStateController;
    }
    }


    /** Sets up late-binding dependencies for this component. */
    /** Sets up late-binding dependencies for this component. */
@@ -98,11 +103,8 @@ public class NotificationInterruptionStateProvider {
            NotificationPresenter notificationPresenter,
            NotificationPresenter notificationPresenter,
            HeadsUpManager headsUpManager,
            HeadsUpManager headsUpManager,
            HeadsUpSuppressor headsUpSuppressor) {
            HeadsUpSuppressor headsUpSuppressor) {
        mPresenter = notificationPresenter;
        setUpWithPresenter(notificationPresenter, headsUpManager, headsUpSuppressor,
        mHeadsUpManager = headsUpManager;
                new ContentObserver(Dependency.get(Dependency.MAIN_HANDLER)) {
        mHeadsUpSuppressor = headsUpSuppressor;

        mHeadsUpObserver = new ContentObserver(Dependency.get(Dependency.MAIN_HANDLER)) {
                    @Override
                    @Override
                    public void onChange(boolean selfChange) {
                    public void onChange(boolean selfChange) {
                        boolean wasUsing = mUseHeadsUp;
                        boolean wasUsing = mUseHeadsUp;
@@ -115,12 +117,25 @@ public class NotificationInterruptionStateProvider {
                        if (wasUsing != mUseHeadsUp) {
                        if (wasUsing != mUseHeadsUp) {
                            if (!mUseHeadsUp) {
                            if (!mUseHeadsUp) {
                                Log.d(TAG,
                                Log.d(TAG,
                                "dismissing any existing heads up notification on disable event");
                                        "dismissing any existing heads up notification on disable"
                                                + " event");
                                mHeadsUpManager.releaseAllImmediately();
                                mHeadsUpManager.releaseAllImmediately();
                            }
                            }
                        }
                        }
                    }
                    }
        };
                });
    }

    /** Sets up late-binding dependencies for this component. */
    public void setUpWithPresenter(
            NotificationPresenter notificationPresenter,
            HeadsUpManager headsUpManager,
            HeadsUpSuppressor headsUpSuppressor,
            ContentObserver observer) {
        mPresenter = notificationPresenter;
        mHeadsUpManager = headsUpManager;
        mHeadsUpSuppressor = headsUpSuppressor;
        mHeadsUpObserver = observer;


        if (ENABLE_HEADS_UP) {
        if (ENABLE_HEADS_UP) {
            mContext.getContentResolver().registerContentObserver(
            mContext.getContentResolver().registerContentObserver(
@@ -134,13 +149,6 @@ public class NotificationInterruptionStateProvider {
        mHeadsUpObserver.onChange(true); // set up
        mHeadsUpObserver.onChange(true); // set up
    }
    }


    private ShadeController getShadeController() {
        if (mShadeController == null) {
            mShadeController = Dependency.get(ShadeController.class);
        }
        return mShadeController;
    }

    /**
    /**
     * Whether the notification should appear as a bubble with a fly-out on top of the screen.
     * Whether the notification should appear as a bubble with a fly-out on top of the screen.
     *
     *
@@ -149,6 +157,15 @@ public class NotificationInterruptionStateProvider {
     */
     */
    public boolean shouldBubbleUp(NotificationEntry entry) {
    public boolean shouldBubbleUp(NotificationEntry entry) {
        final StatusBarNotification sbn = entry.notification;
        final StatusBarNotification sbn = entry.notification;

        if (!canAlertCommon(entry)) {
            return false;
        }

        if (!canAlertAwakeCommon(entry)) {
            return false;
        }

        if (!entry.canBubble) {
        if (!entry.canBubble) {
            if (DEBUG) {
            if (DEBUG) {
                Log.d(TAG, "No bubble up: not allowed to bubble: " + sbn.getKey());
                Log.d(TAG, "No bubble up: not allowed to bubble: " + sbn.getKey());
@@ -173,10 +190,6 @@ public class NotificationInterruptionStateProvider {
            return false;
            return false;
        }
        }


        if (!canHeadsUpCommon(entry)) {
            return false;
        }

        return true;
        return true;
    }
    }


@@ -197,23 +210,34 @@ public class NotificationInterruptionStateProvider {
    private boolean shouldHeadsUpWhenAwake(NotificationEntry entry) {
    private boolean shouldHeadsUpWhenAwake(NotificationEntry entry) {
        StatusBarNotification sbn = entry.notification;
        StatusBarNotification sbn = entry.notification;


        boolean inShade = mStatusBarStateController.getState() == SHADE;
        if (!mUseHeadsUp) {
        if (entry.isBubble() && inShade) {
            if (DEBUG) {
            if (DEBUG) {
                Log.d(TAG, "No heads up: in unlocked shade where notification is shown as a "
                Log.d(TAG, "No heads up: no huns");
                        + "bubble: " + sbn.getKey());
            }
            }
            return false;
            return false;
        }
        }


        if (!canAlertCommon(entry)) {
        if (!canAlertCommon(entry)) {
            return false;
        }

        if (!canAlertAwakeCommon(entry)) {
            return false;
        }

        boolean inShade = mStatusBarStateController.getState() == SHADE;
        if (entry.isBubble() && inShade) {
            if (DEBUG) {
            if (DEBUG) {
                Log.d(TAG, "No heads up: notification shouldn't alert: " + sbn.getKey());
                Log.d(TAG, "No heads up: in unlocked shade where notification is shown as a "
                        + "bubble: " + sbn.getKey());
            }
            }
            return false;
            return false;
        }
        }


        if (!canHeadsUpCommon(entry)) {
        if (entry.shouldSuppressPeek()) {
            if (DEBUG) {
                Log.d(TAG, "No heads up: suppressed by DND: " + sbn.getKey());
            }
            return false;
            return false;
        }
        }


@@ -287,16 +311,13 @@ public class NotificationInterruptionStateProvider {
    }
    }


    /**
    /**
     * Common checks between regular heads up and when pulsing.  See
     * Common checks between regular & AOD heads up and bubbles.
     * {@link #shouldHeadsUp(NotificationEntry)} and
     * {@link #shouldHeadsUpWhenDozing(NotificationEntry)}.  Notifications that fail any of these
     * checks
     * should not alert at all.
     *
     *
     * @param entry the entry to check
     * @param entry the entry to check
     * @return true if these checks pass, false if the notification should not alert
     * @return true if these checks pass, false if the notification should not alert
     */
     */
    protected boolean canAlertCommon(NotificationEntry entry) {
    @VisibleForTesting
    public boolean canAlertCommon(NotificationEntry entry) {
        StatusBarNotification sbn = entry.notification;
        StatusBarNotification sbn = entry.notification;


        if (mNotificationFilter.shouldFilterOut(entry)) {
        if (mNotificationFilter.shouldFilterOut(entry)) {
@@ -313,46 +334,36 @@ public class NotificationInterruptionStateProvider {
            }
            }
            return false;
            return false;
        }
        }

        return true;
        return true;
    }
    }


    /**
    /**
     * Common checks between heads up alerting and bubble fly out alerting. See
     * Common checks between alerts that occur while the device is awake (heads up & bubbles).
     * {@link #shouldHeadsUp(NotificationEntry)} and
     * {@link #shouldBubbleUp(NotificationEntry)}. Notifications that fail any of these
     * checks should not interrupt the user on screen.
     *
     *
     * @param entry the entry to check
     * @param entry the entry to check
     * @return true if these checks pass, false if the notification should not interrupt on screen
     * @return true if these checks pass, false if the notification should not alert
     */
     */
    public boolean canHeadsUpCommon(NotificationEntry entry) {
    @VisibleForTesting
    public boolean canAlertAwakeCommon(NotificationEntry entry) {
        StatusBarNotification sbn = entry.notification;
        StatusBarNotification sbn = entry.notification;


        if (!mUseHeadsUp || mPresenter.isDeviceInVrMode()) {
        if (mPresenter.isDeviceInVrMode()) {
            if (DEBUG) {
                Log.d(TAG, "No heads up: no huns or vr mode");
            }
            return false;
        }

        if (entry.shouldSuppressPeek()) {
            if (DEBUG) {
            if (DEBUG) {
                Log.d(TAG, "No heads up: suppressed by DND: " + sbn.getKey());
                Log.d(TAG, "No alerting: no huns or vr mode");
            }
            }
            return false;
            return false;
        }
        }


        if (isSnoozedPackage(sbn)) {
        if (isSnoozedPackage(sbn)) {
            if (DEBUG) {
            if (DEBUG) {
                Log.d(TAG, "No heads up: snoozed package: " + sbn.getKey());
                Log.d(TAG, "No alerting: snoozed package: " + sbn.getKey());
            }
            }
            return false;
            return false;
        }
        }


        if (entry.hasJustLaunchedFullScreenIntent()) {
        if (entry.hasJustLaunchedFullScreenIntent()) {
            if (DEBUG) {
            if (DEBUG) {
                Log.d(TAG, "No heads up: recent fullscreen: " + sbn.getKey());
                Log.d(TAG, "No alerting: recent fullscreen: " + sbn.getKey());
            }
            }
            return false;
            return false;
        }
        }
@@ -370,6 +381,18 @@ public class NotificationInterruptionStateProvider {
        mHeadsUpObserver.onChange(true);
        mHeadsUpObserver.onChange(true);
    }
    }


    /** Whether all alerts are disabled. */
    @VisibleForTesting
    public boolean areNotificationAlertsDisabled() {
        return mDisableNotificationAlerts;
    }

    /** Whether HUNs should be used. */
    @VisibleForTesting
    public boolean getUseHeadsUp() {
        return mUseHeadsUp;
    }

    protected NotificationPresenter getPresenter() {
    protected NotificationPresenter getPresenter() {
        return mPresenter;
        return mPresenter;
    }
    }
+1 −1
Original line number Original line Diff line number Diff line
@@ -161,7 +161,7 @@ public final class NotificationEntry {
     * <p>When a notification is a bubble we don't show it in the shade once the bubble has been
     * <p>When a notification is a bubble we don't show it in the shade once the bubble has been
     * expanded</p>
     * expanded</p>
     */
     */
    private boolean mShowInShadeWhenBubble;
    private boolean mShowInShadeWhenBubble = true;


    /**
    /**
     * Whether the user has dismissed this notification when it was in bubble form.
     * Whether the user has dismissed this notification when it was in bubble form.
+0 −7
Original line number Original line Diff line number Diff line
@@ -2310,9 +2310,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView


    @Override
    @Override
    public int getIntrinsicHeight() {
    public int getIntrinsicHeight() {
        if (isShownAsBubble()) {
            return getMaxExpandHeight();
        }
        if (isUserLocked()) {
        if (isUserLocked()) {
            return getActualHeight();
            return getActualHeight();
        }
        }
@@ -2358,10 +2355,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
        return mStatusbarStateController != null && mStatusbarStateController.isDozing();
        return mStatusbarStateController != null && mStatusbarStateController.isDozing();
    }
    }


    private boolean isShownAsBubble() {
        return mEntry.isBubble() && !mEntry.showInShadeWhenBubble() && !mEntry.isBubbleDismissed();
    }

    @Override
    @Override
    public boolean isGroupExpanded() {
    public boolean isGroupExpanded() {
        return mGroupManager.isGroupExpanded(mStatusBarNotification);
        return mGroupManager.isGroupExpanded(mStatusBarNotification);
+8 −3
Original line number Original line Diff line number Diff line
@@ -57,11 +57,13 @@ import androidx.test.filters.SmallTest;


import com.android.systemui.R;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoveInterceptor;
import com.android.systemui.statusbar.NotificationRemoveInterceptor;
import com.android.systemui.statusbar.NotificationTestHelper;
import com.android.systemui.statusbar.NotificationTestHelper;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationFilter;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.collection.NotificationData;
import com.android.systemui.statusbar.notification.collection.NotificationData;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -171,7 +173,9 @@ public class BubbleControllerTest extends SysuiTestCase {
        when(mZenModeController.getConfig()).thenReturn(mZenModeConfig);
        when(mZenModeController.getConfig()).thenReturn(mZenModeConfig);


        TestableNotificationInterruptionStateProvider interruptionStateProvider =
        TestableNotificationInterruptionStateProvider interruptionStateProvider =
                new TestableNotificationInterruptionStateProvider(mContext);
                new TestableNotificationInterruptionStateProvider(mContext,
                        mock(NotificationFilter.class),
                        mock(StatusBarStateController.class));
        interruptionStateProvider.setUpWithPresenter(
        interruptionStateProvider.setUpWithPresenter(
                mock(NotificationPresenter.class),
                mock(NotificationPresenter.class),
                mock(HeadsUpManager.class),
                mock(HeadsUpManager.class),
@@ -647,8 +651,9 @@ public class BubbleControllerTest extends SysuiTestCase {
    public static class TestableNotificationInterruptionStateProvider extends
    public static class TestableNotificationInterruptionStateProvider extends
            NotificationInterruptionStateProvider {
            NotificationInterruptionStateProvider {


        public TestableNotificationInterruptionStateProvider(Context context) {
        public TestableNotificationInterruptionStateProvider(Context context,
            super(context);
                NotificationFilter filter, StatusBarStateController controller) {
            super(context, filter, controller);
            mUseHeadsUp = true;
            mUseHeadsUp = true;
        }
        }
    }
    }
Loading