Fix no display name for saved contacts for HUN.

This issue is basically a race condition that when the callback is
triggerred, NotificationManager.getActiveNotifications() is not
returning the previous posted HUN which might turn active later. By
caching the notifications on our own, the check if the HUN exists will
be valid. We will cancel the notification explicitly on any action that
will dismiss the notification(action button and fullscreen intent)

Fixes: 146165572
Test: manually
Change-Id: I896dc75dff915f52702dd576ac30482c6c5c5788
diff --git a/src/com/android/car/dialer/notification/InCallNotificationController.java b/src/com/android/car/dialer/notification/InCallNotificationController.java
index e8a0cf1..e68b35b 100644
--- a/src/com/android/car/dialer/notification/InCallNotificationController.java
+++ b/src/com/android/car/dialer/notification/InCallNotificationController.java
@@ -29,13 +29,12 @@
 
 import androidx.annotation.StringRes;
 
-import com.android.car.dialer.Constants;
 import com.android.car.dialer.R;
 import com.android.car.dialer.log.L;
-import com.android.car.dialer.ui.activecall.InCallActivity;
 import com.android.car.telephony.common.CallDetail;
 
-import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
 import java.util.concurrent.CompletableFuture;
 
 /** Controller that manages the heads up notification for incoming calls. */
@@ -81,6 +80,7 @@
     private final Context mContext;
     private final NotificationManager mNotificationManager;
     private final Notification.Builder mNotificationBuilder;
+    private final Set<String> mActiveInCallNotifications;
     private CompletableFuture<Void> mNotificationFuture;
 
     @TargetApi(26)
@@ -94,19 +94,14 @@
                 NotificationManager.IMPORTANCE_HIGH);
         mNotificationManager.createNotificationChannel(notificationChannel);
 
-        Intent intent = new Intent(mContext, InCallActivity.class);
-        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        intent.putExtra(Constants.Intents.EXTRA_SHOW_INCOMING_CALL, true);
-        PendingIntent fullscreenIntent = PendingIntent.getActivity(mContext, 0, intent,
-                PendingIntent.FLAG_UPDATE_CURRENT);
-
         mNotificationBuilder = new Notification.Builder(mContext, CHANNEL_ID)
                 .setSmallIcon(R.drawable.ic_phone)
                 .setContentText(mContext.getString(R.string.notification_incoming_call))
-                .setFullScreenIntent(fullscreenIntent, /* highPriority= */true)
                 .setCategory(Notification.CATEGORY_CALL)
                 .setOngoing(true)
                 .setAutoCancel(false);
+
+        mActiveInCallNotifications = new HashSet<>();
     }
 
 
@@ -121,8 +116,10 @@
 
         CallDetail callDetail = CallDetail.fromTelecomCallDetail(call.getDetails());
         String number = callDetail.getNumber();
-        String tag = call.getDetails().getTelecomCallId();
+        String callId = call.getDetails().getTelecomCallId();
+        mActiveInCallNotifications.add(callId);
         mNotificationBuilder
+                .setFullScreenIntent(getFullscreenIntent(call), /* highPriority= */true)
                 .setLargeIcon((Icon) null)
                 .setContentTitle(number)
                 .setActions(
@@ -131,21 +128,20 @@
                         getAction(call, R.string.decline_call,
                                 NotificationService.ACTION_DECLINE_CALL));
         mNotificationManager.notify(
-                tag,
+                callId,
                 NOTIFICATION_ID,
                 mNotificationBuilder.build());
 
         mNotificationFuture = NotificationUtils.getDisplayNameAndRoundedAvatar(mContext, number)
                 .thenAcceptAsync((pair) -> {
                     // Check that the notification hasn't already been dismissed
-                    if (Arrays.stream(mNotificationManager.getActiveNotifications()).anyMatch((n) ->
-                            n.getId() == NOTIFICATION_ID && TextUtils.equals(n.getTag(), tag))) {
+                    if (mActiveInCallNotifications.contains(callId)) {
                         mNotificationBuilder
                                 .setLargeIcon(pair.second)
                                 .setContentTitle(pair.first);
 
                         mNotificationManager.notify(
-                                tag,
+                                callId,
                                 NOTIFICATION_ID,
                                 mNotificationBuilder.build());
                     }
@@ -156,10 +152,28 @@
     public void cancelInCallNotification(Call call) {
         L.d(TAG, "cancelInCallNotification");
         if (call.getDetails() != null) {
-            mNotificationManager.cancel(call.getDetails().getTelecomCallId(), NOTIFICATION_ID);
+            String callId = call.getDetails().getTelecomCallId();
+            cancelInCallNotification(callId);
         }
     }
 
+    /**
+     * Cancel the incoming call notification for the given call id. Any action that dismisses the
+     * notification needs to call this explicitly.
+     */
+    void cancelInCallNotification(String callId) {
+        if (TextUtils.isEmpty(callId)) {
+            return;
+        }
+        mActiveInCallNotifications.remove(callId);
+        mNotificationManager.cancel(callId, NOTIFICATION_ID);
+    }
+
+    private PendingIntent getFullscreenIntent(Call call) {
+        Intent intent = getIntent(NotificationService.ACTION_SHOW_FULLSCREEN_UI, call);
+        return PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+    }
+
     private Notification.Action getAction(Call call, @StringRes int actionText,
             String intentAction) {
         CharSequence text = mContext.getString(actionText);
diff --git a/src/com/android/car/dialer/notification/NotificationService.java b/src/com/android/car/dialer/notification/NotificationService.java
index 2f28290..f7b8a01 100644
--- a/src/com/android/car/dialer/notification/NotificationService.java
+++ b/src/com/android/car/dialer/notification/NotificationService.java
@@ -25,6 +25,7 @@
 
 import com.android.car.dialer.Constants;
 import com.android.car.dialer.telecom.UiCallManager;
+import com.android.car.dialer.ui.activecall.InCallActivity;
 import com.android.car.telephony.common.TelecomUtils;
 
 import java.util.List;
@@ -37,6 +38,7 @@
 public class NotificationService extends JobIntentService {
     static final String ACTION_ANSWER_CALL = "CD.ACTION_ANSWER_CALL";
     static final String ACTION_DECLINE_CALL = "CD.ACTION_DECLINE_CALL";
+    static final String ACTION_SHOW_FULLSCREEN_UI = "CD.ACTION_SHOW_FULLSCREEN_UI";
     static final String ACTION_CALL_BACK_MISSED = "CD.ACTION_CALL_BACK_MISSED";
     static final String ACTION_MESSAGE_MISSED = "CD.ACTION_MESSAGE_MISSED";
     static final String ACTION_READ_ALL_MISSED = "CD.ACTION_READ_ALL_MISSED";
@@ -62,9 +64,19 @@
         switch (action) {
             case ACTION_ANSWER_CALL:
                 answerCall(callId);
+                InCallNotificationController.get().cancelInCallNotification(callId);
                 break;
             case ACTION_DECLINE_CALL:
                 declineCall(callId);
+                InCallNotificationController.get().cancelInCallNotification(callId);
+                break;
+            case ACTION_SHOW_FULLSCREEN_UI:
+                Intent inCallActivityIntent = new Intent(getApplicationContext(),
+                        InCallActivity.class);
+                inCallActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                inCallActivityIntent.putExtra(Constants.Intents.EXTRA_SHOW_INCOMING_CALL, true);
+                startActivity(inCallActivityIntent);
+                InCallNotificationController.get().cancelInCallNotification(callId);
                 break;
             case ACTION_CALL_BACK_MISSED:
                 UiCallManager.get().placeCall(callId);