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

Commit 5c85d90c authored by Tyler Gunn's avatar Tyler Gunn Committed by Automerger Merge Worker
Browse files

Merge "Synchronize updates of missed call counts and add more logging." into sc-dev am: b5211868

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/services/Telecomm/+/14606927

Change-Id: I4de2f338729c12a041ba3b867001f0aaa036dd1a
parents b9a3c557 b5211868
Loading
Loading
Loading
Loading
+36 −26
Original line number Diff line number Diff line
@@ -67,18 +67,15 @@ import android.text.TextDirectionHeuristics;
import android.text.TextUtils;

import android.telecom.CallerInfo;
import android.util.ArrayMap;

import java.lang.Override;
import java.lang.String;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;

// TODO: Needed for move to system service: import com.android.internal.R;

/**
 * Creates a notification for calls that the user missed (neither answered nor rejected).
@@ -139,8 +136,10 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements
    private final DeviceIdleControllerAdapter mDeviceIdleControllerAdapter;
    private UserHandle mCurrentUserHandle;

    // Used to guard access to mMissedCallCounts
    private final Object mMissedCallCountsLock = new Object();
    // Used to track the number of missed calls.
    private ConcurrentMap<UserHandle, AtomicInteger> mMissedCallCounts;
    private final Map<UserHandle, Integer> mMissedCallCounts;

    private List<UserHandle> mUsersToLoadAfterBootComplete = new ArrayList<>();

@@ -164,7 +163,7 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements
        mDefaultDialerCache = defaultDialerCache;

        mNotificationBuilderFactory = notificationBuilderFactory;
        mMissedCallCounts = new ConcurrentHashMap<>();
        mMissedCallCounts = new ArrayMap<>();
    }

    /** Clears missed call notification and marks the call log's missed calls as read. */
@@ -263,17 +262,16 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements
    }

    private void sendNotificationThroughDefaultDialer(String dialerPackage, CallInfo callInfo,
            UserHandle userHandle) {
        int count = mMissedCallCounts.get(userHandle).get();
            UserHandle userHandle, int missedCallCount) {
        Intent intent = getShowMissedCallIntentForDefaultDialer(dialerPackage)
            .setFlags(Intent.FLAG_RECEIVER_FOREGROUND)
            .putExtra(TelecomManager.EXTRA_CLEAR_MISSED_CALLS_INTENT,
                    createClearMissedCallsPendingIntent(userHandle))
            .putExtra(TelecomManager.EXTRA_NOTIFICATION_COUNT, count)
            .putExtra(TelecomManager.EXTRA_NOTIFICATION_COUNT, missedCallCount)
            .putExtra(TelecomManager.EXTRA_NOTIFICATION_PHONE_NUMBER,
                    callInfo == null ? null : callInfo.getPhoneNumber());

        if (count == 1 && callInfo != null) {
        if (missedCallCount == 1 && callInfo != null) {
            final Uri handleUri = callInfo.getHandle();
            String handle = handleUri == null ? null : handleUri.getSchemeSpecificPart();

@@ -284,8 +282,8 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements
            }
        }


        Log.w(this, "Showing missed calls through default dialer.");
        Log.i(this, "sendNotificationThroughDefaultDialer; count=%d, dialerPackage=%s",
                missedCallCount, intent.getPackage());
        Bundle options = exemptFromPowerSavingTemporarily(dialerPackage, userHandle);
        mContext.sendBroadcastAsUser(intent, userHandle, READ_PHONE_STATE, options);
    }
