Merge "Display unread count for voicemail and update when vm is read." into ub-contactsdialer-a-dev
diff --git a/res/drawable/tab_contacts.xml b/res/drawable/tab_contacts.xml
deleted file mode 100644
index ed3f86b..0000000
--- a/res/drawable/tab_contacts.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2014 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
-  -->
-
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="@color/tab_ripple_color">
-
-    <item>
-        <bitmap android:src="@drawable/ic_people_24dp"
-            android:gravity="center" />
-    </item>
-
-    <item android:id="@android:id/mask">
-        <color android:color="@android:color/white" />
-    </item>
-
-</ripple>
diff --git a/res/drawable/tab_history.xml b/res/drawable/tab_history.xml
deleted file mode 100644
index b1a5318..0000000
--- a/res/drawable/tab_history.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2014 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
-  -->
-
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="@color/tab_ripple_color">
-
-    <item>
-        <bitmap android:src="@drawable/ic_schedule_24dp"
-            android:gravity="center" />
-    </item>
-
-    <item android:id="@android:id/mask">
-        <color android:color="@android:color/white" />
-    </item>
-
-</ripple>
diff --git a/res/drawable/tab_speed_dial.xml b/res/drawable/tab_speed_dial.xml
deleted file mode 100644
index c9c4820..0000000
--- a/res/drawable/tab_speed_dial.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2014 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
-  -->
-
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="@color/tab_ripple_color">
-
-    <item>
-        <bitmap android:src="@drawable/ic_grade_24dp"
-            android:gravity="center" />
-    </item>
-
-    <item android:id="@android:id/mask">
-        <color android:color="@android:color/white" />
-    </item>
-
-</ripple>
diff --git a/res/drawable/tab_voicemail.xml b/res/drawable/tab_voicemail.xml
deleted file mode 100644
index 568891b..0000000
--- a/res/drawable/tab_voicemail.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ 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
-  -->
-
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="@color/tab_ripple_color">
-
-    <item>
-        <bitmap android:src="@drawable/ic_voicemail_24dp"
-            android:gravity="center" />
-    </item>
-
-    <item android:id="@android:id/mask">
-        <color android:color="@android:color/white" />
-    </item>
-
-</ripple>
diff --git a/src/com/android/dialer/DialtactsActivity.java b/src/com/android/dialer/DialtactsActivity.java
index 4342695..4ade04a 100644
--- a/src/com/android/dialer/DialtactsActivity.java
+++ b/src/com/android/dialer/DialtactsActivity.java
@@ -693,6 +693,14 @@
     }
 
     /**
+     * Update the number of unread voicemails (potentially other tabs) displayed next to the tab
+     * icon.
+     */
+    public void updateTabUnreadCounts() {
+        mListsFragment.updateTabUnreadCounts();
+    }
+
+    /**
      * Initiates a fragment transaction to show the dialpad fragment. Animations and other visual
      * updates are handled by a callback which is invoked after the dialpad fragment is shown.
      * @see #onDialpadShown
diff --git a/src/com/android/dialer/calllog/CallLogAsyncTaskUtil.java b/src/com/android/dialer/calllog/CallLogAsyncTaskUtil.java
index 1becc89..5a62a7d 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.dialer.DialtactsActivity;
 import com.android.dialer.PhoneCallDetails;
 import com.android.dialer.util.AsyncTaskExecutor;
 import com.android.dialer.util.AsyncTaskExecutors;
@@ -246,6 +247,8 @@
                 Intent intent = new Intent(context, CallLogNotificationsService.class);
                 intent.setAction(CallLogNotificationsService.ACTION_MARK_NEW_VOICEMAILS_AS_OLD);
                 context.startService(intent);
+
+                ((DialtactsActivity) context).updateTabUnreadCounts();
                 return null;
             }
         });
diff --git a/src/com/android/dialer/calllog/CallLogFragment.java b/src/com/android/dialer/calllog/CallLogFragment.java
index 09e4f02..8762f18 100644
--- a/src/com/android/dialer/calllog/CallLogFragment.java
+++ b/src/com/android/dialer/calllog/CallLogFragment.java
@@ -284,6 +284,9 @@
     }
 
     @Override
+    public void onVoicemailUnreadCountFetched(Cursor cursor) {}
+
+    @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
         View view = inflater.inflate(R.layout.call_log_fragment, container, false);
 
diff --git a/src/com/android/dialer/calllog/CallLogQueryHandler.java b/src/com/android/dialer/calllog/CallLogQueryHandler.java
index 60bdcff..771df99 100644
--- a/src/com/android/dialer/calllog/CallLogQueryHandler.java
+++ b/src/com/android/dialer/calllog/CallLogQueryHandler.java
@@ -59,6 +59,8 @@
     private static final int UPDATE_MARK_MISSED_CALL_AS_READ_TOKEN = 56;
     /** The token for the query to fetch voicemail status messages. */
     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;
 
     private final int mLogLimit;
 
@@ -147,6 +149,13 @@
         }
     }
 
