Merge changes I1c2c08cc,I76a0b43d,Ifa718fb0

* changes:
  Add accessibility label for voicemail transcription rating
  Parity of OldMainActivityPeer with ListsFragment for VM
  Show empty view when there are no voicemails
diff --git a/java/com/android/dialer/app/res/layout/call_log_list_item.xml b/java/com/android/dialer/app/res/layout/call_log_list_item.xml
index 1b776b4..acaa820 100644
--- a/java/com/android/dialer/app/res/layout/call_log_list_item.xml
+++ b/java/com/android/dialer/app/res/layout/call_log_list_item.xml
@@ -202,6 +202,7 @@
                   android:id="@+id/voicemail_transcription_rating_good"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
+                  android:contentDescription="@string/description_rating_good"
                   android:gravity="end|center_vertical"
                   android:focusable="true"
                   android:src="@drawable/quantum_ic_thumb_up_grey600_24"/>
@@ -211,6 +212,7 @@
                   android:id="@+id/voicemail_transcription_rating_bad"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
+                  android:contentDescription="@string/description_rating_bad"
                   android:gravity="end|center_vertical"
                   android:focusable="true"
                   android:src="@drawable/quantum_ic_thumb_down_grey600_24"/>
diff --git a/java/com/android/dialer/app/res/values/strings.xml b/java/com/android/dialer/app/res/values/strings.xml
index 5974f47..7332c31 100644
--- a/java/com/android/dialer/app/res/values/strings.xml
+++ b/java/com/android/dialer/app/res/values/strings.xml
@@ -706,6 +706,14 @@
   <!-- Message displayed after user has rated a voicemail transcription [CHAR LIMIT=30] -->
   <string name="voicemail_transcription_rating_thanks">Thanks for your feedback</string>
 
+  <!-- Describes the thumbs up, 'good' transcription button. Read by TalkBack.
+      [CHAR LIMIT=NONE] -->
+  <string name="description_rating_good">Like</string>
+
+  <!-- Describes the thumbs down, 'bad' transcription button. Read by TalkBack.
+      [CHAR LIMIT=NONE] -->
+  <string name="description_rating_bad">Dislike</string>
+
   <!-- Button text to prompt a user to open an sms conversation [CHAR LIMIT=NONE] -->
   <string name="view_conversation">View</string>
 
diff --git a/java/com/android/dialer/main/impl/OldMainActivityPeer.java b/java/com/android/dialer/main/impl/OldMainActivityPeer.java
index a05ef6d..2999c6b 100644
--- a/java/com/android/dialer/main/impl/OldMainActivityPeer.java
+++ b/java/com/android/dialer/main/impl/OldMainActivityPeer.java
@@ -23,11 +23,14 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.database.ContentObserver;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.Handler;
 import android.provider.CallLog.Calls;
 import android.provider.ContactsContract.QuickContact;
+import android.provider.VoicemailContract;
 import android.support.annotation.Nullable;
 import android.support.design.widget.FloatingActionButton;
 import android.support.design.widget.Snackbar;
@@ -91,9 +94,15 @@
 import com.android.dialer.storage.StorageComponent;
 import com.android.dialer.telecom.TelecomUtil;
 import com.android.dialer.util.DialerUtils;
+import com.android.dialer.util.PermissionsUtil;
 import com.android.dialer.util.TransactionSafeActivity;
+import com.android.dialer.voicemail.listui.error.VoicemailStatusCorruptionHandler;
+import com.android.dialer.voicemail.listui.error.VoicemailStatusCorruptionHandler.Source;
+import com.android.dialer.voicemailstatus.VisualVoicemailEnabledChecker;
+import com.android.dialer.voicemailstatus.VoicemailStatusHelper;
 import com.android.voicemail.VoicemailComponent;
 import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Locale;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -273,7 +282,7 @@
     if (VoicemailComponent.get(context)
         .getVoicemailClient()
         .isVoicemailEnabled(context, defaultUserSelectedAccount)) {
-      LogUtil.i("OldMainActivityPeer.canVoicemailTabBeShown", "Voicemail is not enabled");
+      LogUtil.i("OldMainActivityPeer.canVoicemailTabBeShown", "Voicemail is enabled");
       return true;
     }
     LogUtil.i("OldMainActivityPeer.canVoicemailTabBeShown", "returning false");
