resolve merge conflicts of e14ae7dd12 to master.

Change-Id: I44128233cb86b34db3f7d2b1e4ca1aa0f6d1b518
diff --git a/src/com/android/dialer/calllog/CallLogAdapter.java b/src/com/android/dialer/calllog/CallLogAdapter.java
index af77d86..aa97f7d 100644
--- a/src/com/android/dialer/calllog/CallLogAdapter.java
+++ b/src/com/android/dialer/calllog/CallLogAdapter.java
@@ -164,6 +164,9 @@
                 mCurrentlyExpandedPosition = RecyclerView.NO_POSITION;
                 mCurrentlyExpandedRowId = NO_EXPANDED_LIST_ITEM;
             } else {
+                if (viewHolder.callType == CallLog.Calls.MISSED_TYPE) {
+                    CallLogAsyncTaskUtil.markCallAsRead(mContext, viewHolder.callIds);
+                }
                 expandViewHolderActions(viewHolder);
             }
 
@@ -482,7 +485,8 @@
         details.features = getCallFeatures(c, count);
         details.geocode = c.getString(CallLogQuery.GEOCODED_LOCATION);
         details.transcription = c.getString(CallLogQuery.TRANSCRIPTION);
-        if (details.callTypes[0] == CallLog.Calls.VOICEMAIL_TYPE) {
+        if (details.callTypes[0] == CallLog.Calls.VOICEMAIL_TYPE ||
+                details.callTypes[0] == CallLog.Calls.MISSED_TYPE) {
             details.isRead = c.getInt(CallLogQuery.IS_READ) == 1;
         }
 
diff --git a/src/com/android/dialer/calllog/CallLogAsyncTaskUtil.java b/src/com/android/dialer/calllog/CallLogAsyncTaskUtil.java
index bb7bdbd..d73159c 100644
--- a/src/com/android/dialer/calllog/CallLogAsyncTaskUtil.java
+++ b/src/com/android/dialer/calllog/CallLogAsyncTaskUtil.java
@@ -29,6 +29,7 @@
 import android.util.Log;
 
 import com.android.contacts.common.GeoUtil;
+import com.android.contacts.common.util.PermissionsUtil;
 import com.android.dialer.DialtactsActivity;
 import com.android.dialer.PhoneCallDetails;
 import com.android.dialer.util.AppCompatConstants;
@@ -51,6 +52,7 @@
         DELETE_CALL,
         DELETE_BLOCKED_CALL,
         MARK_VOICEMAIL_READ,
+        MARK_CALL_READ,
         GET_CALL_DETAILS,
     }
 
@@ -379,6 +381,39 @@
         });
     }
 
