Handle missed calls for new call log in old peer.

Test: unit
PiperOrigin-RevId: 191380073
Change-Id: If554d5ee0c55754802692a364bae591c3951c060
diff --git a/java/com/android/dialer/main/impl/OldMainActivityPeer.java b/java/com/android/dialer/main/impl/OldMainActivityPeer.java
index 6d78a51..c15d7c1 100644
--- a/java/com/android/dialer/main/impl/OldMainActivityPeer.java
+++ b/java/com/android/dialer/main/impl/OldMainActivityPeer.java
@@ -68,10 +68,12 @@
 import com.android.dialer.calldetails.OldCallDetailsActivity;
 import com.android.dialer.callintent.CallIntentBuilder;
 import com.android.dialer.callintent.CallSpecificAppData;
+import com.android.dialer.calllog.CallLogComponent;
 import com.android.dialer.calllog.config.CallLogConfigComponent;
 import com.android.dialer.calllog.ui.NewCallLogFragment;
 import com.android.dialer.common.FragmentUtils.FragmentUtilListener;
 import com.android.dialer.common.LogUtil;
+import com.android.dialer.common.concurrent.DefaultFutureCallback;
 import com.android.dialer.common.concurrent.DialerExecutorComponent;
 import com.android.dialer.common.concurrent.ThreadUtil;
 import com.android.dialer.common.concurrent.UiListener;
@@ -96,6 +98,7 @@
 import com.android.dialer.main.impl.bottomnav.BottomNavBar;
 import com.android.dialer.main.impl.bottomnav.BottomNavBar.OnBottomNavTabSelectedListener;
 import com.android.dialer.main.impl.bottomnav.BottomNavBar.TabIndex;
+import com.android.dialer.main.impl.bottomnav.MissedCallCountObserver;
 import com.android.dialer.main.impl.toolbar.MainToolbar;
 import com.android.dialer.metrics.Metrics;
 import com.android.dialer.metrics.MetricsComponent;
@@ -113,7 +116,9 @@
 import com.android.dialer.voicemailstatus.VisualVoicemailEnabledChecker;
 import com.android.dialer.voicemailstatus.VoicemailStatusHelper;
 import com.android.voicemail.VoicemailComponent;
+import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
 import java.util.Locale;
 import java.util.concurrent.TimeUnit;
 
@@ -184,7 +189,9 @@
   private BottomNavBar bottomNav;
   private MainBottomNavBarBottomNavTabListener bottomNavTabListener;
   private View snackbarContainer;
+  private MissedCallCountObserver missedCallCountObserver;
   private UiListener<String> getLastOutgoingCallListener;
+  private UiListener<Integer> missedCallObserverUiListener;
 
   public static Intent getShowTabIntent(Context context, @TabIndex int tabIndex) {
     Intent intent = new Intent(context, MainActivity.class);
@@ -219,6 +226,9 @@
     getLastOutgoingCallListener =
         DialerExecutorComponent.get(activity)
             .createUiListener(activity.getFragmentManager(), "Query last phone number");
+    missedCallObserverUiListener =
+        DialerExecutorComponent.get(activity)
+            .createUiListener(activity.getFragmentManager(), "Missed call observer");
   }
 
   private void initLayout(Bundle savedInstanceState) {
@@ -247,9 +257,13 @@
     boolean showVoicemailTab = canVoicemailTabBeShown(activity);
     bottomNav.showVoicemail(showVoicemailTab);
 
+    missedCallCountObserver =
+        new MissedCallCountObserver(
+            activity.getApplicationContext(), bottomNav, missedCallObserverUiListener);
+
     callLogFragmentListener =
         new MainCallLogFragmentListener(
-            activity, activity.getContentResolver(), bottomNav, toolbar);
+            activity, activity.getContentResolver(), bottomNav, toolbar, bottomNavTabListener);
     bottomNav.addOnTabSelectedListener(callLogFragmentListener);
 
     searchController =
@@ -471,6 +485,13 @@
      */
     bottomNavTabListener.ensureCorrectCallLogShown();
 
