Implement filtering of call log.

This commit adds a menu options to filter the call log to show only
voicemails.

Currently the list is reset whenever the user switching to a different
tab or activity, in fact any time the content of the call log needs to
is refreshed.

Bug: 5035665
Change-Id: I7e412b02e08f8d7a15abc2ea1897b726f30bf1de
diff --git a/res/menu/call_log_options.xml b/res/menu/call_log_options.xml
index 1f8de57..0d14f2f 100644
--- a/res/menu/call_log_options.xml
+++ b/res/menu/call_log_options.xml
@@ -21,6 +21,11 @@
         android:showAsAction="withText" />
 
     <item
+        android:id="@+id/show_voicemails_only"
+        android:title="@string/menu_show_voicemails_only"
+        android:showAsAction="withText" />
+
+    <item
         android:id="@+id/menu_call_settings_call_log"
         android:title="@string/call_settings"
         android:showAsAction="withText" />
diff --git a/res/values/strings.xml b/res/values/strings.xml
index b90898d..83cb770 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1665,4 +1665,7 @@
 
     <!-- The "file name" displayed for vCards received directly via NFC [CHAR LIMIT=16] -->
     <string name="nfc_vcard_file_name">Contact received over NFC</string>
+
+    <!-- Menu item used to show only voicemails in the call log. [CHAR LIMIT=30] -->
+    <string name="menu_show_voicemails_only">Show voicemails only</string>
 </resources>
diff --git a/src/com/android/contacts/calllog/CallLogFragment.java b/src/com/android/contacts/calllog/CallLogFragment.java
index 3383ab2..f61f1de 100644
--- a/src/com/android/contacts/calllog/CallLogFragment.java
+++ b/src/com/android/contacts/calllog/CallLogFragment.java
@@ -974,7 +974,7 @@
 
     private void startCallsQuery() {
         mAdapter.setLoading(true);
-        mCallLogQueryHandler.fetchCalls();
+        mCallLogQueryHandler.fetchAllCalls();
     }
 
     private void startVoicemailStatusQuery() {
@@ -990,6 +990,7 @@
     @Override
     public void onPrepareOptionsMenu(Menu menu) {
         menu.findItem(R.id.delete_all).setVisible(mShowOptionsMenu);
+        menu.findItem(R.id.show_voicemails_only).setVisible(mShowOptionsMenu);
         final MenuItem callSettingsMenuItem = menu.findItem(R.id.menu_call_settings_call_log);
         if (mShowOptionsMenu) {
             callSettingsMenuItem.setVisible(true);
@@ -1006,8 +1007,15 @@
                 ClearCallLogDialog.show(getFragmentManager());
                 return true;
             }
+
+            case R.id.show_voicemails_only: {
+                mCallLogQueryHandler.fetchVoicemailOnly();
+                return true;
+            }
+
+            default:
+                throw new IllegalArgumentException("unknown menu item: " + item.getItemId());
         }
-        return super.onOptionsItemSelected(item);
     }
 
     /*
diff --git a/src/com/android/contacts/calllog/CallLogQueryHandler.java b/src/com/android/contacts/calllog/CallLogQueryHandler.java
index 8569190..fdf55b9 100644
--- a/src/com/android/contacts/calllog/CallLogQueryHandler.java
+++ b/src/com/android/contacts/calllog/CallLogQueryHandler.java
@@ -121,42 +121,57 @@
      * <p>
      * It will asynchronously update the content of the list view when the fetch completes.
      */
-    public void fetchCalls() {
+    public void fetchAllCalls() {
         cancelFetch();
         invalidate();
-        fetchNewCalls();
-        fetchOldCalls();
+        fetchCalls(QUERY_NEW_CALLS_TOKEN, true /*isNew*/, false /*voicemailOnly*/);
+        fetchCalls(QUERY_OLD_CALLS_TOKEN, false /*isNew*/, false /*voicemailOnly*/);
     }
 
+    /**
+     * Fetches the list of calls from the call log but include only the voicemail.
+     * <p>
+     * It will asynchronously update the content of the list view when the fetch completes.
+     */
+    public void fetchVoicemailOnly() {
+        cancelFetch();
+        invalidate();
+        fetchCalls(QUERY_NEW_CALLS_TOKEN, true /*isNew*/, true /*voicemailOnly*/);
+        fetchCalls(QUERY_OLD_CALLS_TOKEN, false /*isNew*/, true /*voicemailOnly*/);
+    }
+
+
     public void fetchVoicemailStatus() {
         startQuery(QUERY_VOICEMAIL_STATUS_TOKEN, null, Status.CONTENT_URI,
                 VoicemailStatusHelperImpl.PROJECTION, null, null, null);
     }
 
-    /** Fetches the list of new calls in the call log. */
-    private void fetchNewCalls() {
-        fetchCalls(QUERY_NEW_CALLS_TOKEN, true);
-    }
-
-    /** Fetch the list of old calls in the call log. */
-    private void fetchOldCalls() {
-        fetchCalls(QUERY_OLD_CALLS_TOKEN, false);
-    }
-
     /** Fetches the list of calls in the call log, either the new one or the old ones. */
-    private void fetchCalls(int token, boolean isNew) {
+    private void fetchCalls(int token, boolean isNew, boolean voicemailOnly) {
         // We need to check for NULL explicitly otherwise entries with where NEW is NULL will not
         // match either the query or its negation.
         String selection =
                 String.format("%s IS NOT NULL AND %s = 1 AND (%s = ? OR %s = ?)",
                         Calls.NEW, Calls.NEW, Calls.TYPE, Calls.TYPE);
-        String[] selectionArgs = new String[]{
-                Integer.toString(Calls.MISSED_TYPE),
-                Integer.toString(Calls.VOICEMAIL_TYPE),
-        };
+        final String[] selectionArgs;
         if (!isNew) {
+            // Negate the query.
             selection = String.format("NOT (%s)", selection);
         }
+        if (voicemailOnly) {
+            // Add a clause to fetch only items of type voicemail.
+            selection = String.format("(%s) AND (%s = ?)", selection, Calls.TYPE);
+            selectionArgs = new String[]{
+                    Integer.toString(Calls.MISSED_TYPE),
+                    Integer.toString(Calls.VOICEMAIL_TYPE),
+                    Integer.toString(Calls.VOICEMAIL_TYPE),
+            };
+        } else {
+            selectionArgs = new String[]{
+                    Integer.toString(Calls.MISSED_TYPE),
+                    Integer.toString(Calls.VOICEMAIL_TYPE),
+            };
+        }
         startQuery(token, null, Calls.CONTENT_URI_WITH_VOICEMAIL,
                 CallLogQuery._PROJECTION, selection, selectionArgs, Calls.DEFAULT_SORT_ORDER);
     }