+    public static void markCallAsRead(final Context context, final long[] callIds) {
+        if (!PermissionsUtil.hasPhonePermissions(context)) {
+            return;
+        }
+        if (sAsyncTaskExecutor == null) {
+            initTaskExecutor();
+        }
+
+        sAsyncTaskExecutor.submit(Tasks.MARK_CALL_READ, new AsyncTask<Void, Void, Void>() {
+            @Override
+            public Void doInBackground(Void... params) {
+
+                StringBuilder where = new StringBuilder();
+                where.append(CallLog.Calls.TYPE).append(" = ").append(CallLog.Calls.MISSED_TYPE);
+                where.append(" AND ");
+
+                Long[] callIdLongs = new Long[callIds.length];
+                for (int i = 0; i < callIds.length; i++) {
+                    callIdLongs[i] = callIds[i];
+                }
+                where.append(CallLog.Calls._ID).append(
+                        " IN (" + TextUtils.join(",", callIdLongs) + ")");
+
+                ContentValues values = new ContentValues(1);
+                values.put(CallLog.Calls.IS_READ, "1");
+                context.getContentResolver().update(
+                        CallLog.Calls.CONTENT_URI, values, where.toString(), null);
+                ((DialtactsActivity) context).updateTabUnreadCounts();
+                return null;
+            }
+        });
+    }
+
     @VisibleForTesting
     public static void resetForTest() {
         sAsyncTaskExecutor = null;
diff --git a/src/com/android/dialer/calllog/CallLogFragment.java b/src/com/android/dialer/calllog/CallLogFragment.java
index 41ff7d3..3646315 100644
--- a/src/com/android/dialer/calllog/CallLogFragment.java
+++ b/src/com/android/dialer/calllog/CallLogFragment.java
@@ -41,6 +41,7 @@
 import com.android.contacts.common.GeoUtil;
 import com.android.contacts.common.util.PermissionsUtil;
 import com.android.dialer.R;
+import com.android.dialer.list.ListsFragment;
 import com.android.dialer.util.EmptyLoader;
 import com.android.dialer.voicemail.VoicemailPlaybackPresenter;
 import com.android.dialer.widget.EmptyContentView;
@@ -278,6 +279,9 @@
     public void onVoicemailUnreadCountFetched(Cursor cursor) {}
 
     @Override
+    public void onMissedCallsUnreadCountFetched(Cursor cursor) {}
+
+    @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
         View view = inflater.inflate(R.layout.call_log_fragment, container, false);
         setupView(view, null);
@@ -378,6 +382,7 @@
     @Override
     public void fetchCalls() {
         mCallLogQueryHandler.fetchCalls(mCallTypeFilter, mDateLimit);
+        ((ListsFragment) getParentFragment()).updateTabUnreadCounts();
     }
 
     private void updateEmptyMessage(int filterType) {
@@ -443,7 +448,7 @@
 
             fetchCalls();
             mCallLogQueryHandler.fetchVoicemailStatus();
-
+            mCallLogQueryHandler.fetchMissedCallsUnreadCount();
             updateOnTransition(true /* onEntry */);
             mRefreshDataRequired = false;
         } else {
@@ -467,12 +472,11 @@
             // On either of the transitions we update the missed call and voicemail notifications.
             // While exiting we additionally consume all missed calls (by marking them as read).
             mCallLogQueryHandler.markNewCallsAsOld();
-            if (!onEntry) {
-                mCallLogQueryHandler.markMissedCallsAsRead();
-            }
             if (mCallTypeFilter == Calls.VOICEMAIL_TYPE) {
                 CallLogNotificationsHelper.updateVoicemailNotifications(getActivity());
-            } else {
+            } else if (((ListsFragment) getParentFragment()).getCurrentTabIndex() ==
+                    ListsFragment.TAB_INDEX_HISTORY && !onEntry) {
+                mCallLogQueryHandler.markMissedCallsAsRead();
                 CallLogNotificationsHelper.removeMissedCallNotifications(getActivity());
             }
         }
diff --git a/src/com/android/dialer/calllog/CallLogQueryHandler.java b/src/com/android/dialer/calllog/CallLogQueryHandler.java
index 4cb835b..9ff74cf 100644
--- a/src/com/android/dialer/calllog/CallLogQueryHandler.java
+++ b/src/com/android/dialer/calllog/CallLogQueryHandler.java
@@ -62,6 +62,8 @@
     private static final int QUERY_VOICEMAIL_STATUS_TOKEN = 57;
     /** The token for the query to fetch the number of unread voicemails. */
     private static final int QUERY_VOICEMAIL_UNREAD_COUNT_TOKEN = 58;
+    /** The token for the query to fetch the number of missed calls. */
+    private static final int QUERY_MISSED_CALLS_UNREAD_COUNT_TOKEN = 59;
 
     private final int mLogLimit;
 
@@ -225,19 +227,25 @@
         if (!PermissionsUtil.hasPhonePermissions(mContext)) {
             return;
         }
-        // Mark all "new" calls as not new anymore.
-        StringBuilder where = new StringBuilder();
-        where.append(Calls.IS_READ).append(" = 0");
-        where.append(" AND ");
-        where.append(Calls.TYPE).append(" = ").append(Calls.MISSED_TYPE);
 
         ContentValues values = new ContentValues(1);
         values.put(Calls.IS_READ, "1");
 
         startUpdate(UPDATE_MARK_MISSED_CALL_AS_READ_TOKEN, null, Calls.CONTENT_URI, values,
-                where.toString(), null);
+                getUnreadMissedCallsQuery(), null);
     }
 
+    /** Fetch all missed calls received since last time the tab was opened. */
+    public void fetchMissedCallsUnreadCount() {
+        if (!PermissionsUtil.hasPhonePermissions(mContext)) {
+            return;
+        }
+
+        startQuery(QUERY_MISSED_CALLS_UNREAD_COUNT_TOKEN, null, Calls.CONTENT_URI,
+                new String[]{Calls._ID}, getUnreadMissedCallsQuery(), null, null);
+    }
+
+
     @Override
     protected synchronized void onNotNullableQueryComplete(int token, Object cookie,
             Cursor cursor) {
@@ -253,6 +261,8 @@
                 updateVoicemailStatus(cursor);
             } else if (token == QUERY_VOICEMAIL_UNREAD_COUNT_TOKEN) {
                 updateVoicemailUnreadCount(cursor);
+            } else if (token == QUERY_MISSED_CALLS_UNREAD_COUNT_TOKEN) {
+                updateMissedCallsUnreadCount(cursor);
             } else {
                 Log.w(TAG, "Unknown query completed: ignoring: " + token);
             }