+    public void fetchVoicemailUnreadCount() {
+        if (TelecomUtil.hasReadWriteVoicemailPermissions(mContext)) {
+            startQuery(QUERY_VOICEMAIL_UNREAD_COUNT_TOKEN, null, Voicemails.CONTENT_URI,
+                new String[] { Voicemails._ID }, Voicemails.IS_READ + "=0", null, null);
+        }
+    }
+
     /** Fetches the list of calls in the call log. */
     private void fetchCalls(int token, int callType, boolean newOnly, long newerThan) {
         // We need to check for NULL explicitly otherwise entries with where READ is NULL
@@ -243,6 +252,8 @@
                 }
             } else if (token == QUERY_VOICEMAIL_STATUS_TOKEN) {
                 updateVoicemailStatus(cursor);
+            } else if (token == QUERY_VOICEMAIL_UNREAD_COUNT_TOKEN) {
+                updateVoicemailUnreadCount(cursor);
             } else {
                 Log.w(TAG, "Unknown query completed: ignoring: " + token);
             }
@@ -273,11 +284,21 @@
         }
     }
 
+    private void updateVoicemailUnreadCount(Cursor statusCursor) {
+        final Listener listener = mListener.get();
+        if (listener != null) {
+            listener.onVoicemailUnreadCountFetched(statusCursor);
+        }
+    }
+
     /** Listener to completion of various queries. */
     public interface Listener {
         /** Called when {@link CallLogQueryHandler#fetchVoicemailStatus()} completes. */
         void onVoicemailStatusFetched(Cursor statusCursor);
 
+        /** Called when {@link CallLogQueryHandler#fetchVoicemailUnreadCount()} completes. */
+        void onVoicemailUnreadCountFetched(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 feab201..09a4cb2 100644
--- a/src/com/android/dialer/list/ListsFragment.java
+++ b/src/com/android/dialer/list/ListsFragment.java
@@ -110,6 +110,7 @@
      * The position of the currently selected tab.
      */
     private int mTabIndex = TAB_INDEX_SPEED_DIAL;
+    private CallLogQueryHandler mCallLogQueryHandler;
 
     public class ViewPagerAdapter extends FragmentPagerAdapter {
         public ViewPagerAdapter(FragmentManager fm) {
@@ -199,9 +200,9 @@
         }
 
         // Fetch voicemail status to determine if we should show the voicemail tab.
-        CallLogQueryHandler callLogQueryHandler =
+        mCallLogQueryHandler =
                 new CallLogQueryHandler(getActivity(), getActivity().getContentResolver(), this);
-        callLogQueryHandler.fetchVoicemailStatus();
+        mCallLogQueryHandler.fetchVoicemailStatus();
         Trace.endSection();
     }
 
@@ -227,13 +228,13 @@
         mTabTitles[TAB_INDEX_VOICEMAIL] = getResources().getString(R.string.tab_voicemail);
 
         mTabIcons = new int[TAB_COUNT_WITH_VOICEMAIL];
-        mTabIcons[TAB_INDEX_SPEED_DIAL] = R.drawable.tab_speed_dial;
-        mTabIcons[TAB_INDEX_HISTORY] = R.drawable.tab_history;
-        mTabIcons[TAB_INDEX_ALL_CONTACTS] = R.drawable.tab_contacts;
-        mTabIcons[TAB_INDEX_VOICEMAIL] = R.drawable.tab_voicemail;
+        mTabIcons[TAB_INDEX_SPEED_DIAL] = R.drawable.ic_grade_24dp;
+        mTabIcons[TAB_INDEX_HISTORY] = R.drawable.ic_schedule_24dp;
+        mTabIcons[TAB_INDEX_ALL_CONTACTS] = R.drawable.ic_people_24dp;
+        mTabIcons[TAB_INDEX_VOICEMAIL] = R.drawable.ic_voicemail_24dp;
 
         mViewPagerTabs = (ViewPagerTabs) parentView.findViewById(R.id.lists_pager_header);
-        mViewPagerTabs.setTabIcons(mTabIcons);
+        mViewPagerTabs.configureTabIcons(mTabIcons);
         mViewPagerTabs.setViewPager(mViewPager);
         addOnPageChangeListener(mViewPagerTabs);
 
@@ -319,8 +320,12 @@
             mViewPagerTabs.setViewPager(mViewPager);
 
             mPrefs.edit()
-                    .putBoolean(PREF_KEY_HAS_ACTIVE_VOICEMAIL_PROVIDER, hasActiveVoicemailProvider)
-                    .commit();
+                  .putBoolean(PREF_KEY_HAS_ACTIVE_VOICEMAIL_PROVIDER, hasActiveVoicemailProvider)
+                  .commit();
+        }
+
+        if (hasActiveVoicemailProvider) {
+            mCallLogQueryHandler.fetchVoicemailUnreadCount();
         }
 
         if (mHasActiveVoicemailProvider && mShowVoicemailTabAfterVoicemailStatusIsFetched) {
@@ -330,6 +335,23 @@
     }
 
     @Override
+    public void onVoicemailUnreadCountFetched(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_VOICEMAIL);
+        mViewPagerTabs.setViewPager(mViewPager);
+    }
+
+    @Override
     public boolean onCallsFetched(Cursor statusCursor) {
         // Return false; did not take ownership of cursor
         return false;
@@ -339,6 +361,16 @@
         return mTabIndex;
     }
 
+    /**
+     * External method to update unread count because the unread count changes when the user
+     * expands a voicemail in the call log.
+     */
+    public void updateTabUnreadCounts() {
+        if (mHasActiveVoicemailProvider) {
+            mCallLogQueryHandler.fetchVoicemailUnreadCount();
+        }
+    }
+
     public void showRemoveView(boolean show) {
         mRemoveViewContent.setVisibility(show ? View.VISIBLE : View.GONE);
         mRemoveView.setAlpha(show ? 0 : 1);