@@ -706,7 +715,6 @@
    *   <li>Marking missed calls as read when appropriate. See {@link
    *       #markMissedCallsAsReadAndRemoveNotification()}
    *   <li>TODO(calderwoodra): multiselect
-   *   <li>TODO(calderwoodra): voicemail status
    * </ul>
    *
    * @see CallLogFragmentListener
@@ -727,6 +735,15 @@
     private long timeSelected = -1;
     private boolean activityIsAlive;
 
+    private final ContentObserver voicemailStatusObserver =
+        new ContentObserver(new Handler()) {
+          @Override
+          public void onChange(boolean selfChange) {
+            super.onChange(selfChange);
+            callLogQueryHandler.fetchVoicemailStatus();
+          }
+        };
+
     MainCallLogFragmentListener(
         Context context,
         ContentResolver contentResolver,
@@ -738,6 +755,21 @@
       this.toolbar = toolbar;
     }
 
+    private void registerVoicemailStatusContentObserver(Context context) {
+
+      if (PermissionsUtil.hasReadVoicemailPermissions(context)
+          && PermissionsUtil.hasAddVoicemailPermissions(context)) {
+        context
+            .getContentResolver()
+            .registerContentObserver(
+                VoicemailContract.Status.CONTENT_URI, true, voicemailStatusObserver);
+      } else {
+        LogUtil.w(
+            "MainCallLogFragmentListener.registerVoicemailStatusContentObserver",
+            "no voicemail read/add permissions");
+      }
+    }
+
     @Override
     public void updateTabUnreadCounts() {
       callLogQueryHandler.fetchMissedCallsUnreadCount();
@@ -752,7 +784,42 @@
 
     @Override
     public void onVoicemailStatusFetched(Cursor statusCursor) {
-      // TODO(calderwoodra): handle this when voicemail is implemented
+      LogUtil.i("OldMainActivityPeer.MainCallLogFragmentListener", "onVoicemailStatusFetched");
+      VoicemailStatusCorruptionHandler.maybeFixVoicemailStatus(
+          context, statusCursor, Source.Activity);
+
+      // Update hasActiveVoicemailProvider, which controls the number of tabs displayed.
+      int numberOfActiveVoicemailSources =
+          VoicemailStatusHelper.getNumberActivityVoicemailSources(statusCursor);
+
+      boolean hasActiveVoicemailProvider = numberOfActiveVoicemailSources > 0;
+      LogUtil.i(
+          "OldMainActivityPeer.onVoicemailStatusFetched",
+          String.format(
+              Locale.US,
+              "hasActiveVoicemailProvider:%b, number of active voicemail sources:%d",
+              hasActiveVoicemailProvider,
+              numberOfActiveVoicemailSources));
+
+      if (hasActiveVoicemailProvider) {
+        // TODO(yueg): Use new logging for VVM_TAB_VISIBLE
+        // Logger.get(context).logImpression(DialerImpression.Type.VVM_TAB_VISIBLE);
+        bottomNavBar.showVoicemail(true);
+        callLogQueryHandler.fetchVoicemailUnreadCount();
+      } else {
+        bottomNavBar.showVoicemail(false);
+      }
+
+      StorageComponent.get(context)
+          .unencryptedSharedPrefs()
+          .edit()
+          .putBoolean(
+              VisualVoicemailEnabledChecker.PREF_KEY_HAS_ACTIVE_VOICEMAIL_PROVIDER,
+              hasActiveVoicemailProvider)
+          .apply();
+
+      // TODO(uabdullah): Check if we need to force move to the VM tab (e.g in the event of
+      // clicking a vm notification and a status wasn't yet fetched).
     }
 
     @Override
@@ -812,6 +879,7 @@
 
     public void onActivityResume() {
       activityIsAlive = true;
+      registerVoicemailStatusContentObserver(context);
       callLogQueryHandler.fetchVoicemailStatus();
       callLogQueryHandler.fetchMissedCallsUnreadCount();
       // Reset the tab on resume to restart the timer
@@ -820,6 +888,7 @@
 
     /** Should be called when {@link Activity#onStop()} is called. */
     public void onActivityStop(boolean changingConfigurations, boolean keyguardLocked) {
+      context.getContentResolver().unregisterContentObserver(voicemailStatusObserver);
       activityIsAlive = false;
       if (viewedCallLogTabPastTimeThreshold() && !changingConfigurations && !keyguardLocked) {
         markMissedCallsAsReadAndRemoveNotification();
diff --git a/java/com/android/dialer/main/impl/bottomnav/BottomNavBar.java b/java/com/android/dialer/main/impl/bottomnav/BottomNavBar.java
index d9a446f..5ee33fc 100644
--- a/java/com/android/dialer/main/impl/bottomnav/BottomNavBar.java
+++ b/java/com/android/dialer/main/impl/bottomnav/BottomNavBar.java
@@ -23,6 +23,7 @@
 import android.view.View;
 import android.widget.LinearLayout;
 import com.android.dialer.common.Assert;
+import com.android.dialer.common.LogUtil;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
@@ -123,8 +124,25 @@
     }
   }
 
+  /**
+   * Displays or hides the voicemail tab.
+   *
+   * <p>In the event that the voicemail tab was earlier visible but is now no longer visible, we
+   * move to the speed dial tab.
+   *
+   * @param showTab whether to hide or show the voicemail
+   */
   public void showVoicemail(boolean showTab) {
+    LogUtil.i("OldMainActivityPeer.showVoicemail", "showing Tab:%b", showTab);
+    int voicemailpreviousVisibility = voicemail.getVisibility();
     voicemail.setVisibility(showTab ? View.VISIBLE : View.GONE);
+    int voicemailcurrentVisibility = voicemail.getVisibility();
+
+    if (voicemailpreviousVisibility != voicemailcurrentVisibility
+        && voicemailpreviousVisibility == View.VISIBLE) {
+      LogUtil.i("OldMainActivityPeer.showVoicemail", "hid VM tab and moved to speed dial tab");
+      selectTab(TabIndex.SPEED_DIAL);
+    }
   }
 
   public void setNotificationCount(@TabIndex int tab, int count) {
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java b/java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java
index 9296d04..6d71dad 100644
--- a/java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java
+++ b/java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java
@@ -30,6 +30,7 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.FrameLayout;
 import com.android.dialer.calllog.CallLogComponent;
 import com.android.dialer.calllog.RefreshAnnotatedCallLogReceiver;
 import com.android.dialer.common.LogUtil;
@@ -38,6 +39,7 @@
 import com.android.dialer.glidephotomanager.GlidePhotoManagerComponent;
 import com.android.dialer.voicemail.listui.error.VoicemailStatus;
 import com.android.dialer.voicemailstatus.VoicemailStatusQuery;
+import com.android.dialer.widget.EmptyContentView;
 import com.android.voicemail.VoicemailComponent;
 import com.google.common.collect.ImmutableList;
 import com.google.common.util.concurrent.ListenableFuture;
@@ -52,6 +54,11 @@
   private RefreshAnnotatedCallLogReceiver refreshAnnotatedCallLogReceiver;
   private UiListener<ImmutableList<VoicemailStatus>> queryVoicemailStatusTableListener;
 
+  // View required to show/hide recycler and empty views
+  FrameLayout fragmentRootFrameLayout;
+
+  private EmptyContentView emptyContentView;
+
   public NewVoicemailFragment() {
     LogUtil.enterBlock("NewVoicemailFragment.NewVoicemailFragment");
   }
@@ -147,10 +154,14 @@
   public View onCreateView(
       LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
     LogUtil.enterBlock("NewVoicemailFragment.onCreateView");
-    View view = inflater.inflate(R.layout.new_voicemail_call_log_fragment, container, false);
-    recyclerView = view.findViewById(R.id.new_voicemail_call_log_recycler_view);
+
+    fragmentRootFrameLayout =
+        (FrameLayout) inflater.inflate(R.layout.new_voicemail_call_log_fragment, container, false);
+    recyclerView = fragmentRootFrameLayout.findViewById(R.id.new_voicemail_call_log_recycler_view);
+
+    emptyContentView = fragmentRootFrameLayout.findViewById(R.id.empty_content_view);
     getLoaderManager().restartLoader(0, null, this);
-    return view;
+    return fragmentRootFrameLayout;
   }
 
   @Override
@@ -162,6 +173,12 @@
   @Override
   public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
     LogUtil.i("NewVoicemailFragment.onLoadFinished", "cursor size is %d", data.getCount());
+    if (data.getCount() == 0) {
+      showEmptyVoicemailFragmentView();
+      return;
+    }
+    showView(recyclerView);
+
     if (recyclerView.getAdapter() == null) {
       recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
       // TODO(uabdullah): Replace getActivity().getFragmentManager() with getChildFragment()
@@ -182,9 +199,24 @@
           recyclerView.getAdapter());
       ((NewVoicemailAdapter) recyclerView.getAdapter()).updateCursor(data);
       ((NewVoicemailAdapter) recyclerView.getAdapter()).checkAndPlayVoicemail();
+      queryAndUpdateVoicemailStatusAlert();
     }
+  }
 
-    queryAndUpdateVoicemailStatusAlert();
+  /** Shows the view when there are no voicemails to be displayed * */
+  private void showEmptyVoicemailFragmentView() {
+    LogUtil.enterBlock("NewVoicemailFragmentListener.showEmptyVoicemailFragmentView");
+
+    showView(emptyContentView);
+
+    emptyContentView.setDescription((R.string.empty_voicemail_tab_text));
+    emptyContentView.setImage(R.drawable.quantum_ic_schedule_vd_theme_24);
+  }
+
+  private void showView(View view) {
+    LogUtil.i("NewVoicemailFragmentListener.showView", "Showing view: " + view);
+    emptyContentView.setVisibility(view == emptyContentView ? View.VISIBLE : View.GONE);
+    recyclerView.setVisibility(view == recyclerView ? View.VISIBLE : View.GONE);
   }
 
   private void registerRefreshAnnotatedCallLogReceiver() {
diff --git a/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_call_log_fragment.xml b/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_call_log_fragment.xml
index 9daa3e1..fd9e0f2 100644
--- a/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_call_log_fragment.xml
+++ b/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_call_log_fragment.xml
@@ -15,21 +15,35 @@
   ~ limitations under the License
   -->
 
-
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/fragment_my_frame_layout"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
+    android:id="@+id/new_voicemail_frame_layout"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
     android:orientation="vertical">
-  <include layout="@layout/voicemail_tos_fragment"/>
 
   <android.support.v7.widget.RecyclerView
       xmlns:android="http://schemas.android.com/apk/res/android"
       android:id="@+id/new_voicemail_call_log_recycler_view"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
-      android:background="@color/background_dialer_light"
       android:paddingBottom="@dimen/floating_action_button_list_bottom_padding"
-      android:clipToPadding="false"/>
+      android:background="@color/background_dialer_light"
+      android:clipToPadding="false"
+      android:visibility="gone"
+      />
+
+
+  <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+      android:layout_width="match_parent"
+      android:layout_height="match_parent">
+
+    <com.android.dialer.widget.EmptyContentView
+        android:id="@+id/empty_content_view"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:visibility="gone"/>
+
+  </FrameLayout>
 
 </FrameLayout>
diff --git a/java/com/android/dialer/voicemail/listui/res/values/strings.xml b/java/com/android/dialer/voicemail/listui/res/values/strings.xml
index db33c19..d12a71e 100644
--- a/java/com/android/dialer/voicemail/listui/res/values/strings.xml
+++ b/java/com/android/dialer/voicemail/listui/res/values/strings.xml
@@ -57,4 +57,7 @@
   <!-- Label indicating who provided the voicemail transcription [CHAR LIMIT=64] -->
   <string name="voicemail_transcription_branding_text">Transcribed by Google</string>
 
+  <!-- Text displayed when the list of voicemails is empty [CHAR LIMIT=NONE] -->
+  <string name="empty_voicemail_tab_text">Your voicemail inbox is empty.</string>
+
 </resources>
diff --git a/java/com/android/dialer/widget/res/layout/empty_content_view.xml b/java/com/android/dialer/widget/res/layout/empty_content_view.xml
index 1777443..9aac6f4 100644
--- a/java/com/android/dialer/widget/res/layout/empty_content_view.xml
+++ b/java/com/android/dialer/widget/res/layout/empty_content_view.xml
@@ -18,7 +18,7 @@
   <ImageView
     android:id="@+id/empty_list_view_image"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content"
+    android:layout_height="108dp"
     android:gravity="center_horizontal"/>
 
   <TextView