@@ -276,6 +286,17 @@
 
     }
 
+    /**
+     * @return Query string to get all unread missed calls.
+     */
+    private String getUnreadMissedCallsQuery() {
+        StringBuilder where = new StringBuilder();
+        where.append(Calls.IS_READ).append(" = 0");
+        where.append(" AND ");
+        where.append(Calls.TYPE).append(" = ").append(Calls.MISSED_TYPE);
+        return where.toString();
+    }
+
     private void updateVoicemailStatus(Cursor statusCursor) {
         final Listener listener = mListener.get();
         if (listener != null) {
@@ -290,6 +311,13 @@
         }
     }
 
+    private void updateMissedCallsUnreadCount(Cursor statusCursor) {
+        final Listener listener = mListener.get();
+        if (listener != null) {
+            listener.onMissedCallsUnreadCountFetched(statusCursor);
+        }
+    }
+
     /** Listener to completion of various queries. */
     public interface Listener {
         /** Called when {@link CallLogQueryHandler#fetchVoicemailStatus()} completes. */
@@ -298,6 +326,9 @@
         /** Called when {@link CallLogQueryHandler#fetchVoicemailUnreadCount()} completes. */
         void onVoicemailUnreadCountFetched(Cursor cursor);
 
+        /** Called when {@link CallLogQueryHandler#fetchMissedCallsUnreadCount()} completes. */
+        void onMissedCallsUnreadCountFetched(Cursor cursor);
+
         /**
          * Called when {@link CallLogQueryHandler#fetchCalls(int)} complete.
          * Returns true if takes ownership of cursor.
diff --git a/src/com/android/dialer/list/ListsFragment.java b/src/com/android/dialer/list/ListsFragment.java
index d5caa1a..9f76148 100644
--- a/src/com/android/dialer/list/ListsFragment.java
+++ b/src/com/android/dialer/list/ListsFragment.java
@@ -192,6 +192,7 @@
         mCallLogQueryHandler =
                 new CallLogQueryHandler(getActivity(), getActivity().getContentResolver(), this);
         mCallLogQueryHandler.fetchVoicemailStatus();
+        mCallLogQueryHandler.fetchMissedCallsUnreadCount();
         Trace.endSection();
     }
 
@@ -347,6 +348,23 @@
     }
 
     @Override
+    public void onMissedCallsUnreadCountFetched(Cursor cursor) {
+        if (getActivity() == null || getActivity().isFinishing() || cursor == null) {
+            return;
+        }
+
+        int count = 0;
+        try {
+            count = cursor.getCount();
+        } finally {
+            cursor.close();
+        }
+
+        mViewPagerTabs.setUnreadCount(count, TAB_INDEX_HISTORY);
+        mViewPagerTabs.updateTab(TAB_INDEX_HISTORY);
+    }
+
+    @Override
     public boolean onCallsFetched(Cursor statusCursor) {
         // Return false; did not take ownership of cursor
         return false;
@@ -361,8 +379,11 @@
      * expands a voicemail in the call log.
      */
     public void updateTabUnreadCounts() {
-        if (mHasActiveVoicemailProvider && mCallLogQueryHandler != null) {
-            mCallLogQueryHandler.fetchVoicemailUnreadCount();
+        if (mCallLogQueryHandler != null) {
+            mCallLogQueryHandler.fetchMissedCallsUnreadCount();
+            if (mHasActiveVoicemailProvider) {
+                mCallLogQueryHandler.fetchVoicemailUnreadCount();
+            }
         }
     }
 
diff --git a/src/com/android/dialer/voicemail/VisualVoicemailEnabledChecker.java b/src/com/android/dialer/voicemail/VisualVoicemailEnabledChecker.java
index 3134b14..80a0368 100644
--- a/src/com/android/dialer/voicemail/VisualVoicemailEnabledChecker.java
+++ b/src/com/android/dialer/voicemail/VisualVoicemailEnabledChecker.java
@@ -91,6 +91,11 @@
     }
 
     @Override
+    public void onMissedCallsUnreadCountFetched(Cursor cursor) {
+        // Do nothing
+    }
+
+    @Override
     public boolean onCallsFetched(Cursor combinedCursor) {
         // Do nothing
         return false;