+    if (bottomNavTabListener.newCallLogFragmentActive()) {
+      missedCallCountObserver.onChange(false); // Set the initial value for the badge
+      activity
+          .getContentResolver()
+          .registerContentObserver(Calls.CONTENT_URI, true, missedCallCountObserver);
+    }
+
     // add 1 sec delay to get memory snapshot so that dialer wont react slowly on resume.
     ThreadUtil.postDelayedOnUiThread(
         () ->
@@ -489,6 +510,7 @@
   public void onActivityPause() {
     searchController.onActivityPause();
     LocalBroadcastManager.getInstance(activity).unregisterReceiver(disableNewCallLogReceiver);
+    activity.getContentResolver().unregisterContentObserver(missedCallCountObserver);
   }
 
   @Override
@@ -819,6 +841,7 @@
     private final Context context;
     private final BottomNavBar bottomNavBar;
     private final Toolbar toolbar;
+    private final MainBottomNavBarBottomNavTabListener bottomNavTabListener;
 
     private @TabIndex int currentTab = TabIndex.SPEED_DIAL;
     private long timeSelected = -1;
@@ -837,11 +860,13 @@
         Context context,
         ContentResolver contentResolver,
         BottomNavBar bottomNavBar,
-        Toolbar toolbar) {
+        Toolbar toolbar,
+        MainBottomNavBarBottomNavTabListener bottomNavTabListener) {
       callLogQueryHandler = new CallLogQueryHandler(context, contentResolver, this);
       this.context = context;
       this.bottomNavBar = bottomNavBar;
       this.toolbar = toolbar;
+      this.bottomNavTabListener = bottomNavTabListener;
     }
 
     private void registerVoicemailStatusContentObserver(Context context) {
@@ -953,8 +978,15 @@
     }
 
     private void markMissedCallsAsReadAndRemoveNotification() {
-      callLogQueryHandler.markMissedCallsAsRead();
-      CallLogNotificationsService.cancelAllMissedCalls(context);
+      if (bottomNavTabListener.newCallLogFragmentActive()) {
+        Futures.addCallback(
+            CallLogComponent.get(context).getClearMissedCalls().clearAll(),
+            new DefaultFutureCallback<>(),
+            MoreExecutors.directExecutor());
+      } else {
+        callLogQueryHandler.markMissedCallsAsRead();
+        CallLogNotificationsService.cancelAllMissedCalls(context);
+      }
     }
 
     private void setCurrentTab(@TabIndex int tabIndex) {
@@ -969,7 +1001,9 @@
       activityIsAlive = true;
       registerVoicemailStatusContentObserver(context);
       callLogQueryHandler.fetchVoicemailStatus();
-      callLogQueryHandler.fetchMissedCallsUnreadCount();
+      if (!bottomNavTabListener.newCallLogFragmentActive()) {
+        callLogQueryHandler.fetchMissedCallsUnreadCount();
+      }
       // Reset the tab on resume to restart the timer
       setCurrentTab(bottomNavBar.getSelectedTab());
     }
@@ -978,7 +1012,11 @@
     public void onActivityStop(boolean changingConfigurations, boolean keyguardLocked) {
       context.getContentResolver().unregisterContentObserver(voicemailStatusObserver);
       activityIsAlive = false;
-      if (viewedCallLogTabPastTimeThreshold() && !changingConfigurations && !keyguardLocked) {
+      // The new call log fragment handles this on its own.
+      if (!bottomNavTabListener.newCallLogFragmentActive()
+          && viewedCallLogTabPastTimeThreshold()
+          && !changingConfigurations
+          && !keyguardLocked) {
         markMissedCallsAsReadAndRemoveNotification();
       }
     }
@@ -1239,6 +1277,14 @@
       }
     }
 
+    boolean newCallLogFragmentActive() {
+      return supportFragmentManager.findFragmentByTag(CALL_LOG_TAG) != null
+          || (fragmentManager.findFragmentByTag(CALL_LOG_TAG) == null
+              && CallLogConfigComponent.get(activity)
+                  .callLogConfig()
+                  .isNewCallLogFragmentEnabled());
+    }
+
     @Override
     public void onContactsSelected() {
       LogUtil.enterBlock("MainBottomNavBarBottomNavTabListener.onContactsSelected");
diff --git a/java/com/android/dialer/main/impl/bottomnav/MissedCallCountObserver.java b/java/com/android/dialer/main/impl/bottomnav/MissedCallCountObserver.java
new file mode 100644
index 0000000..2760634
--- /dev/null
+++ b/java/com/android/dialer/main/impl/bottomnav/MissedCallCountObserver.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2018 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.dialer.main.impl.bottomnav;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.provider.CallLog.Calls;
+import com.android.dialer.common.concurrent.DialerExecutorComponent;
+import com.android.dialer.common.concurrent.UiListener;
+import com.android.dialer.main.impl.bottomnav.BottomNavBar.TabIndex;
+import com.android.dialer.util.PermissionsUtil;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * Observes the call log and updates the badge count to show the number of unread missed calls.
+ *
+ * <p>Used only when the new call log fragment is enabled.
+ */
+public final class MissedCallCountObserver extends ContentObserver {
+  private final Context appContext;
+  private final BottomNavBar bottomNavBar;
+  private final UiListener<Integer> uiListener;
+
+  public MissedCallCountObserver(
+      Context appContext, BottomNavBar bottomNavBar, UiListener<Integer> uiListener) {
+    super(null);
+    this.appContext = appContext;
+    this.bottomNavBar = bottomNavBar;
+    this.uiListener = uiListener;
+  }
+
+  @SuppressLint("MissingPermission")
+  @Override
+  public void onChange(boolean selfChange) {
+    ListenableFuture<Integer> countFuture =
+        DialerExecutorComponent.get(appContext)
+            .backgroundExecutor()
+            .submit(
+                () -> {
+                  if (!PermissionsUtil.hasCallLogReadPermissions(appContext)) {
+                    return 0;
+                  }
+                  try (Cursor cursor =
+                      appContext
+                          .getContentResolver()
+                          .query(
+                              Calls.CONTENT_URI,
+                              new String[] {Calls._ID},
+                              Calls.IS_READ + " = ? AND " + Calls.TYPE + " = ?",
+                              new String[] {"0", Integer.toString(Calls.MISSED_TYPE)},
+                              /* sortOrder= */ null)) {
+                    return cursor == null ? 0 : cursor.getCount();
+                  }
+                });
+    uiListener.listen(
+        appContext,
+        countFuture,
+        count -> bottomNavBar.setNotificationCount(TabIndex.CALL_LOG, count == null ? 0 : count),
+        throwable -> {
+          throw new RuntimeException(throwable);
+        });
+  }
+}