blob: e8a80d9f587d2b519ad35be81f1425b2adb80e07 [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.statusbar.policy;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;
import android.app.Notification;
import android.os.*;
import android.service.notification.StatusBarNotification;
import com.android.systemui.SwipeHelper;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
/**
* Test the Heads Up Notification.
*
* Specifically the policy that a notificaiton must remain visibile for a minimum period of time.
*/
public class HeadsUpNotificationTest extends SysuiTestCase {
private static final String TAG = "HeadsUpNotificationTest";
private static int TOUCH_SENSITIVITY = 100;
private static int NOTIFICATION_DECAY = 10000;
private static int MINIMUM_DISPLAY_TIME = 3000;
private static int SNOOZE_TIME = 60000;
private static long TOO_SOON = 1000L; // less than MINIMUM_DISPLAY_TIME
private static long LATER = 5000L; // more than MINIMUM_DISPLAY_TIME
private static long REMAINING_VISIBILITY = MINIMUM_DISPLAY_TIME - TOO_SOON;
protected HeadsUpNotificationView mHeadsUp;
@Mock protected PhoneStatusBar mMockStatusBar;
@Mock private HeadsUpNotificationView.Clock mClock;
@Mock private SwipeHelper mMockSwipeHelper;
@Mock private HeadsUpNotificationView.EdgeSwipeHelper mMockEdgeSwipeHelper;
@Override
protected void setUp() throws Exception {
super.setUp();
MockitoAnnotations.initMocks(this);
mHeadsUp = new HeadsUpNotificationView(mContext,
mClock, mMockSwipeHelper, mMockEdgeSwipeHelper,
NOTIFICATION_DECAY, MINIMUM_DISPLAY_TIME, TOUCH_SENSITIVITY, SNOOZE_TIME);
mHeadsUp.setBar(mMockStatusBar);
}
private NotificationData.Entry makeNotification(String key) {
StatusBarNotification sbn = mock(StatusBarNotification.class);
when(sbn.getKey()).thenReturn(key);
return new NotificationData.Entry(sbn, null);
}
public void testPostAndDecay() {
NotificationData.Entry a = makeNotification("a");
mHeadsUp.showNotification(a);
Mockito.verify(mMockStatusBar, never()).scheduleHeadsUpClose();
Mockito.verify(mMockStatusBar, times(1)).scheduleHeadsUpOpen();
ArgumentCaptor<Long> decayArg = ArgumentCaptor.forClass(Long.class);
Mockito.verify(mMockStatusBar).scheduleHeadsUpDecay(decayArg.capture());
// New notification gets a full decay time.
assertEquals(NOTIFICATION_DECAY, (long) decayArg.getValue());
}
public void testPostAndDeleteTooSoon() {
when(mClock.currentTimeMillis()).thenReturn(0L);
NotificationData.Entry a = makeNotification("a");
mHeadsUp.showNotification(a);
reset(mMockStatusBar);
when(mClock.currentTimeMillis()).thenReturn(TOO_SOON);
mHeadsUp.removeNotification(a.key);
ArgumentCaptor<Long> decayArg = ArgumentCaptor.forClass(Long.class);
Mockito.verify(mMockStatusBar, never()).scheduleHeadsUpClose();
Mockito.verify(mMockStatusBar).scheduleHeadsUpDecay(decayArg.capture());
// Leave the window up for the balance of the minumum time.
assertEquals(REMAINING_VISIBILITY, (long) decayArg.getValue());
}
public void testPostAndDeleteLater() {
when(mClock.currentTimeMillis()).thenReturn(0L);
NotificationData.Entry a = makeNotification("a");
mHeadsUp.showNotification(a);
reset(mMockStatusBar);
when(mClock.currentTimeMillis()).thenReturn(LATER);
mHeadsUp.removeNotification(a.key);
// Delete closes immediately if the minimum time window is satisfied.
Mockito.verify(mMockStatusBar, times(1)).scheduleHeadsUpClose();
Mockito.verify(mMockStatusBar, never()).scheduleHeadsUpDecay(anyInt());
}
// This is a bad test. It should not care that there is a call to scheduleHeadsUpClose(),
// but it happens that there will be one, so it is important that it happen before the
// call to scheduleHeadsUpOpen(), so that the final state is open.
// Maybe mMockStatusBar should instead be a fake that tracks the open/closed state.
public void testPostAndReplaceTooSoon() {
InOrder callOrder = inOrder(mMockStatusBar);
when(mClock.currentTimeMillis()).thenReturn(0L);
NotificationData.Entry a = makeNotification("a");
mHeadsUp.showNotification(a);
reset(mMockStatusBar);
when(mClock.currentTimeMillis()).thenReturn(TOO_SOON);
NotificationData.Entry b = makeNotification("b");
mHeadsUp.showNotification(b);
Mockito.verify(mMockStatusBar, times(1)).scheduleHeadsUpClose();
ArgumentCaptor<Long> decayArg = ArgumentCaptor.forClass(Long.class);
Mockito.verify(mMockStatusBar, times(1)).scheduleHeadsUpDecay(decayArg.capture());
// New notification gets a full decay time.
assertEquals(NOTIFICATION_DECAY, (long) decayArg.getValue());
// Make sure close was called before open, so that the heads up stays open.
callOrder.verify(mMockStatusBar).scheduleHeadsUpClose();
callOrder.verify(mMockStatusBar).scheduleHeadsUpOpen();
}
public void testPostAndUpdateAlertAgain() {
when(mClock.currentTimeMillis()).thenReturn(0L);
NotificationData.Entry a = makeNotification("a");
mHeadsUp.showNotification(a);
reset(mMockStatusBar);
when(mClock.currentTimeMillis()).thenReturn(TOO_SOON);
mHeadsUp.updateNotification(a, true);
Mockito.verify(mMockStatusBar, never()).scheduleHeadsUpClose();
ArgumentCaptor<Long> decayArg = ArgumentCaptor.forClass(Long.class);
Mockito.verify(mMockStatusBar, times(1)).scheduleHeadsUpDecay(decayArg.capture());
// Alert again gets a full decay time.
assertEquals(NOTIFICATION_DECAY, (long) decayArg.getValue());
}
public void testPostAndUpdateAlertAgainFastFail() {
when(mClock.currentTimeMillis()).thenReturn(0L);
NotificationData.Entry a = makeNotification("a");
mHeadsUp.showNotification(a);
reset(mMockStatusBar);
when(mClock.currentTimeMillis()).thenReturn(TOO_SOON);
NotificationData.Entry a_prime = makeNotification("a");
mHeadsUp.updateNotification(a_prime, true);
Mockito.verify(mMockStatusBar, never()).scheduleHeadsUpClose();
ArgumentCaptor<Long> decayArg = ArgumentCaptor.forClass(Long.class);
Mockito.verify(mMockStatusBar, times(1)).scheduleHeadsUpDecay(decayArg.capture());
// Alert again gets a full decay time.
assertEquals(NOTIFICATION_DECAY, (long) decayArg.getValue());
}
public void testPostAndUpdateNoAlertAgain() {
when(mClock.currentTimeMillis()).thenReturn(0L);
NotificationData.Entry a = makeNotification("a");
mHeadsUp.showNotification(a);
reset(mMockStatusBar);
when(mClock.currentTimeMillis()).thenReturn(TOO_SOON);
mHeadsUp.updateNotification(a, false);
Mockito.verify(mMockStatusBar, never()).scheduleHeadsUpClose();
Mockito.verify(mMockStatusBar, never()).scheduleHeadsUpDecay(anyInt());
}
public void testPostAndUpdateNoAlertAgainFastFail() {
when(mClock.currentTimeMillis()).thenReturn(0L);
NotificationData.Entry a = makeNotification("a");
mHeadsUp.showNotification(a);
reset(mMockStatusBar);
when(mClock.currentTimeMillis()).thenReturn(TOO_SOON);
NotificationData.Entry a_prime = makeNotification("a");
mHeadsUp.updateNotification(a_prime, false);
Mockito.verify(mMockStatusBar, never()).scheduleHeadsUpClose();
Mockito.verify(mMockStatusBar, never()).scheduleHeadsUpDecay(anyInt());
}
public void testPostAndUpdateLowPriorityTooSoon() {
when(mClock.currentTimeMillis()).thenReturn(0L);
NotificationData.Entry a = makeNotification("a");
mHeadsUp.showNotification(a);
reset(mMockStatusBar);
when(mClock.currentTimeMillis()).thenReturn(TOO_SOON);
mHeadsUp.release();
Mockito.verify(mMockStatusBar, never()).scheduleHeadsUpClose();
ArgumentCaptor<Long> decayArg = ArgumentCaptor.forClass(Long.class);
Mockito.verify(mMockStatusBar, times(1)).scheduleHeadsUpDecay(decayArg.capture());
// Down grade on update leaves the window up for the balance of the minumum time.
assertEquals(REMAINING_VISIBILITY, (long) decayArg.getValue());
}
public void testPostAndUpdateLowPriorityTooSoonFastFail() {
when(mClock.currentTimeMillis()).thenReturn(0L);
NotificationData.Entry a = makeNotification("a");
mHeadsUp.showNotification(a);
reset(mMockStatusBar);
when(mClock.currentTimeMillis()).thenReturn(TOO_SOON);
NotificationData.Entry a_prime = makeNotification("a");
mHeadsUp.updateNotification(a_prime, false);
mHeadsUp.release();
Mockito.verify(mMockStatusBar, never()).scheduleHeadsUpClose();
ArgumentCaptor<Long> decayArg = ArgumentCaptor.forClass(Long.class);
Mockito.verify(mMockStatusBar, times(1)).scheduleHeadsUpDecay(decayArg.capture());
// Down grade on update leaves the window up for the balance of the minumum time.
assertEquals(REMAINING_VISIBILITY, (long) decayArg.getValue());
}
public void testPostAndUpdateLowPriorityLater() {
when(mClock.currentTimeMillis()).thenReturn(0L);
NotificationData.Entry a = makeNotification("a");
mHeadsUp.showNotification(a);
reset(mMockStatusBar);
when(mClock.currentTimeMillis()).thenReturn(LATER);
mHeadsUp.release();
// Down grade on update closes immediately if the minimum time window is satisfied.
Mockito.verify(mMockStatusBar, times(1)).scheduleHeadsUpClose();
Mockito.verify(mMockStatusBar, never()).scheduleHeadsUpDecay(anyInt());
}
public void testPostAndUpdateLowPriorityLaterFastFail() {
when(mClock.currentTimeMillis()).thenReturn(0L);
NotificationData.Entry a = makeNotification("a");
mHeadsUp.showNotification(a);
reset(mMockStatusBar);
when(mClock.currentTimeMillis()).thenReturn(LATER);
NotificationData.Entry a_prime = makeNotification("a");
mHeadsUp.updateNotification(a_prime, false);
mHeadsUp.release();
// Down grade on update closes immediately if the minimum time window is satisfied.
Mockito.verify(mMockStatusBar, times(1)).scheduleHeadsUpClose();
Mockito.verify(mMockStatusBar, never()).scheduleHeadsUpDecay(anyInt());
}
}