blob: c8ebd1240149c37fe69dfe690b4975d805204f5a [file] [log] [blame]
/*
* Copyright (C) 2020 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.people.widget;
import static android.view.Display.DEFAULT_DISPLAY;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Intent;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import android.service.notification.NotificationListenerService;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
import androidx.test.filters.SmallTest;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
import com.android.systemui.wmshell.BubblesManager;
import com.android.wm.shell.bubbles.Bubble;
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;
import java.util.Optional;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
public class LaunchConversationActivityTest extends SysuiTestCase {
private static final String EMPTY_STRING = "";
private static final String PACKAGE_NAME = "com.android.systemui.tests";
private static final String NOTIF_KEY = "notifKey";
private static final String NOTIF_KEY_NO_ENTRY = "notifKeyNoEntry";
private static final String NOTIF_KEY_NO_RANKING = "notifKeyNoRanking";
private static final String NOTIF_KEY_CAN_BUBBLE = "notifKeyCanBubble";
private static final UserHandle USER_HANDLE = UserHandle.of(0);
private static final int NOTIF_COUNT = 10;
private static final int NOTIF_RANK = 2;
private LaunchConversationActivity mActivity;
@Mock
private NotificationVisibilityProvider mVisibilityProvider;
@Mock
private CommonNotifCollection mNotifCollection;
@Mock
private IStatusBarService mIStatusBarService;
@Mock
private NotificationEntry mNotifEntry;
@Mock
private NotificationEntry mNotifEntryNoRanking;
@Mock
private NotificationEntry mNotifEntryCanBubble;
@Mock
private BubblesManager mBubblesManager;
@Mock
private NotificationListenerService.Ranking mRanking;
@Mock
private UserManager mUserManager;
@Mock
private CommandQueue mCommandQueue;
@Captor
private ArgumentCaptor<NotificationVisibility> mNotificationVisibilityCaptor;
@Captor
private ArgumentCaptor<CommandQueue.Callbacks> mCallbacksCaptor;
private Intent mIntent;
private FakeSystemClock mFakeSystemClock = new FakeSystemClock();
private FakeExecutor mBgExecutor = new FakeExecutor(mFakeSystemClock);
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mActivity = new LaunchConversationActivity(
mVisibilityProvider,
mNotifCollection,
Optional.of(mBubblesManager),
mUserManager,
mCommandQueue,
mBgExecutor
);
verify(mCommandQueue, times(1)).addCallback(mCallbacksCaptor.capture());
mActivity.setIsForTesting(true, mIStatusBarService);
mIntent = new Intent();
mIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_TILE_ID, "tile ID");
mIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_PACKAGE_NAME, PACKAGE_NAME);
mIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_USER_HANDLE, USER_HANDLE);
when(mNotifCollection.getEntry(NOTIF_KEY)).thenReturn(mNotifEntry);
when(mNotifCollection.getEntry(NOTIF_KEY_NO_ENTRY)).thenReturn(null);
when(mNotifCollection.getEntry(NOTIF_KEY_NO_RANKING)).thenReturn(mNotifEntryNoRanking);
when(mNotifCollection.getEntry(NOTIF_KEY_CAN_BUBBLE)).thenReturn(mNotifEntryCanBubble);
when(mVisibilityProvider.obtain(anyString(), anyBoolean())).thenAnswer(
invocation-> {
String key = invocation.getArgument(0);
boolean visible = invocation.getArgument(1);
return NotificationVisibility.obtain(key, NOTIF_RANK, NOTIF_COUNT, visible);
});
when(mVisibilityProvider.obtain(any(NotificationEntry.class), anyBoolean())).thenAnswer(
invocation-> {
String key = invocation.<NotificationEntry>getArgument(0).getKey();
boolean visible = invocation.getArgument(1);
return NotificationVisibility.obtain(key, NOTIF_RANK, NOTIF_COUNT, visible);
});
when(mNotifEntry.getRanking()).thenReturn(mRanking);
when(mNotifEntryCanBubble.getRanking()).thenReturn(mRanking);
when(mNotifEntryCanBubble.canBubble()).thenReturn(true);
when(mNotifEntryNoRanking.getRanking()).thenReturn(null);
when(mUserManager.isQuietModeEnabled(any(UserHandle.class))).thenReturn(false);
}
@Test
public void testDoNotClearNotificationIfNoKey() throws Exception {
mIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_NOTIFICATION_KEY,
EMPTY_STRING);
mActivity.setIntent(mIntent);
mActivity.onCreate(new Bundle());
verify(mIStatusBarService, never()).onNotificationClear(
any(), anyInt(), any(), anyInt(), anyInt(), any());
}
@Test
public void testDoNotClearNotificationIfNoNotificationEntry() throws Exception {
mIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_NOTIFICATION_KEY,
NOTIF_KEY_NO_ENTRY);
mActivity.setIntent(mIntent);
mActivity.onCreate(new Bundle());
verify(mIStatusBarService, never()).onNotificationClear(
any(), anyInt(), any(), anyInt(), anyInt(), any());
}
@Test
public void testDoNotClearNotificationIfNoRanking() throws Exception {
mIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_NOTIFICATION_KEY,
NOTIF_KEY_NO_RANKING);
mActivity.setIntent(mIntent);
mActivity.onCreate(new Bundle());
verify(mIStatusBarService, never()).onNotificationClear(
any(), anyInt(), any(), anyInt(), anyInt(), any());
}
@Test
public void testEntryClearsNotificationAndDoesNotOpenBubble() throws Exception {
mIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_NOTIFICATION_KEY,
NOTIF_KEY);
mActivity.setIntent(mIntent);
mActivity.onCreate(new Bundle());
assertThat(mActivity.isFinishing()).isTrue();
mCallbacksCaptor.getValue().appTransitionFinished(DEFAULT_DISPLAY);
// Ensure callback removed
verify(mCommandQueue).removeCallback(any());
// Clear the notification for bubbles.
FakeExecutor.exhaustExecutors(mBgExecutor);
verify(mIStatusBarService, times(1)).onNotificationClear(any(),
anyInt(), any(), anyInt(), anyInt(), mNotificationVisibilityCaptor.capture());
// Do not select the bubble.
verify(mBubblesManager, never()).expandStackAndSelectBubble(any(Bubble.class));
verify(mBubblesManager, never()).expandStackAndSelectBubble(any(NotificationEntry.class));
NotificationVisibility nv = mNotificationVisibilityCaptor.getValue();
assertThat(nv.count).isEqualTo(NOTIF_COUNT);
assertThat(nv.rank).isEqualTo(NOTIF_RANK);
}
@Test
public void testBubbleEntryOpensBubbleAndDoesNotClearNotification() throws Exception {
when(mBubblesManager.getBubbleWithShortcutId(any())).thenReturn(null);
mIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_NOTIFICATION_KEY,
NOTIF_KEY_CAN_BUBBLE);
mActivity.setIntent(mIntent);
mActivity.onCreate(new Bundle());
assertThat(mActivity.isFinishing()).isTrue();
mCallbacksCaptor.getValue().appTransitionFinished(DEFAULT_DISPLAY);
// Ensure callback removed
verify(mCommandQueue).removeCallback(any());
// Don't clear the notification for bubbles.
verify(mIStatusBarService, never()).onNotificationClear(any(),
anyInt(), any(), anyInt(), anyInt(), any());
// Select the bubble.
verify(mBubblesManager, times(1)).getBubbleWithShortcutId(any());
verify(mBubblesManager, times(1)).expandStackAndSelectBubble(eq(mNotifEntryCanBubble));
}
@Test
public void testQuietModeOpensQuietModeDialog() throws Exception {
mIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_NOTIFICATION_KEY,
NOTIF_KEY);
when(mUserManager.isQuietModeEnabled(eq(USER_HANDLE))).thenReturn(true);
mActivity.setIntent(mIntent);
mActivity.onCreate(new Bundle());
assertThat(mActivity.isFinishing()).isTrue();
mCallbacksCaptor.getValue().appTransitionFinished(DEFAULT_DISPLAY);
// Ensure callback removed
verify(mCommandQueue).removeCallback(any());
// Don't clear the notification for bubbles.
verify(mIStatusBarService, never()).onNotificationClear(any(),
anyInt(), any(), anyInt(), anyInt(), any());
// Do not select the bubble.
verify(mBubblesManager, never()).expandStackAndSelectBubble(any(Bubble.class));
verify(mBubblesManager, never()).expandStackAndSelectBubble(any(NotificationEntry.class));
}
@Test
public void testBubbleWithNoNotifOpensBubble() throws Exception {
Bubble bubble = mock(Bubble.class);
when(mBubblesManager.getBubbleWithShortcutId(any())).thenReturn(bubble);
mIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_NOTIFICATION_KEY,
EMPTY_STRING);
mActivity.setIntent(mIntent);
mActivity.onCreate(new Bundle());
assertThat(mActivity.isFinishing()).isTrue();
mCallbacksCaptor.getValue().appTransitionFinished(DEFAULT_DISPLAY);
// Ensure callback removed
verify(mCommandQueue).removeCallback(any());
// Select the bubble.
verify(mBubblesManager, times(1)).expandStackAndSelectBubble(eq(bubble));
}
}