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

Commit 31313008 authored by András Kurucz's avatar András Kurucz Committed by Android (Google) Code Review
Browse files

Merge "Don't suppress pulsing notifications if we are already pulsing" into main

parents eb553a4e 48f2781a
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -1074,3 +1074,13 @@ flag {
    purpose: PURPOSE_BUGFIX
  }
}

flag {
  name: "notification_pulsing_fix"
  namespace: "systemui"
  description: "Allow showing new pulsing notifications when the device is already pulsing."
  bug: "335560575"
  metadata {
    purpose: PURPOSE_BUGFIX
  }
}
+7 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.InstanceId;
import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.Flags;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dock.DockManager;
@@ -564,6 +565,12 @@ public class DozeTriggers implements DozeMachine.Part {
            return;
        }

        // When already in pulsing, we can show the new Notification without requesting a new pulse.
        if (Flags.notificationPulsingFix()
                && dozeState == State.DOZE_PULSING && reason == DozeLog.PULSE_REASON_NOTIFICATION) {
            return;
        }

        if (!mAllowPulseTriggers || mDozeHost.isPulsePending()
                || !canPulse(dozeState, performedProxCheck)) {
            if (!mAllowPulseTriggers) {
+71 −4
Original line number Diff line number Diff line
@@ -21,12 +21,14 @@ import static com.android.systemui.doze.DozeMachine.State.INITIALIZED;
import static com.android.systemui.doze.DozeMachine.State.UNINITIALIZED;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -35,6 +37,7 @@ import static org.mockito.Mockito.when;
import android.app.StatusBarManager;
import android.hardware.Sensor;
import android.hardware.display.AmbientDisplayConfiguration;
import android.platform.test.annotations.EnableFlags;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
import android.view.Display;
@@ -43,6 +46,7 @@ import androidx.test.filters.SmallTest;

import com.android.internal.logging.InstanceId;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.Flags;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.broadcast.BroadcastDispatcher;
@@ -71,6 +75,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

@@ -85,6 +90,7 @@ public class DozeTriggersTest extends SysuiTestCase {
    private DozeHost mHost;
    @Mock
    private BroadcastDispatcher mBroadcastDispatcher;
    private final AmbientDisplayConfiguration mConfig = DozeConfigurationUtil.createMockConfig();
    @Mock
    private DockManager mDockManager;
    @Mock
@@ -105,6 +111,8 @@ public class DozeTriggersTest extends SysuiTestCase {
    private SelectedUserInteractor mSelectedUserInteractor;
    @Mock
    private SessionTracker mSessionTracker;
    @Captor
    private ArgumentCaptor<DozeHost.Callback> mHostCallbackCaptor;

    private DozeTriggers mTriggers;
    private FakeSensorManager mSensors;
@@ -116,7 +124,7 @@ public class DozeTriggersTest extends SysuiTestCase {
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        setupDozeTriggers(
                DozeConfigurationUtil.createMockConfig(),
                mConfig,
                DozeConfigurationUtil.createMockParameters());
    }

@@ -173,11 +181,70 @@ public class DozeTriggersTest extends SysuiTestCase {
        verify(mMachine).requestPulse(anyInt());
    }

    @Test
    public void testOnNotification_startsPulseRequest() {
        // GIVEN device is dozing
        Runnable pulseSuppressListener = mock(Runnable.class);
        when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE);
        doAnswer(invocation -> null).when(mHost).addCallback(mHostCallbackCaptor.capture());
        mTriggers.transitionTo(UNINITIALIZED, DozeMachine.State.INITIALIZED);
        mTriggers.transitionTo(DozeMachine.State.INITIALIZED, DozeMachine.State.DOZE);
        clearInvocations(mMachine);

        // WHEN receive an alerting notification
        mHostCallbackCaptor.getValue().onNotificationAlerted(pulseSuppressListener);

        // THEN entering to pulse
        verify(mHost).setPulsePending(true);
        // AND suppress listeners are NOT notified
        verify(pulseSuppressListener, never()).run();
    }

    @Test
    public void testOnNotification_cannotPulse_notificationSuppressed() {
        // GIVEN device is dozing
        Runnable pulseSuppressListener = mock(Runnable.class);
        when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE);
        doAnswer(invocation -> null).when(mHost).addCallback(mHostCallbackCaptor.capture());
        mTriggers.transitionTo(UNINITIALIZED, DozeMachine.State.INITIALIZED);
        mTriggers.transitionTo(DozeMachine.State.INITIALIZED, DozeMachine.State.DOZE);
        clearInvocations(mMachine);
        // AND pulsing is disabled
        when(mConfig.pulseOnNotificationEnabled(anyInt())).thenReturn(false);

        // WHEN receive an alerting notification
        mHostCallbackCaptor.getValue().onNotificationAlerted(pulseSuppressListener);

        // THEN NOT starting pulse
        verify(mHost, never()).setPulsePending(anyBoolean());
        // AND the notification is suppressed
        verify(pulseSuppressListener).run();
    }

    @Test
    @EnableFlags(Flags.FLAG_NOTIFICATION_PULSING_FIX)
    public void testOnNotification_alreadyPulsing_notificationNotSuppressed() {
        // GIVEN device is pulsing
        Runnable pulseSuppressListener = mock(Runnable.class);
        when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE_PULSING);
        doAnswer(invocation -> null).when(mHost).addCallback(mHostCallbackCaptor.capture());
        mTriggers.transitionTo(UNINITIALIZED, DozeMachine.State.INITIALIZED);
        mTriggers.transitionTo(DozeMachine.State.INITIALIZED, DozeMachine.State.DOZE_PULSING);
        clearInvocations(mMachine);

        // WHEN receive an alerting notification
        mHostCallbackCaptor.getValue().onNotificationAlerted(pulseSuppressListener);

        // THEN entering to pulse
        verify(mHost, never()).setPulsePending(anyBoolean());
        // AND suppress listeners are NOT notified
        verify(pulseSuppressListener, never()).run();
    }

    @Test
    public void testOnNotification_noPulseIfPulseIsNotPendingAnymore() {
        when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE);
        ArgumentCaptor<DozeHost.Callback> captor = ArgumentCaptor.forClass(DozeHost.Callback.class);
        doAnswer(invocation -> null).when(mHost).addCallback(captor.capture());
        doAnswer(invocation -> null).when(mHost).addCallback(mHostCallbackCaptor.capture());

        mTriggers.transitionTo(UNINITIALIZED, DozeMachine.State.INITIALIZED);
        mTriggers.transitionTo(DozeMachine.State.INITIALIZED, DozeMachine.State.DOZE);
@@ -189,7 +256,7 @@ public class DozeTriggersTest extends SysuiTestCase {

        // WHEN prox check returns FAR
        mProximitySensor.setLastEvent(new ThresholdSensorEvent(false, 2));
        captor.getValue().onNotificationAlerted(null /* pulseSuppressedListener */);
        mHostCallbackCaptor.getValue().onNotificationAlerted(null /* pulseSuppressedListener */);
        mProximitySensor.alertListeners();

        // THEN don't request pulse because the pending pulse was abandoned early