/*
 * Copyright (C) 2015 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.telecom.tests;

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;

import android.app.BroadcastOptions;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.Context;
import android.content.IContentProvider;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.ICancellationSignal;
import android.os.Looper;
import android.os.UserHandle;
import android.provider.CallLog;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.SmallTest;

import android.telecom.CallerInfo;
import com.android.server.telecom.CallerInfoLookupHelper;
import com.android.server.telecom.Constants;
import com.android.server.telecom.DefaultDialerCache;
import com.android.server.telecom.DeviceIdleControllerAdapter;
import com.android.server.telecom.MissedCallNotifier;
import com.android.server.telecom.PhoneAccountRegistrar;
import com.android.server.telecom.TelecomBroadcastIntentProcessor;
import com.android.server.telecom.TelecomSystem;
import com.android.server.telecom.components.TelecomBroadcastReceiver;
import com.android.server.telecom.ui.MissedCallNotifierImpl;
import com.android.server.telecom.ui.MissedCallNotifierImpl.NotificationBuilderFactory;

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.Mock;
import org.mockito.MockitoAnnotations;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isNull;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@RunWith(JUnit4.class)
public class MissedCallNotifierImplTest extends TelecomTestCase {

    private static class MockMissedCallCursorBuilder {
        private class CallLogRow {
            String number;
            int presentation;
            long date;

            public CallLogRow(String number, int presentation, long date) {
                this.number = number;
                this.presentation = presentation;
                this.date = date;
            }
        }

        private List<CallLogRow> mRows;

        MockMissedCallCursorBuilder() {
            mRows = new LinkedList<>();
            mRows.add(null);
        }

        public MockMissedCallCursorBuilder addEntry(String number, int presentation, long date) {
            mRows.add(new CallLogRow(number, presentation, date));
            return this;
        }

        public Cursor build() {
            Cursor c = mock(Cursor.class);
            when(c.moveToNext()).thenAnswer(unused -> {
                mRows.remove(0);
                return mRows.size() > 0;
            });
            when(c.getString(MissedCallNotifierImpl.CALL_LOG_COLUMN_NUMBER))
                    .thenAnswer(unused -> mRows.get(0).number);
            when(c.getInt(MissedCallNotifierImpl.CALL_LOG_COLUMN_NUMBER_PRESENTATION))
                    .thenAnswer(unused -> mRows.get(0).presentation);
            when(c.getLong(MissedCallNotifierImpl.CALL_LOG_COLUMN_DATE))
                    .thenAnswer(unused -> mRows.get(0).date);
            return c;
        }
    }

    private static final long TIMEOUT_DELAY = 5000;
    private static final Uri TEL_CALL_HANDLE = Uri.parse("tel:+11915552620");
    private static final Uri SIP_CALL_HANDLE = Uri.parse("sip:testaddress@testdomain.com");
    private static final String CALLER_NAME = "Fake Name";
    private static final String MISSED_CALL_TITLE = "Missed Call";
    private static final String MISSED_CALLS_TITLE = "Missed Calls";
    private static final String MISSED_CALLS_MSG = "%s missed calls";
    private static final String USER_CALL_ACTIVITY_LABEL = "Phone";
    private static final String DEFAULT_DIALER_PACKAGE = "com.android.server.telecom.test";

    private static final int REQUEST_ID = 0;
    private static final long CALL_TIMESTAMP;
    static {
         CALL_TIMESTAMP = System.currentTimeMillis() - 60 * 1000 * 5;
    }

    private static final UserHandle PRIMARY_USER = UserHandle.of(0);
    private static final UserHandle SECONARY_USER = UserHandle.of(12);
    private static final int NO_CAPABILITY = 0;
    private static final int TEST_TIMEOUT = 1000;
    private static final long TEST_POWER_EXEMPT_TIME_MS = 1000;
    private static final ComponentName COMPONENT_NAME = new ComponentName(
            "com.anything", "com.whatever");

    @Mock
    private NotificationManager mNotificationManager;

    @Mock
    private PhoneAccountRegistrar mPhoneAccountRegistrar;

    @Mock
    private TelecomManager mTelecomManager;

    @Mock TelecomSystem mTelecomSystem;
    @Mock private DefaultDialerCache mDefaultDialerCache;
    @Mock private DeviceIdleControllerAdapter mDeviceIdleControllerAdapter;

    @Override
    @Before
    public void setUp() throws Exception {
        super.setUp();
        MockitoAnnotations.initMocks(this);

        mContext = mComponentContextFixture.getTestDouble().getApplicationContext();
        mNotificationManager = (NotificationManager) mContext.getSystemService(
                Context.NOTIFICATION_SERVICE);
        TelephonyManager fakeTelephonyManager = (TelephonyManager) mContext.getSystemService(
                Context.TELEPHONY_SERVICE);
        when(fakeTelephonyManager.getNetworkCountryIso()).thenReturn("US");
        doReturn(new ApplicationInfo()).when(mContext).getApplicationInfo();
        doReturn("com.android.server.telecom.tests").when(mContext).getPackageName();

        mComponentContextFixture.putResource(R.string.notification_missedCallTitle,
                MISSED_CALL_TITLE);
        mComponentContextFixture.putResource(R.string.notification_missedCallsTitle,
                MISSED_CALLS_TITLE);
        mComponentContextFixture.putResource(R.string.notification_missedCallsMsg,
                MISSED_CALLS_MSG);
        mComponentContextFixture.putResource(R.string.userCallActivityLabel,
                USER_CALL_ACTIVITY_LABEL);
        mComponentContextFixture.setTelecomManager(mTelecomManager);
    }

    @Override
    @After
    public void tearDown() throws Exception {
        TelecomSystem.setInstance(null);
        when(mTelecomSystem.isBootComplete()).thenReturn(false);
        super.tearDown();
    }

    @SmallTest
    @Test
    public void testCancelNotificationInPrimaryUser() {
        cancelNotificationTestInternal(PRIMARY_USER);
    }

    @SmallTest
    @Test
    public void testCancelNotificationInSecondaryUser() {
        cancelNotificationTestInternal(SECONARY_USER);
    }

    @SmallTest
    @Test
    public void testDefaultDialerClear() {
        MissedCallNotifier missedCallNotifier = setupMissedCallNotificationThroughDefaultDialer();
        missedCallNotifier.clearMissedCalls(PRIMARY_USER);

        ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
        verify(mContext).sendBroadcastAsUser(intentArgumentCaptor.capture(), any(),
                anyString(), any());
        Intent sentIntent = intentArgumentCaptor.getValue();
        assertEquals(0, sentIntent.getIntExtra(TelecomManager.EXTRA_NOTIFICATION_COUNT, -1));
    }

    @SmallTest
    @Test
    public void testDefaultDialerIncrement() {
        MissedCallNotifier missedCallNotifier = setupMissedCallNotificationThroughDefaultDialer();
        PhoneAccount phoneAccount = makePhoneAccount(PRIMARY_USER, NO_CAPABILITY);
        MissedCallNotifier.CallInfo fakeCall = makeFakeCallInfo(TEL_CALL_HANDLE, CALLER_NAME,
                CALL_TIMESTAMP, phoneAccount.getAccountHandle());

        missedCallNotifier.showMissedCallNotification(fakeCall);
        ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
        verify(mContext).sendBroadcastAsUser(intentArgumentCaptor.capture(), any(),
                anyString(), any());

        Intent sentIntent = intentArgumentCaptor.getValue();
        assertEquals(1, sentIntent.getIntExtra(TelecomManager.EXTRA_NOTIFICATION_COUNT, -1));
    }

    private MissedCallNotifier setupMissedCallNotificationThroughDefaultDialer() {
        mComponentContextFixture.addIntentReceiver(
                TelecomManager.ACTION_SHOW_MISSED_CALLS_NOTIFICATION, COMPONENT_NAME);
        when(mDefaultDialerCache.getDefaultDialerApplication(anyInt())).thenReturn(
                DEFAULT_DIALER_PACKAGE);

        Notification.Builder builder1 = makeNotificationBuilder("builder1");
        Notification.Builder builder2 = makeNotificationBuilder("builder2");
        MissedCallNotifierImpl.NotificationBuilderFactory fakeBuilderFactory =
                makeNotificationBuilderFactory(builder1, builder1, builder2, builder2);
        return makeMissedCallNotifier(fakeBuilderFactory, PRIMARY_USER);
    }

    private void cancelNotificationTestInternal(UserHandle userHandle) {
        Notification.Builder builder1 = makeNotificationBuilder("builder1");
        Notification.Builder builder2 = makeNotificationBuilder("builder2");
        MissedCallNotifierImpl.NotificationBuilderFactory fakeBuilderFactory =
                makeNotificationBuilderFactory(builder1, builder1, builder2, builder2);

        MissedCallNotifier missedCallNotifier = makeMissedCallNotifier(fakeBuilderFactory,
                PRIMARY_USER);
        PhoneAccount phoneAccount = makePhoneAccount(userHandle, NO_CAPABILITY);
        MissedCallNotifier.CallInfo fakeCall = makeFakeCallInfo(TEL_CALL_HANDLE, CALLER_NAME,
                CALL_TIMESTAMP, phoneAccount.getAccountHandle());

        missedCallNotifier.showMissedCallNotification(fakeCall);
        missedCallNotifier.clearMissedCalls(userHandle);
        missedCallNotifier.showMissedCallNotification(fakeCall);

        ArgumentCaptor<Integer> requestIdCaptor = ArgumentCaptor.forClass(
                Integer.class);
        verify(mNotificationManager, times(2)).notifyAsUser(nullable(String.class),
                requestIdCaptor.capture(), nullable(Notification.class), eq(userHandle));
        verify(mNotificationManager).cancelAsUser(nullable(String.class),
                eq(requestIdCaptor.getValue()), eq(userHandle));

        // Verify that the second call to showMissedCallNotification behaves like it were the first.
        verify(builder2).setContentText(CALLER_NAME);
    }

    @SmallTest
    @Test
    public void testNotifyMultipleMissedCalls() {
        Notification.Builder[] builders = new Notification.Builder[4];

        for (int i = 0; i < 4; i++) {
            builders[i] = makeNotificationBuilder("builder" + Integer.toString(i));
        }

        PhoneAccount phoneAccount = makePhoneAccount(PRIMARY_USER, NO_CAPABILITY);
        MissedCallNotifier.CallInfo fakeCall = makeFakeCallInfo(TEL_CALL_HANDLE, CALLER_NAME,
                CALL_TIMESTAMP, phoneAccount.getAccountHandle());

        MissedCallNotifierImpl.NotificationBuilderFactory fakeBuilderFactory =
                makeNotificationBuilderFactory(builders);

        MissedCallNotifier missedCallNotifier = new MissedCallNotifierImpl(mContext,
                mPhoneAccountRegistrar, mDefaultDialerCache, fakeBuilderFactory,
                mDeviceIdleControllerAdapter);

        missedCallNotifier.showMissedCallNotification(fakeCall);
        missedCallNotifier.showMissedCallNotification(fakeCall);

        // The following captor is to capture the two notifications that got passed into
        // notifyAsUser. This distinguishes between the builders used for the full notification
        // (i.e. the one potentially containing sensitive information, such as phone numbers),
        // and the builders used for the notifications shown on the lockscreen, which have been
        // scrubbed of such sensitive info. The notifications which are used as arguments
        // to notifyAsUser are the versions which contain sensitive information.
        ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass(
                Notification.class);
        verify(mNotificationManager, times(2)).notifyAsUser(nullable(String.class), eq(1),
                notificationArgumentCaptor.capture(), eq(PRIMARY_USER));
        HashSet<String> privateNotifications = new HashSet<>();
        for (Notification n : notificationArgumentCaptor.getAllValues()) {
            privateNotifications.add(n.toString());
        }

        for (int i = 0; i < 4; i++) {
            Notification.Builder builder = builders[i];
            verify(builder).setWhen(CALL_TIMESTAMP);
            if (i >= 2) {
                // The builders after the first two are for multiple missed calls. The notification
                // for subsequent missed calls is expected to be different in terms of the text
                // contents of the notification, and that is verified here.
                if (privateNotifications.contains(builder.toString())) {
                    verify(builder).setContentText(String.format(MISSED_CALLS_MSG, 2));
                    verify(builder).setContentTitle(MISSED_CALLS_TITLE);
                } else {
                    verify(builder).setContentText(MISSED_CALLS_TITLE);
                    verify(builder).setContentTitle(USER_CALL_ACTIVITY_LABEL);
                }
                verify(builder, never()).addAction(any(Notification.Action.class));
            } else {
                if (privateNotifications.contains(builder.toString())) {
                    verify(builder).setContentText(CALLER_NAME);
                    verify(builder).setContentTitle(MISSED_CALL_TITLE);
                } else {
                    verify(builder).setContentText(MISSED_CALL_TITLE);
                    verify(builder).setContentTitle(USER_CALL_ACTIVITY_LABEL);
                }
            }
        }
    }

    @SmallTest
    @Test
    public void testNotifySingleCallInPrimaryUser() {
        PhoneAccount phoneAccount = makePhoneAccount(PRIMARY_USER, NO_CAPABILITY);
        notifySingleCallTestInternal(phoneAccount, PRIMARY_USER);
    }

    @SmallTest
    @Test
    public void testNotifySingleCallInSecondaryUser() {
        PhoneAccount phoneAccount = makePhoneAccount(SECONARY_USER, NO_CAPABILITY);
        notifySingleCallTestInternal(phoneAccount, PRIMARY_USER);
    }

    @SmallTest
    @Test
    public void testNotifySingleCallInSecondaryUserWithMultiUserCapability() {
        PhoneAccount phoneAccount = makePhoneAccount(PRIMARY_USER,
                PhoneAccount.CAPABILITY_MULTI_USER);
        notifySingleCallTestInternal(phoneAccount, PRIMARY_USER);
    }

    @SmallTest
    @Test
    public void testNotifySingleCallWhenCurrentUserIsSecondaryUser() {
        PhoneAccount phoneAccount = makePhoneAccount(PRIMARY_USER, NO_CAPABILITY);
        notifySingleCallTestInternal(phoneAccount, SECONARY_USER);
    }

    @SmallTest
    @Test
    public void testNotifySingleCall() {
        PhoneAccount phoneAccount = makePhoneAccount(PRIMARY_USER, NO_CAPABILITY);
        notifySingleCallTestInternal(phoneAccount, PRIMARY_USER);
    }

    private void notifySingleCallTestInternal(PhoneAccount phoneAccount, UserHandle currentUser) {
        Notification.Builder builder1 = makeNotificationBuilder("builder1");
        Notification.Builder builder2 = makeNotificationBuilder("builder2");
        MissedCallNotifierImpl.NotificationBuilderFactory fakeBuilderFactory =
                makeNotificationBuilderFactory(builder1, builder2);

        MissedCallNotifier missedCallNotifier = makeMissedCallNotifier(fakeBuilderFactory,
                currentUser);

        MissedCallNotifier.CallInfo fakeCall = makeFakeCallInfo(TEL_CALL_HANDLE, CALLER_NAME,
                CALL_TIMESTAMP, phoneAccount.getAccountHandle());
        missedCallNotifier.showMissedCallNotification(fakeCall);

        ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass(
                Notification.class);

        UserHandle expectedUserHandle;
        if (phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) {
            expectedUserHandle = currentUser;
        } else {
            expectedUserHandle = phoneAccount.getAccountHandle().getUserHandle();
        }
        verify(mNotificationManager).notifyAsUser(nullable(String.class), eq(1),
                notificationArgumentCaptor.capture(), eq((expectedUserHandle)));

        Notification.Builder builder;
        Notification.Builder publicBuilder;

        if (notificationArgumentCaptor.getValue().toString().equals("builder1")) {
            builder = builder1;
            publicBuilder = builder2;
        } else {
            builder = builder2;
            publicBuilder = builder1;
        }

        verify(builder).setWhen(CALL_TIMESTAMP);
        verify(publicBuilder).setWhen(CALL_TIMESTAMP);

        verify(builder).setContentText(CALLER_NAME);
        verify(publicBuilder).setContentText(MISSED_CALL_TITLE);

        verify(builder).setContentTitle(MISSED_CALL_TITLE);
        verify(publicBuilder).setContentTitle(USER_CALL_ACTIVITY_LABEL);

        // Create two intents that correspond to call-back and respond back with SMS, and assert
        // that these pending intents have in fact been registered.
        Intent callBackIntent = new Intent(
                TelecomBroadcastIntentProcessor.ACTION_CALL_BACK_FROM_NOTIFICATION,
                TEL_CALL_HANDLE,
                mContext,
                TelecomBroadcastReceiver.class);
        Intent smsIntent = new Intent(
                TelecomBroadcastIntentProcessor.ACTION_SEND_SMS_FROM_NOTIFICATION,
                Uri.fromParts(Constants.SCHEME_SMSTO, TEL_CALL_HANDLE.getSchemeSpecificPart(), null),
                mContext,
                TelecomBroadcastReceiver.class);

        assertNotNull(PendingIntent.getBroadcast(mContext, REQUEST_ID,
                callBackIntent, PendingIntent.FLAG_NO_CREATE | PendingIntent.FLAG_IMMUTABLE));
        assertNotNull(PendingIntent.getBroadcast(mContext, REQUEST_ID,
                smsIntent, PendingIntent.FLAG_NO_CREATE | PendingIntent.FLAG_IMMUTABLE));
    }

    @SmallTest
    @Test
    public void testNoSmsBackAfterMissedSipCall() {
        Notification.Builder builder1 = makeNotificationBuilder("builder1");
        MissedCallNotifierImpl.NotificationBuilderFactory fakeBuilderFactory =
                makeNotificationBuilderFactory(builder1);

        MissedCallNotifier missedCallNotifier = new MissedCallNotifierImpl(mContext,
                mPhoneAccountRegistrar, mDefaultDialerCache, fakeBuilderFactory,
                mDeviceIdleControllerAdapter);
        PhoneAccount phoneAccount = makePhoneAccount(PRIMARY_USER, NO_CAPABILITY);

        MissedCallNotifier.CallInfo fakeCall =
                makeFakeCallInfo(SIP_CALL_HANDLE, CALLER_NAME, CALL_TIMESTAMP,
                phoneAccount.getAccountHandle());
        missedCallNotifier.showMissedCallNotification(fakeCall);

        // Create two intents that correspond to call-back and respond back with SMS, and assert
        // that in the case of a SIP call, no SMS intent is generated.
        Intent callBackIntent = new Intent(
                TelecomBroadcastIntentProcessor.ACTION_CALL_BACK_FROM_NOTIFICATION,
                SIP_CALL_HANDLE,
                mContext,
                TelecomBroadcastReceiver.class);
        Intent smsIntent = new Intent(
                TelecomBroadcastIntentProcessor.ACTION_SEND_SMS_FROM_NOTIFICATION,
                Uri.fromParts(Constants.SCHEME_SMSTO, SIP_CALL_HANDLE.getSchemeSpecificPart(),
                        null),
                mContext,
                TelecomBroadcastReceiver.class);

        assertNotNull(PendingIntent.getBroadcast(mContext, REQUEST_ID,
                callBackIntent, PendingIntent.FLAG_NO_CREATE | PendingIntent.FLAG_IMMUTABLE));
        assertNull(PendingIntent.getBroadcast(mContext, REQUEST_ID,
                smsIntent, PendingIntent.FLAG_NO_CREATE | PendingIntent.FLAG_IMMUTABLE));
    }

    @SmallTest
    @Test
    public void testLoadOneCallFromDb() throws Exception {
        CallerInfoLookupHelper mockCallerInfoLookupHelper = mock(CallerInfoLookupHelper.class);
        MissedCallNotifier.CallInfoFactory mockCallInfoFactory =
                mock(MissedCallNotifier.CallInfoFactory.class);

        Uri queryUri = ContentProvider.maybeAddUserId(CallLog.Calls.CONTENT_URI,
                PRIMARY_USER.getIdentifier());
        IContentProvider cp = getContentProviderForUser(PRIMARY_USER.getIdentifier());

        Cursor mockMissedCallsCursor = new MockMissedCallCursorBuilder()
                .addEntry(TEL_CALL_HANDLE.getSchemeSpecificPart(),
                        CallLog.Calls.PRESENTATION_ALLOWED, CALL_TIMESTAMP)
                .build();

        when(cp.query(any(), eq(queryUri), nullable(String[].class),
                nullable(Bundle.class), nullable(ICancellationSignal.class)))
                .thenReturn(mockMissedCallsCursor);

        PhoneAccount phoneAccount = makePhoneAccount(PRIMARY_USER, NO_CAPABILITY);
        MissedCallNotifier.CallInfo fakeCallInfo = makeFakeCallInfo(TEL_CALL_HANDLE,
                CALLER_NAME, CALL_TIMESTAMP, phoneAccount.getAccountHandle());
        when(mockCallInfoFactory.makeCallInfo(nullable(CallerInfo.class),
                nullable(PhoneAccountHandle.class), nullable(Uri.class), eq(CALL_TIMESTAMP)))
                .thenReturn(fakeCallInfo);

        Notification.Builder builder1 = makeNotificationBuilder("builder1");
        MissedCallNotifierImpl.NotificationBuilderFactory fakeBuilderFactory =
                makeNotificationBuilderFactory(builder1);

        MissedCallNotifier missedCallNotifier = new MissedCallNotifierImpl(mContext,
                mPhoneAccountRegistrar, mDefaultDialerCache, fakeBuilderFactory,
                mDeviceIdleControllerAdapter);

        // AsyncQueryHandler used in reloadFromDatabase interacts poorly with the below
        // timeout-verify, so run this in a new handler to mitigate that.
        Handler h = new Handler(Looper.getMainLooper());
        h.post(() -> missedCallNotifier.reloadFromDatabase(
                mockCallerInfoLookupHelper, mockCallInfoFactory, PRIMARY_USER));
        waitForHandlerAction(h, TEST_TIMEOUT);

        // TelecomSystem.getInstance returns null in this test, so we expect that nothing will
        // happen.
        verify(mockCallerInfoLookupHelper, never()).startLookup(any(Uri.class),
                any(CallerInfoLookupHelper.OnQueryCompleteListener.class));
        // Simulate a boot-complete
        TelecomSystem.setInstance(mTelecomSystem);
        when(mTelecomSystem.isBootComplete()).thenReturn(true);
        h.post(() -> missedCallNotifier.reloadAfterBootComplete(mockCallerInfoLookupHelper,
                mockCallInfoFactory));
        waitForHandlerAction(h, TEST_TIMEOUT);

        Uri escapedHandle = Uri.fromParts(PhoneAccount.SCHEME_TEL,
                TEL_CALL_HANDLE.getSchemeSpecificPart(), null);
        ArgumentCaptor<CallerInfoLookupHelper.OnQueryCompleteListener> listenerCaptor =
                ArgumentCaptor.forClass(CallerInfoLookupHelper.OnQueryCompleteListener.class);
        verify(mockCallerInfoLookupHelper, timeout(TEST_TIMEOUT)).startLookup(eq(escapedHandle),
                listenerCaptor.capture());

        CallerInfo ci = new CallerInfo();
        listenerCaptor.getValue().onCallerInfoQueryComplete(escapedHandle, ci);
        verify(mockCallInfoFactory).makeCallInfo(eq(ci), isNull(PhoneAccountHandle.class),
                eq(escapedHandle), eq(CALL_TIMESTAMP));
    }

    @SmallTest
    @Test
    public void testLoadTwoCallsFromDb() throws Exception {
        TelecomSystem.setInstance(mTelecomSystem);
        when(mTelecomSystem.isBootComplete()).thenReturn(true);
        CallerInfoLookupHelper mockCallerInfoLookupHelper = mock(CallerInfoLookupHelper.class);
        MissedCallNotifier.CallInfoFactory mockCallInfoFactory =
                mock(MissedCallNotifier.CallInfoFactory.class);

        Cursor mockMissedCallsCursor = new MockMissedCallCursorBuilder()
                .addEntry(TEL_CALL_HANDLE.getSchemeSpecificPart(),
                        CallLog.Calls.PRESENTATION_ALLOWED, CALL_TIMESTAMP)
                .addEntry(SIP_CALL_HANDLE.getSchemeSpecificPart(),
                        CallLog.Calls.PRESENTATION_ALLOWED, CALL_TIMESTAMP)
                .build();

        Uri queryUri = ContentProvider.maybeAddUserId(CallLog.Calls.CONTENT_URI,
                PRIMARY_USER.getIdentifier());
        IContentProvider cp = getContentProviderForUser(PRIMARY_USER.getIdentifier());

        when(cp.query(any(), eq(queryUri), nullable(String[].class),
                nullable(Bundle.class), nullable(ICancellationSignal.class)))
                .thenReturn(mockMissedCallsCursor);

        PhoneAccount phoneAccount = makePhoneAccount(PRIMARY_USER, NO_CAPABILITY);
        MissedCallNotifier.CallInfo fakeCallInfo = makeFakeCallInfo(TEL_CALL_HANDLE,
                CALLER_NAME, CALL_TIMESTAMP, phoneAccount.getAccountHandle());
        when(mockCallInfoFactory.makeCallInfo(nullable(CallerInfo.class),
                nullable(PhoneAccountHandle.class), nullable(Uri.class), eq(CALL_TIMESTAMP)))
                .thenReturn(fakeCallInfo);

        Notification.Builder builder1 = makeNotificationBuilder("builder1");
        MissedCallNotifierImpl.NotificationBuilderFactory fakeBuilderFactory =
                makeNotificationBuilderFactory(builder1);

        MissedCallNotifier missedCallNotifier = new MissedCallNotifierImpl(mContext,
                mPhoneAccountRegistrar, mDefaultDialerCache, fakeBuilderFactory,
                mDeviceIdleControllerAdapter);

        // AsyncQueryHandler used in reloadFromDatabase interacts poorly with the below
        // timeout-verify, so run this in a new handler to mitigate that.
        Handler h = new Handler(Looper.getMainLooper());
        h.post(() -> missedCallNotifier.reloadFromDatabase(
                mockCallerInfoLookupHelper, mockCallInfoFactory, PRIMARY_USER));
        waitForHandlerAction(h, TEST_TIMEOUT);

        Uri escapedTelHandle = Uri.fromParts(PhoneAccount.SCHEME_TEL,
                TEL_CALL_HANDLE.getSchemeSpecificPart(), null);
        Uri escapedSipHandle = Uri.fromParts(PhoneAccount.SCHEME_SIP,
                SIP_CALL_HANDLE.getSchemeSpecificPart(), null);

        ArgumentCaptor<CallerInfoLookupHelper.OnQueryCompleteListener> listenerCaptor =
                ArgumentCaptor.forClass(CallerInfoLookupHelper.OnQueryCompleteListener.class);
        verify(mockCallerInfoLookupHelper, timeout(TEST_TIMEOUT)).startLookup(eq(escapedTelHandle),
                listenerCaptor.capture());
        verify(mockCallerInfoLookupHelper, timeout(TEST_TIMEOUT)).startLookup(eq(escapedSipHandle),
                listenerCaptor.capture());

        CallerInfo ci = new CallerInfo();
        listenerCaptor.getAllValues().get(0).onCallerInfoQueryComplete(escapedTelHandle, ci);
        listenerCaptor.getAllValues().get(1).onCallerInfoQueryComplete(escapedSipHandle, ci);

        // Verify that two notifications were generated, both with the same id.
        verify(mNotificationManager, times(2)).notifyAsUser(nullable(String.class), eq(1),
                nullable(Notification.class), eq(PRIMARY_USER));
    }

    @SmallTest
    @Test
    public void testDialerHandleMissedCall() {
        // Configure Notifier to send missed call intent and let dialer handle
        enableDialerHandlesMissedCall();

        Notification.Builder builder1 = makeNotificationBuilder("builder1");
        MissedCallNotifierImpl.NotificationBuilderFactory fakeBuilderFactory =
                makeNotificationBuilderFactory(builder1);

        MissedCallNotifier missedCallNotifier = new MissedCallNotifierImpl(mContext,
                mPhoneAccountRegistrar, mDefaultDialerCache, fakeBuilderFactory,
                mDeviceIdleControllerAdapter);
        PhoneAccount phoneAccount = makePhoneAccount(PRIMARY_USER, NO_CAPABILITY);

        MissedCallNotifier.CallInfo fakeCall =
                makeFakeCallInfo(SIP_CALL_HANDLE, CALLER_NAME, CALL_TIMESTAMP,
                        phoneAccount.getAccountHandle());
        missedCallNotifier.showMissedCallNotification(fakeCall);

        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
        ArgumentCaptor<Bundle> bundleCaptor =
                ArgumentCaptor.forClass(Bundle.class);
        verify(mDeviceIdleControllerAdapter).exemptAppTemporarilyForEvent(
                eq(COMPONENT_NAME.getPackageName()), anyLong(), anyInt(), any());
        verify(mContext).sendBroadcastAsUser(
                intentCaptor.capture(),
                any(),
                eq(android.Manifest.permission.READ_PHONE_STATE), bundleCaptor.capture());
        assertNotNull("Not expecting null intent", intentCaptor.getValue());
        assertEquals("Incorrect intent received",
                TelecomManager.ACTION_SHOW_MISSED_CALLS_NOTIFICATION,
                intentCaptor.getValue().getAction());
        assertNotNull("Not expecting null options bundle", bundleCaptor.getValue());
        BroadcastOptions options = new BroadcastOptions(bundleCaptor.getValue());
        assertTrue("App must have a temporary exemption set.",
                options.getTemporaryAppAllowlistDuration() > 0);

        // A notification should never be posted by Telecom
        verify(mNotificationManager, never()).notifyAsUser(nullable(String.class), anyInt(),
                nullable(Notification.class), eq(PRIMARY_USER));
    }

    private Notification.Builder makeNotificationBuilder(String label) {
        Notification.Builder builder = spy(new Notification.Builder(mContext));
        Notification notification = mock(Notification.class);
        when(notification.toString()).thenReturn(label);
        when(builder.toString()).thenReturn(label);
        doReturn(notification).when(builder).build();
        return builder;
    }

    private MissedCallNotifier.CallInfo makeFakeCallInfo(Uri handle, String name, long timestamp,
            PhoneAccountHandle phoneAccountHandle) {
        MissedCallNotifier.CallInfo fakeCall = mock(MissedCallNotifier.CallInfo.class);
        when(fakeCall.getHandle()).thenReturn(handle);
        when(fakeCall.getHandleSchemeSpecificPart()).thenReturn(handle.getSchemeSpecificPart());
        when(fakeCall.getName()).thenReturn(name);
        when(fakeCall.getCreationTimeMillis()).thenReturn(timestamp);
        when(fakeCall.getPhoneAccountHandle()).thenReturn(phoneAccountHandle);
        return fakeCall;
    }

    private MissedCallNotifierImpl.NotificationBuilderFactory makeNotificationBuilderFactory(
            Notification.Builder... builders) {
        MissedCallNotifierImpl.NotificationBuilderFactory builderFactory =
                mock(MissedCallNotifierImpl.NotificationBuilderFactory.class);
        when(builderFactory.getBuilder(mContext)).thenReturn(builders[0],
                Arrays.copyOfRange(builders, 1, builders.length));
        return builderFactory;
    }

    private MissedCallNotifier makeMissedCallNotifier(
            NotificationBuilderFactory fakeBuilderFactory, UserHandle currentUser) {
        MissedCallNotifier missedCallNotifier = new MissedCallNotifierImpl(mContext,
                mPhoneAccountRegistrar, mDefaultDialerCache, fakeBuilderFactory,
                mDeviceIdleControllerAdapter);
        missedCallNotifier.setCurrentUserHandle(currentUser);
        return missedCallNotifier;
    }

    private PhoneAccount makePhoneAccount(UserHandle userHandle, int capability) {
        PhoneAccountHandle phoneAccountHandle = new PhoneAccountHandle(COMPONENT_NAME, "id",
                userHandle);
        PhoneAccount.Builder builder = new PhoneAccount.Builder(phoneAccountHandle, "test");
        builder.setCapabilities(capability);
        PhoneAccount phoneAccount = builder.build();
        when(mPhoneAccountRegistrar.getPhoneAccountUnchecked(phoneAccountHandle))
                .thenReturn(phoneAccount);
        return phoneAccount;
    }

    private void enableDialerHandlesMissedCall() {
        doReturn(COMPONENT_NAME.getPackageName()).when(mDefaultDialerCache).
                getDefaultDialerApplication(anyInt());
        mComponentContextFixture.addIntentReceiver(
                TelecomManager.ACTION_SHOW_MISSED_CALLS_NOTIFICATION, COMPONENT_NAME);
    }

    private IContentProvider getContentProviderForUser(int userId) {
        return mContext.getContentResolver().acquireProvider(userId + "@call_log");
    }

}
