/*
 * 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.server.people.data;

import static android.app.people.ConversationStatus.ACTIVITY_ANNIVERSARY;
import static android.app.people.ConversationStatus.ACTIVITY_GAME;
import static android.service.notification.NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED;
import static android.service.notification.NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED;
import static android.service.notification.NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED;

import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;

import static com.google.common.truth.Truth.assertThat;

import static junit.framework.Assert.fail;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.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.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Person;
import android.app.job.JobScheduler;
import android.app.people.ConversationChannel;
import android.app.people.ConversationStatus;
import android.app.prediction.AppTarget;
import android.app.prediction.AppTargetEvent;
import android.app.prediction.AppTargetId;
import android.app.usage.UsageStatsManagerInternal;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.LauncherApps.ShortcutChangeCallback;
import android.content.pm.LauncherApps.ShortcutQuery;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutServiceInternal;
import android.content.pm.UserInfo;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.CancellationSignal;
import android.os.Looper;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.test.TestLooper;
import android.provider.ContactsContract;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.telecom.TelecomManager;
import android.telephony.TelephonyManager;
import android.text.format.DateUtils;
import android.util.Range;

import com.android.internal.app.ChooserActivity;
import com.android.internal.content.PackageMonitor;
import com.android.server.LocalServices;
import com.android.server.notification.NotificationManagerInternal;
import com.android.server.people.PeopleService;
import com.android.server.pm.parsing.pkg.AndroidPackage;

import com.google.common.collect.Iterables;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;

@RunWith(JUnit4.class)
public final class DataManagerTest {

    private static final int USER_ID_PRIMARY = 0;
    private static final int USER_ID_PRIMARY_MANAGED = 10;
    private static final int USER_ID_SECONDARY = 11;
    private static final String TEST_PKG_NAME = "pkg";
    private static final String TEST_CLASS_NAME = "class";
    private static final String TEST_SHORTCUT_ID = "sc";
    private static final String TEST_SHORTCUT_ID_2 = "sc2";
    private static final int TEST_PKG_UID = 35;
    private static final String CONTACT_URI = "content://com.android.contacts/contacts/lookup/123";
    private static final String PHONE_NUMBER = "+1234567890";
    private static final String NOTIFICATION_CHANNEL_ID = "test : sc";
    private static final String PARENT_NOTIFICATION_CHANNEL_ID = "test";
    private static final long MILLIS_PER_MINUTE = 1000L * 60L;
    private static final String GENERIC_KEY = "key";
    private static final String CUSTOM_KEY = "custom";

    @Mock
    private Context mContext;
    @Mock
    private ShortcutServiceInternal mShortcutServiceInternal;
    @Mock
    private UsageStatsManagerInternal mUsageStatsManagerInternal;
    @Mock
    private PackageManagerInternal mPackageManagerInternal;
    @Mock
    private NotificationManagerInternal mNotificationManagerInternal;
    @Mock
    private UserManager mUserManager;
    @Mock
    private PackageManager mPackageManager;
    @Mock
    private TelephonyManager mTelephonyManager;
    @Mock
    private TelecomManager mTelecomManager;
    @Mock
    private ContentResolver mContentResolver;
    @Mock
    private JobScheduler mJobScheduler;
    @Mock
    private StatusBarNotification mGenericSbn;
    @Mock
    private StatusBarNotification mConvoSbn;
    @Mock
    private NotificationListenerService.RankingMap mRankingMap;
    @Mock
    private Notification mNotification;
    @Mock
    private AlarmManager mAlarmManager;

    @Captor
    private ArgumentCaptor<ShortcutChangeCallback> mShortcutChangeCallbackCaptor;
    @Captor
    private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor;
    @Captor
    private ArgumentCaptor<Integer> mQueryFlagsCaptor;

    private ScheduledExecutorService mExecutorService;
    private NotificationChannel mNotificationChannel;
    private NotificationChannel mParentNotificationChannel;
    private DataManager mDataManager;
    private CancellationSignal mCancellationSignal;
    private ShortcutChangeCallback mShortcutChangeCallback;
    private ShortcutInfo mShortcutInfo;
    private TestInjector mInjector;
    private TestLooper mLooper;

    @Before
    public void setUp() throws PackageManager.NameNotFoundException {
        MockitoAnnotations.initMocks(this);

        addLocalServiceMock(ShortcutServiceInternal.class, mShortcutServiceInternal);

        addLocalServiceMock(UsageStatsManagerInternal.class, mUsageStatsManagerInternal);

        addLocalServiceMock(PackageManagerInternal.class, mPackageManagerInternal);
        AndroidPackage androidPackage = mock(AndroidPackage.class);
        when(androidPackage.getPackageName()).thenReturn(TEST_PKG_NAME);
        doAnswer(ans -> {
            Consumer<AndroidPackage> callback = (Consumer<AndroidPackage>) ans.getArguments()[0];
            callback.accept(androidPackage);
            return null;
        }).when(mPackageManagerInternal).forEachInstalledPackage(any(Consumer.class), anyInt());

        addLocalServiceMock(NotificationManagerInternal.class, mNotificationManagerInternal);
        mParentNotificationChannel = new NotificationChannel(
                PARENT_NOTIFICATION_CHANNEL_ID, "test channel",
                NotificationManager.IMPORTANCE_DEFAULT);

        when(mContext.getContentResolver()).thenReturn(mContentResolver);
        when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
        when(mContext.getPackageName()).thenReturn("android");
        when(mContext.getPackageManager()).thenReturn(mPackageManager);

        Context originalContext = getInstrumentation().getTargetContext();
        when(mContext.getApplicationInfo()).thenReturn(originalContext.getApplicationInfo());
        when(mContext.getUser()).thenReturn(originalContext.getUser());
        when(mContext.getPackageName()).thenReturn(originalContext.getPackageName());

        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
        when(mContext.getSystemServiceName(UserManager.class)).thenReturn(
                Context.USER_SERVICE);
        when(mContext.getSystemService(Context.ALARM_SERVICE)).thenReturn(mAlarmManager);
        when(mContext.getSystemServiceName(AlarmManager.class)).thenReturn(
                Context.ALARM_SERVICE);

        when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);

        when(mContext.getSystemService(Context.TELECOM_SERVICE)).thenReturn(mTelecomManager);
        when(mContext.getSystemServiceName(TelecomManager.class)).thenReturn(
                Context.TELECOM_SERVICE);
        when(mTelecomManager.getDefaultDialerPackage(any(UserHandle.class)))
                .thenReturn(TEST_PKG_NAME);

        when(mContext.getSystemService(Context.JOB_SCHEDULER_SERVICE)).thenReturn(mJobScheduler);
        when(mContext.getSystemServiceName(JobScheduler.class)).thenReturn(
                Context.JOB_SCHEDULER_SERVICE);

        mExecutorService = new MockScheduledExecutorService();

        when(mUserManager.getEnabledProfiles(USER_ID_PRIMARY))
                .thenReturn(Arrays.asList(
                        buildUserInfo(USER_ID_PRIMARY),
                        buildUserInfo(USER_ID_PRIMARY_MANAGED)));
        when(mUserManager.getEnabledProfiles(USER_ID_SECONDARY))
                .thenReturn(Collections.singletonList(buildUserInfo(USER_ID_SECONDARY)));

        when(mPackageManager.getPackageUidAsUser(TEST_PKG_NAME, USER_ID_PRIMARY))
                .thenReturn(TEST_PKG_UID);

        mNotificationChannel = new NotificationChannel(
                NOTIFICATION_CHANNEL_ID, "test channel", NotificationManager.IMPORTANCE_DEFAULT);
        mNotificationChannel.setConversationId(PARENT_NOTIFICATION_CHANNEL_ID, TEST_SHORTCUT_ID);
        when(mNotificationManagerInternal.getNotificationChannel(anyString(), anyInt(),
                eq(mNotificationChannel.getId()))).thenReturn(mNotificationChannel);
        when(mNotificationManagerInternal.getNotificationChannel(anyString(), anyInt(),
                eq(mParentNotificationChannel.getId()))).thenReturn(mParentNotificationChannel);

        when(mGenericSbn.getKey()).thenReturn(GENERIC_KEY);
        when(mGenericSbn.getNotification()).thenReturn(mNotification);
        when(mGenericSbn.getPackageName()).thenReturn(TEST_PKG_NAME);
        when(mGenericSbn.getUser()).thenReturn(UserHandle.of(USER_ID_PRIMARY));
        when(mGenericSbn.getPostTime()).thenReturn(System.currentTimeMillis());
        when(mConvoSbn.getKey()).thenReturn(CUSTOM_KEY);
        when(mConvoSbn.getNotification()).thenReturn(mNotification);
        when(mConvoSbn.getPackageName()).thenReturn(TEST_PKG_NAME);
        when(mConvoSbn.getUser()).thenReturn(UserHandle.of(USER_ID_PRIMARY));
        when(mConvoSbn.getPostTime()).thenReturn(System.currentTimeMillis());

        when(mNotification.getShortcutId()).thenReturn(TEST_SHORTCUT_ID);

        mCancellationSignal = new CancellationSignal();

        mInjector = new TestInjector();
        mLooper = new TestLooper();
        mDataManager = new DataManager(mContext, mInjector, mLooper.getLooper());
        mDataManager.initialize();

        when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(),
                anyString(), anyInt(), any())).thenReturn(true);

        mShortcutInfo = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        when(mShortcutServiceInternal.getShortcuts(
                anyInt(), anyString(), anyLong(), anyString(), anyList(), any(), any(),
                anyInt(), anyInt(), anyInt(), anyInt()))
                .thenReturn(Collections.singletonList(mShortcutInfo));
        verify(mShortcutServiceInternal).addShortcutChangeCallback(
                mShortcutChangeCallbackCaptor.capture());
        mShortcutChangeCallback = mShortcutChangeCallbackCaptor.getValue();

        verify(mContext, times(1)).registerReceiver(any(), any());
        verify(mContext, times(1)).registerReceiver(any(), any(), anyInt());
    }

    @After
    public void tearDown() {
        LocalServices.removeServiceForTest(ShortcutServiceInternal.class);
        LocalServices.removeServiceForTest(UsageStatsManagerInternal.class);
        LocalServices.removeServiceForTest(PackageManagerInternal.class);
    }

    @Test
    public void testAccessConversationFromTheSameProfileGroup() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
        mDataManager.onUserUnlocked(USER_ID_PRIMARY_MANAGED);
        mDataManager.onUserUnlocked(USER_ID_SECONDARY);

        mDataManager.addOrUpdateConversationInfo(
                buildShortcutInfo("pkg_1", USER_ID_PRIMARY, "sc_1",
                        buildPerson(true, false)));
        mDataManager.addOrUpdateConversationInfo(
                buildShortcutInfo("pkg_2", USER_ID_PRIMARY_MANAGED, "sc_2",
                        buildPerson(false, true)));
        mDataManager.addOrUpdateConversationInfo(
                buildShortcutInfo("pkg_3", USER_ID_SECONDARY, "sc_3", buildPerson()));

        List<ConversationInfo> conversations = getConversationsInPrimary();

        // USER_ID_SECONDARY is not in the same profile group as USER_ID_PRIMARY.
        assertEquals(2, conversations.size());

        assertEquals("sc_1", conversations.get(0).getShortcutId());
        assertTrue(conversations.get(0).isPersonImportant());
        assertFalse(conversations.get(0).isPersonBot());
        assertFalse(conversations.get(0).isContactStarred());
        assertEquals(PHONE_NUMBER, conversations.get(0).getContactPhoneNumber());

        assertEquals("sc_2", conversations.get(1).getShortcutId());
        assertFalse(conversations.get(1).isPersonImportant());
        assertTrue(conversations.get(1).isPersonBot());
        assertFalse(conversations.get(0).isContactStarred());
        assertEquals(PHONE_NUMBER, conversations.get(0).getContactPhoneNumber());
    }

    @Test
    public void testAccessConversationForUnlockedUsersOnly() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
        mDataManager.addOrUpdateConversationInfo(
                buildShortcutInfo("pkg_1", USER_ID_PRIMARY, "sc_1", buildPerson()));
        mDataManager.addOrUpdateConversationInfo(
                buildShortcutInfo("pkg_2", USER_ID_PRIMARY_MANAGED, "sc_2", buildPerson()));

        List<ConversationInfo> conversations = getConversationsInPrimary();

        // USER_ID_PRIMARY_MANAGED is not locked, so only USER_ID_PRIMARY's conversation is stored.
        assertEquals(1, conversations.size());
        assertEquals("sc_1", conversations.get(0).getShortcutId());

        mDataManager.onUserStopping(USER_ID_PRIMARY);
        conversations = getConversationsInPrimary();
        assertTrue(conversations.isEmpty());
    }

    @Test
    public void testGetShortcut() {
        mDataManager.getShortcut(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID);
        verify(mShortcutServiceInternal).getShortcuts(anyInt(), anyString(), anyLong(),
                eq(TEST_PKG_NAME), eq(Collections.singletonList(TEST_SHORTCUT_ID)),
                eq(null), eq(null), anyInt(), eq(USER_ID_PRIMARY), anyInt(), anyInt());
    }

    @Test
    public void testReportAppTargetEvent_directSharing()
            throws IntentFilter.MalformedMimeTypeException {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        mDataManager.addOrUpdateConversationInfo(shortcut);

        AppTarget appTarget = new AppTarget.Builder(new AppTargetId(TEST_SHORTCUT_ID), shortcut)
                .build();
        AppTargetEvent appTargetEvent =
                new AppTargetEvent.Builder(appTarget, AppTargetEvent.ACTION_LAUNCH)
                        .setLaunchLocation(ChooserActivity.LAUNCH_LOCATION_DIRECT_SHARE)
                        .build();
        IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SEND, "image/jpg");
        mDataManager.reportShareTargetEvent(appTargetEvent, intentFilter);

        List<Range<Long>> activeShareTimeSlots = getActiveSlotsForTestShortcut(
                Event.SHARE_EVENT_TYPES);
        assertEquals(1, activeShareTimeSlots.size());
    }

    @Test
    public void testReportAppTargetEvent_directSharing_createConversation()
            throws IntentFilter.MalformedMimeTypeException {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                null);
        AppTarget appTarget = new AppTarget.Builder(new AppTargetId(TEST_SHORTCUT_ID), shortcut)
                .build();
        AppTargetEvent appTargetEvent =
                new AppTargetEvent.Builder(appTarget, AppTargetEvent.ACTION_LAUNCH)
                        .setLaunchLocation(ChooserActivity.LAUNCH_LOCATION_DIRECT_SHARE)
                        .build();
        IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SEND, "image/jpg");

        mDataManager.reportShareTargetEvent(appTargetEvent, intentFilter);

        List<Range<Long>> activeShareTimeSlots = getActiveSlotsForTestShortcut(
                Event.SHARE_EVENT_TYPES);
        assertEquals(1, activeShareTimeSlots.size());
        ConversationInfo conversationInfo = mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY)
                .getConversationStore()
                .getConversation(TEST_SHORTCUT_ID);
        assertNotNull(conversationInfo);
        assertEquals(conversationInfo.getShortcutId(), TEST_SHORTCUT_ID);
    }

    @Test
    public void testReportAppTargetEvent_appSharing()
            throws IntentFilter.MalformedMimeTypeException {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
        AppTarget appTarget = new AppTarget.Builder(
                new AppTargetId(TEST_SHORTCUT_ID),
                TEST_PKG_NAME,
                UserHandle.of(USER_ID_PRIMARY))
                .setClassName(TEST_CLASS_NAME)
                .build();
        AppTargetEvent appTargetEvent =
                new AppTargetEvent.Builder(appTarget, AppTargetEvent.ACTION_LAUNCH)
                        .build();
        IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SEND, "image/jpg");

        mDataManager.reportShareTargetEvent(appTargetEvent, intentFilter);

        List<Range<Long>> activeShareTimeSlots = getActiveSlotsForAppShares();
        assertEquals(1, activeShareTimeSlots.size());
    }

    @Test
    public void testContactsChanged() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
        mDataManager.onUserUnlocked(USER_ID_SECONDARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        mDataManager.addOrUpdateConversationInfo(shortcut);

        final String newPhoneNumber = "+1000000000";
        mInjector.mContactsQueryHelper.mIsStarred = true;
        mInjector.mContactsQueryHelper.mPhoneNumber = newPhoneNumber;

        ContentObserver contentObserver = mDataManager.getContactsContentObserverForTesting(
                USER_ID_PRIMARY);
        contentObserver.onChange(false, ContactsContract.Contacts.CONTENT_URI, USER_ID_PRIMARY);

        List<ConversationInfo> conversations = getConversationsInPrimary();
        assertEquals(1, conversations.size());

        assertEquals(TEST_SHORTCUT_ID, conversations.get(0).getShortcutId());
        assertTrue(conversations.get(0).isContactStarred());
        assertEquals(newPhoneNumber, conversations.get(0).getContactPhoneNumber());
    }

    @Test
    public void testNotificationPosted() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        mDataManager.addOrUpdateConversationInfo(shortcut);

        sendGenericNotification();

        List<Range<Long>> activeNotificationOpenTimeSlots = getActiveSlotsForTestShortcut(
                Event.NOTIFICATION_EVENT_TYPES);
        assertEquals(1, activeNotificationOpenTimeSlots.size());
    }

    @Test
    public void testNotificationOpened() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
        mDataManager.addOrUpdateConversationInfo(shortcut);

        NotificationListenerService listenerService =
                mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);

        listenerService.onNotificationRemoved(mGenericSbn, null,
                NotificationListenerService.REASON_CLICK);

        List<Range<Long>> activeNotificationOpenTimeSlots = getActiveSlotsForTestShortcut(
                Event.NOTIFICATION_EVENT_TYPES);
        assertEquals(1, activeNotificationOpenTimeSlots.size());
    }

    @Test
    public void testUncacheShortcutsWhenNotificationsDismissed() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
        NotificationListenerService listenerService =
                mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);

        // The cached conversations are above the limit because every conversation has active
        // notifications. To uncache one of them, the notifications for that conversation need to
        // be dismissed.
        for (int i = 0; i < DataManager.MAX_CACHED_RECENT_SHORTCUTS + 1; i++) {
            String shortcutId = TEST_SHORTCUT_ID + i;
            ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, shortcutId,
                    buildPerson());
            shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
            mDataManager.addOrUpdateConversationInfo(shortcut);
            when(mNotification.getShortcutId()).thenReturn(shortcutId);
            sendGenericNotification();
        }

        // Post another notification for the last conversation.
        sendGenericNotification();

        // Removing one of the two notifications does not un-cache the shortcut.
        listenerService.onNotificationRemoved(mGenericSbn, null,
                NotificationListenerService.REASON_CANCEL);
        verify(mShortcutServiceInternal, never()).uncacheShortcuts(
                anyInt(), any(), anyString(), any(), anyInt(), anyInt());

        // Removing the second notification un-caches the shortcut.
        listenerService.onNotificationRemoved(mGenericSbn, null,
                NotificationListenerService.REASON_CANCEL_ALL);
        verify(mShortcutServiceInternal).uncacheShortcuts(
                anyInt(), any(), eq(TEST_PKG_NAME), anyList(), eq(USER_ID_PRIMARY),
                eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
    }

    @Test
    public void testConversationIsNotRecentIfCustomized() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        mDataManager.addOrUpdateConversationInfo(shortcut);

        NotificationListenerService listenerService =
                mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);

        sendGenericNotification();
        shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
        mDataManager.addOrUpdateConversationInfo(shortcut);

        assertEquals(1, mDataManager.getRecentConversations(USER_ID_PRIMARY).size());

        listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY),
                mNotificationChannel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED);

        assertTrue(mDataManager.getRecentConversations(USER_ID_PRIMARY).isEmpty());
    }

    @Test
    public void testAddConversationsListener() throws Exception {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        mDataManager.addOrUpdateConversationInfo(shortcut);
        ConversationChannel conversationChannel = mDataManager.getConversation(TEST_PKG_NAME,
                USER_ID_PRIMARY,
                TEST_SHORTCUT_ID);

        PeopleService.ConversationsListener listener = mock(
                PeopleService.ConversationsListener.class);
        mDataManager.addConversationsListener(listener);

        List<ConversationChannel> changedConversations = Arrays.asList(conversationChannel);
        verify(listener, times(0)).onConversationsUpdate(eq(changedConversations));
        mDataManager.notifyConversationsListeners(changedConversations);
        mLooper.dispatchAll();

        verify(listener, times(1)).onConversationsUpdate(eq(changedConversations));
    }

    @Test
    public void testAddConversationListenersNotifiesMultipleConversations() throws Exception {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        mDataManager.addOrUpdateConversationInfo(shortcut);
        ConversationChannel conversationChannel = mDataManager.getConversation(TEST_PKG_NAME,
                USER_ID_PRIMARY,
                TEST_SHORTCUT_ID);
        ShortcutInfo shortcut2 = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY,
                TEST_SHORTCUT_ID_2,
                buildPerson());
        mDataManager.addOrUpdateConversationInfo(shortcut2);
        mLooper.dispatchAll();
        ConversationChannel conversationChannel2 = mDataManager.getConversation(TEST_PKG_NAME,
                USER_ID_PRIMARY,
                TEST_SHORTCUT_ID_2);
        PeopleService.ConversationsListener listener = mock(
                PeopleService.ConversationsListener.class);
        mDataManager.addConversationsListener(listener);

        List<ConversationChannel> changedConversations = Arrays.asList(conversationChannel,
                conversationChannel2);
        verify(listener, times(0)).onConversationsUpdate(eq(changedConversations));
        mDataManager.notifyConversationsListeners(changedConversations);
        mLooper.dispatchAll();

        verify(listener, times(1)).onConversationsUpdate(eq(changedConversations));
        ArgumentCaptor<List<ConversationChannel>> capturedConversation = ArgumentCaptor.forClass(
                List.class);
        verify(listener, times(1)).onConversationsUpdate(capturedConversation.capture());
        assertThat(capturedConversation.getValue()).containsExactly(conversationChannel,
                conversationChannel2);
    }

    @Test
    public void testAddOrUpdateStatusNotifiesConversationsListeners() throws Exception {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        mDataManager.addOrUpdateConversationInfo(shortcut);
        mLooper.dispatchAll();
        PeopleService.ConversationsListener listener = mock(
                PeopleService.ConversationsListener.class);
        mDataManager.addConversationsListener(listener);

        ConversationStatus status = new ConversationStatus.Builder("cs1", ACTIVITY_GAME).build();
        mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, status);
        mLooper.dispatchAll();

        ArgumentCaptor<List<ConversationChannel>> capturedConversation = ArgumentCaptor.forClass(
                List.class);
        verify(listener, times(1)).onConversationsUpdate(capturedConversation.capture());
        ConversationChannel result = Iterables.getOnlyElement(capturedConversation.getValue());
        assertThat(result.getStatuses()).containsExactly(status);
        assertEquals(result.getShortcutInfo().getId(), TEST_SHORTCUT_ID);
    }

    @Test
    public void testGetConversationReturnsCustomizedConversation() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        mDataManager.addOrUpdateConversationInfo(shortcut);

        sendConvoNotification();
        shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
        mDataManager.addOrUpdateConversationInfo(shortcut);

        assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
                TEST_SHORTCUT_ID)).isNotNull();

        ConversationChannel result = mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
                TEST_SHORTCUT_ID);
        assertThat(result).isNotNull();
        assertThat(result.hasBirthdayToday()).isFalse();
        assertThat(result.getStatuses()).isEmpty();
    }

    @Test
    public void testGetConversation() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
        assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
                TEST_SHORTCUT_ID)).isNull();

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        shortcut.setCached(ShortcutInfo.FLAG_PINNED);
        mDataManager.addOrUpdateConversationInfo(shortcut);
        assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
                TEST_SHORTCUT_ID)).isNotNull();
        assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
                TEST_SHORTCUT_ID + "1")).isNull();

        sendConvoNotification();
        ConversationStatus cs = new ConversationStatus.Builder("id", ACTIVITY_ANNIVERSARY).build();
        mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs);

        ConversationChannel result = mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
                TEST_SHORTCUT_ID);
        assertThat(result).isNotNull();
        assertEquals(shortcut.getId(), result.getShortcutInfo().getId());
        assertEquals(1, result.getShortcutInfo().getPersons().length);
        assertEquals(CONTACT_URI, result.getShortcutInfo().getPersons()[0].getUri());
        assertEquals(mNotificationChannel.getId(), result.getNotificationChannel().getId());
        assertEquals(mParentNotificationChannel.getId(),
                result.getNotificationChannel().getParentChannelId());
        assertEquals(mConvoSbn.getPostTime(), result.getLastEventTimestamp());
        assertTrue(result.hasActiveNotifications());
        assertFalse(result.hasBirthdayToday());
        assertThat(result.getStatuses()).containsExactly(cs);
    }

    @Test
    public void testOnNotificationChannelModified() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
        assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
                TEST_SHORTCUT_ID)).isNull();

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        shortcut.setCached(ShortcutInfo.FLAG_PINNED);
        mDataManager.addOrUpdateConversationInfo(shortcut);

        sendConvoNotification();

        ConversationChannel result = mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
                TEST_SHORTCUT_ID);
        assertFalse(result.getNotificationChannel().canBubble());

        NotificationChannel updated = new NotificationChannel(mNotificationChannel.getId(),
                mNotificationChannel.getDescription(), mNotificationChannel.getImportance());
        updated.setConversationId(mNotificationChannel.getParentChannelId(),
                mNotificationChannel.getConversationId());
        updated.setAllowBubbles(true);
        NotificationListenerService listenerService =
                mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
        listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY),
                updated, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED);

        ConversationInfo ci = mDataManager.getConversationInfo(TEST_PKG_NAME, USER_ID_PRIMARY,
                TEST_SHORTCUT_ID);
        assertThat(ci).isNotNull();
        assertEquals(mNotificationChannel.getId(), ci.getNotificationChannelId());
        assertEquals(mParentNotificationChannel.getId(), ci.getParentNotificationChannelId());
        assertTrue(ci.isBubbled());
    }

    @Test
    public void testGetConversation_demoted() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
        assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
                TEST_SHORTCUT_ID)).isNull();

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        shortcut.setCached(ShortcutInfo.FLAG_PINNED);
        mDataManager.addOrUpdateConversationInfo(shortcut);
        assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
                TEST_SHORTCUT_ID)).isNotNull();

        mNotificationChannel.setDemoted(true);
        NotificationListenerService listenerService =
                mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
        listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY),
                mNotificationChannel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED);

        assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
                TEST_SHORTCUT_ID)).isNull();
    }

    @Test
    public void testGetConversationGetsPersonsData() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        shortcut.setCached(ShortcutInfo.FLAG_PINNED);
        mDataManager.addOrUpdateConversationInfo(shortcut);

        sendGenericNotification();
        mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID);

        verify(mShortcutServiceInternal).getShortcuts(
                anyInt(), anyString(), anyLong(), anyString(), anyList(), any(), any(),
                mQueryFlagsCaptor.capture(), anyInt(), anyInt(), anyInt());
        Integer queryFlags = mQueryFlagsCaptor.getValue();
        assertThat(hasFlag(queryFlags, ShortcutQuery.FLAG_GET_PERSONS_DATA)).isTrue();
    }

    @Test
    public void testIsConversation() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
        assertThat(mDataManager.isConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
                TEST_SHORTCUT_ID)).isFalse();

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        shortcut.setCached(ShortcutInfo.FLAG_PINNED);
        mDataManager.addOrUpdateConversationInfo(shortcut);
        assertThat(mDataManager.isConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
                TEST_SHORTCUT_ID)).isTrue();
        assertThat(mDataManager.isConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
                TEST_SHORTCUT_ID + "1")).isFalse();
    }

    @Test
    public void testIsConversation_demoted() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
        assertThat(mDataManager.isConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
                TEST_SHORTCUT_ID)).isFalse();

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        shortcut.setCached(ShortcutInfo.FLAG_PINNED);
        mDataManager.addOrUpdateConversationInfo(shortcut);

        mNotificationChannel.setDemoted(true);
        NotificationListenerService listenerService =
                mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
        listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY),
                mNotificationChannel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED);

        assertThat(mDataManager.isConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
                TEST_SHORTCUT_ID)).isFalse();
    }

    @Test
    public void testNotificationChannelCreated() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
        mDataManager.onUserUnlocked(USER_ID_SECONDARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        mDataManager.addOrUpdateConversationInfo(shortcut);

        NotificationListenerService listenerService =
                mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
        listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY),
                mNotificationChannel, NOTIFICATION_CHANNEL_OR_GROUP_ADDED);

        ConversationInfo conversationInfo = mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY)
                .getConversationStore()
                .getConversation(TEST_SHORTCUT_ID);
        assertEquals(NOTIFICATION_CHANNEL_ID, conversationInfo.getNotificationChannelId());
        assertFalse(conversationInfo.isImportant());
        assertFalse(conversationInfo.isNotificationSilenced());
        assertFalse(conversationInfo.isDemoted());
    }

    @Test
    public void testNotificationChannelModified() {
        mNotificationChannel.setImportantConversation(true);

        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
        mDataManager.onUserUnlocked(USER_ID_SECONDARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        mDataManager.addOrUpdateConversationInfo(shortcut);

        NotificationListenerService listenerService =
                mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
        listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY),
                mNotificationChannel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED);

        ConversationInfo conversationInfo = mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY)
                .getConversationStore()
                .getConversation(TEST_SHORTCUT_ID);
        assertEquals(NOTIFICATION_CHANNEL_ID, conversationInfo.getNotificationChannelId());
        assertTrue(conversationInfo.isImportant());
        assertFalse(conversationInfo.isNotificationSilenced());
        assertFalse(conversationInfo.isDemoted());
    }

    @Test
    public void testNotificationChannelDeleted() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
        mDataManager.onUserUnlocked(USER_ID_SECONDARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        mDataManager.addOrUpdateConversationInfo(shortcut);

        NotificationListenerService listenerService =
                mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
        listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY),
                mNotificationChannel, NOTIFICATION_CHANNEL_OR_GROUP_ADDED);
        ConversationInfo conversationInfo = mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY)
                .getConversationStore()
                .getConversation(TEST_SHORTCUT_ID);
        assertEquals(NOTIFICATION_CHANNEL_ID, conversationInfo.getNotificationChannelId());

        listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY),
                mNotificationChannel, NOTIFICATION_CHANNEL_OR_GROUP_DELETED);
        conversationInfo = mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY)
                .getConversationStore()
                .getConversation(TEST_SHORTCUT_ID);
        assertNull(conversationInfo.getNotificationChannelId());
        assertFalse(conversationInfo.isImportant());
        assertFalse(conversationInfo.isNotificationSilenced());
        assertFalse(conversationInfo.isDemoted());
    }

    @Test
    public void testShortcutAddedOrUpdated() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
        PeopleService.ConversationsListener listener = mock(
                PeopleService.ConversationsListener.class);
        mDataManager.addConversationsListener(listener);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        mShortcutChangeCallback.onShortcutsAddedOrUpdated(TEST_PKG_NAME,
                Collections.singletonList(shortcut), UserHandle.of(USER_ID_PRIMARY));
        mLooper.dispatchAll();

        List<ConversationInfo> conversations = getConversationsInPrimary();

        assertEquals(1, conversations.size());
        assertEquals(TEST_SHORTCUT_ID, conversations.get(0).getShortcutId());
        ArgumentCaptor<List<ConversationChannel>> capturedConversation = ArgumentCaptor.forClass(
                List.class);
        verify(listener, times(1)).onConversationsUpdate(capturedConversation.capture());
        ConversationChannel result = Iterables.getOnlyElement(capturedConversation.getValue());
        assertEquals(result.getShortcutInfo().getId(), TEST_SHORTCUT_ID);
    }

    @Test
    public void testShortcutsDeleted() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);

        ShortcutInfo shortcut1 = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, "sc1",
                buildPerson());
        ShortcutInfo shortcut2 = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, "sc2",
                buildPerson());
        ShortcutInfo shortcut3 = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, "sc3",
                buildPerson());
        mShortcutChangeCallback.onShortcutsAddedOrUpdated(TEST_PKG_NAME,
                Arrays.asList(shortcut1, shortcut2, shortcut3), UserHandle.of(USER_ID_PRIMARY));
        mShortcutChangeCallback.onShortcutsRemoved(TEST_PKG_NAME,
                List.of(shortcut1, shortcut3), UserHandle.of(USER_ID_PRIMARY));

        List<ConversationInfo> conversations = getConversationsInPrimary();

        assertEquals(1, conversations.size());
        assertEquals("sc2", conversations.get(0).getShortcutId());

        verify(mNotificationManagerInternal)
                .onConversationRemoved(TEST_PKG_NAME, TEST_PKG_UID, Set.of("sc1", "sc3"));
    }

    @Test
    public void testCallLogContentObserver() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
        mDataManager.onUserUnlocked(USER_ID_SECONDARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        mDataManager.addOrUpdateConversationInfo(shortcut);

        ContentObserver contentObserver = mDataManager.getCallLogContentObserverForTesting();
        contentObserver.onChange(false);
        long currentTimestamp = System.currentTimeMillis();
        mInjector.mCallLogQueryHelper.mEventConsumer.accept(PHONE_NUMBER,
                new Event(currentTimestamp - MILLIS_PER_MINUTE * 15L, Event.TYPE_CALL_OUTGOING));
        mInjector.mCallLogQueryHelper.mEventConsumer.accept(PHONE_NUMBER,
                new Event(currentTimestamp - MILLIS_PER_MINUTE * 10L, Event.TYPE_CALL_INCOMING));
        mInjector.mCallLogQueryHelper.mEventConsumer.accept(PHONE_NUMBER,
                new Event(currentTimestamp - MILLIS_PER_MINUTE * 5L, Event.TYPE_CALL_MISSED));

        List<Range<Long>> activeTimeSlots = getActiveSlotsForTestShortcut(Event.CALL_EVENT_TYPES);
        assertEquals(3, activeTimeSlots.size());
    }

    @Test
    public void testMmsSmsContentObserver() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
        mDataManager.onUserUnlocked(USER_ID_SECONDARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        mDataManager.addOrUpdateConversationInfo(shortcut);
        mDataManager.getUserDataForTesting(USER_ID_PRIMARY).setDefaultSmsApp(TEST_PKG_NAME);

        ContentObserver contentObserver = mDataManager.getMmsSmsContentObserverForTesting();
        contentObserver.onChange(false);
        long currentTimestamp = System.currentTimeMillis();
        Event outgoingSmsEvent =
                new Event(currentTimestamp - MILLIS_PER_MINUTE * 10L, Event.TYPE_SMS_OUTGOING);
        Event incomingSmsEvent =
                new Event(currentTimestamp - MILLIS_PER_MINUTE * 5L, Event.TYPE_SMS_INCOMING);
        mInjector.mMmsQueryHelper.mEventConsumer.accept(PHONE_NUMBER, outgoingSmsEvent);
        mInjector.mSmsQueryHelper.mEventConsumer.accept(PHONE_NUMBER, incomingSmsEvent);

        List<Range<Long>> activeTimeSlots = getActiveSlotsForTestShortcut(Event.SMS_EVENT_TYPES);
        assertEquals(2, activeTimeSlots.size());
    }

    @Test
    public void testConversationLastEventTimestampUpdate() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        mDataManager.addOrUpdateConversationInfo(shortcut);

        PackageData packageData = mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY);
        ConversationInfo conversationInfo =
                packageData.getConversationStore().getConversation(TEST_SHORTCUT_ID);
        Event event = new Event(123L, Event.TYPE_IN_APP_CONVERSATION);

        mInjector.mUsageStatsQueryHelper.mEventListener.onEvent(packageData, conversationInfo,
                event);
        ConversationInfo newConversationInfo =
                packageData.getConversationStore().getConversation(TEST_SHORTCUT_ID);
        assertEquals(123L, newConversationInfo.getLastEventTimestamp());
    }

    @Test
    public void testDeleteUninstalledPackageDataOnPackageRemoved() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        mDataManager.addOrUpdateConversationInfo(shortcut);
        assertNotNull(mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY));

        PackageMonitor packageMonitor = mDataManager.getPackageMonitorForTesting(USER_ID_PRIMARY);
        Intent intent = new Intent(Intent.ACTION_PACKAGE_REMOVED);
        intent.putExtra(Intent.EXTRA_USER_HANDLE, USER_ID_PRIMARY);
        intent.setData(Uri.parse("package:" + TEST_PKG_NAME));
        packageMonitor.onReceive(mContext, intent);
        assertNull(mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY));
    }

    @Test
    public void testPruneUninstalledPackageData() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        mDataManager.addOrUpdateConversationInfo(shortcut);
        assertNotNull(mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY));

        doAnswer(ans -> null).when(mPackageManagerInternal)
                .forEachInstalledPackage(any(Consumer.class), anyInt());
        mDataManager.pruneDataForUser(USER_ID_PRIMARY, mCancellationSignal);
        assertNull(mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY));
    }

    @Test
    public void testPruneCallEventsFromNonDialer() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        mDataManager.addOrUpdateConversationInfo(shortcut);

        long currentTimestamp = System.currentTimeMillis();
        mInjector.mCallLogQueryHelper.mEventConsumer.accept(PHONE_NUMBER,
                new Event(currentTimestamp - MILLIS_PER_MINUTE, Event.TYPE_CALL_OUTGOING));

        List<Range<Long>> activeTimeSlots = getActiveSlotsForTestShortcut(Event.CALL_EVENT_TYPES);
        assertEquals(1, activeTimeSlots.size());

        mDataManager.getUserDataForTesting(USER_ID_PRIMARY).setDefaultDialer(null);
        mDataManager.pruneDataForUser(USER_ID_PRIMARY, mCancellationSignal);
        activeTimeSlots = getActiveSlotsForTestShortcut(Event.CALL_EVENT_TYPES);
        assertTrue(activeTimeSlots.isEmpty());
    }

    @Test
    public void testPruneSmsEventsFromNonDefaultSmsApp() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        mDataManager.addOrUpdateConversationInfo(shortcut);
        mDataManager.getUserDataForTesting(USER_ID_PRIMARY).setDefaultSmsApp(TEST_PKG_NAME);

        long currentTimestamp = System.currentTimeMillis();
        mInjector.mMmsQueryHelper.mEventConsumer.accept(PHONE_NUMBER,
                new Event(currentTimestamp - MILLIS_PER_MINUTE, Event.TYPE_SMS_OUTGOING));

        List<Range<Long>> activeTimeSlots = getActiveSlotsForTestShortcut(Event.SMS_EVENT_TYPES);
        assertEquals(1, activeTimeSlots.size());

        mDataManager.getUserDataForTesting(USER_ID_PRIMARY).setDefaultSmsApp(null);
        mDataManager.pruneDataForUser(USER_ID_PRIMARY, mCancellationSignal);
        activeTimeSlots = getActiveSlotsForTestShortcut(Event.SMS_EVENT_TYPES);
        assertTrue(activeTimeSlots.isEmpty());
    }

    @Test
    public void testPruneExpiredConversationStatuses() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        mDataManager.addOrUpdateConversationInfo(shortcut);

        ConversationStatus cs1 = new ConversationStatus.Builder("cs1", 9)
                .setEndTimeMillis(System.currentTimeMillis())
                .build();
        ConversationStatus cs2 = new ConversationStatus.Builder("cs2", 10)
                .build();
        ConversationStatus cs3 = new ConversationStatus.Builder("cs3", 1)
                .setEndTimeMillis(Long.MAX_VALUE)
                .build();
        mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs1);
        mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs2);
        mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs3);
        mLooper.dispatchAll();

        PeopleService.ConversationsListener listener = mock(
                PeopleService.ConversationsListener.class);
        mDataManager.addConversationsListener(listener);
        mDataManager.pruneDataForUser(USER_ID_PRIMARY, mCancellationSignal);
        mLooper.dispatchAll();

        assertThat(mDataManager.getStatuses(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID))
                .doesNotContain(cs1);
        assertThat(mDataManager.getStatuses(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID))
                .contains(cs2);
        assertThat(mDataManager.getStatuses(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID))
                .contains(cs3);
        ArgumentCaptor<List<ConversationChannel>> capturedConversation = ArgumentCaptor.forClass(
                List.class);
        verify(listener, times(1)).onConversationsUpdate(capturedConversation.capture());
        List<ConversationChannel> results = capturedConversation.getValue();
        ConversationChannel result = Iterables.getOnlyElement(capturedConversation.getValue());
        // CHeck cs1 has been removed and only cs2 and cs3 remain.
        assertThat(result.getStatuses()).containsExactly(cs2, cs3);
    }

    @Test
    public void testDoNotUncacheShortcutWithActiveNotifications() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
        NotificationListenerService listenerService =
                mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);

        for (int i = 0; i < DataManager.MAX_CACHED_RECENT_SHORTCUTS + 1; i++) {
            String shortcutId = TEST_SHORTCUT_ID + i;
            ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, shortcutId,
                    buildPerson());
            shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
            mDataManager.addOrUpdateConversationInfo(shortcut);
            when(mNotification.getShortcutId()).thenReturn(shortcutId);
            sendGenericNotification();
        }

        mDataManager.pruneDataForUser(USER_ID_PRIMARY, mCancellationSignal);

        verify(mShortcutServiceInternal, never()).uncacheShortcuts(
                anyInt(), anyString(), anyString(), anyList(), anyInt(), anyInt());
    }

    @Test
    public void testUncacheOldestCachedShortcut() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
        NotificationListenerService listenerService =
                mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);

        for (int i = 0; i < DataManager.MAX_CACHED_RECENT_SHORTCUTS + 1; i++) {
            String shortcutId = TEST_SHORTCUT_ID + i;
            ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, shortcutId,
                    buildPerson());
            shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
            mDataManager.addOrUpdateConversationInfo(shortcut);
            when(mNotification.getShortcutId()).thenReturn(shortcutId);
            when(mGenericSbn.getPostTime()).thenReturn(100L + i);
            sendGenericNotification();
            listenerService.onNotificationRemoved(mGenericSbn, null,
                    NotificationListenerService.REASON_CANCEL);
        }

        // Only the shortcut #0 is uncached, all the others are not.
        verify(mShortcutServiceInternal).uncacheShortcuts(
                anyInt(), any(), eq(TEST_PKG_NAME),
                eq(Collections.singletonList(TEST_SHORTCUT_ID + 0)), eq(USER_ID_PRIMARY),
                eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
        for (int i = 1; i < DataManager.MAX_CACHED_RECENT_SHORTCUTS + 1; i++) {
            verify(mShortcutServiceInternal, never()).uncacheShortcuts(
                    anyInt(), anyString(), anyString(),
                    eq(Collections.singletonList(TEST_SHORTCUT_ID + i)), anyInt(),
                    eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
        }
    }

    @Test
    public void testUncacheOldestCachedShortcut_missingNotificationEvents() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);

        for (int i = 0; i < DataManager.MAX_CACHED_RECENT_SHORTCUTS + 1; i++) {
            String shortcutId = TEST_SHORTCUT_ID + i;
            ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, shortcutId,
                    buildPerson());
            shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
            mShortcutChangeCallback.onShortcutsAddedOrUpdated(
                    TEST_PKG_NAME,
                    Collections.singletonList(shortcut),
                    UserHandle.of(USER_ID_PRIMARY));
            mLooper.dispatchAll();
        }

        // Only the shortcut #0 is uncached, all the others are not.
        verify(mShortcutServiceInternal).uncacheShortcuts(
                anyInt(), any(), eq(TEST_PKG_NAME),
                eq(Collections.singletonList(TEST_SHORTCUT_ID + 0)), eq(USER_ID_PRIMARY),
                eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
        for (int i = 1; i < DataManager.MAX_CACHED_RECENT_SHORTCUTS + 1; i++) {
            verify(mShortcutServiceInternal, never()).uncacheShortcuts(
                    anyInt(), anyString(), anyString(),
                    eq(Collections.singletonList(TEST_SHORTCUT_ID + i)), anyInt(),
                    eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
        }
    }

    @Test
    public void testUncacheOldestCachedShortcut_legacyConversation() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);

        // Add an extra conversation with a legacy type (no creationTime)
        ConversationStore conversationStore = mDataManager
                .getUserDataForTesting(USER_ID_PRIMARY)
                .getOrCreatePackageData(TEST_PKG_NAME)
                .getConversationStore();
        ConversationInfo.Builder builder = new ConversationInfo.Builder();
        builder.setShortcutId(TEST_SHORTCUT_ID + 0);
        builder.setShortcutFlags(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
        mDataManager.updateConversationStoreThenNotifyListeners(
                conversationStore,
                builder.build(),
                TEST_PKG_NAME, USER_ID_PRIMARY);
        for (int i = 1; i < DataManager.MAX_CACHED_RECENT_SHORTCUTS + 1; i++) {
            String shortcutId = TEST_SHORTCUT_ID + i;
            ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, shortcutId,
                    buildPerson());
            shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
            mShortcutChangeCallback.onShortcutsAddedOrUpdated(
                    TEST_PKG_NAME,
                    Collections.singletonList(shortcut),
                    UserHandle.of(USER_ID_PRIMARY));
            mLooper.dispatchAll();
        }

        // Only the shortcut #0 is uncached, all the others are not.
        verify(mShortcutServiceInternal).uncacheShortcuts(
                anyInt(), any(), eq(TEST_PKG_NAME),
                eq(Collections.singletonList(TEST_SHORTCUT_ID + 0)), eq(USER_ID_PRIMARY),
                eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
        for (int i = 1; i < DataManager.MAX_CACHED_RECENT_SHORTCUTS + 1; i++) {
            verify(mShortcutServiceInternal, never()).uncacheShortcuts(
                    anyInt(), anyString(), anyString(),
                    eq(Collections.singletonList(TEST_SHORTCUT_ID + i)), anyInt(),
                    eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
        }
    }

    @Test
    public void testBackupAndRestoration()
            throws IntentFilter.MalformedMimeTypeException {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                null);
        AppTarget appTarget = new AppTarget.Builder(new AppTargetId(TEST_SHORTCUT_ID), shortcut)
                .build();
        AppTargetEvent appTargetEvent =
                new AppTargetEvent.Builder(appTarget, AppTargetEvent.ACTION_LAUNCH)
                        .setLaunchLocation(ChooserActivity.LAUNCH_LOCATION_DIRECT_SHARE)
                        .build();
        IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SEND, "image/jpg");

        mDataManager.reportShareTargetEvent(appTargetEvent, intentFilter);
        byte[] payload = mDataManager.getBackupPayload(USER_ID_PRIMARY);

        DataManager dataManager = new DataManager(mContext, mInjector, mLooper.getLooper());
        dataManager.onUserUnlocked(USER_ID_PRIMARY);
        dataManager.restore(USER_ID_PRIMARY, payload);
        ConversationInfo conversationInfo = dataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY)
                .getConversationStore()
                .getConversation(TEST_SHORTCUT_ID);
        assertNotNull(conversationInfo);
        assertEquals(conversationInfo.getShortcutId(), TEST_SHORTCUT_ID);
    }

    @Test
    public void testGetRecentConversations() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
        mDataManager.addOrUpdateConversationInfo(shortcut);

        sendGenericNotification();

        List<ConversationChannel> result = mDataManager.getRecentConversations(USER_ID_PRIMARY);
        assertEquals(1, result.size());
        assertEquals(shortcut.getId(), result.get(0).getShortcutInfo().getId());
        assertEquals(1, result.get(0).getShortcutInfo().getPersons().length);
        assertEquals(CONTACT_URI, result.get(0).getShortcutInfo().getPersons()[0].getUri());
        assertEquals(mParentNotificationChannel.getId(),
                result.get(0).getNotificationChannel().getId());
        assertEquals(null, result.get(0).getNotificationChannel().getParentChannelId());
        assertEquals(mGenericSbn.getPostTime(), result.get(0).getLastEventTimestamp());
        assertTrue(result.get(0).hasActiveNotifications());
    }

    @Test
    public void testGetRecentConversationsGetsPersonsData() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
        mDataManager.addOrUpdateConversationInfo(shortcut);

        sendGenericNotification();

       mDataManager.getRecentConversations(USER_ID_PRIMARY);

        verify(mShortcutServiceInternal).getShortcuts(
                anyInt(), anyString(), anyLong(), anyString(), anyList(), any(), any(),
                mQueryFlagsCaptor.capture(), anyInt(), anyInt(), anyInt());
        Integer queryFlags = mQueryFlagsCaptor.getValue();
        assertThat(hasFlag(queryFlags, ShortcutQuery.FLAG_GET_PERSONS_DATA)).isTrue();
    }

    @Test
    public void testPruneOldRecentConversations() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
        mDataManager.addOrUpdateConversationInfo(shortcut);

        NotificationListenerService listenerService =
                mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
        when(mNotification.getShortcutId()).thenReturn(TEST_SHORTCUT_ID);
        sendGenericNotification();
        listenerService.onNotificationRemoved(mGenericSbn, null,
                NotificationListenerService.REASON_CLICK);

        mDataManager.pruneOldRecentConversations(USER_ID_PRIMARY,
                System.currentTimeMillis() + (10 * DateUtils.DAY_IN_MILLIS) + 1);

        verify(mShortcutServiceInternal).uncacheShortcuts(
                anyInt(), any(), eq(TEST_PKG_NAME), eq(Collections.singletonList(TEST_SHORTCUT_ID)),
                eq(USER_ID_PRIMARY), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
    }

    @Test
    public void testGetLastInteraction() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        mDataManager.addOrUpdateConversationInfo(shortcut);

        sendGenericNotification();

        assertEquals(mGenericSbn.getPostTime(),
                mDataManager.getLastInteraction(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID));
        assertEquals(0L,
                mDataManager.getLastInteraction("not_test_pkg", USER_ID_PRIMARY, TEST_SHORTCUT_ID));
        assertEquals(0L,
                mDataManager.getLastInteraction(TEST_PKG_NAME, USER_ID_PRIMARY_MANAGED,
                        TEST_SHORTCUT_ID));
        assertEquals(0L,
                mDataManager.getLastInteraction(TEST_PKG_NAME, USER_ID_SECONDARY,
                        TEST_SHORTCUT_ID));
    }

    @Test
    public void testAddOrUpdateStatus_noCachedShortcut() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);

        ConversationStatus cs = new ConversationStatus.Builder("id", ACTIVITY_ANNIVERSARY).build();

        try {
            mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs);
            fail("Updated a conversation info that didn't previously exist");
        } catch (IllegalArgumentException e) {
            // good
        }
    }

    @Test
    public void testAddOrUpdateStatus() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        mDataManager.addOrUpdateConversationInfo(shortcut);

        ConversationStatus cs = new ConversationStatus.Builder("id", ACTIVITY_ANNIVERSARY).build();
        mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs);

        assertThat(mDataManager.getStatuses(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID))
                .contains(cs);

        ConversationStatus cs2 = new ConversationStatus.Builder("id2", ACTIVITY_GAME).build();
        mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs2);

        assertThat(mDataManager.getStatuses(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID))
                .contains(cs);
        assertThat(mDataManager.getStatuses(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID))
                .contains(cs2);

        verify(mAlarmManager, never()).setExactAndAllowWhileIdle(anyInt(), anyLong(), any());
    }

    @Test
    public void testAddOrUpdateStatus_schedulesJob() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        mDataManager.addOrUpdateConversationInfo(shortcut);

        ConversationStatus cs = new ConversationStatus.Builder("id", ACTIVITY_ANNIVERSARY)
                .setEndTimeMillis(1000)
                .build();
        mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs);

        ConversationStatus cs2 = new ConversationStatus.Builder("id2", ACTIVITY_GAME)
                .setEndTimeMillis(3000)
                .build();
        mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs2);

        verify(mAlarmManager, times(2)).setExactAndAllowWhileIdle(anyInt(), anyLong(), any());
    }

    @Test
    public void testClearStatus() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        mDataManager.addOrUpdateConversationInfo(shortcut);

        ConversationStatus cs = new ConversationStatus.Builder("id", ACTIVITY_ANNIVERSARY).build();
        ConversationStatus cs2 = new ConversationStatus.Builder("id2", ACTIVITY_GAME).build();
        mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs);
        mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs2);
        mLooper.dispatchAll();

        PeopleService.ConversationsListener listener = mock(
                PeopleService.ConversationsListener.class);
        mDataManager.addConversationsListener(listener);
        mDataManager.clearStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs2.getId());
        mLooper.dispatchAll();

        assertThat(mDataManager.getStatuses(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID))
                .contains(cs);
        assertThat(mDataManager.getStatuses(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID))
                .doesNotContain(cs2);
        ArgumentCaptor<List<ConversationChannel>> capturedConversation = ArgumentCaptor.forClass(
                List.class);
        verify(listener, times(1)).onConversationsUpdate(capturedConversation.capture());
        ConversationChannel result = Iterables.getOnlyElement(capturedConversation.getValue());
        assertThat(result.getStatuses()).containsExactly(cs);
    }

    @Test
    public void testClearStatuses() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        mDataManager.addOrUpdateConversationInfo(shortcut);

        ConversationStatus cs = new ConversationStatus.Builder("id", ACTIVITY_ANNIVERSARY).build();
        ConversationStatus cs2 = new ConversationStatus.Builder("id2", ACTIVITY_GAME).build();
        mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs);
        mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs2);
        mLooper.dispatchAll();

        PeopleService.ConversationsListener listener = mock(
                PeopleService.ConversationsListener.class);
        mDataManager.addConversationsListener(listener);
        mDataManager.clearStatuses(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID);
        mLooper.dispatchAll();

        assertThat(mDataManager.getStatuses(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID))
                .isEmpty();
        ArgumentCaptor<List<ConversationChannel>> capturedConversation = ArgumentCaptor.forClass(
                List.class);
        verify(listener, times(1)).onConversationsUpdate(capturedConversation.capture());
        ConversationChannel result = Iterables.getOnlyElement(capturedConversation.getValue());
        assertThat(result.getStatuses()).isEmpty();
    }

    @Test
    public void testNonCachedShortcutNotInRecentList() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY_MANAGED,
                TEST_SHORTCUT_ID, buildPerson());
        mDataManager.addOrUpdateConversationInfo(shortcut);

        sendGenericNotification();

        List<ConversationChannel> result = mDataManager.getRecentConversations(USER_ID_PRIMARY);
        assertTrue(result.isEmpty());
    }

    @Test
    public void testCustomizedConversationNotInRecentList() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
        mDataManager.addOrUpdateConversationInfo(shortcut);

        // Post a notification and customize the notification settings.
        NotificationListenerService listenerService =
                mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
        sendGenericNotification();
        listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY),
                mNotificationChannel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED);

        List<ConversationChannel> result = mDataManager.getRecentConversations(USER_ID_PRIMARY);
        assertTrue(result.isEmpty());
    }

    @Test
    public void testNotificationRemoved() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
        mDataManager.addOrUpdateConversationInfo(shortcut);

        NotificationListenerService listenerService =
                mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
        sendGenericNotification();
        // posting updates the last interaction time, so delay before deletion
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long approxDeletionTime = System.currentTimeMillis();
        listenerService.onNotificationRemoved(mGenericSbn, null,
                NotificationListenerService.REASON_CANCEL);

        ConversationInfo conversationInfo = mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY)
                .getConversationStore()
                .getConversation(TEST_SHORTCUT_ID);
        assertTrue(conversationInfo.getLastEventTimestamp() - approxDeletionTime < 100);
    }

    @Test
    public void testRemoveRecentConversation() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);

        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                buildPerson());
        shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
        mDataManager.addOrUpdateConversationInfo(shortcut);

        NotificationListenerService listenerService =
                mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
        sendGenericNotification();
        listenerService.onNotificationRemoved(mGenericSbn, null,
                NotificationListenerService.REASON_CANCEL);
        mDataManager.removeRecentConversation(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                USER_ID_PRIMARY);

        verify(mShortcutServiceInternal).uncacheShortcuts(
                anyInt(), any(), eq(TEST_PKG_NAME), eq(Collections.singletonList(TEST_SHORTCUT_ID)),
                eq(USER_ID_PRIMARY), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
    }

    @Test
    public void testRemoveAllRecentConversations() {
        mDataManager.onUserUnlocked(USER_ID_PRIMARY);

        ShortcutInfo shortcut1 = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, "1",
                buildPerson());
        shortcut1.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
        mDataManager.addOrUpdateConversationInfo(shortcut1);

        ShortcutInfo shortcut2 = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, "2",
                buildPerson());
        shortcut2.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
        mDataManager.addOrUpdateConversationInfo(shortcut2);

        NotificationListenerService listenerService =
                mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);

        // Post a notification and then dismiss it for conversation #1.
        when(mNotification.getShortcutId()).thenReturn("1");
        sendGenericNotification();
        listenerService.onNotificationRemoved(mGenericSbn, null,
                NotificationListenerService.REASON_CANCEL);

        // Post a notification for conversation #2, but don't dismiss it. Its shortcut won't be
        // uncached when removeAllRecentConversations() is called.
        when(mNotification.getShortcutId()).thenReturn("2");
        sendGenericNotification();

        mDataManager.removeAllRecentConversations(USER_ID_PRIMARY);

        verify(mShortcutServiceInternal).uncacheShortcuts(
                anyInt(), any(), eq(TEST_PKG_NAME), eq(Collections.singletonList("1")),
                eq(USER_ID_PRIMARY), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
        verify(mShortcutServiceInternal, never()).uncacheShortcuts(
                anyInt(), any(), eq(TEST_PKG_NAME), eq(Collections.singletonList("2")),
                eq(USER_ID_PRIMARY), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
    }

    private static <T> void addLocalServiceMock(Class<T> clazz, T mock) {
        LocalServices.removeServiceForTest(clazz);
        LocalServices.addService(clazz, mock);
    }

    private List<ConversationInfo> getConversationsInPrimary() {
        List<ConversationInfo> conversations = new ArrayList<>();
        mDataManager.forPackagesInProfile(USER_ID_PRIMARY,
                packageData -> packageData.forAllConversations(conversations::add));
        return conversations;
    }

    private List<Range<Long>> getActiveSlotsForTestShortcut(Set<Integer> eventTypes) {
        List<Range<Long>> activeSlots = new ArrayList<>();
        mDataManager.forPackagesInProfile(USER_ID_PRIMARY, packageData ->
                activeSlots.addAll(
                        packageData.getEventHistory(TEST_SHORTCUT_ID)
                                .getEventIndex(eventTypes)
                                .getActiveTimeSlots()));
        return activeSlots;
    }

    private List<Range<Long>> getActiveSlotsForAppShares() {
        List<Range<Long>> activeSlots = new ArrayList<>();
        mDataManager.forPackagesInProfile(USER_ID_PRIMARY, packageData ->
                activeSlots.addAll(
                        packageData.getClassLevelEventHistory(TEST_CLASS_NAME)
                                .getEventIndex(Event.SHARE_EVENT_TYPES)
                                .getActiveTimeSlots()));
        return activeSlots;
    }

    private ShortcutInfo buildShortcutInfo(String packageName, int userId, String id,
            @Nullable Person person) {
        Context mockContext = mock(Context.class);
        when(mockContext.getPackageName()).thenReturn(packageName);
        when(mockContext.getUserId()).thenReturn(userId);
        when(mockContext.getUser()).thenReturn(UserHandle.of(userId));
        ShortcutInfo.Builder builder = new ShortcutInfo.Builder(mockContext, id)
                .setShortLabel(id)
                .setLongLived(true)
                .setIntent(new Intent("TestIntent"));
        if (person != null) {
            builder.setPersons(new Person[]{person});
        }
        return builder.build();
    }

    private Person buildPerson() {
        return buildPerson(true, false);
    }

    private Person buildPerson(boolean isImportant, boolean isBot) {
        return new Person.Builder()
                .setImportant(isImportant)
                .setBot(isBot)
                .setUri(CONTACT_URI)
                .build();
    }

    private UserInfo buildUserInfo(int userId) {
        return new UserInfo(userId, "", 0);
    }

    /**
     * Returns {@code true} iff {@link ShortcutQuery}'s {@code queryFlags} has {@code flag} set.
     */
    private static boolean hasFlag(int queryFlags, int flag) {
        return (queryFlags & flag) != 0;
    }

    // "Sends" a notification to a non-customized notification channel - the notification channel
    // is something generic like "messages" and the notification has a  shortcut id
    private void sendGenericNotification() {
        when(mNotification.getChannelId()).thenReturn(PARENT_NOTIFICATION_CHANNEL_ID);
        doAnswer(invocationOnMock -> {
            NotificationListenerService.Ranking ranking = (NotificationListenerService.Ranking)
                    invocationOnMock.getArguments()[1];
            ranking.populate(
                    (String) invocationOnMock.getArguments()[0],
                    0,
                    false,
                    0,
                    0,
                    mParentNotificationChannel.getImportance(),
                    null, null,
                    mParentNotificationChannel, null, null, true, 0, false, -1, false, null, null,
                    false, false, false, null, 0, false);
            return true;
        }).when(mRankingMap).getRanking(eq(GENERIC_KEY),
                any(NotificationListenerService.Ranking.class));
        NotificationListenerService listenerService =
                mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
        listenerService.onNotificationPosted(mGenericSbn, mRankingMap);
    }

    // "Sends" a notification to a customized notification channel - the notification channel
    // is specific to a person, and the channel has a convo id matching the notification's shortcut
    // and the channel has a parent channel id
    private void sendConvoNotification() {
        when(mNotification.getChannelId()).thenReturn(NOTIFICATION_CHANNEL_ID);
        doAnswer(invocationOnMock -> {
            NotificationListenerService.Ranking ranking = (NotificationListenerService.Ranking)
                    invocationOnMock.getArguments()[1];
            ranking.populate(
                    (String) invocationOnMock.getArguments()[0],
                    0,
                    false,
                    0,
                    0,
                    mNotificationChannel.getImportance(),
                    null, null,
                    mNotificationChannel, null, null, true, 0, false, -1, false, null, null, false,
                    false, false, null, 0, false);
            return true;
        }).when(mRankingMap).getRanking(eq(CUSTOM_KEY),
                any(NotificationListenerService.Ranking.class));

        NotificationListenerService listenerService =
                mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
        listenerService.onNotificationPosted(mConvoSbn, mRankingMap);
    }

    private class TestContactsQueryHelper extends ContactsQueryHelper {

        private Uri mContactUri;
        private boolean mIsStarred;
        private String mPhoneNumber;

        TestContactsQueryHelper(Context context) {
            super(context);
            mContactUri = Uri.parse(CONTACT_URI);
            mIsStarred = false;
            mPhoneNumber = PHONE_NUMBER;
        }

        @Override
        boolean query(@NonNull String contactUri) {
            return true;
        }

        @Override
        boolean querySince(long sinceTime) {
            return true;
        }

        @Override
        @Nullable
        Uri getContactUri() {
            return mContactUri;
        }

        @Override
        boolean isStarred() {
            return mIsStarred;
        }

        @Override
        @Nullable
        String getPhoneNumber() {
            return mPhoneNumber;
        }
    }

    private class TestCallLogQueryHelper extends CallLogQueryHelper {

        private final BiConsumer<String, Event> mEventConsumer;

        TestCallLogQueryHelper(Context context, BiConsumer<String, Event> eventConsumer) {
            super(context, eventConsumer);
            mEventConsumer = eventConsumer;
        }

        @Override
        boolean querySince(long sinceTime) {
            return true;
        }

        @Override
        long getLastCallTimestamp() {
            return 100L;
        }
    }

    private class TestSmsQueryHelper extends SmsQueryHelper {

        private final BiConsumer<String, Event> mEventConsumer;

        TestSmsQueryHelper(Context context, BiConsumer<String, Event> eventConsumer) {
            super(context, eventConsumer);
            mEventConsumer = eventConsumer;
        }

        @Override
        boolean querySince(long sinceTime) {
            return true;
        }

        @Override
        long getLastMessageTimestamp() {
            return 100L;
        }
    }

    private class TestMmsQueryHelper extends MmsQueryHelper {

        private final BiConsumer<String, Event> mEventConsumer;

        TestMmsQueryHelper(Context context, BiConsumer<String, Event> eventConsumer) {
            super(context, eventConsumer);
            mEventConsumer = eventConsumer;
        }

        @Override
        boolean querySince(long sinceTime) {
            return true;
        }

        @Override
        long getLastMessageTimestamp() {
            return 100L;
        }
    }

    private class TestUsageStatsQueryHelper extends UsageStatsQueryHelper {

        private final EventListener mEventListener;

        TestUsageStatsQueryHelper(int userId,
                Function<String, PackageData> packageDataGetter,
                EventListener eventListener) {
            super(userId, packageDataGetter, eventListener);
            mEventListener = eventListener;
        }
    }

    private class TestInjector extends DataManager.Injector {

        private final TestContactsQueryHelper mContactsQueryHelper =
                new TestContactsQueryHelper(mContext);
        private TestCallLogQueryHelper mCallLogQueryHelper;
        private TestMmsQueryHelper mMmsQueryHelper;
        private TestSmsQueryHelper mSmsQueryHelper;
        private TestUsageStatsQueryHelper mUsageStatsQueryHelper;

        @Override
        ScheduledExecutorService createScheduledExecutor() {
            return mExecutorService;
        }

        @Override
        Executor getBackgroundExecutor() {
            return Runnable::run;
        }

        @Override
        ContactsQueryHelper createContactsQueryHelper(Context context) {
            return mContactsQueryHelper;
        }

        @Override
        CallLogQueryHelper createCallLogQueryHelper(Context context,
                BiConsumer<String, Event> eventConsumer) {
            mCallLogQueryHelper = new TestCallLogQueryHelper(context, eventConsumer);
            return mCallLogQueryHelper;
        }

        @Override
        MmsQueryHelper createMmsQueryHelper(Context context,
                BiConsumer<String, Event> eventConsumer) {
            mMmsQueryHelper = new TestMmsQueryHelper(context, eventConsumer);
            return mMmsQueryHelper;
        }

        @Override
        SmsQueryHelper createSmsQueryHelper(Context context,
                BiConsumer<String, Event> eventConsumer) {
            mSmsQueryHelper = new TestSmsQueryHelper(context, eventConsumer);
            return mSmsQueryHelper;
        }

        @Override
        UsageStatsQueryHelper createUsageStatsQueryHelper(@UserIdInt int userId,
                Function<String, PackageData> packageDataGetter,
                UsageStatsQueryHelper.EventListener eventListener) {
            mUsageStatsQueryHelper =
                    new TestUsageStatsQueryHelper(userId, packageDataGetter, eventListener);
            return mUsageStatsQueryHelper;
        }
    }
}