@@ -293,7 +291,7 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements
    /**
     * Create a system notification for the missed call.
     *
     * @param call The missed call.
     * @param callInfo The missed call.
     */
    @Override
    public void showMissedCallNotification(@NonNull CallInfo callInfo) {
@@ -311,13 +309,21 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements
    }

    private void showMissedCallNotification(@NonNull CallInfo callInfo, UserHandle userHandle) {
        Log.i(this, "showMissedCallNotification: userHandle=%d", userHandle.getIdentifier());
        mMissedCallCounts.putIfAbsent(userHandle, new AtomicInteger(0));
        int missCallCounts = mMissedCallCounts.get(userHandle).incrementAndGet();
        int missedCallCounts;
        synchronized (mMissedCallCountsLock) {
            Integer currentCount = mMissedCallCounts.get(userHandle);
            missedCallCounts = currentCount == null ? 0 : currentCount;
            missedCallCounts++;
            mMissedCallCounts.put(userHandle, missedCallCounts);
        }

        Log.i(this, "showMissedCallNotification: userHandle=%d, missedCallCount=%d",
                userHandle.getIdentifier(), missedCallCounts);

        String dialerPackage = getDefaultDialerPackage(userHandle);
        if (shouldManageNotificationThroughDefaultDialer(dialerPackage, userHandle)) {
            sendNotificationThroughDefaultDialer(dialerPackage, callInfo, userHandle);
            sendNotificationThroughDefaultDialer(dialerPackage, callInfo, userHandle,
                    missedCallCounts);
            return;
        }

@@ -327,7 +333,7 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements
        // Display the first line of the notification:
        // 1 missed call: <caller name || handle>
        // More than 1 missed call: <number of calls> + "missed calls"
        if (missCallCounts == 1) {
        if (missedCallCounts == 1) {
            expandedText = getNameForMissedCallNotification(callInfo);

            CallerInfo ci = callInfo.getCallerInfo();
@@ -339,7 +345,7 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements
        } else {
            titleResId = R.string.notification_missedCallsTitle;
            expandedText =
                    mContext.getString(R.string.notification_missedCallsMsg, missCallCounts);
                    mContext.getString(R.string.notification_missedCallsMsg, missedCallCounts);
        }

        // Create a public viewable version of the notification, suitable for display when sensitive
@@ -381,7 +387,7 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements
        String handle = callInfo.getHandleSchemeSpecificPart();

        // Add additional actions when there is only 1 missed call, like call-back and SMS.
        if (missCallCounts == 1) {
        if (missedCallCounts == 1) {
            Log.d(this, "Add actions with number %s.", Log.piiHandle(handle));

            if (!TextUtils.isEmpty(handle)
@@ -410,7 +416,7 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements
            }
        } else {
            Log.d(this, "Suppress actions. handle: %s, missedCalls: %d.", Log.piiHandle(handle),
                    missCallCounts);
                    missedCallCounts);
        }

        Notification notification = builder.build();
@@ -430,12 +436,14 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements
    /** Cancels the "missed call" notification. */
    private void cancelMissedCallNotification(UserHandle userHandle) {
        // Reset the number of missed calls to 0.
        mMissedCallCounts.putIfAbsent(userHandle, new AtomicInteger(0));
        mMissedCallCounts.get(userHandle).set(0);
        synchronized(mMissedCallCountsLock) {
            mMissedCallCounts.put(userHandle, 0);
        }

        String dialerPackage = getDefaultDialerPackage(userHandle);
        if (shouldManageNotificationThroughDefaultDialer(dialerPackage, userHandle)) {
            sendNotificationThroughDefaultDialer(dialerPackage, null, userHandle);
            sendNotificationThroughDefaultDialer(dialerPackage, null, userHandle,
                    0 /* missedCallCount */);
            return;
        }

@@ -612,7 +620,9 @@ public class MissedCallNotifierImpl extends CallsManagerListenerBase implements
                Log.d(MissedCallNotifierImpl.this, "onQueryComplete()...");
                if (cursor != null) {
                    try {
                        synchronized(mMissedCallCountsLock) {
                            mMissedCallCounts.remove(userHandle);
                        }
                        while (cursor.moveToNext()) {
                            // Get data about the missed call from the cursor
                            final String handleString = cursor.getString(CALL_LOG_COLUMN_NUMBER);
+50 −0
Original line number Diff line number Diff line
@@ -29,6 +29,8 @@ 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;
@@ -65,11 +67,13 @@ 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;
@@ -79,6 +83,7 @@ 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;
@@ -132,6 +137,7 @@ public class MissedCallNotifierImplTest extends TelecomTestCase {
        }
    }

    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";
@@ -139,6 +145,7 @@ public class MissedCallNotifierImplTest extends TelecomTestCase {
    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;
@@ -213,6 +220,49 @@ public class MissedCallNotifierImplTest extends TelecomTestCase {
        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");